diff options
272 files changed, 7637 insertions, 7041 deletions
diff --git a/Documentation/fb/00-INDEX b/Documentation/fb/00-INDEX index caabbd395e6..a618fd99c9f 100644 --- a/Documentation/fb/00-INDEX +++ b/Documentation/fb/00-INDEX | |||
@@ -11,8 +11,6 @@ aty128fb.txt | |||
11 | - info on the ATI Rage128 frame buffer driver. | 11 | - info on the ATI Rage128 frame buffer driver. |
12 | cirrusfb.txt | 12 | cirrusfb.txt |
13 | - info on the driver for Cirrus Logic chipsets. | 13 | - info on the driver for Cirrus Logic chipsets. |
14 | cyblafb/ | ||
15 | - directory with documentation files related to the cyblafb driver. | ||
16 | deferred_io.txt | 14 | deferred_io.txt |
17 | - an introduction to deferred IO. | 15 | - an introduction to deferred IO. |
18 | fbcon.txt | 16 | fbcon.txt |
diff --git a/Documentation/fb/cyblafb/bugs b/Documentation/fb/cyblafb/bugs deleted file mode 100644 index 9443a6d72cd..00000000000 --- a/Documentation/fb/cyblafb/bugs +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | Bugs | ||
2 | ==== | ||
3 | |||
4 | I currently don't know of any bug. Please do send reports to: | ||
5 | - linux-fbdev-devel@lists.sourceforge.net | ||
6 | - Knut_Petersen@t-online.de. | ||
7 | |||
8 | |||
9 | Untested features | ||
10 | ================= | ||
11 | |||
12 | All LCD stuff is untested. If it worked in tridentfb, it should work in | ||
13 | cyblafb. Please test and report the results to Knut_Petersen@t-online.de. | ||
diff --git a/Documentation/fb/cyblafb/credits b/Documentation/fb/cyblafb/credits deleted file mode 100644 index 0eb3b443dc2..00000000000 --- a/Documentation/fb/cyblafb/credits +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | Thanks to | ||
2 | ========= | ||
3 | * Alan Hourihane, for writing the X trident driver | ||
4 | * Jani Monoses, for writing the tridentfb driver | ||
5 | * Antonino A. Daplas, for review of the first published | ||
6 | version of cyblafb and some code | ||
7 | * Jochen Hein, for testing and a helpfull bug report | ||
diff --git a/Documentation/fb/cyblafb/documentation b/Documentation/fb/cyblafb/documentation deleted file mode 100644 index bb1aac04842..00000000000 --- a/Documentation/fb/cyblafb/documentation +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | Available Documentation | ||
2 | ======================= | ||
3 | |||
4 | Apollo PLE 133 Chipset VT8601A North Bridge Datasheet, Rev. 1.82, October 22, | ||
5 | 2001, available from VIA: | ||
6 | |||
7 | http://www.viavpsd.com/product/6/15/DS8601A182.pdf | ||
8 | |||
9 | The datasheet is incomplete, some registers that need to be programmed are not | ||
10 | explained at all and important bits are listed as "reserved". But you really | ||
11 | need the datasheet to understand the code. "p. xxx" comments refer to page | ||
12 | numbers of this document. | ||
13 | |||
14 | XFree/XOrg drivers are available and of good quality, looking at the code | ||
15 | there is a good idea if the datasheet does not provide enough information | ||
16 | or if the datasheet seems to be wrong. | ||
17 | |||
diff --git a/Documentation/fb/cyblafb/fb.modes b/Documentation/fb/cyblafb/fb.modes deleted file mode 100644 index fe0e5223ba8..00000000000 --- a/Documentation/fb/cyblafb/fb.modes +++ /dev/null | |||
@@ -1,154 +0,0 @@ | |||
1 | # | ||
2 | # Sample fb.modes file | ||
3 | # | ||
4 | # Provides an incomplete list of working modes for | ||
5 | # the cyberblade/i1 graphics core. | ||
6 | # | ||
7 | # The value 4294967256 is used instead of -40. Of course, -40 is not | ||
8 | # a really reasonable value, but chip design does not always follow | ||
9 | # logic. Believe me, it's ok, and it's the way the BIOS does it. | ||
10 | # | ||
11 | # fbset requires 4294967256 in fb.modes and -40 as an argument to | ||
12 | # the -t parameter. That's also not too reasonable, and it might change | ||
13 | # in the future or might even be differt for your current version. | ||
14 | # | ||
15 | |||
16 | mode "640x480-50" | ||
17 | geometry 640 480 2048 4096 8 | ||
18 | timings 47619 4294967256 24 17 0 216 3 | ||
19 | endmode | ||
20 | |||
21 | mode "640x480-60" | ||
22 | geometry 640 480 2048 4096 8 | ||
23 | timings 39682 4294967256 24 17 0 216 3 | ||
24 | endmode | ||
25 | |||
26 | mode "640x480-70" | ||
27 | geometry 640 480 2048 4096 8 | ||
28 | timings 34013 4294967256 24 17 0 216 3 | ||
29 | endmode | ||
30 | |||
31 | mode "640x480-72" | ||
32 | geometry 640 480 2048 4096 8 | ||
33 | timings 33068 4294967256 24 17 0 216 3 | ||
34 | endmode | ||
35 | |||
36 | mode "640x480-75" | ||
37 | geometry 640 480 2048 4096 8 | ||
38 | timings 31746 4294967256 24 17 0 216 3 | ||
39 | endmode | ||
40 | |||
41 | mode "640x480-80" | ||
42 | geometry 640 480 2048 4096 8 | ||
43 | timings 29761 4294967256 24 17 0 216 3 | ||
44 | endmode | ||
45 | |||
46 | mode "640x480-85" | ||
47 | geometry 640 480 2048 4096 8 | ||
48 | timings 28011 4294967256 24 17 0 216 3 | ||
49 | endmode | ||
50 | |||
51 | mode "800x600-50" | ||
52 | geometry 800 600 2048 4096 8 | ||
53 | timings 30303 96 24 14 0 136 11 | ||
54 | endmode | ||
55 | |||
56 | mode "800x600-60" | ||
57 | geometry 800 600 2048 4096 8 | ||
58 | timings 25252 96 24 14 0 136 11 | ||
59 | endmode | ||
60 | |||
61 | mode "800x600-70" | ||
62 | geometry 800 600 2048 4096 8 | ||
63 | timings 21645 96 24 14 0 136 11 | ||
64 | endmode | ||
65 | |||
66 | mode "800x600-72" | ||
67 | geometry 800 600 2048 4096 8 | ||
68 | timings 21043 96 24 14 0 136 11 | ||
69 | endmode | ||
70 | |||
71 | mode "800x600-75" | ||
72 | geometry 800 600 2048 4096 8 | ||
73 | timings 20202 96 24 14 0 136 11 | ||
74 | endmode | ||
75 | |||
76 | mode "800x600-80" | ||
77 | geometry 800 600 2048 4096 8 | ||
78 | timings 18939 96 24 14 0 136 11 | ||
79 | endmode | ||
80 | |||
81 | mode "800x600-85" | ||
82 | geometry 800 600 2048 4096 8 | ||
83 | timings 17825 96 24 14 0 136 11 | ||
84 | endmode | ||
85 | |||
86 | mode "1024x768-50" | ||
87 | geometry 1024 768 2048 4096 8 | ||
88 | timings 19054 144 24 29 0 120 3 | ||
89 | endmode | ||
90 | |||
91 | mode "1024x768-60" | ||
92 | geometry 1024 768 2048 4096 8 | ||
93 | timings 15880 144 24 29 0 120 3 | ||
94 | endmode | ||
95 | |||
96 | mode "1024x768-70" | ||
97 | geometry 1024 768 2048 4096 8 | ||
98 | timings 13610 144 24 29 0 120 3 | ||
99 | endmode | ||
100 | |||
101 | mode "1024x768-72" | ||
102 | geometry 1024 768 2048 4096 8 | ||
103 | timings 13232 144 24 29 0 120 3 | ||
104 | endmode | ||
105 | |||
106 | mode "1024x768-75" | ||
107 | geometry 1024 768 2048 4096 8 | ||
108 | timings 12703 144 24 29 0 120 3 | ||
109 | endmode | ||
110 | |||
111 | mode "1024x768-80" | ||
112 | geometry 1024 768 2048 4096 8 | ||
113 | timings 11910 144 24 29 0 120 3 | ||
114 | endmode | ||
115 | |||
116 | mode "1024x768-85" | ||
117 | geometry 1024 768 2048 4096 8 | ||
118 | timings 11209 144 24 29 0 120 3 | ||
119 | endmode | ||
120 | |||
121 | mode "1280x1024-50" | ||
122 | geometry 1280 1024 2048 4096 8 | ||
123 | timings 11114 232 16 39 0 160 3 | ||
124 | endmode | ||
125 | |||
126 | mode "1280x1024-60" | ||
127 | geometry 1280 1024 2048 4096 8 | ||
128 | timings 9262 232 16 39 0 160 3 | ||
129 | endmode | ||
130 | |||
131 | mode "1280x1024-70" | ||
132 | geometry 1280 1024 2048 4096 8 | ||
133 | timings 7939 232 16 39 0 160 3 | ||
134 | endmode | ||
135 | |||
136 | mode "1280x1024-72" | ||
137 | geometry 1280 1024 2048 4096 8 | ||
138 | timings 7719 232 16 39 0 160 3 | ||
139 | endmode | ||
140 | |||
141 | mode "1280x1024-75" | ||
142 | geometry 1280 1024 2048 4096 8 | ||
143 | timings 7410 232 16 39 0 160 3 | ||
144 | endmode | ||
145 | |||
146 | mode "1280x1024-80" | ||
147 | geometry 1280 1024 2048 4096 8 | ||
148 | timings 6946 232 16 39 0 160 3 | ||
149 | endmode | ||
150 | |||
151 | mode "1280x1024-85" | ||
152 | geometry 1280 1024 2048 4096 8 | ||
153 | timings 6538 232 16 39 0 160 3 | ||
154 | endmode | ||
diff --git a/Documentation/fb/cyblafb/performance b/Documentation/fb/cyblafb/performance deleted file mode 100644 index 8d15d5dfc6b..00000000000 --- a/Documentation/fb/cyblafb/performance +++ /dev/null | |||
@@ -1,79 +0,0 @@ | |||
1 | Speed | ||
2 | ===== | ||
3 | |||
4 | CyBlaFB is much faster than tridentfb and vesafb. Compare the performance data | ||
5 | for mode 1280x1024-[8,16,32]@61 Hz. | ||
6 | |||
7 | Test 1: Cat a file with 2000 lines of 0 characters. | ||
8 | Test 2: Cat a file with 2000 lines of 80 characters. | ||
9 | Test 3: Cat a file with 2000 lines of 160 characters. | ||
10 | |||
11 | All values show system time use in seconds, kernel 2.6.12 was used for | ||
12 | the measurements. 2.6.13 is a bit slower, 2.6.14 hopefully will include a | ||
13 | patch that speeds up kernel bitblitting a lot ( > 20%). | ||
14 | |||
15 | +-----------+-----------------------------------------------------+ | ||
16 | | | not accelerated | | ||
17 | | TRIDENTFB +-----------------+-----------------+-----------------+ | ||
18 | | of 2.6.12 | 8 bpp | 16 bpp | 32 bpp | | ||
19 | | | noypan | ypan | noypan | ypan | noypan | ypan | | ||
20 | +-----------+--------+--------+--------+--------+--------+--------+ | ||
21 | | Test 1 | 4.31 | 4.33 | 6.05 | 12.81 | ---- | ---- | | ||
22 | | Test 2 | 67.94 | 5.44 | 123.16 | 14.79 | ---- | ---- | | ||
23 | | Test 3 | 131.36 | 6.55 | 240.12 | 16.76 | ---- | ---- | | ||
24 | +-----------+--------+--------+--------+--------+--------+--------+ | ||
25 | | Comments | | | completely bro- | | ||
26 | | | | | ken, monitor | | ||
27 | | | | | switches off | | ||
28 | +-----------+-----------------+-----------------+-----------------+ | ||
29 | |||
30 | |||
31 | +-----------+-----------------------------------------------------+ | ||
32 | | | accelerated | | ||
33 | | TRIDENTFB +-----------------+-----------------+-----------------+ | ||
34 | | of 2.6.12 | 8 bpp | 16 bpp | 32 bpp | | ||
35 | | | noypan | ypan | noypan | ypan | noypan | ypan | | ||
36 | +-----------+--------+--------+--------+--------+--------+--------+ | ||
37 | | Test 1 | ---- | ---- | 20.62 | 1.22 | ---- | ---- | | ||
38 | | Test 2 | ---- | ---- | 22.61 | 3.19 | ---- | ---- | | ||
39 | | Test 3 | ---- | ---- | 24.59 | 5.16 | ---- | ---- | | ||
40 | +-----------+--------+--------+--------+--------+--------+--------+ | ||
41 | | Comments | broken, writing | broken, ok only | completely bro- | | ||
42 | | | to wrong places | if bgcolor is | ken, monitor | | ||
43 | | | on screen + bug | black, bug in | switches off | | ||
44 | | | in fillrect() | fillrect() | | | ||
45 | +-----------+-----------------+-----------------+-----------------+ | ||
46 | |||
47 | |||
48 | +-----------+-----------------------------------------------------+ | ||
49 | | | not accelerated | | ||
50 | | VESAFB +-----------------+-----------------+-----------------+ | ||
51 | | of 2.6.12 | 8 bpp | 16 bpp | 32 bpp | | ||
52 | | | noypan | ypan | noypan | ypan | noypan | ypan | | ||
53 | +-----------+--------+--------+--------+--------+--------+--------+ | ||
54 | | Test 1 | 4.26 | 3.76 | 5.99 | 7.23 | ---- | ---- | | ||
55 | | Test 2 | 65.65 | 4.89 | 120.88 | 9.08 | ---- | ---- | | ||
56 | | Test 3 | 126.91 | 5.94 | 235.77 | 11.03 | ---- | ---- | | ||
57 | +-----------+--------+--------+--------+--------+--------+--------+ | ||
58 | | Comments | vga=0x307 | vga=0x31a | vga=0x31b not | | ||
59 | | | fh=80kHz | fh=80kHz | supported by | | ||
60 | | | fv=75kHz | fv=75kHz | video BIOS and | | ||
61 | | | | | hardware | | ||
62 | +-----------+-----------------+-----------------+-----------------+ | ||
63 | |||
64 | |||
65 | +-----------+-----------------------------------------------------+ | ||
66 | | | accelerated | | ||
67 | | CYBLAFB +-----------------+-----------------+-----------------+ | ||
68 | | | 8 bpp | 16 bpp | 32 bpp | | ||
69 | | | noypan | ypan | noypan | ypan | noypan | ypan | | ||
70 | +-----------+--------+--------+--------+--------+--------+--------+ | ||
71 | | Test 1 | 8.02 | 0.23 | 19.04 | 0.61 | 57.12 | 2.74 | | ||
72 | | Test 2 | 8.38 | 0.55 | 19.39 | 0.92 | 57.54 | 3.13 | | ||
73 | | Test 3 | 8.73 | 0.86 | 19.74 | 1.24 | 57.95 | 3.51 | | ||
74 | +-----------+--------+--------+--------+--------+--------+--------+ | ||
75 | | Comments | | | | | ||
76 | | | | | | | ||
77 | | | | | | | ||
78 | | | | | | | ||
79 | +-----------+-----------------+-----------------+-----------------+ | ||
diff --git a/Documentation/fb/cyblafb/todo b/Documentation/fb/cyblafb/todo deleted file mode 100644 index c5f6d0eae54..00000000000 --- a/Documentation/fb/cyblafb/todo +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | TODO / Missing features | ||
2 | ======================= | ||
3 | |||
4 | Verify LCD stuff "stretch" and "center" options are | ||
5 | completely untested ... this code needs to be | ||
6 | verified. As I don't have access to such | ||
7 | hardware, please contact me if you are | ||
8 | willing run some tests. | ||
9 | |||
10 | Interlaced video modes The reason that interleaved | ||
11 | modes are disabled is that I do not know | ||
12 | the meaning of the vertical interlace | ||
13 | parameter. Also the datasheet mentions a | ||
14 | bit d8 of a horizontal interlace parameter, | ||
15 | but nowhere the lower 8 bits. Please help | ||
16 | if you can. | ||
17 | |||
18 | low-res double scan modes Who needs it? | ||
19 | |||
20 | accelerated color blitting Who needs it? The console driver does use color | ||
21 | blitting for nothing but drawing the penguine, | ||
22 | everything else is done using color expanding | ||
23 | blitting of 1bpp character bitmaps. | ||
24 | |||
25 | ioctls Who needs it? | ||
26 | |||
27 | TV-out Will be done later. Use "vga= " at boot time | ||
28 | to set a suitable video mode. | ||
29 | |||
30 | ??? Feel free to contact me if you have any | ||
31 | feature requests | ||
diff --git a/Documentation/fb/cyblafb/usage b/Documentation/fb/cyblafb/usage deleted file mode 100644 index a39bb3d402a..00000000000 --- a/Documentation/fb/cyblafb/usage +++ /dev/null | |||
@@ -1,217 +0,0 @@ | |||
1 | CyBlaFB is a framebuffer driver for the Cyberblade/i1 graphics core integrated | ||
2 | into the VIA Apollo PLE133 (aka vt8601) south bridge. It is developed and | ||
3 | tested using a VIA EPIA 5000 board. | ||
4 | |||
5 | Cyblafb - compiled into the kernel or as a module? | ||
6 | ================================================== | ||
7 | |||
8 | You might compile cyblafb either as a module or compile it permanently into the | ||
9 | kernel. | ||
10 | |||
11 | Unless you have a real reason to do so you should not compile both vesafb and | ||
12 | cyblafb permanently into the kernel. It's possible and it helps during the | ||
13 | developement cycle, but it's useless and will at least block some otherwise | ||
14 | usefull memory for ordinary users. | ||
15 | |||
16 | Selecting Modes | ||
17 | =============== | ||
18 | |||
19 | Startup Mode | ||
20 | ============ | ||
21 | |||
22 | First of all, you might use the "vga=???" boot parameter as it is | ||
23 | documented in vesafb.txt and svga.txt. Cyblafb will detect the video | ||
24 | mode selected and will use the geometry and timings found by | ||
25 | inspecting the hardware registers. | ||
26 | |||
27 | video=cyblafb vga=0x317 | ||
28 | |||
29 | Alternatively you might use a combination of the mode, ref and bpp | ||
30 | parameters. If you compiled the driver into the kernel, add something | ||
31 | like this to the kernel command line: | ||
32 | |||
33 | video=cyblafb:1280x1024,bpp=16,ref=50 ... | ||
34 | |||
35 | If you compiled the driver as a module, the same mode would be | ||
36 | selected by the following command: | ||
37 | |||
38 | modprobe cyblafb mode=1280x1024 bpp=16 ref=50 ... | ||
39 | |||
40 | None of the modes possible to select as startup modes are affected by | ||
41 | the problems described at the end of the next subsection. | ||
42 | |||
43 | For all startup modes cyblafb chooses a virtual x resolution of 2048, | ||
44 | the only exception is mode 1280x1024 in combination with 32 bpp. This | ||
45 | allows ywrap scrolling for all those modes if rotation is 0 or 2, and | ||
46 | also fast scrolling if rotation is 1 or 3. The default virtual y reso- | ||
47 | lution is 4096 for bpp == 8, 2048 for bpp==16 and 1024 for bpp == 32, | ||
48 | again with the only exception of 1280x1024 at 32 bpp. | ||
49 | |||
50 | Please do set your video memory size to 8 Mb in the Bios setup. Other | ||
51 | values will work, but performace is decreased for a lot of modes. | ||
52 | |||
53 | Mode changes using fbset | ||
54 | ======================== | ||
55 | |||
56 | You might use fbset to change the video mode, see "man fbset". Cyblafb | ||
57 | generally does assume that you know what you are doing. But it does | ||
58 | some checks, especially those that are needed to prevent you from | ||
59 | damaging your hardware. | ||
60 | |||
61 | - only 8, 16, 24 and 32 bpp video modes are accepted | ||
62 | - interlaced video modes are not accepted | ||
63 | - double scan video modes are not accepted | ||
64 | - if a flat panel is found, cyblafb does not allow you | ||
65 | to program a resolution higher than the physical | ||
66 | resolution of the flat panel monitor | ||
67 | - cyblafb does not allow vclk to exceed 230 MHz. As 32 bpp | ||
68 | and (currently) 24 bit modes use a doubled vclk internally, | ||
69 | the dotclock limit as seen by fbset is 115 MHz for those | ||
70 | modes and 230 MHz for 8 and 16 bpp modes. | ||
71 | - cyblafb will allow you to select very high resolutions as | ||
72 | long as the hardware can be programmed to these modes. The | ||
73 | documented limit 1600x1200 is not enforced, but don't expect | ||
74 | perfect signal quality. | ||
75 | |||
76 | Any request that violates the rules given above will be either changed | ||
77 | to something the hardware supports or an error value will be returned. | ||
78 | |||
79 | If you program a virtual y resolution higher than the hardware limit, | ||
80 | cyblafb will silently decrease that value to the highest possible | ||
81 | value. The same is true for a virtual x resolution that is not | ||
82 | supported by the hardware. Cyblafb tries to adapt vyres first because | ||
83 | vxres decides if ywrap scrolling is possible or not. | ||
84 | |||
85 | Attempts to disable acceleration are ignored, I believe that this is | ||
86 | safe. | ||
87 | |||
88 | Some video modes that should work do not work as expected. If you use | ||
89 | the standard fb.modes, fbset 640x480-60 will program that mode, but | ||
90 | you will see a vertical area, about two characters wide, with only | ||
91 | much darker characters than the other characters on the screen. | ||
92 | Cyblafb does allow that mode to be set, as it does not violate the | ||
93 | official specifications. It would need a lot of code to reliably sort | ||
94 | out all invalid modes, playing around with the margin values will | ||
95 | give a valid mode quickly. And if cyblafb would detect such an invalid | ||
96 | mode, should it silently alter the requested values or should it | ||
97 | report an error? Both options have some pros and cons. As stated | ||
98 | above, none of the startup modes are affected, and if you set | ||
99 | verbosity to 1 or higher, cyblafb will print the fbset command that | ||
100 | would be needed to program that mode using fbset. | ||
101 | |||
102 | |||
103 | Other Parameters | ||
104 | ================ | ||
105 | |||
106 | |||
107 | crt don't autodetect, assume monitor connected to | ||
108 | standard VGA connector | ||
109 | |||
110 | fp don't autodetect, assume flat panel display | ||
111 | connected to flat panel monitor interface | ||
112 | |||
113 | nativex inform driver about native x resolution of | ||
114 | flat panel monitor connected to special | ||
115 | interface (should be autodetected) | ||
116 | |||
117 | stretch stretch image to adapt low resolution modes to | ||
118 | higer resolutions of flat panel monitors | ||
119 | connected to special interface | ||
120 | |||
121 | center center image to adapt low resolution modes to | ||
122 | higer resolutions of flat panel monitors | ||
123 | connected to special interface | ||
124 | |||
125 | memsize use if autodetected memsize is wrong ... | ||
126 | should never be necessary | ||
127 | |||
128 | nopcirr disable PCI read retry | ||
129 | nopciwr disable PCI write retry | ||
130 | nopcirb disable PCI read bursts | ||
131 | nopciwb disable PCI write bursts | ||
132 | |||
133 | bpp bpp for specified modes | ||
134 | valid values: 8 || 16 || 24 || 32 | ||
135 | |||
136 | ref refresh rate for specified mode | ||
137 | valid values: 50 <= ref <= 85 | ||
138 | |||
139 | mode 640x480 or 800x600 or 1024x768 or 1280x1024 | ||
140 | if not specified, the startup mode will be detected | ||
141 | and used, so you might also use the vga=??? parameter | ||
142 | described in vesafb.txt. If you do not specify a mode, | ||
143 | bpp and ref parameters are ignored. | ||
144 | |||
145 | verbosity 0 is the default, increase to at least 2 for every | ||
146 | bug report! | ||
147 | |||
148 | Development hints | ||
149 | ================= | ||
150 | |||
151 | It's much faster do compile a module and to load the new version after | ||
152 | unloading the old module than to compile a new kernel and to reboot. So if you | ||
153 | try to work on cyblafb, it might be a good idea to use cyblafb as a module. | ||
154 | In real life, fast often means dangerous, and that's also the case here. If | ||
155 | you introduce a serious bug when cyblafb is compiled into the kernel, the | ||
156 | kernel will lock or oops with a high probability before the file system is | ||
157 | mounted, and the danger for your data is low. If you load a broken own version | ||
158 | of cyblafb on a running system, the danger for the integrity of the file | ||
159 | system is much higher as you might need a hard reset afterwards. Decide | ||
160 | yourself. | ||
161 | |||
162 | Module unloading, the vfb method | ||
163 | ================================ | ||
164 | |||
165 | If you want to unload/reload cyblafb using the virtual framebuffer, you need | ||
166 | to enable vfb support in the kernel first. After that, load the modules as | ||
167 | shown below: | ||
168 | |||
169 | modprobe vfb vfb_enable=1 | ||
170 | modprobe fbcon | ||
171 | modprobe cyblafb | ||
172 | fbset -fb /dev/fb1 1280x1024-60 -vyres 2662 | ||
173 | con2fb /dev/fb1 /dev/tty1 | ||
174 | ... | ||
175 | |||
176 | If you now made some changes to cyblafb and want to reload it, you might do it | ||
177 | as show below: | ||
178 | |||
179 | con2fb /dev/fb0 /dev/tty1 | ||
180 | ... | ||
181 | rmmod cyblafb | ||
182 | modprobe cyblafb | ||
183 | con2fb /dev/fb1 /dev/tty1 | ||
184 | ... | ||
185 | |||
186 | Of course, you might choose another mode, and most certainly you also want to | ||
187 | map some other /dev/tty* to the real framebuffer device. You might also choose | ||
188 | to compile fbcon as a kernel module or place it permanently in the kernel. | ||
189 | |||
190 | I do not know of any way to unload fbcon, and fbcon will prevent the | ||
191 | framebuffer device loaded first from unloading. [If there is a way, then | ||
192 | please add a description here!] | ||
193 | |||
194 | Module unloading, the vesafb method | ||
195 | =================================== | ||
196 | |||
197 | Configure the kernel: | ||
198 | |||
199 | <*> Support for frame buffer devices | ||
200 | [*] VESA VGA graphics support | ||
201 | <M> Cyberblade/i1 support | ||
202 | |||
203 | Add e.g. "video=vesafb:ypan vga=0x307" to the kernel parameters. The ypan | ||
204 | parameter is important, choose any vga parameter you like as long as it is | ||
205 | a graphics mode. | ||
206 | |||
207 | After booting, load cyblafb without any mode and bpp parameter and assign | ||
208 | cyblafb to individual ttys using con2fb, e.g.: | ||
209 | |||
210 | modprobe cyblafb | ||
211 | con2fb /dev/fb1 /dev/tty1 | ||
212 | |||
213 | Unloading cyblafb works without problems after you assign vesafb to all | ||
214 | ttys again, e.g.: | ||
215 | |||
216 | con2fb /dev/fb0 /dev/tty1 | ||
217 | rmmod cyblafb | ||
diff --git a/Documentation/fb/cyblafb/whatsnew b/Documentation/fb/cyblafb/whatsnew deleted file mode 100644 index 76c07a26e04..00000000000 --- a/Documentation/fb/cyblafb/whatsnew +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | 0.62 | ||
2 | ==== | ||
3 | |||
4 | - the vesafb parameter has been removed as I decided to allow the | ||
5 | feature without any special parameter. | ||
6 | |||
7 | - Cyblafb does not use the vga style of panning any longer, now the | ||
8 | "right view" register in the graphics engine IO space is used. Without | ||
9 | that change it was impossible to use all available memory, and without | ||
10 | access to all available memory it is impossible to ywrap. | ||
11 | |||
12 | - The imageblit function now uses hardware acceleration for all font | ||
13 | widths. Hardware blitting across pixel column 2048 is broken in the | ||
14 | cyberblade/i1 graphics core, but we work around that hardware bug. | ||
15 | |||
16 | - modes with vxres != xres are supported now. | ||
17 | |||
18 | - ywrap scrolling is supported now and the default. This is a big | ||
19 | performance gain. | ||
20 | |||
21 | - default video modes use vyres > yres and vxres > xres to allow | ||
22 | almost optimal scrolling speed for normal and rotated screens | ||
23 | |||
24 | - some features mainly usefull for debugging the upper layers of the | ||
25 | framebuffer system have been added, have a look at the code | ||
26 | |||
27 | - fixed: Oops after unloading cyblafb when reading /proc/io* | ||
28 | |||
29 | - we work around some bugs of the higher framebuffer layers. | ||
diff --git a/Documentation/fb/cyblafb/whycyblafb b/Documentation/fb/cyblafb/whycyblafb deleted file mode 100644 index a123bc11e69..00000000000 --- a/Documentation/fb/cyblafb/whycyblafb +++ /dev/null | |||
@@ -1,85 +0,0 @@ | |||
1 | I tried the following framebuffer drivers: | ||
2 | |||
3 | - TRIDENTFB is full of bugs. Acceleration is broken for Blade3D | ||
4 | graphics cores like the cyberblade/i1. It claims to support a great | ||
5 | number of devices, but documentation for most of these devices is | ||
6 | unfortunately not available. There is _no_ reason to use tridentfb | ||
7 | for cyberblade/i1 + CRT users. VESAFB is faster, and the one | ||
8 | advantage, mode switching, is broken in tridentfb. | ||
9 | |||
10 | - VESAFB is used by many distributions as a standard. Vesafb does | ||
11 | not support mode switching. VESAFB is a bit faster than the working | ||
12 | configurations of TRIDENTFB, but it is still too slow, even if you | ||
13 | use ypan. | ||
14 | |||
15 | - EPIAFB (you'll find it on sourceforge) supports the Cyberblade/i1 | ||
16 | graphics core, but it still has serious bugs and developement seems | ||
17 | to have stopped. This is the one driver with TV-out support. If you | ||
18 | do need this feature, try epiafb. | ||
19 | |||
20 | None of these drivers was a real option for me. | ||
21 | |||
22 | I believe that is unreasonable to change code that announces to support 20 | ||
23 | devices if I only have more or less sufficient documentation for exactly one | ||
24 | of these. The risk of breaking device foo while fixing device bar is too high. | ||
25 | |||
26 | So I decided to start CyBlaFB as a stripped down tridentfb. | ||
27 | |||
28 | All code specific to other Trident chips has been removed. After that there | ||
29 | were a lot of cosmetic changes to increase the readability of the code. All | ||
30 | register names were changed to those mnemonics used in the datasheet. Function | ||
31 | and macro names were changed if they hindered easy understanding of the code. | ||
32 | |||
33 | After that I debugged the code and implemented some new features. I'll try to | ||
34 | give a little summary of the main changes: | ||
35 | |||
36 | - calculation of vertical and horizontal timings was fixed | ||
37 | |||
38 | - video signal quality has been improved dramatically | ||
39 | |||
40 | - acceleration: | ||
41 | |||
42 | - fillrect and copyarea were fixed and reenabled | ||
43 | |||
44 | - color expanding imageblit was newly implemented, color | ||
45 | imageblit (only used to draw the penguine) still uses the | ||
46 | generic code. | ||
47 | |||
48 | - init of the acceleration engine was improved and moved to a | ||
49 | place where it really works ... | ||
50 | |||
51 | - sync function has a timeout now and tries to reset and | ||
52 | reinit the accel engine if necessary | ||
53 | |||
54 | - fewer slow copyarea calls when doing ypan scrolling by using | ||
55 | undocumented bit d21 of screen start address stored in | ||
56 | CR2B[5]. BIOS does use it also, so this should be safe. | ||
57 | |||
58 | - cyblafb rejects any attempt to set modes that would cause vclk | ||
59 | values above reasonable 230 MHz. 32bit modes use a clock | ||
60 | multiplicator of 2, so fbset does show the correct values for | ||
61 | pixclock but not for vclk in this case. The fbset limit is 115 MHz | ||
62 | for 32 bpp modes. | ||
63 | |||
64 | - cyblafb rejects modes known to be broken or unimplemented (all | ||
65 | interlaced modes, all doublescan modes for now) | ||
66 | |||
67 | - cyblafb now works independant of the video mode in effect at startup | ||
68 | time (tridentfb does not init all needed registers to reasonable | ||
69 | values) | ||
70 | |||
71 | - switching between video modes does work reliably now | ||
72 | |||
73 | - the first video mode now is the one selected on startup using the | ||
74 | vga=???? mechanism or any of | ||
75 | - 640x480, 800x600, 1024x768, 1280x1024 | ||
76 | - 8, 16, 24 or 32 bpp | ||
77 | - refresh between 50 Hz and 85 Hz, 1 Hz steps (1280x1024-32 | ||
78 | is limited to 63Hz) | ||
79 | |||
80 | - pci retry and pci burst mode are settable (try to disable if you | ||
81 | experience latency problems) | ||
82 | |||
83 | - built as a module cyblafb might be unloaded and reloaded using | ||
84 | the vfb module and con2vt or might be used together with vesafb | ||
85 | |||
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 5e02b83ac12..ea7d1bdad34 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -311,6 +311,18 @@ Who: Vlad Yasevich <vladislav.yasevich@hp.com> | |||
311 | 311 | ||
312 | --------------------------- | 312 | --------------------------- |
313 | 313 | ||
314 | What: Ability for non root users to shm_get hugetlb pages based on mlock | ||
315 | resource limits | ||
316 | When: 2.6.31 | ||
317 | Why: Non root users need to be part of /proc/sys/vm/hugetlb_shm_group or | ||
318 | have CAP_IPC_LOCK to be able to allocate shm segments backed by | ||
319 | huge pages. The mlock based rlimit check to allow shm hugetlb is | ||
320 | inconsistent with mmap based allocations. Hence it is being | ||
321 | deprecated. | ||
322 | Who: Ravikiran Thirumalai <kiran@scalex86.org> | ||
323 | |||
324 | --------------------------- | ||
325 | |||
314 | What: CONFIG_THERMAL_HWMON | 326 | What: CONFIG_THERMAL_HWMON |
315 | When: January 2009 | 327 | When: January 2009 |
316 | Why: This option was introduced just to allow older lm-sensors userspace | 328 | Why: This option was introduced just to allow older lm-sensors userspace |
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 4e78ce67784..76efe5b71d7 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking | |||
@@ -505,7 +505,7 @@ prototypes: | |||
505 | void (*open)(struct vm_area_struct*); | 505 | void (*open)(struct vm_area_struct*); |
506 | void (*close)(struct vm_area_struct*); | 506 | void (*close)(struct vm_area_struct*); |
507 | int (*fault)(struct vm_area_struct*, struct vm_fault *); | 507 | int (*fault)(struct vm_area_struct*, struct vm_fault *); |
508 | int (*page_mkwrite)(struct vm_area_struct *, struct page *); | 508 | int (*page_mkwrite)(struct vm_area_struct *, struct vm_fault *); |
509 | int (*access)(struct vm_area_struct *, unsigned long, void*, int, int); | 509 | int (*access)(struct vm_area_struct *, unsigned long, void*, int, int); |
510 | 510 | ||
511 | locking rules: | 511 | locking rules: |
diff --git a/Documentation/hwmon/lis3lv02d b/Documentation/hwmon/lis3lv02d index 287f8c90265..effe949a728 100644 --- a/Documentation/hwmon/lis3lv02d +++ b/Documentation/hwmon/lis3lv02d | |||
@@ -1,11 +1,11 @@ | |||
1 | Kernel driver lis3lv02d | 1 | Kernel driver lis3lv02d |
2 | ================== | 2 | ======================= |
3 | 3 | ||
4 | Supported chips: | 4 | Supported chips: |
5 | 5 | ||
6 | * STMicroelectronics LIS3LV02DL and LIS3LV02DQ | 6 | * STMicroelectronics LIS3LV02DL and LIS3LV02DQ |
7 | 7 | ||
8 | Author: | 8 | Authors: |
9 | Yan Burman <burman.yan@gmail.com> | 9 | Yan Burman <burman.yan@gmail.com> |
10 | Eric Piel <eric.piel@tremplin-utc.net> | 10 | Eric Piel <eric.piel@tremplin-utc.net> |
11 | 11 | ||
@@ -15,7 +15,7 @@ Description | |||
15 | 15 | ||
16 | This driver provides support for the accelerometer found in various HP | 16 | This driver provides support for the accelerometer found in various HP |
17 | laptops sporting the feature officially called "HP Mobile Data | 17 | laptops sporting the feature officially called "HP Mobile Data |
18 | Protection System 3D" or "HP 3D DriveGuard". It detect automatically | 18 | Protection System 3D" or "HP 3D DriveGuard". It detects automatically |
19 | laptops with this sensor. Known models (for now the HP 2133, nc6420, | 19 | laptops with this sensor. Known models (for now the HP 2133, nc6420, |
20 | nc2510, nc8510, nc84x0, nw9440 and nx9420) will have their axis | 20 | nc2510, nc8510, nc84x0, nw9440 and nx9420) will have their axis |
21 | automatically oriented on standard way (eg: you can directly play | 21 | automatically oriented on standard way (eg: you can directly play |
@@ -27,7 +27,7 @@ position - 3D position that the accelerometer reports. Format: "(x,y,z)" | |||
27 | calibrate - read: values (x, y, z) that are used as the base for input | 27 | calibrate - read: values (x, y, z) that are used as the base for input |
28 | class device operation. | 28 | class device operation. |
29 | write: forces the base to be recalibrated with the current | 29 | write: forces the base to be recalibrated with the current |
30 | position. | 30 | position. |
31 | rate - reports the sampling rate of the accelerometer device in HZ | 31 | rate - reports the sampling rate of the accelerometer device in HZ |
32 | 32 | ||
33 | This driver also provides an absolute input class device, allowing | 33 | This driver also provides an absolute input class device, allowing |
@@ -48,7 +48,7 @@ For better compatibility between the various laptops. The values reported by | |||
48 | the accelerometer are converted into a "standard" organisation of the axes | 48 | the accelerometer are converted into a "standard" organisation of the axes |
49 | (aka "can play neverball out of the box"): | 49 | (aka "can play neverball out of the box"): |
50 | * When the laptop is horizontal the position reported is about 0 for X and Y | 50 | * When the laptop is horizontal the position reported is about 0 for X and Y |
51 | and a positive value for Z | 51 | and a positive value for Z |
52 | * If the left side is elevated, X increases (becomes positive) | 52 | * If the left side is elevated, X increases (becomes positive) |
53 | * If the front side (where the touchpad is) is elevated, Y decreases | 53 | * If the front side (where the touchpad is) is elevated, Y decreases |
54 | (becomes negative) | 54 | (becomes negative) |
@@ -59,3 +59,13 @@ email to the authors to add it to the database. When reporting a new | |||
59 | laptop, please include the output of "dmidecode" plus the value of | 59 | laptop, please include the output of "dmidecode" plus the value of |
60 | /sys/devices/platform/lis3lv02d/position in these four cases. | 60 | /sys/devices/platform/lis3lv02d/position in these four cases. |
61 | 61 | ||
62 | Q&A | ||
63 | --- | ||
64 | |||
65 | Q: How do I safely simulate freefall? I have an HP "portable | ||
66 | workstation" which has about 3.5kg and a plastic case, so letting it | ||
67 | fall to the ground is out of question... | ||
68 | |||
69 | A: The sensor is pretty sensitive, so your hands can do it. Lift it | ||
70 | into free space, follow the fall with your hands for like 10 | ||
71 | centimeters. That should be enough to trigger the detection. | ||
diff --git a/Documentation/hwmon/ltc4215 b/Documentation/hwmon/ltc4215 new file mode 100644 index 00000000000..2e6a21eb656 --- /dev/null +++ b/Documentation/hwmon/ltc4215 | |||
@@ -0,0 +1,50 @@ | |||
1 | Kernel driver ltc4215 | ||
2 | ===================== | ||
3 | |||
4 | Supported chips: | ||
5 | * Linear Technology LTC4215 | ||
6 | Prefix: 'ltc4215' | ||
7 | Addresses scanned: 0x44 | ||
8 | Datasheet: | ||
9 | http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1006,C1163,P17572,D12697 | ||
10 | |||
11 | Author: Ira W. Snyder <iws@ovro.caltech.edu> | ||
12 | |||
13 | |||
14 | Description | ||
15 | ----------- | ||
16 | |||
17 | The LTC4215 controller allows a board to be safely inserted and removed | ||
18 | from a live backplane. | ||
19 | |||
20 | |||
21 | Usage Notes | ||
22 | ----------- | ||
23 | |||
24 | This driver does not probe for LTC4215 devices, due to the fact that some | ||
25 | of the possible addresses are unfriendly to probing. You will need to use | ||
26 | the "force" parameter to tell the driver where to find the device. | ||
27 | |||
28 | Example: the following will load the driver for an LTC4215 at address 0x44 | ||
29 | on I2C bus #0: | ||
30 | $ modprobe ltc4215 force=0,0x44 | ||
31 | |||
32 | |||
33 | Sysfs entries | ||
34 | ------------- | ||
35 | |||
36 | The LTC4215 has built-in limits for overvoltage, undervoltage, and | ||
37 | undercurrent warnings. This makes it very likely that the reference | ||
38 | circuit will be used. | ||
39 | |||
40 | in1_input input voltage | ||
41 | in2_input output voltage | ||
42 | |||
43 | in1_min_alarm input undervoltage alarm | ||
44 | in1_max_alarm input overvoltage alarm | ||
45 | |||
46 | curr1_input current | ||
47 | curr1_max_alarm overcurrent alarm | ||
48 | |||
49 | power1_input power usage | ||
50 | power1_alarm power bad alarm | ||
diff --git a/Documentation/misc-devices/isl29003 b/Documentation/misc-devices/isl29003 new file mode 100644 index 00000000000..c4ff5f38e01 --- /dev/null +++ b/Documentation/misc-devices/isl29003 | |||
@@ -0,0 +1,62 @@ | |||
1 | Kernel driver isl29003 | ||
2 | ===================== | ||
3 | |||
4 | Supported chips: | ||
5 | * Intersil ISL29003 | ||
6 | Prefix: 'isl29003' | ||
7 | Addresses scanned: none | ||
8 | Datasheet: | ||
9 | http://www.intersil.com/data/fn/fn7464.pdf | ||
10 | |||
11 | Author: Daniel Mack <daniel@caiaq.de> | ||
12 | |||
13 | |||
14 | Description | ||
15 | ----------- | ||
16 | The ISL29003 is an integrated light sensor with a 16-bit integrating type | ||
17 | ADC, I2C user programmable lux range select for optimized counts/lux, and | ||
18 | I2C multi-function control and monitoring capabilities. The internal ADC | ||
19 | provides 16-bit resolution while rejecting 50Hz and 60Hz flicker caused by | ||
20 | artificial light sources. | ||
21 | |||
22 | The driver allows to set the lux range, the bit resolution, the operational | ||
23 | mode (see below) and the power state of device and can read the current lux | ||
24 | value, of course. | ||
25 | |||
26 | |||
27 | Detection | ||
28 | --------- | ||
29 | |||
30 | The ISL29003 does not have an ID register which could be used to identify | ||
31 | it, so the detection routine will just try to read from the configured I2C | ||
32 | addess and consider the device to be present as soon as it ACKs the | ||
33 | transfer. | ||
34 | |||
35 | |||
36 | Sysfs entries | ||
37 | ------------- | ||
38 | |||
39 | range: | ||
40 | 0: 0 lux to 1000 lux (default) | ||
41 | 1: 0 lux to 4000 lux | ||
42 | 2: 0 lux to 16,000 lux | ||
43 | 3: 0 lux to 64,000 lux | ||
44 | |||
45 | resolution: | ||
46 | 0: 2^16 cycles (default) | ||
47 | 1: 2^12 cycles | ||
48 | 2: 2^8 cycles | ||
49 | 3: 2^4 cycles | ||
50 | |||
51 | mode: | ||
52 | 0: diode1's current (unsigned 16bit) (default) | ||
53 | 1: diode1's current (unsigned 16bit) | ||
54 | 2: difference between diodes (l1 - l2, signed 15bit) | ||
55 | |||
56 | power_state: | ||
57 | 0: device is disabled (default) | ||
58 | 1: device is enabled | ||
59 | |||
60 | lux (read only): | ||
61 | returns the value from the last sensor reading | ||
62 | |||
diff --git a/Documentation/powerpc/dts-bindings/mmc-spi-slot.txt b/Documentation/powerpc/dts-bindings/mmc-spi-slot.txt new file mode 100644 index 00000000000..c39ac289195 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/mmc-spi-slot.txt | |||
@@ -0,0 +1,23 @@ | |||
1 | MMC/SD/SDIO slot directly connected to a SPI bus | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : should be "mmc-spi-slot". | ||
5 | - reg : should specify SPI address (chip-select number). | ||
6 | - spi-max-frequency : maximum frequency for this device (Hz). | ||
7 | - voltage-ranges : two cells are required, first cell specifies minimum | ||
8 | slot voltage (mV), second cell specifies maximum slot voltage (mV). | ||
9 | Several ranges could be specified. | ||
10 | - gpios : (optional) may specify GPIOs in this order: Card-Detect GPIO, | ||
11 | Write-Protect GPIO. | ||
12 | |||
13 | Example: | ||
14 | |||
15 | mmc-slot@0 { | ||
16 | compatible = "fsl,mpc8323rdb-mmc-slot", | ||
17 | "mmc-spi-slot"; | ||
18 | reg = <0>; | ||
19 | gpios = <&qe_pio_d 14 1 | ||
20 | &qe_pio_d 15 0>; | ||
21 | voltage-ranges = <3300 3300>; | ||
22 | spi-max-frequency = <50000000>; | ||
23 | }; | ||
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt index 9e592c718af..afa2946892d 100644 --- a/Documentation/sysrq.txt +++ b/Documentation/sysrq.txt | |||
@@ -81,6 +81,8 @@ On all - write a character to /proc/sysrq-trigger. e.g.: | |||
81 | 81 | ||
82 | 'i' - Send a SIGKILL to all processes, except for init. | 82 | 'i' - Send a SIGKILL to all processes, except for init. |
83 | 83 | ||
84 | 'j' - Forcibly "Just thaw it" - filesystems frozen by the FIFREEZE ioctl. | ||
85 | |||
84 | 'k' - Secure Access Key (SAK) Kills all programs on the current virtual | 86 | 'k' - Secure Access Key (SAK) Kills all programs on the current virtual |
85 | console. NOTE: See important comments below in SAK section. | 87 | console. NOTE: See important comments below in SAK section. |
86 | 88 | ||
@@ -160,6 +162,9 @@ t'E'rm and k'I'll are useful if you have some sort of runaway process you | |||
160 | are unable to kill any other way, especially if it's spawning other | 162 | are unable to kill any other way, especially if it's spawning other |
161 | processes. | 163 | processes. |
162 | 164 | ||
165 | "'J'ust thaw it" is useful if your system becomes unresponsive due to a frozen | ||
166 | (probably root) filesystem via the FIFREEZE ioctl. | ||
167 | |||
163 | * Sometimes SysRq seems to get 'stuck' after using it, what can I do? | 168 | * Sometimes SysRq seems to get 'stuck' after using it, what can I do? |
164 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 169 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
165 | That happens to me, also. I've found that tapping shift, alt, and control | 170 | That happens to me, also. I've found that tapping shift, alt, and control |
diff --git a/MAINTAINERS b/MAINTAINERS index c5f4e9d27b6..a64f2920a8f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -357,6 +357,7 @@ S: Odd Fixes for 2.4; Maintained for 2.6. | |||
357 | P: Ivan Kokshaysky | 357 | P: Ivan Kokshaysky |
358 | M: ink@jurassic.park.msu.ru | 358 | M: ink@jurassic.park.msu.ru |
359 | S: Maintained for 2.4; PCI support for 2.6. | 359 | S: Maintained for 2.4; PCI support for 2.6. |
360 | L: linux-alpha@vger.kernel.org | ||
360 | 361 | ||
361 | AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER | 362 | AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER |
362 | P: Thomas Dahlmann | 363 | P: Thomas Dahlmann |
diff --git a/arch/alpha/include/asm/machvec.h b/arch/alpha/include/asm/machvec.h index fea4ea75b79..13cd4274381 100644 --- a/arch/alpha/include/asm/machvec.h +++ b/arch/alpha/include/asm/machvec.h | |||
@@ -80,7 +80,7 @@ struct alpha_machine_vector | |||
80 | void (*update_irq_hw)(unsigned long, unsigned long, int); | 80 | void (*update_irq_hw)(unsigned long, unsigned long, int); |
81 | void (*ack_irq)(unsigned long); | 81 | void (*ack_irq)(unsigned long); |
82 | void (*device_interrupt)(unsigned long vector); | 82 | void (*device_interrupt)(unsigned long vector); |
83 | void (*machine_check)(u64 vector, u64 la); | 83 | void (*machine_check)(unsigned long vector, unsigned long la); |
84 | 84 | ||
85 | void (*smp_callin)(void); | 85 | void (*smp_callin)(void); |
86 | void (*init_arch)(void); | 86 | void (*init_arch)(void); |
diff --git a/arch/alpha/include/asm/system.h b/arch/alpha/include/asm/system.h index afe20fa58c9..5aa40cca4f2 100644 --- a/arch/alpha/include/asm/system.h +++ b/arch/alpha/include/asm/system.h | |||
@@ -309,518 +309,71 @@ extern int __min_ipl; | |||
309 | #define tbia() __tbi(-2, /* no second argument */) | 309 | #define tbia() __tbi(-2, /* no second argument */) |
310 | 310 | ||
311 | /* | 311 | /* |
312 | * Atomic exchange. | 312 | * Atomic exchange routines. |
313 | * Since it can be used to implement critical sections | ||
314 | * it must clobber "memory" (also for interrupts in UP). | ||
315 | */ | 313 | */ |
316 | 314 | ||
317 | static inline unsigned long | 315 | #define __ASM__MB |
318 | __xchg_u8(volatile char *m, unsigned long val) | 316 | #define ____xchg(type, args...) __xchg ## type ## _local(args) |
319 | { | 317 | #define ____cmpxchg(type, args...) __cmpxchg ## type ## _local(args) |
320 | unsigned long ret, tmp, addr64; | 318 | #include <asm/xchg.h> |
321 | |||
322 | __asm__ __volatile__( | ||
323 | " andnot %4,7,%3\n" | ||
324 | " insbl %1,%4,%1\n" | ||
325 | "1: ldq_l %2,0(%3)\n" | ||
326 | " extbl %2,%4,%0\n" | ||
327 | " mskbl %2,%4,%2\n" | ||
328 | " or %1,%2,%2\n" | ||
329 | " stq_c %2,0(%3)\n" | ||
330 | " beq %2,2f\n" | ||
331 | #ifdef CONFIG_SMP | ||
332 | " mb\n" | ||
333 | #endif | ||
334 | ".subsection 2\n" | ||
335 | "2: br 1b\n" | ||
336 | ".previous" | ||
337 | : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64) | ||
338 | : "r" ((long)m), "1" (val) : "memory"); | ||
339 | |||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | static inline unsigned long | ||
344 | __xchg_u16(volatile short *m, unsigned long val) | ||
345 | { | ||
346 | unsigned long ret, tmp, addr64; | ||
347 | |||
348 | __asm__ __volatile__( | ||
349 | " andnot %4,7,%3\n" | ||
350 | " inswl %1,%4,%1\n" | ||
351 | "1: ldq_l %2,0(%3)\n" | ||
352 | " extwl %2,%4,%0\n" | ||
353 | " mskwl %2,%4,%2\n" | ||
354 | " or %1,%2,%2\n" | ||
355 | " stq_c %2,0(%3)\n" | ||
356 | " beq %2,2f\n" | ||
357 | #ifdef CONFIG_SMP | ||
358 | " mb\n" | ||
359 | #endif | ||
360 | ".subsection 2\n" | ||
361 | "2: br 1b\n" | ||
362 | ".previous" | ||
363 | : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64) | ||
364 | : "r" ((long)m), "1" (val) : "memory"); | ||
365 | |||
366 | return ret; | ||
367 | } | ||
368 | |||
369 | static inline unsigned long | ||
370 | __xchg_u32(volatile int *m, unsigned long val) | ||
371 | { | ||
372 | unsigned long dummy; | ||
373 | |||
374 | __asm__ __volatile__( | ||
375 | "1: ldl_l %0,%4\n" | ||
376 | " bis $31,%3,%1\n" | ||
377 | " stl_c %1,%2\n" | ||
378 | " beq %1,2f\n" | ||
379 | #ifdef CONFIG_SMP | ||
380 | " mb\n" | ||
381 | #endif | ||
382 | ".subsection 2\n" | ||
383 | "2: br 1b\n" | ||
384 | ".previous" | ||
385 | : "=&r" (val), "=&r" (dummy), "=m" (*m) | ||
386 | : "rI" (val), "m" (*m) : "memory"); | ||
387 | |||
388 | return val; | ||
389 | } | ||
390 | |||
391 | static inline unsigned long | ||
392 | __xchg_u64(volatile long *m, unsigned long val) | ||
393 | { | ||
394 | unsigned long dummy; | ||
395 | |||
396 | __asm__ __volatile__( | ||
397 | "1: ldq_l %0,%4\n" | ||
398 | " bis $31,%3,%1\n" | ||
399 | " stq_c %1,%2\n" | ||
400 | " beq %1,2f\n" | ||
401 | #ifdef CONFIG_SMP | ||
402 | " mb\n" | ||
403 | #endif | ||
404 | ".subsection 2\n" | ||
405 | "2: br 1b\n" | ||
406 | ".previous" | ||
407 | : "=&r" (val), "=&r" (dummy), "=m" (*m) | ||
408 | : "rI" (val), "m" (*m) : "memory"); | ||
409 | 319 | ||
410 | return val; | 320 | #define xchg_local(ptr,x) \ |
411 | } | 321 | ({ \ |
412 | 322 | __typeof__(*(ptr)) _x_ = (x); \ | |
413 | /* This function doesn't exist, so you'll get a linker error | 323 | (__typeof__(*(ptr))) __xchg_local((ptr), (unsigned long)_x_, \ |
414 | if something tries to do an invalid xchg(). */ | 324 | sizeof(*(ptr))); \ |
415 | extern void __xchg_called_with_bad_pointer(void); | ||
416 | |||
417 | #define __xchg(ptr, x, size) \ | ||
418 | ({ \ | ||
419 | unsigned long __xchg__res; \ | ||
420 | volatile void *__xchg__ptr = (ptr); \ | ||
421 | switch (size) { \ | ||
422 | case 1: __xchg__res = __xchg_u8(__xchg__ptr, x); break; \ | ||
423 | case 2: __xchg__res = __xchg_u16(__xchg__ptr, x); break; \ | ||
424 | case 4: __xchg__res = __xchg_u32(__xchg__ptr, x); break; \ | ||
425 | case 8: __xchg__res = __xchg_u64(__xchg__ptr, x); break; \ | ||
426 | default: __xchg_called_with_bad_pointer(); __xchg__res = x; \ | ||
427 | } \ | ||
428 | __xchg__res; \ | ||
429 | }) | ||
430 | |||
431 | #define xchg(ptr,x) \ | ||
432 | ({ \ | ||
433 | __typeof__(*(ptr)) _x_ = (x); \ | ||
434 | (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \ | ||
435 | }) | 325 | }) |
436 | 326 | ||
437 | static inline unsigned long | 327 | #define cmpxchg_local(ptr, o, n) \ |
438 | __xchg_u8_local(volatile char *m, unsigned long val) | 328 | ({ \ |
439 | { | 329 | __typeof__(*(ptr)) _o_ = (o); \ |
440 | unsigned long ret, tmp, addr64; | 330 | __typeof__(*(ptr)) _n_ = (n); \ |
441 | 331 | (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \ | |
442 | __asm__ __volatile__( | 332 | (unsigned long)_n_, \ |
443 | " andnot %4,7,%3\n" | 333 | sizeof(*(ptr))); \ |
444 | " insbl %1,%4,%1\n" | ||
445 | "1: ldq_l %2,0(%3)\n" | ||
446 | " extbl %2,%4,%0\n" | ||
447 | " mskbl %2,%4,%2\n" | ||
448 | " or %1,%2,%2\n" | ||
449 | " stq_c %2,0(%3)\n" | ||
450 | " beq %2,2f\n" | ||
451 | ".subsection 2\n" | ||
452 | "2: br 1b\n" | ||
453 | ".previous" | ||
454 | : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64) | ||
455 | : "r" ((long)m), "1" (val) : "memory"); | ||
456 | |||
457 | return ret; | ||
458 | } | ||
459 | |||
460 | static inline unsigned long | ||
461 | __xchg_u16_local(volatile short *m, unsigned long val) | ||
462 | { | ||
463 | unsigned long ret, tmp, addr64; | ||
464 | |||
465 | __asm__ __volatile__( | ||
466 | " andnot %4,7,%3\n" | ||
467 | " inswl %1,%4,%1\n" | ||
468 | "1: ldq_l %2,0(%3)\n" | ||
469 | " extwl %2,%4,%0\n" | ||
470 | " mskwl %2,%4,%2\n" | ||
471 | " or %1,%2,%2\n" | ||
472 | " stq_c %2,0(%3)\n" | ||
473 | " beq %2,2f\n" | ||
474 | ".subsection 2\n" | ||
475 | "2: br 1b\n" | ||
476 | ".previous" | ||
477 | : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64) | ||
478 | : "r" ((long)m), "1" (val) : "memory"); | ||
479 | |||
480 | return ret; | ||
481 | } | ||
482 | |||
483 | static inline unsigned long | ||
484 | __xchg_u32_local(volatile int *m, unsigned long val) | ||
485 | { | ||
486 | unsigned long dummy; | ||
487 | |||
488 | __asm__ __volatile__( | ||
489 | "1: ldl_l %0,%4\n" | ||
490 | " bis $31,%3,%1\n" | ||
491 | " stl_c %1,%2\n" | ||
492 | " beq %1,2f\n" | ||
493 | ".subsection 2\n" | ||
494 | "2: br 1b\n" | ||
495 | ".previous" | ||
496 | : "=&r" (val), "=&r" (dummy), "=m" (*m) | ||
497 | : "rI" (val), "m" (*m) : "memory"); | ||
498 | |||
499 | return val; | ||
500 | } | ||
501 | |||
502 | static inline unsigned long | ||
503 | __xchg_u64_local(volatile long *m, unsigned long val) | ||
504 | { | ||
505 | unsigned long dummy; | ||
506 | |||
507 | __asm__ __volatile__( | ||
508 | "1: ldq_l %0,%4\n" | ||
509 | " bis $31,%3,%1\n" | ||
510 | " stq_c %1,%2\n" | ||
511 | " beq %1,2f\n" | ||
512 | ".subsection 2\n" | ||
513 | "2: br 1b\n" | ||
514 | ".previous" | ||
515 | : "=&r" (val), "=&r" (dummy), "=m" (*m) | ||
516 | : "rI" (val), "m" (*m) : "memory"); | ||
517 | |||
518 | return val; | ||
519 | } | ||
520 | |||
521 | #define __xchg_local(ptr, x, size) \ | ||
522 | ({ \ | ||
523 | unsigned long __xchg__res; \ | ||
524 | volatile void *__xchg__ptr = (ptr); \ | ||
525 | switch (size) { \ | ||
526 | case 1: __xchg__res = __xchg_u8_local(__xchg__ptr, x); break; \ | ||
527 | case 2: __xchg__res = __xchg_u16_local(__xchg__ptr, x); break; \ | ||
528 | case 4: __xchg__res = __xchg_u32_local(__xchg__ptr, x); break; \ | ||
529 | case 8: __xchg__res = __xchg_u64_local(__xchg__ptr, x); break; \ | ||
530 | default: __xchg_called_with_bad_pointer(); __xchg__res = x; \ | ||
531 | } \ | ||
532 | __xchg__res; \ | ||
533 | }) | ||
534 | |||
535 | #define xchg_local(ptr,x) \ | ||
536 | ({ \ | ||
537 | __typeof__(*(ptr)) _x_ = (x); \ | ||
538 | (__typeof__(*(ptr))) __xchg_local((ptr), (unsigned long)_x_, \ | ||
539 | sizeof(*(ptr))); \ | ||
540 | }) | 334 | }) |
541 | 335 | ||
542 | /* | 336 | #define cmpxchg64_local(ptr, o, n) \ |
543 | * Atomic compare and exchange. Compare OLD with MEM, if identical, | 337 | ({ \ |
544 | * store NEW in MEM. Return the initial value in MEM. Success is | 338 | BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ |
545 | * indicated by comparing RETURN with OLD. | 339 | cmpxchg_local((ptr), (o), (n)); \ |
546 | * | 340 | }) |
547 | * The memory barrier should be placed in SMP only when we actually | ||
548 | * make the change. If we don't change anything (so if the returned | ||
549 | * prev is equal to old) then we aren't acquiring anything new and | ||
550 | * we don't need any memory barrier as far I can tell. | ||
551 | */ | ||
552 | |||
553 | #define __HAVE_ARCH_CMPXCHG 1 | ||
554 | |||
555 | static inline unsigned long | ||
556 | __cmpxchg_u8(volatile char *m, long old, long new) | ||
557 | { | ||
558 | unsigned long prev, tmp, cmp, addr64; | ||
559 | |||
560 | __asm__ __volatile__( | ||
561 | " andnot %5,7,%4\n" | ||
562 | " insbl %1,%5,%1\n" | ||
563 | "1: ldq_l %2,0(%4)\n" | ||
564 | " extbl %2,%5,%0\n" | ||
565 | " cmpeq %0,%6,%3\n" | ||
566 | " beq %3,2f\n" | ||
567 | " mskbl %2,%5,%2\n" | ||
568 | " or %1,%2,%2\n" | ||
569 | " stq_c %2,0(%4)\n" | ||
570 | " beq %2,3f\n" | ||
571 | #ifdef CONFIG_SMP | ||
572 | " mb\n" | ||
573 | #endif | ||
574 | "2:\n" | ||
575 | ".subsection 2\n" | ||
576 | "3: br 1b\n" | ||
577 | ".previous" | ||
578 | : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64) | ||
579 | : "r" ((long)m), "Ir" (old), "1" (new) : "memory"); | ||
580 | |||
581 | return prev; | ||
582 | } | ||
583 | |||
584 | static inline unsigned long | ||
585 | __cmpxchg_u16(volatile short *m, long old, long new) | ||
586 | { | ||
587 | unsigned long prev, tmp, cmp, addr64; | ||
588 | |||
589 | __asm__ __volatile__( | ||
590 | " andnot %5,7,%4\n" | ||
591 | " inswl %1,%5,%1\n" | ||
592 | "1: ldq_l %2,0(%4)\n" | ||
593 | " extwl %2,%5,%0\n" | ||
594 | " cmpeq %0,%6,%3\n" | ||
595 | " beq %3,2f\n" | ||
596 | " mskwl %2,%5,%2\n" | ||
597 | " or %1,%2,%2\n" | ||
598 | " stq_c %2,0(%4)\n" | ||
599 | " beq %2,3f\n" | ||
600 | #ifdef CONFIG_SMP | ||
601 | " mb\n" | ||
602 | #endif | ||
603 | "2:\n" | ||
604 | ".subsection 2\n" | ||
605 | "3: br 1b\n" | ||
606 | ".previous" | ||
607 | : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64) | ||
608 | : "r" ((long)m), "Ir" (old), "1" (new) : "memory"); | ||
609 | |||
610 | return prev; | ||
611 | } | ||
612 | |||
613 | static inline unsigned long | ||
614 | __cmpxchg_u32(volatile int *m, int old, int new) | ||
615 | { | ||
616 | unsigned long prev, cmp; | ||
617 | |||
618 | __asm__ __volatile__( | ||
619 | "1: ldl_l %0,%5\n" | ||
620 | " cmpeq %0,%3,%1\n" | ||
621 | " beq %1,2f\n" | ||
622 | " mov %4,%1\n" | ||
623 | " stl_c %1,%2\n" | ||
624 | " beq %1,3f\n" | ||
625 | #ifdef CONFIG_SMP | ||
626 | " mb\n" | ||
627 | #endif | ||
628 | "2:\n" | ||
629 | ".subsection 2\n" | ||
630 | "3: br 1b\n" | ||
631 | ".previous" | ||
632 | : "=&r"(prev), "=&r"(cmp), "=m"(*m) | ||
633 | : "r"((long) old), "r"(new), "m"(*m) : "memory"); | ||
634 | |||
635 | return prev; | ||
636 | } | ||
637 | 341 | ||
638 | static inline unsigned long | ||
639 | __cmpxchg_u64(volatile long *m, unsigned long old, unsigned long new) | ||
640 | { | ||
641 | unsigned long prev, cmp; | ||
642 | |||
643 | __asm__ __volatile__( | ||
644 | "1: ldq_l %0,%5\n" | ||
645 | " cmpeq %0,%3,%1\n" | ||
646 | " beq %1,2f\n" | ||
647 | " mov %4,%1\n" | ||
648 | " stq_c %1,%2\n" | ||
649 | " beq %1,3f\n" | ||
650 | #ifdef CONFIG_SMP | 342 | #ifdef CONFIG_SMP |
651 | " mb\n" | 343 | #undef __ASM__MB |
344 | #define __ASM__MB "\tmb\n" | ||
652 | #endif | 345 | #endif |
653 | "2:\n" | 346 | #undef ____xchg |
654 | ".subsection 2\n" | 347 | #undef ____cmpxchg |
655 | "3: br 1b\n" | 348 | #define ____xchg(type, args...) __xchg ##type(args) |
656 | ".previous" | 349 | #define ____cmpxchg(type, args...) __cmpxchg ##type(args) |
657 | : "=&r"(prev), "=&r"(cmp), "=m"(*m) | 350 | #include <asm/xchg.h> |
658 | : "r"((long) old), "r"(new), "m"(*m) : "memory"); | 351 | |
659 | 352 | #define xchg(ptr,x) \ | |
660 | return prev; | 353 | ({ \ |
661 | } | 354 | __typeof__(*(ptr)) _x_ = (x); \ |
662 | 355 | (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, \ | |
663 | /* This function doesn't exist, so you'll get a linker error | 356 | sizeof(*(ptr))); \ |
664 | if something tries to do an invalid cmpxchg(). */ | ||
665 | extern void __cmpxchg_called_with_bad_pointer(void); | ||
666 | |||
667 | static __always_inline unsigned long | ||
668 | __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) | ||
669 | { | ||
670 | switch (size) { | ||
671 | case 1: | ||
672 | return __cmpxchg_u8(ptr, old, new); | ||
673 | case 2: | ||
674 | return __cmpxchg_u16(ptr, old, new); | ||
675 | case 4: | ||
676 | return __cmpxchg_u32(ptr, old, new); | ||
677 | case 8: | ||
678 | return __cmpxchg_u64(ptr, old, new); | ||
679 | } | ||
680 | __cmpxchg_called_with_bad_pointer(); | ||
681 | return old; | ||
682 | } | ||
683 | |||
684 | #define cmpxchg(ptr, o, n) \ | ||
685 | ({ \ | ||
686 | __typeof__(*(ptr)) _o_ = (o); \ | ||
687 | __typeof__(*(ptr)) _n_ = (n); \ | ||
688 | (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ | ||
689 | (unsigned long)_n_, sizeof(*(ptr))); \ | ||
690 | }) | 357 | }) |
691 | #define cmpxchg64(ptr, o, n) \ | ||
692 | ({ \ | ||
693 | BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ | ||
694 | cmpxchg((ptr), (o), (n)); \ | ||
695 | }) | ||
696 | |||
697 | static inline unsigned long | ||
698 | __cmpxchg_u8_local(volatile char *m, long old, long new) | ||
699 | { | ||
700 | unsigned long prev, tmp, cmp, addr64; | ||
701 | |||
702 | __asm__ __volatile__( | ||
703 | " andnot %5,7,%4\n" | ||
704 | " insbl %1,%5,%1\n" | ||
705 | "1: ldq_l %2,0(%4)\n" | ||
706 | " extbl %2,%5,%0\n" | ||
707 | " cmpeq %0,%6,%3\n" | ||
708 | " beq %3,2f\n" | ||
709 | " mskbl %2,%5,%2\n" | ||
710 | " or %1,%2,%2\n" | ||
711 | " stq_c %2,0(%4)\n" | ||
712 | " beq %2,3f\n" | ||
713 | "2:\n" | ||
714 | ".subsection 2\n" | ||
715 | "3: br 1b\n" | ||
716 | ".previous" | ||
717 | : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64) | ||
718 | : "r" ((long)m), "Ir" (old), "1" (new) : "memory"); | ||
719 | |||
720 | return prev; | ||
721 | } | ||
722 | |||
723 | static inline unsigned long | ||
724 | __cmpxchg_u16_local(volatile short *m, long old, long new) | ||
725 | { | ||
726 | unsigned long prev, tmp, cmp, addr64; | ||
727 | |||
728 | __asm__ __volatile__( | ||
729 | " andnot %5,7,%4\n" | ||
730 | " inswl %1,%5,%1\n" | ||
731 | "1: ldq_l %2,0(%4)\n" | ||
732 | " extwl %2,%5,%0\n" | ||
733 | " cmpeq %0,%6,%3\n" | ||
734 | " beq %3,2f\n" | ||
735 | " mskwl %2,%5,%2\n" | ||
736 | " or %1,%2,%2\n" | ||
737 | " stq_c %2,0(%4)\n" | ||
738 | " beq %2,3f\n" | ||
739 | "2:\n" | ||
740 | ".subsection 2\n" | ||
741 | "3: br 1b\n" | ||
742 | ".previous" | ||
743 | : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64) | ||
744 | : "r" ((long)m), "Ir" (old), "1" (new) : "memory"); | ||
745 | |||
746 | return prev; | ||
747 | } | ||
748 | |||
749 | static inline unsigned long | ||
750 | __cmpxchg_u32_local(volatile int *m, int old, int new) | ||
751 | { | ||
752 | unsigned long prev, cmp; | ||
753 | |||
754 | __asm__ __volatile__( | ||
755 | "1: ldl_l %0,%5\n" | ||
756 | " cmpeq %0,%3,%1\n" | ||
757 | " beq %1,2f\n" | ||
758 | " mov %4,%1\n" | ||
759 | " stl_c %1,%2\n" | ||
760 | " beq %1,3f\n" | ||
761 | "2:\n" | ||
762 | ".subsection 2\n" | ||
763 | "3: br 1b\n" | ||
764 | ".previous" | ||
765 | : "=&r"(prev), "=&r"(cmp), "=m"(*m) | ||
766 | : "r"((long) old), "r"(new), "m"(*m) : "memory"); | ||
767 | |||
768 | return prev; | ||
769 | } | ||
770 | |||
771 | static inline unsigned long | ||
772 | __cmpxchg_u64_local(volatile long *m, unsigned long old, unsigned long new) | ||
773 | { | ||
774 | unsigned long prev, cmp; | ||
775 | |||
776 | __asm__ __volatile__( | ||
777 | "1: ldq_l %0,%5\n" | ||
778 | " cmpeq %0,%3,%1\n" | ||
779 | " beq %1,2f\n" | ||
780 | " mov %4,%1\n" | ||
781 | " stq_c %1,%2\n" | ||
782 | " beq %1,3f\n" | ||
783 | "2:\n" | ||
784 | ".subsection 2\n" | ||
785 | "3: br 1b\n" | ||
786 | ".previous" | ||
787 | : "=&r"(prev), "=&r"(cmp), "=m"(*m) | ||
788 | : "r"((long) old), "r"(new), "m"(*m) : "memory"); | ||
789 | |||
790 | return prev; | ||
791 | } | ||
792 | |||
793 | static __always_inline unsigned long | ||
794 | __cmpxchg_local(volatile void *ptr, unsigned long old, unsigned long new, | ||
795 | int size) | ||
796 | { | ||
797 | switch (size) { | ||
798 | case 1: | ||
799 | return __cmpxchg_u8_local(ptr, old, new); | ||
800 | case 2: | ||
801 | return __cmpxchg_u16_local(ptr, old, new); | ||
802 | case 4: | ||
803 | return __cmpxchg_u32_local(ptr, old, new); | ||
804 | case 8: | ||
805 | return __cmpxchg_u64_local(ptr, old, new); | ||
806 | } | ||
807 | __cmpxchg_called_with_bad_pointer(); | ||
808 | return old; | ||
809 | } | ||
810 | 358 | ||
811 | #define cmpxchg_local(ptr, o, n) \ | 359 | #define cmpxchg(ptr, o, n) \ |
812 | ({ \ | 360 | ({ \ |
813 | __typeof__(*(ptr)) _o_ = (o); \ | 361 | __typeof__(*(ptr)) _o_ = (o); \ |
814 | __typeof__(*(ptr)) _n_ = (n); \ | 362 | __typeof__(*(ptr)) _n_ = (n); \ |
815 | (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \ | 363 | (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ |
816 | (unsigned long)_n_, sizeof(*(ptr))); \ | 364 | (unsigned long)_n_, sizeof(*(ptr)));\ |
817 | }) | 365 | }) |
818 | #define cmpxchg64_local(ptr, o, n) \ | 366 | |
819 | ({ \ | 367 | #define cmpxchg64(ptr, o, n) \ |
820 | BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ | 368 | ({ \ |
821 | cmpxchg_local((ptr), (o), (n)); \ | 369 | BUILD_BUG_ON(sizeof(*(ptr)) != 8); \ |
370 | cmpxchg((ptr), (o), (n)); \ | ||
822 | }) | 371 | }) |
823 | 372 | ||
373 | #undef __ASM__MB | ||
374 | #undef ____cmpxchg | ||
375 | |||
376 | #define __HAVE_ARCH_CMPXCHG 1 | ||
824 | 377 | ||
825 | #endif /* __ASSEMBLY__ */ | 378 | #endif /* __ASSEMBLY__ */ |
826 | 379 | ||
diff --git a/arch/alpha/include/asm/types.h b/arch/alpha/include/asm/types.h index c1541353cce..f072f344497 100644 --- a/arch/alpha/include/asm/types.h +++ b/arch/alpha/include/asm/types.h | |||
@@ -8,7 +8,12 @@ | |||
8 | * not a major issue. However, for interoperability, libraries still | 8 | * not a major issue. However, for interoperability, libraries still |
9 | * need to be careful to avoid a name clashes. | 9 | * need to be careful to avoid a name clashes. |
10 | */ | 10 | */ |
11 | |||
12 | #ifdef __KERNEL__ | ||
13 | #include <asm-generic/int-ll64.h> | ||
14 | #else | ||
11 | #include <asm-generic/int-l64.h> | 15 | #include <asm-generic/int-l64.h> |
16 | #endif | ||
12 | 17 | ||
13 | #ifndef __ASSEMBLY__ | 18 | #ifndef __ASSEMBLY__ |
14 | 19 | ||
diff --git a/arch/alpha/include/asm/uaccess.h b/arch/alpha/include/asm/uaccess.h index 22de3b434a2..163f3053001 100644 --- a/arch/alpha/include/asm/uaccess.h +++ b/arch/alpha/include/asm/uaccess.h | |||
@@ -498,13 +498,13 @@ struct exception_table_entry | |||
498 | }; | 498 | }; |
499 | 499 | ||
500 | /* Returns the new pc */ | 500 | /* Returns the new pc */ |
501 | #define fixup_exception(map_reg, fixup, pc) \ | 501 | #define fixup_exception(map_reg, _fixup, pc) \ |
502 | ({ \ | 502 | ({ \ |
503 | if ((fixup)->fixup.bits.valreg != 31) \ | 503 | if ((_fixup)->fixup.bits.valreg != 31) \ |
504 | map_reg((fixup)->fixup.bits.valreg) = 0; \ | 504 | map_reg((_fixup)->fixup.bits.valreg) = 0; \ |
505 | if ((fixup)->fixup.bits.errreg != 31) \ | 505 | if ((_fixup)->fixup.bits.errreg != 31) \ |
506 | map_reg((fixup)->fixup.bits.errreg) = -EFAULT; \ | 506 | map_reg((_fixup)->fixup.bits.errreg) = -EFAULT; \ |
507 | (pc) + (fixup)->fixup.bits.nextinsn; \ | 507 | (pc) + (_fixup)->fixup.bits.nextinsn; \ |
508 | }) | 508 | }) |
509 | 509 | ||
510 | 510 | ||
diff --git a/arch/alpha/include/asm/xchg.h b/arch/alpha/include/asm/xchg.h new file mode 100644 index 00000000000..beba1b803e0 --- /dev/null +++ b/arch/alpha/include/asm/xchg.h | |||
@@ -0,0 +1,258 @@ | |||
1 | #ifndef __ALPHA_SYSTEM_H | ||
2 | #error Do not include xchg.h directly! | ||
3 | #else | ||
4 | /* | ||
5 | * xchg/xchg_local and cmpxchg/cmpxchg_local share the same code | ||
6 | * except that local version do not have the expensive memory barrier. | ||
7 | * So this file is included twice from asm/system.h. | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Atomic exchange. | ||
12 | * Since it can be used to implement critical sections | ||
13 | * it must clobber "memory" (also for interrupts in UP). | ||
14 | */ | ||
15 | |||
16 | static inline unsigned long | ||
17 | ____xchg(_u8, volatile char *m, unsigned long val) | ||
18 | { | ||
19 | unsigned long ret, tmp, addr64; | ||
20 | |||
21 | __asm__ __volatile__( | ||
22 | " andnot %4,7,%3\n" | ||
23 | " insbl %1,%4,%1\n" | ||
24 | "1: ldq_l %2,0(%3)\n" | ||
25 | " extbl %2,%4,%0\n" | ||
26 | " mskbl %2,%4,%2\n" | ||
27 | " or %1,%2,%2\n" | ||
28 | " stq_c %2,0(%3)\n" | ||
29 | " beq %2,2f\n" | ||
30 | __ASM__MB | ||
31 | ".subsection 2\n" | ||
32 | "2: br 1b\n" | ||
33 | ".previous" | ||
34 | : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64) | ||
35 | : "r" ((long)m), "1" (val) : "memory"); | ||
36 | |||
37 | return ret; | ||
38 | } | ||
39 | |||
40 | static inline unsigned long | ||
41 | ____xchg(_u16, volatile short *m, unsigned long val) | ||
42 | { | ||
43 | unsigned long ret, tmp, addr64; | ||
44 | |||
45 | __asm__ __volatile__( | ||
46 | " andnot %4,7,%3\n" | ||
47 | " inswl %1,%4,%1\n" | ||
48 | "1: ldq_l %2,0(%3)\n" | ||
49 | " extwl %2,%4,%0\n" | ||
50 | " mskwl %2,%4,%2\n" | ||
51 | " or %1,%2,%2\n" | ||
52 | " stq_c %2,0(%3)\n" | ||
53 | " beq %2,2f\n" | ||
54 | __ASM__MB | ||
55 | ".subsection 2\n" | ||
56 | "2: br 1b\n" | ||
57 | ".previous" | ||
58 | : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64) | ||
59 | : "r" ((long)m), "1" (val) : "memory"); | ||
60 | |||
61 | return ret; | ||
62 | } | ||
63 | |||
64 | static inline unsigned long | ||
65 | ____xchg(_u32, volatile int *m, unsigned long val) | ||
66 | { | ||
67 | unsigned long dummy; | ||
68 | |||
69 | __asm__ __volatile__( | ||
70 | "1: ldl_l %0,%4\n" | ||
71 | " bis $31,%3,%1\n" | ||
72 | " stl_c %1,%2\n" | ||
73 | " beq %1,2f\n" | ||
74 | __ASM__MB | ||
75 | ".subsection 2\n" | ||
76 | "2: br 1b\n" | ||
77 | ".previous" | ||
78 | : "=&r" (val), "=&r" (dummy), "=m" (*m) | ||
79 | : "rI" (val), "m" (*m) : "memory"); | ||
80 | |||
81 | return val; | ||
82 | } | ||
83 | |||
84 | static inline unsigned long | ||
85 | ____xchg(_u64, volatile long *m, unsigned long val) | ||
86 | { | ||
87 | unsigned long dummy; | ||
88 | |||
89 | __asm__ __volatile__( | ||
90 | "1: ldq_l %0,%4\n" | ||
91 | " bis $31,%3,%1\n" | ||
92 | " stq_c %1,%2\n" | ||
93 | " beq %1,2f\n" | ||
94 | __ASM__MB | ||
95 | ".subsection 2\n" | ||
96 | "2: br 1b\n" | ||
97 | ".previous" | ||
98 | : "=&r" (val), "=&r" (dummy), "=m" (*m) | ||
99 | : "rI" (val), "m" (*m) : "memory"); | ||
100 | |||
101 | return val; | ||
102 | } | ||
103 | |||
104 | /* This function doesn't exist, so you'll get a linker error | ||
105 | if something tries to do an invalid xchg(). */ | ||
106 | extern void __xchg_called_with_bad_pointer(void); | ||
107 | |||
108 | static __always_inline unsigned long | ||
109 | ____xchg(, volatile void *ptr, unsigned long x, int size) | ||
110 | { | ||
111 | switch (size) { | ||
112 | case 1: | ||
113 | return ____xchg(_u8, ptr, x); | ||
114 | case 2: | ||
115 | return ____xchg(_u16, ptr, x); | ||
116 | case 4: | ||
117 | return ____xchg(_u32, ptr, x); | ||
118 | case 8: | ||
119 | return ____xchg(_u64, ptr, x); | ||
120 | } | ||
121 | __xchg_called_with_bad_pointer(); | ||
122 | return x; | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * Atomic compare and exchange. Compare OLD with MEM, if identical, | ||
127 | * store NEW in MEM. Return the initial value in MEM. Success is | ||
128 | * indicated by comparing RETURN with OLD. | ||
129 | * | ||
130 | * The memory barrier should be placed in SMP only when we actually | ||
131 | * make the change. If we don't change anything (so if the returned | ||
132 | * prev is equal to old) then we aren't acquiring anything new and | ||
133 | * we don't need any memory barrier as far I can tell. | ||
134 | */ | ||
135 | |||
136 | static inline unsigned long | ||
137 | ____cmpxchg(_u8, volatile char *m, unsigned char old, unsigned char new) | ||
138 | { | ||
139 | unsigned long prev, tmp, cmp, addr64; | ||
140 | |||
141 | __asm__ __volatile__( | ||
142 | " andnot %5,7,%4\n" | ||
143 | " insbl %1,%5,%1\n" | ||
144 | "1: ldq_l %2,0(%4)\n" | ||
145 | " extbl %2,%5,%0\n" | ||
146 | " cmpeq %0,%6,%3\n" | ||
147 | " beq %3,2f\n" | ||
148 | " mskbl %2,%5,%2\n" | ||
149 | " or %1,%2,%2\n" | ||
150 | " stq_c %2,0(%4)\n" | ||
151 | " beq %2,3f\n" | ||
152 | __ASM__MB | ||
153 | "2:\n" | ||
154 | ".subsection 2\n" | ||
155 | "3: br 1b\n" | ||
156 | ".previous" | ||
157 | : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64) | ||
158 | : "r" ((long)m), "Ir" (old), "1" (new) : "memory"); | ||
159 | |||
160 | return prev; | ||
161 | } | ||
162 | |||
163 | static inline unsigned long | ||
164 | ____cmpxchg(_u16, volatile short *m, unsigned short old, unsigned short new) | ||
165 | { | ||
166 | unsigned long prev, tmp, cmp, addr64; | ||
167 | |||
168 | __asm__ __volatile__( | ||
169 | " andnot %5,7,%4\n" | ||
170 | " inswl %1,%5,%1\n" | ||
171 | "1: ldq_l %2,0(%4)\n" | ||
172 | " extwl %2,%5,%0\n" | ||
173 | " cmpeq %0,%6,%3\n" | ||
174 | " beq %3,2f\n" | ||
175 | " mskwl %2,%5,%2\n" | ||
176 | " or %1,%2,%2\n" | ||
177 | " stq_c %2,0(%4)\n" | ||
178 | " beq %2,3f\n" | ||
179 | __ASM__MB | ||
180 | "2:\n" | ||
181 | ".subsection 2\n" | ||
182 | "3: br 1b\n" | ||
183 | ".previous" | ||
184 | : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64) | ||
185 | : "r" ((long)m), "Ir" (old), "1" (new) : "memory"); | ||
186 | |||
187 | return prev; | ||
188 | } | ||
189 | |||
190 | static inline unsigned long | ||
191 | ____cmpxchg(_u32, volatile int *m, int old, int new) | ||
192 | { | ||
193 | unsigned long prev, cmp; | ||
194 | |||
195 | __asm__ __volatile__( | ||
196 | "1: ldl_l %0,%5\n" | ||
197 | " cmpeq %0,%3,%1\n" | ||
198 | " beq %1,2f\n" | ||
199 | " mov %4,%1\n" | ||
200 | " stl_c %1,%2\n" | ||
201 | " beq %1,3f\n" | ||
202 | __ASM__MB | ||
203 | "2:\n" | ||
204 | ".subsection 2\n" | ||
205 | "3: br 1b\n" | ||
206 | ".previous" | ||
207 | : "=&r"(prev), "=&r"(cmp), "=m"(*m) | ||
208 | : "r"((long) old), "r"(new), "m"(*m) : "memory"); | ||
209 | |||
210 | return prev; | ||
211 | } | ||
212 | |||
213 | static inline unsigned long | ||
214 | ____cmpxchg(_u64, volatile long *m, unsigned long old, unsigned long new) | ||
215 | { | ||
216 | unsigned long prev, cmp; | ||
217 | |||
218 | __asm__ __volatile__( | ||
219 | "1: ldq_l %0,%5\n" | ||
220 | " cmpeq %0,%3,%1\n" | ||
221 | " beq %1,2f\n" | ||
222 | " mov %4,%1\n" | ||
223 | " stq_c %1,%2\n" | ||
224 | " beq %1,3f\n" | ||
225 | __ASM__MB | ||
226 | "2:\n" | ||
227 | ".subsection 2\n" | ||
228 | "3: br 1b\n" | ||
229 | ".previous" | ||
230 | : "=&r"(prev), "=&r"(cmp), "=m"(*m) | ||
231 | : "r"((long) old), "r"(new), "m"(*m) : "memory"); | ||
232 | |||
233 | return prev; | ||
234 | } | ||
235 | |||
236 | /* This function doesn't exist, so you'll get a linker error | ||
237 | if something tries to do an invalid cmpxchg(). */ | ||
238 | extern void __cmpxchg_called_with_bad_pointer(void); | ||
239 | |||
240 | static __always_inline unsigned long | ||
241 | ____cmpxchg(, volatile void *ptr, unsigned long old, unsigned long new, | ||
242 | int size) | ||
243 | { | ||
244 | switch (size) { | ||
245 | case 1: | ||
246 | return ____cmpxchg(_u8, ptr, old, new); | ||
247 | case 2: | ||
248 | return ____cmpxchg(_u16, ptr, old, new); | ||
249 | case 4: | ||
250 | return ____cmpxchg(_u32, ptr, old, new); | ||
251 | case 8: | ||
252 | return ____cmpxchg(_u64, ptr, old, new); | ||
253 | } | ||
254 | __cmpxchg_called_with_bad_pointer(); | ||
255 | return old; | ||
256 | } | ||
257 | |||
258 | #endif | ||
diff --git a/arch/alpha/kernel/err_ev6.c b/arch/alpha/kernel/err_ev6.c index 11aee012a8a..985e5c1681a 100644 --- a/arch/alpha/kernel/err_ev6.c +++ b/arch/alpha/kernel/err_ev6.c | |||
@@ -157,8 +157,8 @@ ev6_parse_cbox(u64 c_addr, u64 c1_syn, u64 c2_syn, | |||
157 | err_print_prefix, | 157 | err_print_prefix, |
158 | streamname[stream], bitsname[bits], sourcename[source]); | 158 | streamname[stream], bitsname[bits], sourcename[source]); |
159 | 159 | ||
160 | printk("%s Address: 0x%016lx\n" | 160 | printk("%s Address: 0x%016llx\n" |
161 | " Syndrome[upper.lower]: %02lx.%02lx\n", | 161 | " Syndrome[upper.lower]: %02llx.%02llx\n", |
162 | err_print_prefix, | 162 | err_print_prefix, |
163 | c_addr, | 163 | c_addr, |
164 | c2_syn, c1_syn); | 164 | c2_syn, c1_syn); |
diff --git a/arch/alpha/kernel/err_ev7.c b/arch/alpha/kernel/err_ev7.c index 68cd493f54c..73770c6ca01 100644 --- a/arch/alpha/kernel/err_ev7.c +++ b/arch/alpha/kernel/err_ev7.c | |||
@@ -246,13 +246,13 @@ ev7_process_pal_subpacket(struct el_subpacket *header) | |||
246 | 246 | ||
247 | switch(header->type) { | 247 | switch(header->type) { |
248 | case EL_TYPE__PAL__LOGOUT_FRAME: | 248 | case EL_TYPE__PAL__LOGOUT_FRAME: |
249 | printk("%s*** MCHK occurred on LPID %ld (RBOX %lx)\n", | 249 | printk("%s*** MCHK occurred on LPID %ld (RBOX %llx)\n", |
250 | err_print_prefix, | 250 | err_print_prefix, |
251 | packet->by_type.logout.whami, | 251 | packet->by_type.logout.whami, |
252 | packet->by_type.logout.rbox_whami); | 252 | packet->by_type.logout.rbox_whami); |
253 | el_print_timestamp(&packet->by_type.logout.timestamp); | 253 | el_print_timestamp(&packet->by_type.logout.timestamp); |
254 | printk("%s EXC_ADDR: %016lx\n" | 254 | printk("%s EXC_ADDR: %016llx\n" |
255 | " HALT_CODE: %lx\n", | 255 | " HALT_CODE: %llx\n", |
256 | err_print_prefix, | 256 | err_print_prefix, |
257 | packet->by_type.logout.exc_addr, | 257 | packet->by_type.logout.exc_addr, |
258 | packet->by_type.logout.halt_code); | 258 | packet->by_type.logout.halt_code); |
diff --git a/arch/alpha/kernel/err_marvel.c b/arch/alpha/kernel/err_marvel.c index 413bf37eb09..6bfd243efba 100644 --- a/arch/alpha/kernel/err_marvel.c +++ b/arch/alpha/kernel/err_marvel.c | |||
@@ -129,7 +129,7 @@ marvel_print_po7_crrct_sym(u64 crrct_sym) | |||
129 | 129 | ||
130 | 130 | ||
131 | printk("%s Correctable Error Symptoms:\n" | 131 | printk("%s Correctable Error Symptoms:\n" |
132 | "%s Syndrome: 0x%lx\n", | 132 | "%s Syndrome: 0x%llx\n", |
133 | err_print_prefix, | 133 | err_print_prefix, |
134 | err_print_prefix, EXTRACT(crrct_sym, IO7__PO7_CRRCT_SYM__SYN)); | 134 | err_print_prefix, EXTRACT(crrct_sym, IO7__PO7_CRRCT_SYM__SYN)); |
135 | marvel_print_err_cyc(EXTRACT(crrct_sym, IO7__PO7_CRRCT_SYM__ERR_CYC)); | 135 | marvel_print_err_cyc(EXTRACT(crrct_sym, IO7__PO7_CRRCT_SYM__ERR_CYC)); |
@@ -186,7 +186,7 @@ marvel_print_po7_uncrr_sym(u64 uncrr_sym, u64 valid_mask) | |||
186 | uncrr_sym &= valid_mask; | 186 | uncrr_sym &= valid_mask; |
187 | 187 | ||
188 | if (EXTRACT(valid_mask, IO7__PO7_UNCRR_SYM__SYN)) | 188 | if (EXTRACT(valid_mask, IO7__PO7_UNCRR_SYM__SYN)) |
189 | printk("%s Syndrome: 0x%lx\n", | 189 | printk("%s Syndrome: 0x%llx\n", |
190 | err_print_prefix, | 190 | err_print_prefix, |
191 | EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__SYN)); | 191 | EXTRACT(uncrr_sym, IO7__PO7_UNCRR_SYM__SYN)); |
192 | 192 | ||
@@ -307,7 +307,7 @@ marvel_print_po7_ugbge_sym(u64 ugbge_sym) | |||
307 | sprintf(opcode_str, "BlkIO"); | 307 | sprintf(opcode_str, "BlkIO"); |
308 | break; | 308 | break; |
309 | default: | 309 | default: |
310 | sprintf(opcode_str, "0x%lx\n", | 310 | sprintf(opcode_str, "0x%llx\n", |
311 | EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_OPCODE)); | 311 | EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_OPCODE)); |
312 | break; | 312 | break; |
313 | } | 313 | } |
@@ -321,7 +321,7 @@ marvel_print_po7_ugbge_sym(u64 ugbge_sym) | |||
321 | opcode_str); | 321 | opcode_str); |
322 | 322 | ||
323 | if (0xC5 != EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_OPCODE)) | 323 | if (0xC5 != EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_OPCODE)) |
324 | printk("%s Packet Offset 0x%08lx\n", | 324 | printk("%s Packet Offset 0x%08llx\n", |
325 | err_print_prefix, | 325 | err_print_prefix, |
326 | EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_PKT_OFF)); | 326 | EXTRACT(ugbge_sym, IO7__PO7_UGBGE_SYM__UPH_PKT_OFF)); |
327 | } | 327 | } |
@@ -480,8 +480,8 @@ marvel_print_po7_err_sum(struct ev7_pal_io_subpacket *io) | |||
480 | printk("%s Lost Error\n", err_print_prefix); | 480 | printk("%s Lost Error\n", err_print_prefix); |
481 | 481 | ||
482 | printk("%s Failing Packet:\n" | 482 | printk("%s Failing Packet:\n" |
483 | "%s Cycle 1: %016lx\n" | 483 | "%s Cycle 1: %016llx\n" |
484 | "%s Cycle 2: %016lx\n", | 484 | "%s Cycle 2: %016llx\n", |
485 | err_print_prefix, | 485 | err_print_prefix, |
486 | err_print_prefix, io->po7_err_pkt0, | 486 | err_print_prefix, io->po7_err_pkt0, |
487 | err_print_prefix, io->po7_err_pkt1); | 487 | err_print_prefix, io->po7_err_pkt1); |
@@ -515,9 +515,9 @@ marvel_print_pox_tlb_err(u64 tlb_err) | |||
515 | if (!(tlb_err & IO7__POX_TLBERR__ERR_VALID)) | 515 | if (!(tlb_err & IO7__POX_TLBERR__ERR_VALID)) |
516 | return; | 516 | return; |
517 | 517 | ||
518 | printk("%s TLB Error on index 0x%lx:\n" | 518 | printk("%s TLB Error on index 0x%llx:\n" |
519 | "%s - %s\n" | 519 | "%s - %s\n" |
520 | "%s - Addr: 0x%016lx\n", | 520 | "%s - Addr: 0x%016llx\n", |
521 | err_print_prefix, | 521 | err_print_prefix, |
522 | EXTRACT(tlb_err, IO7__POX_TLBERR__ERR_TLB_PTR), | 522 | EXTRACT(tlb_err, IO7__POX_TLBERR__ERR_TLB_PTR), |
523 | err_print_prefix, | 523 | err_print_prefix, |
@@ -579,7 +579,7 @@ marvel_print_pox_spl_cmplt(u64 spl_cmplt) | |||
579 | sprintf(message, "Uncorrectable Split Write Data Error"); | 579 | sprintf(message, "Uncorrectable Split Write Data Error"); |
580 | break; | 580 | break; |
581 | default: | 581 | default: |
582 | sprintf(message, "%08lx\n", | 582 | sprintf(message, "%08llx\n", |
583 | EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__MESSAGE)); | 583 | EXTRACT(spl_cmplt, IO7__POX_SPLCMPLT__MESSAGE)); |
584 | break; | 584 | break; |
585 | } | 585 | } |
@@ -620,9 +620,9 @@ marvel_print_pox_trans_sum(u64 trans_sum) | |||
620 | return; | 620 | return; |
621 | 621 | ||
622 | printk("%s Transaction Summary:\n" | 622 | printk("%s Transaction Summary:\n" |
623 | "%s Command: 0x%lx - %s\n" | 623 | "%s Command: 0x%llx - %s\n" |
624 | "%s Address: 0x%016lx%s\n" | 624 | "%s Address: 0x%016llx%s\n" |
625 | "%s PCI-X Master Slot: 0x%lx\n", | 625 | "%s PCI-X Master Slot: 0x%llx\n", |
626 | err_print_prefix, | 626 | err_print_prefix, |
627 | err_print_prefix, | 627 | err_print_prefix, |
628 | EXTRACT(trans_sum, IO7__POX_TRANSUM__PCIX_CMD), | 628 | EXTRACT(trans_sum, IO7__POX_TRANSUM__PCIX_CMD), |
@@ -964,12 +964,12 @@ marvel_process_io_error(struct ev7_lf_subpackets *lf_subpackets, int print) | |||
964 | 964 | ||
965 | #if 0 | 965 | #if 0 |
966 | printk("%s PORT 7 ERROR:\n" | 966 | printk("%s PORT 7 ERROR:\n" |
967 | "%s PO7_ERROR_SUM: %016lx\n" | 967 | "%s PO7_ERROR_SUM: %016llx\n" |
968 | "%s PO7_UNCRR_SYM: %016lx\n" | 968 | "%s PO7_UNCRR_SYM: %016llx\n" |
969 | "%s PO7_CRRCT_SYM: %016lx\n" | 969 | "%s PO7_CRRCT_SYM: %016llx\n" |
970 | "%s PO7_UGBGE_SYM: %016lx\n" | 970 | "%s PO7_UGBGE_SYM: %016llx\n" |
971 | "%s PO7_ERR_PKT0: %016lx\n" | 971 | "%s PO7_ERR_PKT0: %016llx\n" |
972 | "%s PO7_ERR_PKT1: %016lx\n", | 972 | "%s PO7_ERR_PKT1: %016llx\n", |
973 | err_print_prefix, | 973 | err_print_prefix, |
974 | err_print_prefix, io->po7_error_sum, | 974 | err_print_prefix, io->po7_error_sum, |
975 | err_print_prefix, io->po7_uncrr_sym, | 975 | err_print_prefix, io->po7_uncrr_sym, |
@@ -987,12 +987,12 @@ marvel_process_io_error(struct ev7_lf_subpackets *lf_subpackets, int print) | |||
987 | if (!MARVEL_IO_ERR_VALID(io->ports[i].pox_err_sum)) | 987 | if (!MARVEL_IO_ERR_VALID(io->ports[i].pox_err_sum)) |
988 | continue; | 988 | continue; |
989 | 989 | ||
990 | printk("%s PID %u PORT %d POx_ERR_SUM: %016lx\n", | 990 | printk("%s PID %u PORT %d POx_ERR_SUM: %016llx\n", |
991 | err_print_prefix, | 991 | err_print_prefix, |
992 | lf_subpackets->io_pid, i, io->ports[i].pox_err_sum); | 992 | lf_subpackets->io_pid, i, io->ports[i].pox_err_sum); |
993 | marvel_print_pox_err(io->ports[i].pox_err_sum, &io->ports[i]); | 993 | marvel_print_pox_err(io->ports[i].pox_err_sum, &io->ports[i]); |
994 | 994 | ||
995 | printk("%s [ POx_FIRST_ERR: %016lx ]\n", | 995 | printk("%s [ POx_FIRST_ERR: %016llx ]\n", |
996 | err_print_prefix, io->ports[i].pox_first_err); | 996 | err_print_prefix, io->ports[i].pox_first_err); |
997 | marvel_print_pox_err(io->ports[i].pox_first_err, | 997 | marvel_print_pox_err(io->ports[i].pox_first_err, |
998 | &io->ports[i]); | 998 | &io->ports[i]); |
diff --git a/arch/alpha/kernel/err_titan.c b/arch/alpha/kernel/err_titan.c index 257449ed15e..c7e28a88d6e 100644 --- a/arch/alpha/kernel/err_titan.c +++ b/arch/alpha/kernel/err_titan.c | |||
@@ -107,12 +107,12 @@ titan_parse_p_serror(int which, u64 serror, int print) | |||
107 | if (!print) | 107 | if (!print) |
108 | return status; | 108 | return status; |
109 | 109 | ||
110 | printk("%s PChip %d SERROR: %016lx\n", | 110 | printk("%s PChip %d SERROR: %016llx\n", |
111 | err_print_prefix, which, serror); | 111 | err_print_prefix, which, serror); |
112 | if (serror & TITAN__PCHIP_SERROR__ECCMASK) { | 112 | if (serror & TITAN__PCHIP_SERROR__ECCMASK) { |
113 | printk("%s %sorrectable ECC Error:\n" | 113 | printk("%s %sorrectable ECC Error:\n" |
114 | " Source: %-6s Command: %-8s Syndrome: 0x%08x\n" | 114 | " Source: %-6s Command: %-8s Syndrome: 0x%08x\n" |
115 | " Address: 0x%lx\n", | 115 | " Address: 0x%llx\n", |
116 | err_print_prefix, | 116 | err_print_prefix, |
117 | (serror & TITAN__PCHIP_SERROR__UECC) ? "Unc" : "C", | 117 | (serror & TITAN__PCHIP_SERROR__UECC) ? "Unc" : "C", |
118 | serror_src[EXTRACT(serror, TITAN__PCHIP_SERROR__SRC)], | 118 | serror_src[EXTRACT(serror, TITAN__PCHIP_SERROR__SRC)], |
@@ -223,7 +223,7 @@ titan_parse_p_perror(int which, int port, u64 perror, int print) | |||
223 | if (!print) | 223 | if (!print) |
224 | return status; | 224 | return status; |
225 | 225 | ||
226 | printk("%s PChip %d %cPERROR: %016lx\n", | 226 | printk("%s PChip %d %cPERROR: %016llx\n", |
227 | err_print_prefix, which, | 227 | err_print_prefix, which, |
228 | port ? 'A' : 'G', perror); | 228 | port ? 'A' : 'G', perror); |
229 | if (perror & TITAN__PCHIP_PERROR__IPTPW) | 229 | if (perror & TITAN__PCHIP_PERROR__IPTPW) |
@@ -316,7 +316,7 @@ titan_parse_p_agperror(int which, u64 agperror, int print) | |||
316 | addr = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__ADDR) << 3; | 316 | addr = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__ADDR) << 3; |
317 | len = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__LEN); | 317 | len = EXTRACT(agperror, TITAN__PCHIP_AGPERROR__LEN); |
318 | 318 | ||
319 | printk("%s PChip %d AGPERROR: %016lx\n", err_print_prefix, | 319 | printk("%s PChip %d AGPERROR: %016llx\n", err_print_prefix, |
320 | which, agperror); | 320 | which, agperror); |
321 | if (agperror & TITAN__PCHIP_AGPERROR__NOWINDOW) | 321 | if (agperror & TITAN__PCHIP_AGPERROR__NOWINDOW) |
322 | printk("%s No Window\n", err_print_prefix); | 322 | printk("%s No Window\n", err_print_prefix); |
@@ -597,16 +597,16 @@ privateer_process_680_frame(struct el_common *mchk_header, int print) | |||
597 | return status; | 597 | return status; |
598 | 598 | ||
599 | /* TODO - decode instead of just dumping... */ | 599 | /* TODO - decode instead of just dumping... */ |
600 | printk("%s Summary Flags: %016lx\n" | 600 | printk("%s Summary Flags: %016llx\n" |
601 | " CChip DIRx: %016lx\n" | 601 | " CChip DIRx: %016llx\n" |
602 | " System Management IR: %016lx\n" | 602 | " System Management IR: %016llx\n" |
603 | " CPU IR: %016lx\n" | 603 | " CPU IR: %016llx\n" |
604 | " Power Supply IR: %016lx\n" | 604 | " Power Supply IR: %016llx\n" |
605 | " LM78 Fault Status: %016lx\n" | 605 | " LM78 Fault Status: %016llx\n" |
606 | " System Doors: %016lx\n" | 606 | " System Doors: %016llx\n" |
607 | " Temperature Warning: %016lx\n" | 607 | " Temperature Warning: %016llx\n" |
608 | " Fan Control: %016lx\n" | 608 | " Fan Control: %016llx\n" |
609 | " Fatal Power Down Code: %016lx\n", | 609 | " Fatal Power Down Code: %016llx\n", |
610 | err_print_prefix, | 610 | err_print_prefix, |
611 | emchk->summary, | 611 | emchk->summary, |
612 | emchk->c_dirx, | 612 | emchk->c_dirx, |
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index a3b93881140..a91ba28999b 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c | |||
@@ -168,7 +168,7 @@ pcibios_align_resource(void *data, struct resource *res, | |||
168 | */ | 168 | */ |
169 | 169 | ||
170 | /* Align to multiple of size of minimum base. */ | 170 | /* Align to multiple of size of minimum base. */ |
171 | alignto = max(0x1000UL, align); | 171 | alignto = max_t(resource_size_t, 0x1000, align); |
172 | start = ALIGN(start, alignto); | 172 | start = ALIGN(start, alignto); |
173 | if (hose->sparse_mem_base && size <= 7 * 16*MB) { | 173 | if (hose->sparse_mem_base && size <= 7 * 16*MB) { |
174 | if (((start / (16*MB)) & 0x7) == 0) { | 174 | if (((start / (16*MB)) & 0x7) == 0) { |
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c index b9094da05d7..bfb880af959 100644 --- a/arch/alpha/kernel/pci_iommu.c +++ b/arch/alpha/kernel/pci_iommu.c | |||
@@ -247,7 +247,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size, | |||
247 | && paddr + size <= __direct_map_size) { | 247 | && paddr + size <= __direct_map_size) { |
248 | ret = paddr + __direct_map_base; | 248 | ret = paddr + __direct_map_base; |
249 | 249 | ||
250 | DBGA2("pci_map_single: [%p,%lx] -> direct %lx from %p\n", | 250 | DBGA2("pci_map_single: [%p,%zx] -> direct %llx from %p\n", |
251 | cpu_addr, size, ret, __builtin_return_address(0)); | 251 | cpu_addr, size, ret, __builtin_return_address(0)); |
252 | 252 | ||
253 | return ret; | 253 | return ret; |
@@ -258,7 +258,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size, | |||
258 | if (dac_allowed) { | 258 | if (dac_allowed) { |
259 | ret = paddr + alpha_mv.pci_dac_offset; | 259 | ret = paddr + alpha_mv.pci_dac_offset; |
260 | 260 | ||
261 | DBGA2("pci_map_single: [%p,%lx] -> DAC %lx from %p\n", | 261 | DBGA2("pci_map_single: [%p,%zx] -> DAC %llx from %p\n", |
262 | cpu_addr, size, ret, __builtin_return_address(0)); | 262 | cpu_addr, size, ret, __builtin_return_address(0)); |
263 | 263 | ||
264 | return ret; | 264 | return ret; |
@@ -299,7 +299,7 @@ pci_map_single_1(struct pci_dev *pdev, void *cpu_addr, size_t size, | |||
299 | ret = arena->dma_base + dma_ofs * PAGE_SIZE; | 299 | ret = arena->dma_base + dma_ofs * PAGE_SIZE; |
300 | ret += (unsigned long)cpu_addr & ~PAGE_MASK; | 300 | ret += (unsigned long)cpu_addr & ~PAGE_MASK; |
301 | 301 | ||
302 | DBGA2("pci_map_single: [%p,%lx] np %ld -> sg %lx from %p\n", | 302 | DBGA2("pci_map_single: [%p,%zx] np %ld -> sg %llx from %p\n", |
303 | cpu_addr, size, npages, ret, __builtin_return_address(0)); | 303 | cpu_addr, size, npages, ret, __builtin_return_address(0)); |
304 | 304 | ||
305 | return ret; | 305 | return ret; |
@@ -355,14 +355,14 @@ pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, | |||
355 | && dma_addr < __direct_map_base + __direct_map_size) { | 355 | && dma_addr < __direct_map_base + __direct_map_size) { |
356 | /* Nothing to do. */ | 356 | /* Nothing to do. */ |
357 | 357 | ||
358 | DBGA2("pci_unmap_single: direct [%lx,%lx] from %p\n", | 358 | DBGA2("pci_unmap_single: direct [%llx,%zx] from %p\n", |
359 | dma_addr, size, __builtin_return_address(0)); | 359 | dma_addr, size, __builtin_return_address(0)); |
360 | 360 | ||
361 | return; | 361 | return; |
362 | } | 362 | } |
363 | 363 | ||
364 | if (dma_addr > 0xffffffff) { | 364 | if (dma_addr > 0xffffffff) { |
365 | DBGA2("pci64_unmap_single: DAC [%lx,%lx] from %p\n", | 365 | DBGA2("pci64_unmap_single: DAC [%llx,%zx] from %p\n", |
366 | dma_addr, size, __builtin_return_address(0)); | 366 | dma_addr, size, __builtin_return_address(0)); |
367 | return; | 367 | return; |
368 | } | 368 | } |
@@ -373,9 +373,9 @@ pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, | |||
373 | 373 | ||
374 | dma_ofs = (dma_addr - arena->dma_base) >> PAGE_SHIFT; | 374 | dma_ofs = (dma_addr - arena->dma_base) >> PAGE_SHIFT; |
375 | if (dma_ofs * PAGE_SIZE >= arena->size) { | 375 | if (dma_ofs * PAGE_SIZE >= arena->size) { |
376 | printk(KERN_ERR "Bogus pci_unmap_single: dma_addr %lx " | 376 | printk(KERN_ERR "Bogus pci_unmap_single: dma_addr %llx " |
377 | " base %lx size %x\n", dma_addr, arena->dma_base, | 377 | " base %llx size %x\n", |
378 | arena->size); | 378 | dma_addr, arena->dma_base, arena->size); |
379 | return; | 379 | return; |
380 | BUG(); | 380 | BUG(); |
381 | } | 381 | } |
@@ -394,7 +394,7 @@ pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr, size_t size, | |||
394 | 394 | ||
395 | spin_unlock_irqrestore(&arena->lock, flags); | 395 | spin_unlock_irqrestore(&arena->lock, flags); |
396 | 396 | ||
397 | DBGA2("pci_unmap_single: sg [%lx,%lx] np %ld from %p\n", | 397 | DBGA2("pci_unmap_single: sg [%llx,%zx] np %ld from %p\n", |
398 | dma_addr, size, npages, __builtin_return_address(0)); | 398 | dma_addr, size, npages, __builtin_return_address(0)); |
399 | } | 399 | } |
400 | EXPORT_SYMBOL(pci_unmap_single); | 400 | EXPORT_SYMBOL(pci_unmap_single); |
@@ -444,7 +444,7 @@ try_again: | |||
444 | goto try_again; | 444 | goto try_again; |
445 | } | 445 | } |
446 | 446 | ||
447 | DBGA2("pci_alloc_consistent: %lx -> [%p,%x] from %p\n", | 447 | DBGA2("pci_alloc_consistent: %zx -> [%p,%llx] from %p\n", |
448 | size, cpu_addr, *dma_addrp, __builtin_return_address(0)); | 448 | size, cpu_addr, *dma_addrp, __builtin_return_address(0)); |
449 | 449 | ||
450 | return cpu_addr; | 450 | return cpu_addr; |
@@ -464,7 +464,7 @@ pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu_addr, | |||
464 | pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL); | 464 | pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL); |
465 | free_pages((unsigned long)cpu_addr, get_order(size)); | 465 | free_pages((unsigned long)cpu_addr, get_order(size)); |
466 | 466 | ||
467 | DBGA2("pci_free_consistent: [%x,%lx] from %p\n", | 467 | DBGA2("pci_free_consistent: [%llx,%zx] from %p\n", |
468 | dma_addr, size, __builtin_return_address(0)); | 468 | dma_addr, size, __builtin_return_address(0)); |
469 | } | 469 | } |
470 | EXPORT_SYMBOL(pci_free_consistent); | 470 | EXPORT_SYMBOL(pci_free_consistent); |
@@ -551,7 +551,7 @@ sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end, | |||
551 | out->dma_address = paddr + __direct_map_base; | 551 | out->dma_address = paddr + __direct_map_base; |
552 | out->dma_length = size; | 552 | out->dma_length = size; |
553 | 553 | ||
554 | DBGA(" sg_fill: [%p,%lx] -> direct %lx\n", | 554 | DBGA(" sg_fill: [%p,%lx] -> direct %llx\n", |
555 | __va(paddr), size, out->dma_address); | 555 | __va(paddr), size, out->dma_address); |
556 | 556 | ||
557 | return 0; | 557 | return 0; |
@@ -563,7 +563,7 @@ sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end, | |||
563 | out->dma_address = paddr + alpha_mv.pci_dac_offset; | 563 | out->dma_address = paddr + alpha_mv.pci_dac_offset; |
564 | out->dma_length = size; | 564 | out->dma_length = size; |
565 | 565 | ||
566 | DBGA(" sg_fill: [%p,%lx] -> DAC %lx\n", | 566 | DBGA(" sg_fill: [%p,%lx] -> DAC %llx\n", |
567 | __va(paddr), size, out->dma_address); | 567 | __va(paddr), size, out->dma_address); |
568 | 568 | ||
569 | return 0; | 569 | return 0; |
@@ -589,7 +589,7 @@ sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end, | |||
589 | out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr; | 589 | out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr; |
590 | out->dma_length = size; | 590 | out->dma_length = size; |
591 | 591 | ||
592 | DBGA(" sg_fill: [%p,%lx] -> sg %lx np %ld\n", | 592 | DBGA(" sg_fill: [%p,%lx] -> sg %llx np %ld\n", |
593 | __va(paddr), size, out->dma_address, npages); | 593 | __va(paddr), size, out->dma_address, npages); |
594 | 594 | ||
595 | /* All virtually contiguous. We need to find the length of each | 595 | /* All virtually contiguous. We need to find the length of each |
@@ -752,7 +752,7 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, | |||
752 | 752 | ||
753 | if (addr > 0xffffffff) { | 753 | if (addr > 0xffffffff) { |
754 | /* It's a DAC address -- nothing to do. */ | 754 | /* It's a DAC address -- nothing to do. */ |
755 | DBGA(" (%ld) DAC [%lx,%lx]\n", | 755 | DBGA(" (%ld) DAC [%llx,%zx]\n", |
756 | sg - end + nents, addr, size); | 756 | sg - end + nents, addr, size); |
757 | continue; | 757 | continue; |
758 | } | 758 | } |
@@ -760,12 +760,12 @@ pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents, | |||
760 | if (addr >= __direct_map_base | 760 | if (addr >= __direct_map_base |
761 | && addr < __direct_map_base + __direct_map_size) { | 761 | && addr < __direct_map_base + __direct_map_size) { |
762 | /* Nothing to do. */ | 762 | /* Nothing to do. */ |
763 | DBGA(" (%ld) direct [%lx,%lx]\n", | 763 | DBGA(" (%ld) direct [%llx,%zx]\n", |
764 | sg - end + nents, addr, size); | 764 | sg - end + nents, addr, size); |
765 | continue; | 765 | continue; |
766 | } | 766 | } |
767 | 767 | ||
768 | DBGA(" (%ld) sg [%lx,%lx]\n", | 768 | DBGA(" (%ld) sg [%llx,%zx]\n", |
769 | sg - end + nents, addr, size); | 769 | sg - end + nents, addr, size); |
770 | 770 | ||
771 | npages = iommu_num_pages(addr, size, PAGE_SIZE); | 771 | npages = iommu_num_pages(addr, size, PAGE_SIZE); |
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h index fe14c6747cd..567f2598d09 100644 --- a/arch/alpha/kernel/proto.h +++ b/arch/alpha/kernel/proto.h | |||
@@ -20,7 +20,7 @@ struct pci_controller; | |||
20 | extern struct pci_ops apecs_pci_ops; | 20 | extern struct pci_ops apecs_pci_ops; |
21 | extern void apecs_init_arch(void); | 21 | extern void apecs_init_arch(void); |
22 | extern void apecs_pci_clr_err(void); | 22 | extern void apecs_pci_clr_err(void); |
23 | extern void apecs_machine_check(u64, u64); | 23 | extern void apecs_machine_check(unsigned long vector, unsigned long la_ptr); |
24 | extern void apecs_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); | 24 | extern void apecs_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); |
25 | 25 | ||
26 | /* core_cia.c */ | 26 | /* core_cia.c */ |
@@ -29,7 +29,7 @@ extern void cia_init_pci(void); | |||
29 | extern void cia_init_arch(void); | 29 | extern void cia_init_arch(void); |
30 | extern void pyxis_init_arch(void); | 30 | extern void pyxis_init_arch(void); |
31 | extern void cia_kill_arch(int); | 31 | extern void cia_kill_arch(int); |
32 | extern void cia_machine_check(u64, u64); | 32 | extern void cia_machine_check(unsigned long vector, unsigned long la_ptr); |
33 | extern void cia_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); | 33 | extern void cia_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); |
34 | 34 | ||
35 | /* core_irongate.c */ | 35 | /* core_irongate.c */ |
@@ -42,7 +42,7 @@ extern void irongate_machine_check(u64, u64); | |||
42 | /* core_lca.c */ | 42 | /* core_lca.c */ |
43 | extern struct pci_ops lca_pci_ops; | 43 | extern struct pci_ops lca_pci_ops; |
44 | extern void lca_init_arch(void); | 44 | extern void lca_init_arch(void); |
45 | extern void lca_machine_check(u64, u64); | 45 | extern void lca_machine_check(unsigned long vector, unsigned long la_ptr); |
46 | extern void lca_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); | 46 | extern void lca_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); |
47 | 47 | ||
48 | /* core_marvel.c */ | 48 | /* core_marvel.c */ |
@@ -64,7 +64,7 @@ void io7_clear_errors(struct io7 *io7); | |||
64 | extern struct pci_ops mcpcia_pci_ops; | 64 | extern struct pci_ops mcpcia_pci_ops; |
65 | extern void mcpcia_init_arch(void); | 65 | extern void mcpcia_init_arch(void); |
66 | extern void mcpcia_init_hoses(void); | 66 | extern void mcpcia_init_hoses(void); |
67 | extern void mcpcia_machine_check(u64, u64); | 67 | extern void mcpcia_machine_check(unsigned long vector, unsigned long la_ptr); |
68 | extern void mcpcia_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); | 68 | extern void mcpcia_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); |
69 | 69 | ||
70 | /* core_polaris.c */ | 70 | /* core_polaris.c */ |
@@ -72,14 +72,14 @@ extern struct pci_ops polaris_pci_ops; | |||
72 | extern int polaris_read_config_dword(struct pci_dev *, int, u32 *); | 72 | extern int polaris_read_config_dword(struct pci_dev *, int, u32 *); |
73 | extern int polaris_write_config_dword(struct pci_dev *, int, u32); | 73 | extern int polaris_write_config_dword(struct pci_dev *, int, u32); |
74 | extern void polaris_init_arch(void); | 74 | extern void polaris_init_arch(void); |
75 | extern void polaris_machine_check(u64, u64); | 75 | extern void polaris_machine_check(unsigned long vector, unsigned long la_ptr); |
76 | #define polaris_pci_tbi ((void *)0) | 76 | #define polaris_pci_tbi ((void *)0) |
77 | 77 | ||
78 | /* core_t2.c */ | 78 | /* core_t2.c */ |
79 | extern struct pci_ops t2_pci_ops; | 79 | extern struct pci_ops t2_pci_ops; |
80 | extern void t2_init_arch(void); | 80 | extern void t2_init_arch(void); |
81 | extern void t2_kill_arch(int); | 81 | extern void t2_kill_arch(int); |
82 | extern void t2_machine_check(u64, u64); | 82 | extern void t2_machine_check(unsigned long vector, unsigned long la_ptr); |
83 | extern void t2_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); | 83 | extern void t2_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); |
84 | 84 | ||
85 | /* core_titan.c */ | 85 | /* core_titan.c */ |
@@ -94,14 +94,14 @@ extern struct _alpha_agp_info *titan_agp_info(void); | |||
94 | extern struct pci_ops tsunami_pci_ops; | 94 | extern struct pci_ops tsunami_pci_ops; |
95 | extern void tsunami_init_arch(void); | 95 | extern void tsunami_init_arch(void); |
96 | extern void tsunami_kill_arch(int); | 96 | extern void tsunami_kill_arch(int); |
97 | extern void tsunami_machine_check(u64, u64); | 97 | extern void tsunami_machine_check(unsigned long vector, unsigned long la_ptr); |
98 | extern void tsunami_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); | 98 | extern void tsunami_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); |
99 | 99 | ||
100 | /* core_wildfire.c */ | 100 | /* core_wildfire.c */ |
101 | extern struct pci_ops wildfire_pci_ops; | 101 | extern struct pci_ops wildfire_pci_ops; |
102 | extern void wildfire_init_arch(void); | 102 | extern void wildfire_init_arch(void); |
103 | extern void wildfire_kill_arch(int); | 103 | extern void wildfire_kill_arch(int); |
104 | extern void wildfire_machine_check(u64, u64); | 104 | extern void wildfire_machine_check(unsigned long vector, unsigned long la_ptr); |
105 | extern void wildfire_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); | 105 | extern void wildfire_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t); |
106 | extern int wildfire_pa_to_nid(unsigned long); | 106 | extern int wildfire_pa_to_nid(unsigned long); |
107 | extern int wildfire_cpuid_to_nid(int); | 107 | extern int wildfire_cpuid_to_nid(int); |
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c index 02bee6983ce..80df86cd746 100644 --- a/arch/alpha/kernel/setup.c +++ b/arch/alpha/kernel/setup.c | |||
@@ -1255,7 +1255,7 @@ show_cpuinfo(struct seq_file *f, void *slot) | |||
1255 | platform_string(), nr_processors); | 1255 | platform_string(), nr_processors); |
1256 | 1256 | ||
1257 | #ifdef CONFIG_SMP | 1257 | #ifdef CONFIG_SMP |
1258 | seq_printf(f, "cpus active\t\t: %d\n" | 1258 | seq_printf(f, "cpus active\t\t: %u\n" |
1259 | "cpu active mask\t\t: %016lx\n", | 1259 | "cpu active mask\t\t: %016lx\n", |
1260 | num_online_cpus(), cpus_addr(cpu_possible_map)[0]); | 1260 | num_online_cpus(), cpus_addr(cpu_possible_map)[0]); |
1261 | #endif | 1261 | #endif |
diff --git a/arch/alpha/kernel/smc37c669.c b/arch/alpha/kernel/smc37c669.c index fd467b207f0..bca5bda90cd 100644 --- a/arch/alpha/kernel/smc37c669.c +++ b/arch/alpha/kernel/smc37c669.c | |||
@@ -2542,8 +2542,8 @@ void __init SMC669_Init ( int index ) | |||
2542 | SMC37c669_display_device_info( ); | 2542 | SMC37c669_display_device_info( ); |
2543 | #endif | 2543 | #endif |
2544 | local_irq_restore(flags); | 2544 | local_irq_restore(flags); |
2545 | printk( "SMC37c669 Super I/O Controller found @ 0x%lx\n", | 2545 | printk( "SMC37c669 Super I/O Controller found @ 0x%p\n", |
2546 | (unsigned long) SMC_base ); | 2546 | SMC_base ); |
2547 | } | 2547 | } |
2548 | else { | 2548 | else { |
2549 | local_irq_restore(flags); | 2549 | local_irq_restore(flags); |
diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c index e2516f9a896..2b5caf3d9b1 100644 --- a/arch/alpha/kernel/sys_jensen.c +++ b/arch/alpha/kernel/sys_jensen.c | |||
@@ -244,12 +244,11 @@ jensen_init_arch(void) | |||
244 | } | 244 | } |
245 | 245 | ||
246 | static void | 246 | static void |
247 | jensen_machine_check (u64 vector, u64 la) | 247 | jensen_machine_check(unsigned long vector, unsigned long la) |
248 | { | 248 | { |
249 | printk(KERN_CRIT "Machine check\n"); | 249 | printk(KERN_CRIT "Machine check\n"); |
250 | } | 250 | } |
251 | 251 | ||
252 | |||
253 | /* | 252 | /* |
254 | * The System Vector | 253 | * The System Vector |
255 | */ | 254 | */ |
diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c index d232e42be01..9e263256a42 100644 --- a/arch/alpha/kernel/sys_sable.c +++ b/arch/alpha/kernel/sys_sable.c | |||
@@ -453,7 +453,7 @@ sable_lynx_enable_irq(unsigned int irq) | |||
453 | sable_lynx_irq_swizzle->update_irq_hw(bit, mask); | 453 | sable_lynx_irq_swizzle->update_irq_hw(bit, mask); |
454 | spin_unlock(&sable_lynx_irq_lock); | 454 | spin_unlock(&sable_lynx_irq_lock); |
455 | #if 0 | 455 | #if 0 |
456 | printk("%s: mask 0x%lx bit 0x%x irq 0x%x\n", | 456 | printk("%s: mask 0x%lx bit 0x%lx irq 0x%x\n", |
457 | __func__, mask, bit, irq); | 457 | __func__, mask, bit, irq); |
458 | #endif | 458 | #endif |
459 | } | 459 | } |
@@ -469,7 +469,7 @@ sable_lynx_disable_irq(unsigned int irq) | |||
469 | sable_lynx_irq_swizzle->update_irq_hw(bit, mask); | 469 | sable_lynx_irq_swizzle->update_irq_hw(bit, mask); |
470 | spin_unlock(&sable_lynx_irq_lock); | 470 | spin_unlock(&sable_lynx_irq_lock); |
471 | #if 0 | 471 | #if 0 |
472 | printk("%s: mask 0x%lx bit 0x%x irq 0x%x\n", | 472 | printk("%s: mask 0x%lx bit 0x%lx irq 0x%x\n", |
473 | __func__, mask, bit, irq); | 473 | __func__, mask, bit, irq); |
474 | #endif | 474 | #endif |
475 | } | 475 | } |
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index cefc5a355ef..6ee7655b756 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c | |||
@@ -623,7 +623,7 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg, | |||
623 | } | 623 | } |
624 | 624 | ||
625 | lock_kernel(); | 625 | lock_kernel(); |
626 | printk("Bad unaligned kernel access at %016lx: %p %lx %ld\n", | 626 | printk("Bad unaligned kernel access at %016lx: %p %lx %lu\n", |
627 | pc, va, opcode, reg); | 627 | pc, va, opcode, reg); |
628 | do_exit(SIGSEGV); | 628 | do_exit(SIGSEGV); |
629 | 629 | ||
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c index ce4e4296b95..62d4abbaa65 100644 --- a/arch/avr32/mm/fault.c +++ b/arch/avr32/mm/fault.c | |||
@@ -250,21 +250,3 @@ asmlinkage void do_bus_error(unsigned long addr, int write_access, | |||
250 | dump_dtlb(); | 250 | dump_dtlb(); |
251 | die("Bus Error", regs, SIGKILL); | 251 | die("Bus Error", regs, SIGKILL); |
252 | } | 252 | } |
253 | |||
254 | /* | ||
255 | * This functionality is currently not possible to implement because | ||
256 | * we're using segmentation to ensure a fixed mapping of the kernel | ||
257 | * virtual address space. | ||
258 | * | ||
259 | * It would be possible to implement this, but it would require us to | ||
260 | * disable segmentation at startup and load the kernel mappings into | ||
261 | * the TLB like any other pages. There will be lots of trickery to | ||
262 | * avoid recursive invocation of the TLB miss handler, though... | ||
263 | */ | ||
264 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
265 | void kernel_map_pages(struct page *page, int numpages, int enable) | ||
266 | { | ||
267 | |||
268 | } | ||
269 | EXPORT_SYMBOL(kernel_map_pages); | ||
270 | #endif | ||
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 24b1ad5334c..2bef5261d96 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/major.h> | 24 | #include <linux/major.h> |
25 | #include <linux/fcntl.h> | 25 | #include <linux/fcntl.h> |
26 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
27 | #include <linux/seq_file.h> | ||
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
28 | #include <linux/capability.h> | 29 | #include <linux/capability.h> |
29 | #include <linux/console.h> | 30 | #include <linux/console.h> |
@@ -848,38 +849,36 @@ static int rs_open(struct tty_struct *tty, struct file * filp) | |||
848 | * /proc fs routines.... | 849 | * /proc fs routines.... |
849 | */ | 850 | */ |
850 | 851 | ||
851 | static inline int line_info(char *buf, struct serial_state *state) | 852 | static inline void line_info(struct seq_file *m, struct serial_state *state) |
852 | { | 853 | { |
853 | return sprintf(buf, "%d: uart:%s port:%lX irq:%d\n", | 854 | seq_printf(m, "%d: uart:%s port:%lX irq:%d\n", |
854 | state->line, uart_config[state->type].name, | 855 | state->line, uart_config[state->type].name, |
855 | state->port, state->irq); | 856 | state->port, state->irq); |
856 | } | 857 | } |
857 | 858 | ||
858 | static int rs_read_proc(char *page, char **start, off_t off, int count, | 859 | static int rs_proc_show(struct seq_file *m, void *v) |
859 | int *eof, void *data) | ||
860 | { | 860 | { |
861 | int i, len = 0, l; | 861 | int i; |
862 | off_t begin = 0; | 862 | |
863 | 863 | seq_printf(m, "simserinfo:1.0 driver:%s\n", serial_version); | |
864 | len += sprintf(page, "simserinfo:1.0 driver:%s\n", serial_version); | 864 | for (i = 0; i < NR_PORTS; i++) |
865 | for (i = 0; i < NR_PORTS && len < 4000; i++) { | 865 | line_info(m, &rs_table[i]); |
866 | l = line_info(page + len, &rs_table[i]); | 866 | return 0; |
867 | len += l; | ||
868 | if (len+begin > off+count) | ||
869 | goto done; | ||
870 | if (len+begin < off) { | ||
871 | begin += len; | ||
872 | len = 0; | ||
873 | } | ||
874 | } | ||
875 | *eof = 1; | ||
876 | done: | ||
877 | if (off >= len+begin) | ||
878 | return 0; | ||
879 | *start = page + (begin-off); | ||
880 | return ((count < begin+len-off) ? count : begin+len-off); | ||
881 | } | 867 | } |
882 | 868 | ||
869 | static int rs_proc_open(struct inode *inode, struct file *file) | ||
870 | { | ||
871 | return single_open(file, rs_proc_show, NULL); | ||
872 | } | ||
873 | |||
874 | static const struct file_operations rs_proc_fops = { | ||
875 | .owner = THIS_MODULE, | ||
876 | .open = rs_proc_open, | ||
877 | .read = seq_read, | ||
878 | .llseek = seq_lseek, | ||
879 | .release = single_release, | ||
880 | }; | ||
881 | |||
883 | /* | 882 | /* |
884 | * --------------------------------------------------------------------- | 883 | * --------------------------------------------------------------------- |
885 | * rs_init() and friends | 884 | * rs_init() and friends |
@@ -917,7 +916,7 @@ static const struct tty_operations hp_ops = { | |||
917 | .start = rs_start, | 916 | .start = rs_start, |
918 | .hangup = rs_hangup, | 917 | .hangup = rs_hangup, |
919 | .wait_until_sent = rs_wait_until_sent, | 918 | .wait_until_sent = rs_wait_until_sent, |
920 | .read_proc = rs_read_proc, | 919 | .proc_fops = &rs_proc_fops, |
921 | }; | 920 | }; |
922 | 921 | ||
923 | /* | 922 | /* |
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index f0ebb342409..d6747bae52d 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/efi.h> | 20 | #include <linux/efi.h> |
21 | #include <linux/timex.h> | 21 | #include <linux/timex.h> |
22 | #include <linux/clocksource.h> | 22 | #include <linux/clocksource.h> |
23 | #include <linux/platform_device.h> | ||
23 | 24 | ||
24 | #include <asm/machvec.h> | 25 | #include <asm/machvec.h> |
25 | #include <asm/delay.h> | 26 | #include <asm/delay.h> |
@@ -405,6 +406,21 @@ static struct irqaction timer_irqaction = { | |||
405 | .name = "timer" | 406 | .name = "timer" |
406 | }; | 407 | }; |
407 | 408 | ||
409 | static struct platform_device rtc_efi_dev = { | ||
410 | .name = "rtc-efi", | ||
411 | .id = -1, | ||
412 | }; | ||
413 | |||
414 | static int __init rtc_init(void) | ||
415 | { | ||
416 | if (platform_device_register(&rtc_efi_dev) < 0) | ||
417 | printk(KERN_ERR "unable to register rtc device...\n"); | ||
418 | |||
419 | /* not necessarily an error */ | ||
420 | return 0; | ||
421 | } | ||
422 | module_init(rtc_init); | ||
423 | |||
408 | void __init | 424 | void __init |
409 | time_init (void) | 425 | time_init (void) |
410 | { | 426 | { |
diff --git a/arch/mips/include/asm/mach-bcm47xx/gpio.h b/arch/mips/include/asm/mach-bcm47xx/gpio.h index d8ff4cd89ab..1784fde2e28 100644 --- a/arch/mips/include/asm/mach-bcm47xx/gpio.h +++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h | |||
@@ -31,24 +31,28 @@ static inline void gpio_set_value(unsigned gpio, int value) | |||
31 | 31 | ||
32 | static inline int gpio_direction_input(unsigned gpio) | 32 | static inline int gpio_direction_input(unsigned gpio) |
33 | { | 33 | { |
34 | return ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0); | 34 | ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0); |
35 | return 0; | ||
35 | } | 36 | } |
36 | 37 | ||
37 | static inline int gpio_direction_output(unsigned gpio, int value) | 38 | static inline int gpio_direction_output(unsigned gpio, int value) |
38 | { | 39 | { |
39 | return ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio); | 40 | ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio); |
41 | return 0; | ||
40 | } | 42 | } |
41 | 43 | ||
42 | static int gpio_intmask(unsigned gpio, int value) | 44 | static inline int gpio_intmask(unsigned gpio, int value) |
43 | { | 45 | { |
44 | return ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio, | 46 | ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio, |
45 | value ? 1 << gpio : 0); | 47 | value ? 1 << gpio : 0); |
48 | return 0; | ||
46 | } | 49 | } |
47 | 50 | ||
48 | static int gpio_polarity(unsigned gpio, int value) | 51 | static inline int gpio_polarity(unsigned gpio, int value) |
49 | { | 52 | { |
50 | return ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio, | 53 | ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio, |
51 | value ? 1 << gpio : 0); | 54 | value ? 1 << gpio : 0); |
55 | return 0; | ||
52 | } | 56 | } |
53 | 57 | ||
54 | 58 | ||
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c index 060d28dca8a..4481656d106 100644 --- a/arch/mips/mm/highmem.c +++ b/arch/mips/mm/highmem.c | |||
@@ -42,6 +42,7 @@ void *__kmap_atomic(struct page *page, enum km_type type) | |||
42 | if (!PageHighMem(page)) | 42 | if (!PageHighMem(page)) |
43 | return page_address(page); | 43 | return page_address(page); |
44 | 44 | ||
45 | debug_kmap_atomic(type); | ||
45 | idx = type + KM_TYPE_NR*smp_processor_id(); | 46 | idx = type + KM_TYPE_NR*smp_processor_id(); |
46 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 47 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
47 | #ifdef CONFIG_DEBUG_HIGHMEM | 48 | #ifdef CONFIG_DEBUG_HIGHMEM |
@@ -88,6 +89,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type) | |||
88 | 89 | ||
89 | pagefault_disable(); | 90 | pagefault_disable(); |
90 | 91 | ||
92 | debug_kmap_atomic(type); | ||
91 | idx = type + KM_TYPE_NR*smp_processor_id(); | 93 | idx = type + KM_TYPE_NR*smp_processor_id(); |
92 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 94 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
93 | set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot)); | 95 | set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot)); |
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c index 9d46c43a415..e75cae6072c 100644 --- a/arch/parisc/kernel/time.c +++ b/arch/parisc/kernel/time.c | |||
@@ -216,17 +216,14 @@ void __init start_cpu_itimer(void) | |||
216 | per_cpu(cpu_data, cpu).it_value = next_tick; | 216 | per_cpu(cpu_data, cpu).it_value = next_tick; |
217 | } | 217 | } |
218 | 218 | ||
219 | struct platform_device rtc_parisc_dev = { | 219 | static struct platform_device rtc_parisc_dev = { |
220 | .name = "rtc-parisc", | 220 | .name = "rtc-parisc", |
221 | .id = -1, | 221 | .id = -1, |
222 | }; | 222 | }; |
223 | 223 | ||
224 | static int __init rtc_init(void) | 224 | static int __init rtc_init(void) |
225 | { | 225 | { |
226 | int ret; | 226 | if (platform_device_register(&rtc_parisc_dev) < 0) |
227 | |||
228 | ret = platform_device_register(&rtc_parisc_dev); | ||
229 | if (ret < 0) | ||
230 | printk(KERN_ERR "unable to register rtc device...\n"); | 227 | printk(KERN_ERR "unable to register rtc device...\n"); |
231 | 228 | ||
232 | /* not necessarily an error */ | 229 | /* not necessarily an error */ |
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index ad6b1c084fe..45192dce65c 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -228,6 +228,9 @@ config PPC_OF_PLATFORM_PCI | |||
228 | depends on PPC64 # not supported on 32 bits yet | 228 | depends on PPC64 # not supported on 32 bits yet |
229 | default n | 229 | default n |
230 | 230 | ||
231 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC | ||
232 | def_bool y | ||
233 | |||
231 | source "init/Kconfig" | 234 | source "init/Kconfig" |
232 | 235 | ||
233 | source "kernel/Kconfig.freezer" | 236 | source "kernel/Kconfig.freezer" |
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 22091bbfdc9..6aa0b5e087c 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug | |||
@@ -30,6 +30,7 @@ config DEBUG_STACK_USAGE | |||
30 | config DEBUG_PAGEALLOC | 30 | config DEBUG_PAGEALLOC |
31 | bool "Debug page memory allocations" | 31 | bool "Debug page memory allocations" |
32 | depends on DEBUG_KERNEL && !HIBERNATION | 32 | depends on DEBUG_KERNEL && !HIBERNATION |
33 | depends on ARCH_SUPPORTS_DEBUG_PAGEALLOC | ||
33 | help | 34 | help |
34 | Unmap pages from the kernel linear mapping after free_pages(). | 35 | Unmap pages from the kernel linear mapping after free_pages(). |
35 | This results in a large slowdown, but helps to find certain types | 36 | This results in a large slowdown, but helps to find certain types |
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts index dea30910c13..4319bd70a58 100644 --- a/arch/powerpc/boot/dts/mpc832x_rdb.dts +++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts | |||
@@ -152,10 +152,21 @@ | |||
152 | }; | 152 | }; |
153 | 153 | ||
154 | par_io@1400 { | 154 | par_io@1400 { |
155 | #address-cells = <1>; | ||
156 | #size-cells = <1>; | ||
155 | reg = <0x1400 0x100>; | 157 | reg = <0x1400 0x100>; |
158 | ranges = <3 0x1448 0x18>; | ||
159 | compatible = "fsl,mpc8323-qe-pario"; | ||
156 | device_type = "par_io"; | 160 | device_type = "par_io"; |
157 | num-ports = <7>; | 161 | num-ports = <7>; |
158 | 162 | ||
163 | qe_pio_d: gpio-controller@1448 { | ||
164 | #gpio-cells = <2>; | ||
165 | compatible = "fsl,mpc8323-qe-pario-bank"; | ||
166 | reg = <3 0x18>; | ||
167 | gpio-controller; | ||
168 | }; | ||
169 | |||
159 | ucc2pio:ucc_pin@02 { | 170 | ucc2pio:ucc_pin@02 { |
160 | pio-map = < | 171 | pio-map = < |
161 | /* port pin dir open_drain assignment has_irq */ | 172 | /* port pin dir open_drain assignment has_irq */ |
@@ -225,12 +236,25 @@ | |||
225 | }; | 236 | }; |
226 | 237 | ||
227 | spi@4c0 { | 238 | spi@4c0 { |
239 | #address-cells = <1>; | ||
240 | #size-cells = <0>; | ||
228 | cell-index = <0>; | 241 | cell-index = <0>; |
229 | compatible = "fsl,spi"; | 242 | compatible = "fsl,spi"; |
230 | reg = <0x4c0 0x40>; | 243 | reg = <0x4c0 0x40>; |
231 | interrupts = <2>; | 244 | interrupts = <2>; |
232 | interrupt-parent = <&qeic>; | 245 | interrupt-parent = <&qeic>; |
246 | gpios = <&qe_pio_d 13 0>; | ||
233 | mode = "cpu-qe"; | 247 | mode = "cpu-qe"; |
248 | |||
249 | mmc-slot@0 { | ||
250 | compatible = "fsl,mpc8323rdb-mmc-slot", | ||
251 | "mmc-spi-slot"; | ||
252 | reg = <0>; | ||
253 | gpios = <&qe_pio_d 14 1 | ||
254 | &qe_pio_d 15 0>; | ||
255 | voltage-ranges = <3300 3300>; | ||
256 | spi-max-frequency = <50000000>; | ||
257 | }; | ||
234 | }; | 258 | }; |
235 | 259 | ||
236 | spi@500 { | 260 | spi@500 { |
diff --git a/arch/powerpc/include/asm/highmem.h b/arch/powerpc/include/asm/highmem.h index 545028f8648..684a73f4324 100644 --- a/arch/powerpc/include/asm/highmem.h +++ b/arch/powerpc/include/asm/highmem.h | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/highmem.h> | ||
27 | #include <asm/kmap_types.h> | 28 | #include <asm/kmap_types.h> |
28 | #include <asm/tlbflush.h> | 29 | #include <asm/tlbflush.h> |
29 | #include <asm/page.h> | 30 | #include <asm/page.h> |
@@ -94,6 +95,7 @@ static inline void *kmap_atomic_prot(struct page *page, enum km_type type, pgpro | |||
94 | if (!PageHighMem(page)) | 95 | if (!PageHighMem(page)) |
95 | return page_address(page); | 96 | return page_address(page); |
96 | 97 | ||
98 | debug_kmap_atomic(type); | ||
97 | idx = type + KM_TYPE_NR*smp_processor_id(); | 99 | idx = type + KM_TYPE_NR*smp_processor_id(); |
98 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 100 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
99 | #ifdef CONFIG_DEBUG_HIGHMEM | 101 | #ifdef CONFIG_DEBUG_HIGHMEM |
diff --git a/arch/powerpc/include/asm/suspend.h b/arch/powerpc/include/asm/suspend.h index cbf2c9404c3..c6efc3466aa 100644 --- a/arch/powerpc/include/asm/suspend.h +++ b/arch/powerpc/include/asm/suspend.h | |||
@@ -3,7 +3,4 @@ | |||
3 | 3 | ||
4 | static inline int arch_prepare_suspend(void) { return 0; } | 4 | static inline int arch_prepare_suspend(void) { return 0; } |
5 | 5 | ||
6 | void save_processor_state(void); | ||
7 | void restore_processor_state(void); | ||
8 | |||
9 | #endif /* __ASM_POWERPC_SUSPEND_H */ | 6 | #endif /* __ASM_POWERPC_SUSPEND_H */ |
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index 2a1295f1983..567ded7c3b9 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/spi/mmc_spi.h> | 20 | #include <linux/spi/mmc_spi.h> |
21 | #include <linux/mmc/host.h> | 21 | #include <linux/mmc/host.h> |
22 | #include <linux/of_platform.h> | 22 | #include <linux/of_platform.h> |
23 | #include <linux/fsl_devices.h> | ||
23 | 24 | ||
24 | #include <asm/time.h> | 25 | #include <asm/time.h> |
25 | #include <asm/ipic.h> | 26 | #include <asm/ipic.h> |
@@ -39,16 +40,116 @@ | |||
39 | #endif | 40 | #endif |
40 | 41 | ||
41 | #ifdef CONFIG_QUICC_ENGINE | 42 | #ifdef CONFIG_QUICC_ENGINE |
42 | static void mpc83xx_spi_activate_cs(u8 cs, u8 polarity) | 43 | static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk, |
44 | struct spi_board_info *board_infos, | ||
45 | unsigned int num_board_infos, | ||
46 | void (*cs_control)(struct spi_device *dev, | ||
47 | bool on)) | ||
43 | { | 48 | { |
44 | pr_debug("%s %d %d\n", __func__, cs, polarity); | 49 | struct device_node *np; |
45 | par_io_data_set(3, 13, polarity); | 50 | unsigned int i = 0; |
51 | |||
52 | for_each_compatible_node(np, type, compatible) { | ||
53 | int ret; | ||
54 | unsigned int j; | ||
55 | const void *prop; | ||
56 | struct resource res[2]; | ||
57 | struct platform_device *pdev; | ||
58 | struct fsl_spi_platform_data pdata = { | ||
59 | .cs_control = cs_control, | ||
60 | }; | ||
61 | |||
62 | memset(res, 0, sizeof(res)); | ||
63 | |||
64 | pdata.sysclk = sysclk; | ||
65 | |||
66 | prop = of_get_property(np, "reg", NULL); | ||
67 | if (!prop) | ||
68 | goto err; | ||
69 | pdata.bus_num = *(u32 *)prop; | ||
70 | |||
71 | prop = of_get_property(np, "cell-index", NULL); | ||
72 | if (prop) | ||
73 | i = *(u32 *)prop; | ||
74 | |||
75 | prop = of_get_property(np, "mode", NULL); | ||
76 | if (prop && !strcmp(prop, "cpu-qe")) | ||
77 | pdata.qe_mode = 1; | ||
78 | |||
79 | for (j = 0; j < num_board_infos; j++) { | ||
80 | if (board_infos[j].bus_num == pdata.bus_num) | ||
81 | pdata.max_chipselect++; | ||
82 | } | ||
83 | |||
84 | if (!pdata.max_chipselect) | ||
85 | continue; | ||
86 | |||
87 | ret = of_address_to_resource(np, 0, &res[0]); | ||
88 | if (ret) | ||
89 | goto err; | ||
90 | |||
91 | ret = of_irq_to_resource(np, 0, &res[1]); | ||
92 | if (ret == NO_IRQ) | ||
93 | goto err; | ||
94 | |||
95 | pdev = platform_device_alloc("mpc83xx_spi", i); | ||
96 | if (!pdev) | ||
97 | goto err; | ||
98 | |||
99 | ret = platform_device_add_data(pdev, &pdata, sizeof(pdata)); | ||
100 | if (ret) | ||
101 | goto unreg; | ||
102 | |||
103 | ret = platform_device_add_resources(pdev, res, | ||
104 | ARRAY_SIZE(res)); | ||
105 | if (ret) | ||
106 | goto unreg; | ||
107 | |||
108 | ret = platform_device_add(pdev); | ||
109 | if (ret) | ||
110 | goto unreg; | ||
111 | |||
112 | goto next; | ||
113 | unreg: | ||
114 | platform_device_del(pdev); | ||
115 | err: | ||
116 | pr_err("%s: registration failed\n", np->full_name); | ||
117 | next: | ||
118 | i++; | ||
119 | } | ||
120 | |||
121 | return i; | ||
46 | } | 122 | } |
47 | 123 | ||
48 | static void mpc83xx_spi_deactivate_cs(u8 cs, u8 polarity) | 124 | static int __init fsl_spi_init(struct spi_board_info *board_infos, |
125 | unsigned int num_board_infos, | ||
126 | void (*cs_control)(struct spi_device *spi, | ||
127 | bool on)) | ||
49 | { | 128 | { |
50 | pr_debug("%s %d %d\n", __func__, cs, polarity); | 129 | u32 sysclk = -1; |
51 | par_io_data_set(3, 13, !polarity); | 130 | int ret; |
131 | |||
132 | /* SPI controller is either clocked from QE or SoC clock */ | ||
133 | sysclk = get_brgfreq(); | ||
134 | if (sysclk == -1) { | ||
135 | sysclk = fsl_get_sys_freq(); | ||
136 | if (sysclk == -1) | ||
137 | return -ENODEV; | ||
138 | } | ||
139 | |||
140 | ret = of_fsl_spi_probe(NULL, "fsl,spi", sysclk, board_infos, | ||
141 | num_board_infos, cs_control); | ||
142 | if (!ret) | ||
143 | of_fsl_spi_probe("spi", "fsl_spi", sysclk, board_infos, | ||
144 | num_board_infos, cs_control); | ||
145 | |||
146 | return spi_register_board_info(board_infos, num_board_infos); | ||
147 | } | ||
148 | |||
149 | static void mpc83xx_spi_cs_control(struct spi_device *spi, bool on) | ||
150 | { | ||
151 | pr_debug("%s %d %d\n", __func__, spi->chip_select, on); | ||
152 | par_io_data_set(3, 13, on); | ||
52 | } | 153 | } |
53 | 154 | ||
54 | static struct mmc_spi_platform_data mpc832x_mmc_pdata = { | 155 | static struct mmc_spi_platform_data mpc832x_mmc_pdata = { |
@@ -74,9 +175,13 @@ static int __init mpc832x_spi_init(void) | |||
74 | par_io_config_pin(3, 14, 2, 0, 0, 0); /* SD_INSERT, I */ | 175 | par_io_config_pin(3, 14, 2, 0, 0, 0); /* SD_INSERT, I */ |
75 | par_io_config_pin(3, 15, 2, 0, 0, 0); /* SD_PROTECT,I */ | 176 | par_io_config_pin(3, 15, 2, 0, 0, 0); /* SD_PROTECT,I */ |
76 | 177 | ||
77 | return fsl_spi_init(&mpc832x_spi_boardinfo, 1, | 178 | /* |
78 | mpc83xx_spi_activate_cs, | 179 | * Don't bother with legacy stuff when device tree contains |
79 | mpc83xx_spi_deactivate_cs); | 180 | * mmc-spi-slot node. |
181 | */ | ||
182 | if (of_find_compatible_node(NULL, NULL, "mmc-spi-slot")) | ||
183 | return 0; | ||
184 | return fsl_spi_init(&mpc832x_spi_boardinfo, 1, mpc83xx_spi_cs_control); | ||
80 | } | 185 | } |
81 | machine_device_initcall(mpc832x_rdb, mpc832x_spi_init); | 186 | machine_device_initcall(mpc832x_rdb, mpc832x_spi_init); |
82 | #endif /* CONFIG_QUICC_ENGINE */ | 187 | #endif /* CONFIG_QUICC_ENGINE */ |
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index a01c89d3f9b..afe8dbc964a 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
@@ -417,115 +417,6 @@ err: | |||
417 | 417 | ||
418 | arch_initcall(fsl_usb_of_init); | 418 | arch_initcall(fsl_usb_of_init); |
419 | 419 | ||
420 | static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk, | ||
421 | struct spi_board_info *board_infos, | ||
422 | unsigned int num_board_infos, | ||
423 | void (*activate_cs)(u8 cs, u8 polarity), | ||
424 | void (*deactivate_cs)(u8 cs, u8 polarity)) | ||
425 | { | ||
426 | struct device_node *np; | ||
427 | unsigned int i = 0; | ||
428 | |||
429 | for_each_compatible_node(np, type, compatible) { | ||
430 | int ret; | ||
431 | unsigned int j; | ||
432 | const void *prop; | ||
433 | struct resource res[2]; | ||
434 | struct platform_device *pdev; | ||
435 | struct fsl_spi_platform_data pdata = { | ||
436 | .activate_cs = activate_cs, | ||
437 | .deactivate_cs = deactivate_cs, | ||
438 | }; | ||
439 | |||
440 | memset(res, 0, sizeof(res)); | ||
441 | |||
442 | pdata.sysclk = sysclk; | ||
443 | |||
444 | prop = of_get_property(np, "reg", NULL); | ||
445 | if (!prop) | ||
446 | goto err; | ||
447 | pdata.bus_num = *(u32 *)prop; | ||
448 | |||
449 | prop = of_get_property(np, "cell-index", NULL); | ||
450 | if (prop) | ||
451 | i = *(u32 *)prop; | ||
452 | |||
453 | prop = of_get_property(np, "mode", NULL); | ||
454 | if (prop && !strcmp(prop, "cpu-qe")) | ||
455 | pdata.qe_mode = 1; | ||
456 | |||
457 | for (j = 0; j < num_board_infos; j++) { | ||
458 | if (board_infos[j].bus_num == pdata.bus_num) | ||
459 | pdata.max_chipselect++; | ||
460 | } | ||
461 | |||
462 | if (!pdata.max_chipselect) | ||
463 | continue; | ||
464 | |||
465 | ret = of_address_to_resource(np, 0, &res[0]); | ||
466 | if (ret) | ||
467 | goto err; | ||
468 | |||
469 | ret = of_irq_to_resource(np, 0, &res[1]); | ||
470 | if (ret == NO_IRQ) | ||
471 | goto err; | ||
472 | |||
473 | pdev = platform_device_alloc("mpc83xx_spi", i); | ||
474 | if (!pdev) | ||
475 | goto err; | ||
476 | |||
477 | ret = platform_device_add_data(pdev, &pdata, sizeof(pdata)); | ||
478 | if (ret) | ||
479 | goto unreg; | ||
480 | |||
481 | ret = platform_device_add_resources(pdev, res, | ||
482 | ARRAY_SIZE(res)); | ||
483 | if (ret) | ||
484 | goto unreg; | ||
485 | |||
486 | ret = platform_device_add(pdev); | ||
487 | if (ret) | ||
488 | goto unreg; | ||
489 | |||
490 | goto next; | ||
491 | unreg: | ||
492 | platform_device_del(pdev); | ||
493 | err: | ||
494 | pr_err("%s: registration failed\n", np->full_name); | ||
495 | next: | ||
496 | i++; | ||
497 | } | ||
498 | |||
499 | return i; | ||
500 | } | ||
501 | |||
502 | int __init fsl_spi_init(struct spi_board_info *board_infos, | ||
503 | unsigned int num_board_infos, | ||
504 | void (*activate_cs)(u8 cs, u8 polarity), | ||
505 | void (*deactivate_cs)(u8 cs, u8 polarity)) | ||
506 | { | ||
507 | u32 sysclk = -1; | ||
508 | int ret; | ||
509 | |||
510 | #ifdef CONFIG_QUICC_ENGINE | ||
511 | /* SPI controller is either clocked from QE or SoC clock */ | ||
512 | sysclk = get_brgfreq(); | ||
513 | #endif | ||
514 | if (sysclk == -1) { | ||
515 | sysclk = fsl_get_sys_freq(); | ||
516 | if (sysclk == -1) | ||
517 | return -ENODEV; | ||
518 | } | ||
519 | |||
520 | ret = of_fsl_spi_probe(NULL, "fsl,spi", sysclk, board_infos, | ||
521 | num_board_infos, activate_cs, deactivate_cs); | ||
522 | if (!ret) | ||
523 | of_fsl_spi_probe("spi", "fsl_spi", sysclk, board_infos, | ||
524 | num_board_infos, activate_cs, deactivate_cs); | ||
525 | |||
526 | return spi_register_board_info(board_infos, num_board_infos); | ||
527 | } | ||
528 | |||
529 | #if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) | 420 | #if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) |
530 | static __be32 __iomem *rstcr; | 421 | static __be32 __iomem *rstcr; |
531 | 422 | ||
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h index 9c744e4285a..42381bb6cd5 100644 --- a/arch/powerpc/sysdev/fsl_soc.h +++ b/arch/powerpc/sysdev/fsl_soc.h | |||
@@ -4,6 +4,8 @@ | |||
4 | 4 | ||
5 | #include <asm/mmu.h> | 5 | #include <asm/mmu.h> |
6 | 6 | ||
7 | struct spi_device; | ||
8 | |||
7 | extern phys_addr_t get_immrbase(void); | 9 | extern phys_addr_t get_immrbase(void); |
8 | #if defined(CONFIG_CPM2) || defined(CONFIG_QUICC_ENGINE) || defined(CONFIG_8xx) | 10 | #if defined(CONFIG_CPM2) || defined(CONFIG_QUICC_ENGINE) || defined(CONFIG_8xx) |
9 | extern u32 get_brgfreq(void); | 11 | extern u32 get_brgfreq(void); |
@@ -17,11 +19,6 @@ extern u32 fsl_get_sys_freq(void); | |||
17 | struct spi_board_info; | 19 | struct spi_board_info; |
18 | struct device_node; | 20 | struct device_node; |
19 | 21 | ||
20 | extern int fsl_spi_init(struct spi_board_info *board_infos, | ||
21 | unsigned int num_board_infos, | ||
22 | void (*activate_cs)(u8 cs, u8 polarity), | ||
23 | void (*deactivate_cs)(u8 cs, u8 polarity)); | ||
24 | |||
25 | extern void fsl_rstcr_restart(char *cmd); | 22 | extern void fsl_rstcr_restart(char *cmd); |
26 | 23 | ||
27 | #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) | 24 | #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) |
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 2a8af5e1634..dcb667c4375 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -72,6 +72,9 @@ config PGSTE | |||
72 | config VIRT_CPU_ACCOUNTING | 72 | config VIRT_CPU_ACCOUNTING |
73 | def_bool y | 73 | def_bool y |
74 | 74 | ||
75 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC | ||
76 | def_bool y | ||
77 | |||
75 | mainmenu "Linux Kernel Configuration" | 78 | mainmenu "Linux Kernel Configuration" |
76 | 79 | ||
77 | config S390 | 80 | config S390 |
diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug index 4599fa06bd8..7e297a3cde3 100644 --- a/arch/s390/Kconfig.debug +++ b/arch/s390/Kconfig.debug | |||
@@ -9,6 +9,7 @@ source "lib/Kconfig.debug" | |||
9 | config DEBUG_PAGEALLOC | 9 | config DEBUG_PAGEALLOC |
10 | bool "Debug page memory allocations" | 10 | bool "Debug page memory allocations" |
11 | depends on DEBUG_KERNEL | 11 | depends on DEBUG_KERNEL |
12 | depends on ARCH_SUPPORTS_DEBUG_PAGEALLOC | ||
12 | help | 13 | help |
13 | Unmap pages from the kernel linear mapping after free_pages(). | 14 | Unmap pages from the kernel linear mapping after free_pages(). |
14 | This results in a slowdown, but helps to find certain types of | 15 | This results in a slowdown, but helps to find certain types of |
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index c3ea215334f..cc12cd48bbc 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -124,6 +124,9 @@ config ARCH_NO_VIRT_TO_BUS | |||
124 | config OF | 124 | config OF |
125 | def_bool y | 125 | def_bool y |
126 | 126 | ||
127 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC | ||
128 | def_bool y if SPARC64 | ||
129 | |||
127 | source "init/Kconfig" | 130 | source "init/Kconfig" |
128 | 131 | ||
129 | source "kernel/Kconfig.freezer" | 132 | source "kernel/Kconfig.freezer" |
diff --git a/arch/sparc/Kconfig.debug b/arch/sparc/Kconfig.debug index b8a15e271bf..d001b42041a 100644 --- a/arch/sparc/Kconfig.debug +++ b/arch/sparc/Kconfig.debug | |||
@@ -24,7 +24,8 @@ config STACK_DEBUG | |||
24 | 24 | ||
25 | config DEBUG_PAGEALLOC | 25 | config DEBUG_PAGEALLOC |
26 | bool "Debug page memory allocations" | 26 | bool "Debug page memory allocations" |
27 | depends on SPARC64 && DEBUG_KERNEL && !HIBERNATION | 27 | depends on DEBUG_KERNEL && !HIBERNATION |
28 | depends on ARCH_SUPPORTS_DEBUG_PAGEALLOC | ||
28 | help | 29 | help |
29 | Unmap pages from the kernel linear mapping after free_pages(). | 30 | Unmap pages from the kernel linear mapping after free_pages(). |
30 | This results in a large slowdown, but helps to find certain types | 31 | This results in a large slowdown, but helps to find certain types |
diff --git a/arch/sparc/mm/highmem.c b/arch/sparc/mm/highmem.c index 752d0c9fb54..7916feba6e4 100644 --- a/arch/sparc/mm/highmem.c +++ b/arch/sparc/mm/highmem.c | |||
@@ -39,6 +39,7 @@ void *kmap_atomic(struct page *page, enum km_type type) | |||
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 | idx = type + KM_TYPE_NR*smp_processor_id(); | 43 | idx = type + KM_TYPE_NR*smp_processor_id(); |
43 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 44 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
44 | 45 | ||
diff --git a/arch/um/drivers/pcap_user.h b/arch/um/drivers/pcap_user.h index 96b80b565ee..d8ba6153f91 100644 --- a/arch/um/drivers/pcap_user.h +++ b/arch/um/drivers/pcap_user.h | |||
@@ -19,13 +19,3 @@ extern const struct net_user_info pcap_user_info; | |||
19 | 19 | ||
20 | extern int pcap_user_read(int fd, void *buf, int len, struct pcap_data *pri); | 20 | extern int pcap_user_read(int fd, void *buf, int len, struct pcap_data *pri); |
21 | 21 | ||
22 | /* | ||
23 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
24 | * Emacs will notice this stuff at the end of the file and automatically | ||
25 | * adjust the settings for this buffer only. This must remain at the end | ||
26 | * of the file. | ||
27 | * --------------------------------------------------------------------------- | ||
28 | * Local variables: | ||
29 | * c-file-style: "linux" | ||
30 | * End: | ||
31 | */ | ||
diff --git a/arch/um/drivers/port.h b/arch/um/drivers/port.h index 9117609a575..372a80c0556 100644 --- a/arch/um/drivers/port.h +++ b/arch/um/drivers/port.h | |||
@@ -18,13 +18,3 @@ extern void port_remove_dev(void *d); | |||
18 | 18 | ||
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | /* | ||
22 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
23 | * Emacs will notice this stuff at the end of the file and automatically | ||
24 | * adjust the settings for this buffer only. This must remain at the end | ||
25 | * of the file. | ||
26 | * --------------------------------------------------------------------------- | ||
27 | * Local variables: | ||
28 | * c-file-style: "linux" | ||
29 | * End: | ||
30 | */ | ||
diff --git a/arch/um/drivers/ssl.h b/arch/um/drivers/ssl.h index 98412aa6660..314d17725ce 100644 --- a/arch/um/drivers/ssl.h +++ b/arch/um/drivers/ssl.h | |||
@@ -11,13 +11,3 @@ extern void ssl_receive_char(int line, char ch); | |||
11 | 11 | ||
12 | #endif | 12 | #endif |
13 | 13 | ||
14 | /* | ||
15 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
16 | * Emacs will notice this stuff at the end of the file and automatically | ||
17 | * adjust the settings for this buffer only. This must remain at the end | ||
18 | * of the file. | ||
19 | * --------------------------------------------------------------------------- | ||
20 | * Local variables: | ||
21 | * c-file-style: "linux" | ||
22 | * End: | ||
23 | */ | ||
diff --git a/arch/um/drivers/stdio_console.h b/arch/um/drivers/stdio_console.h index 505a3d5bea5..6d8275f71fd 100644 --- a/arch/um/drivers/stdio_console.h +++ b/arch/um/drivers/stdio_console.h | |||
@@ -9,13 +9,3 @@ | |||
9 | extern void save_console_flags(void); | 9 | extern void save_console_flags(void); |
10 | #endif | 10 | #endif |
11 | 11 | ||
12 | /* | ||
13 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
14 | * Emacs will notice this stuff at the end of the file and automatically | ||
15 | * adjust the settings for this buffer only. This must remain at the end | ||
16 | * of the file. | ||
17 | * --------------------------------------------------------------------------- | ||
18 | * Local variables: | ||
19 | * c-file-style: "linux" | ||
20 | * End: | ||
21 | */ | ||
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 0a868118cf0..d42f826a8ab 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
@@ -17,7 +17,6 @@ | |||
17 | * James McMechan | 17 | * James McMechan |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #define MAJOR_NR UBD_MAJOR | ||
21 | #define UBD_SHIFT 4 | 20 | #define UBD_SHIFT 4 |
22 | 21 | ||
23 | #include "linux/kernel.h" | 22 | #include "linux/kernel.h" |
@@ -115,7 +114,7 @@ static struct block_device_operations ubd_blops = { | |||
115 | }; | 114 | }; |
116 | 115 | ||
117 | /* Protected by ubd_lock */ | 116 | /* Protected by ubd_lock */ |
118 | static int fake_major = MAJOR_NR; | 117 | static int fake_major = UBD_MAJOR; |
119 | static struct gendisk *ubd_gendisk[MAX_DEV]; | 118 | static struct gendisk *ubd_gendisk[MAX_DEV]; |
120 | static struct gendisk *fake_gendisk[MAX_DEV]; | 119 | static struct gendisk *fake_gendisk[MAX_DEV]; |
121 | 120 | ||
@@ -299,7 +298,7 @@ static int ubd_setup_common(char *str, int *index_out, char **error_out) | |||
299 | } | 298 | } |
300 | 299 | ||
301 | mutex_lock(&ubd_lock); | 300 | mutex_lock(&ubd_lock); |
302 | if(fake_major != MAJOR_NR){ | 301 | if (fake_major != UBD_MAJOR) { |
303 | *error_out = "Can't assign a fake major twice"; | 302 | *error_out = "Can't assign a fake major twice"; |
304 | goto out1; | 303 | goto out1; |
305 | } | 304 | } |
@@ -818,13 +817,13 @@ static int ubd_disk_register(int major, u64 size, int unit, | |||
818 | disk->first_minor = unit << UBD_SHIFT; | 817 | disk->first_minor = unit << UBD_SHIFT; |
819 | disk->fops = &ubd_blops; | 818 | disk->fops = &ubd_blops; |
820 | set_capacity(disk, size / 512); | 819 | set_capacity(disk, size / 512); |
821 | if(major == MAJOR_NR) | 820 | if (major == UBD_MAJOR) |
822 | sprintf(disk->disk_name, "ubd%c", 'a' + unit); | 821 | sprintf(disk->disk_name, "ubd%c", 'a' + unit); |
823 | else | 822 | else |
824 | sprintf(disk->disk_name, "ubd_fake%d", unit); | 823 | sprintf(disk->disk_name, "ubd_fake%d", unit); |
825 | 824 | ||
826 | /* sysfs register (not for ide fake devices) */ | 825 | /* sysfs register (not for ide fake devices) */ |
827 | if (major == MAJOR_NR) { | 826 | if (major == UBD_MAJOR) { |
828 | ubd_devs[unit].pdev.id = unit; | 827 | ubd_devs[unit].pdev.id = unit; |
829 | ubd_devs[unit].pdev.name = DRIVER_NAME; | 828 | ubd_devs[unit].pdev.name = DRIVER_NAME; |
830 | ubd_devs[unit].pdev.dev.release = ubd_device_release; | 829 | ubd_devs[unit].pdev.dev.release = ubd_device_release; |
@@ -871,13 +870,13 @@ static int ubd_add(int n, char **error_out) | |||
871 | ubd_dev->queue->queuedata = ubd_dev; | 870 | ubd_dev->queue->queuedata = ubd_dev; |
872 | 871 | ||
873 | blk_queue_max_hw_segments(ubd_dev->queue, MAX_SG); | 872 | blk_queue_max_hw_segments(ubd_dev->queue, MAX_SG); |
874 | err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); | 873 | err = ubd_disk_register(UBD_MAJOR, ubd_dev->size, n, &ubd_gendisk[n]); |
875 | if(err){ | 874 | if(err){ |
876 | *error_out = "Failed to register device"; | 875 | *error_out = "Failed to register device"; |
877 | goto out_cleanup; | 876 | goto out_cleanup; |
878 | } | 877 | } |
879 | 878 | ||
880 | if(fake_major != MAJOR_NR) | 879 | if (fake_major != UBD_MAJOR) |
881 | ubd_disk_register(fake_major, ubd_dev->size, n, | 880 | ubd_disk_register(fake_major, ubd_dev->size, n, |
882 | &fake_gendisk[n]); | 881 | &fake_gendisk[n]); |
883 | 882 | ||
@@ -1059,10 +1058,10 @@ static int __init ubd_init(void) | |||
1059 | char *error; | 1058 | char *error; |
1060 | int i, err; | 1059 | int i, err; |
1061 | 1060 | ||
1062 | if (register_blkdev(MAJOR_NR, "ubd")) | 1061 | if (register_blkdev(UBD_MAJOR, "ubd")) |
1063 | return -1; | 1062 | return -1; |
1064 | 1063 | ||
1065 | if (fake_major != MAJOR_NR) { | 1064 | if (fake_major != UBD_MAJOR) { |
1066 | char name[sizeof("ubd_nnn\0")]; | 1065 | char name[sizeof("ubd_nnn\0")]; |
1067 | 1066 | ||
1068 | snprintf(name, sizeof(name), "ubd_%d", fake_major); | 1067 | snprintf(name, sizeof(name), "ubd_%d", fake_major); |
diff --git a/arch/um/drivers/xterm.h b/arch/um/drivers/xterm.h index f33a6e77b18..56b9c4aba42 100644 --- a/arch/um/drivers/xterm.h +++ b/arch/um/drivers/xterm.h | |||
@@ -10,13 +10,3 @@ extern int xterm_fd(int socket, int *pid_out); | |||
10 | 10 | ||
11 | #endif | 11 | #endif |
12 | 12 | ||
13 | /* | ||
14 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
15 | * Emacs will notice this stuff at the end of the file and automatically | ||
16 | * adjust the settings for this buffer only. This must remain at the end | ||
17 | * of the file. | ||
18 | * --------------------------------------------------------------------------- | ||
19 | * Local variables: | ||
20 | * c-file-style: "linux" | ||
21 | * End: | ||
22 | */ | ||
diff --git a/arch/um/include/asm/irq_vectors.h b/arch/um/include/asm/irq_vectors.h index 62ddba6fc73..272a81e0ce1 100644 --- a/arch/um/include/asm/irq_vectors.h +++ b/arch/um/include/asm/irq_vectors.h | |||
@@ -8,13 +8,3 @@ | |||
8 | 8 | ||
9 | #endif | 9 | #endif |
10 | 10 | ||
11 | /* | ||
12 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
13 | * Emacs will notice this stuff at the end of the file and automatically | ||
14 | * adjust the settings for this buffer only. This must remain at the end | ||
15 | * of the file. | ||
16 | * --------------------------------------------------------------------------- | ||
17 | * Local variables: | ||
18 | * c-file-style: "linux" | ||
19 | * End: | ||
20 | */ | ||
diff --git a/arch/um/include/asm/mmu.h b/arch/um/include/asm/mmu.h index 2cf35c21d69..cf259de5153 100644 --- a/arch/um/include/asm/mmu.h +++ b/arch/um/include/asm/mmu.h | |||
@@ -10,13 +10,3 @@ | |||
10 | 10 | ||
11 | #endif | 11 | #endif |
12 | 12 | ||
13 | /* | ||
14 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
15 | * Emacs will notice this stuff at the end of the file and automatically | ||
16 | * adjust the settings for this buffer only. This must remain at the end | ||
17 | * of the file. | ||
18 | * --------------------------------------------------------------------------- | ||
19 | * Local variables: | ||
20 | * c-file-style: "linux" | ||
21 | * End: | ||
22 | */ | ||
diff --git a/arch/um/include/asm/pda.h b/arch/um/include/asm/pda.h index 0d8bf33ffd4..ddcd774fc2a 100644 --- a/arch/um/include/asm/pda.h +++ b/arch/um/include/asm/pda.h | |||
@@ -19,13 +19,3 @@ extern struct foo me; | |||
19 | 19 | ||
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | /* | ||
23 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
24 | * Emacs will notice this stuff at the end of the file and automatically | ||
25 | * adjust the settings for this buffer only. This must remain at the end | ||
26 | * of the file. | ||
27 | * --------------------------------------------------------------------------- | ||
28 | * Local variables: | ||
29 | * c-file-style: "linux" | ||
30 | * End: | ||
31 | */ | ||
diff --git a/arch/um/include/asm/pgalloc.h b/arch/um/include/asm/pgalloc.h index 9062a6e7224..718984359f8 100644 --- a/arch/um/include/asm/pgalloc.h +++ b/arch/um/include/asm/pgalloc.h | |||
@@ -60,13 +60,3 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | |||
60 | 60 | ||
61 | #endif | 61 | #endif |
62 | 62 | ||
63 | /* | ||
64 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
65 | * Emacs will notice this stuff at the end of the file and automatically | ||
66 | * adjust the settings for this buffer only. This must remain at the end | ||
67 | * of the file. | ||
68 | * --------------------------------------------------------------------------- | ||
69 | * Local variables: | ||
70 | * c-file-style: "linux" | ||
71 | * End: | ||
72 | */ | ||
diff --git a/arch/um/include/asm/pgtable-3level.h b/arch/um/include/asm/pgtable-3level.h index 0446f456b42..084de4a9fc7 100644 --- a/arch/um/include/asm/pgtable-3level.h +++ b/arch/um/include/asm/pgtable-3level.h | |||
@@ -134,13 +134,3 @@ static inline pmd_t pfn_pmd(pfn_t page_nr, pgprot_t pgprot) | |||
134 | 134 | ||
135 | #endif | 135 | #endif |
136 | 136 | ||
137 | /* | ||
138 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
139 | * Emacs will notice this stuff at the end of the file and automatically | ||
140 | * adjust the settings for this buffer only. This must remain at the end | ||
141 | * of the file. | ||
142 | * --------------------------------------------------------------------------- | ||
143 | * Local variables: | ||
144 | * c-file-style: "linux" | ||
145 | * End: | ||
146 | */ | ||
diff --git a/arch/um/include/shared/frame_kern.h b/arch/um/include/shared/frame_kern.h index ce9514f5721..76078490c25 100644 --- a/arch/um/include/shared/frame_kern.h +++ b/arch/um/include/shared/frame_kern.h | |||
@@ -20,13 +20,3 @@ extern int setup_signal_stack_si(unsigned long stack_top, int sig, | |||
20 | 20 | ||
21 | #endif | 21 | #endif |
22 | 22 | ||
23 | /* | ||
24 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
25 | * Emacs will notice this stuff at the end of the file and automatically | ||
26 | * adjust the settings for this buffer only. This must remain at the end | ||
27 | * of the file. | ||
28 | * --------------------------------------------------------------------------- | ||
29 | * Local variables: | ||
30 | * c-file-style: "linux" | ||
31 | * End: | ||
32 | */ | ||
diff --git a/arch/um/include/shared/initrd.h b/arch/um/include/shared/initrd.h index 439b9a81498..22673bcc273 100644 --- a/arch/um/include/shared/initrd.h +++ b/arch/um/include/shared/initrd.h | |||
@@ -10,13 +10,3 @@ extern int load_initrd(char *filename, void *buf, int size); | |||
10 | 10 | ||
11 | #endif | 11 | #endif |
12 | 12 | ||
13 | /* | ||
14 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
15 | * Emacs will notice this stuff at the end of the file and automatically | ||
16 | * adjust the settings for this buffer only. This must remain at the end | ||
17 | * of the file. | ||
18 | * --------------------------------------------------------------------------- | ||
19 | * Local variables: | ||
20 | * c-file-style: "linux" | ||
21 | * End: | ||
22 | */ | ||
diff --git a/arch/um/include/shared/irq_kern.h b/arch/um/include/shared/irq_kern.h index fba3895274f..b05d22f3d84 100644 --- a/arch/um/include/shared/irq_kern.h +++ b/arch/um/include/shared/irq_kern.h | |||
@@ -16,13 +16,3 @@ extern int um_request_irq(unsigned int irq, int fd, int type, | |||
16 | 16 | ||
17 | #endif | 17 | #endif |
18 | 18 | ||
19 | /* | ||
20 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
21 | * Emacs will notice this stuff at the end of the file and automatically | ||
22 | * adjust the settings for this buffer only. This must remain at the end | ||
23 | * of the file. | ||
24 | * --------------------------------------------------------------------------- | ||
25 | * Local variables: | ||
26 | * c-file-style: "linux" | ||
27 | * End: | ||
28 | */ | ||
diff --git a/arch/um/include/shared/mem_kern.h b/arch/um/include/shared/mem_kern.h index cb7e196d366..69be0fd0ce4 100644 --- a/arch/um/include/shared/mem_kern.h +++ b/arch/um/include/shared/mem_kern.h | |||
@@ -18,13 +18,3 @@ extern void register_remapper(struct remapper *info); | |||
18 | 18 | ||
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | /* | ||
22 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
23 | * Emacs will notice this stuff at the end of the file and automatically | ||
24 | * adjust the settings for this buffer only. This must remain at the end | ||
25 | * of the file. | ||
26 | * --------------------------------------------------------------------------- | ||
27 | * Local variables: | ||
28 | * c-file-style: "linux" | ||
29 | * End: | ||
30 | */ | ||
diff --git a/arch/um/include/shared/ubd_user.h b/arch/um/include/shared/ubd_user.h index bb66517f073..3845051f1b1 100644 --- a/arch/um/include/shared/ubd_user.h +++ b/arch/um/include/shared/ubd_user.h | |||
@@ -14,13 +14,3 @@ extern int kernel_fd; | |||
14 | 14 | ||
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | /* | ||
18 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
19 | * Emacs will notice this stuff at the end of the file and automatically | ||
20 | * adjust the settings for this buffer only. This must remain at the end | ||
21 | * of the file. | ||
22 | * --------------------------------------------------------------------------- | ||
23 | * Local variables: | ||
24 | * c-file-style: "linux" | ||
25 | * End: | ||
26 | */ | ||
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 499e5e95e60..388ec0a3ea9 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile | |||
@@ -28,7 +28,7 @@ $(obj)/config.tmp: $(objtree)/.config FORCE | |||
28 | $(call if_changed,quote1) | 28 | $(call if_changed,quote1) |
29 | 29 | ||
30 | quiet_cmd_quote1 = QUOTE $@ | 30 | quiet_cmd_quote1 = QUOTE $@ |
31 | cmd_quote1 = sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' \ | 31 | cmd_quote1 = sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n",/' \ |
32 | $< > $@ | 32 | $< > $@ |
33 | 33 | ||
34 | $(obj)/config.c: $(src)/config.c.in $(obj)/config.tmp FORCE | 34 | $(obj)/config.c: $(src)/config.c.in $(obj)/config.tmp FORCE |
@@ -36,9 +36,9 @@ $(obj)/config.c: $(src)/config.c.in $(obj)/config.tmp FORCE | |||
36 | 36 | ||
37 | quiet_cmd_quote2 = QUOTE $@ | 37 | quiet_cmd_quote2 = QUOTE $@ |
38 | cmd_quote2 = sed -e '/CONFIG/{' \ | 38 | cmd_quote2 = sed -e '/CONFIG/{' \ |
39 | -e 's/"CONFIG"\;/""/' \ | 39 | -e 's/"CONFIG"//' \ |
40 | -e 'r $(obj)/config.tmp' \ | 40 | -e 'r $(obj)/config.tmp' \ |
41 | -e 'a \' \ | 41 | -e 'a \' \ |
42 | -e '""\;' \ | 42 | -e '""' \ |
43 | -e '}' \ | 43 | -e '}' \ |
44 | $< > $@ | 44 | $< > $@ |
diff --git a/arch/um/kernel/config.c.in b/arch/um/kernel/config.c.in index c062cbfe386..b7a43feafde 100644 --- a/arch/um/kernel/config.c.in +++ b/arch/um/kernel/config.c.in | |||
@@ -7,11 +7,15 @@ | |||
7 | #include <stdlib.h> | 7 | #include <stdlib.h> |
8 | #include "init.h" | 8 | #include "init.h" |
9 | 9 | ||
10 | static __initdata char *config = "CONFIG"; | 10 | static __initdata const char *config[] = { |
11 | "CONFIG" | ||
12 | }; | ||
11 | 13 | ||
12 | static int __init print_config(char *line, int *add) | 14 | static int __init print_config(char *line, int *add) |
13 | { | 15 | { |
14 | printf("%s", config); | 16 | int i; |
17 | for (i = 0; i < sizeof(config)/sizeof(config[0]); i++) | ||
18 | printf("%s", config[i]); | ||
15 | exit(0); | 19 | exit(0); |
16 | } | 20 | } |
17 | 21 | ||
@@ -20,13 +24,3 @@ __uml_setup("--showconfig", print_config, | |||
20 | " Prints the config file that this UML binary was generated from.\n\n" | 24 | " Prints the config file that this UML binary was generated from.\n\n" |
21 | ); | 25 | ); |
22 | 26 | ||
23 | /* | ||
24 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
25 | * Emacs will notice this stuff at the end of the file and automatically | ||
26 | * adjust the settings for this buffer only. This must remain at the end | ||
27 | * of the file. | ||
28 | * --------------------------------------------------------------------------- | ||
29 | * Local variables: | ||
30 | * c-file-style: "linux" | ||
31 | * End: | ||
32 | */ | ||
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 183db26d01b..02ee9adff54 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c | |||
@@ -244,7 +244,7 @@ static void __init check_sysemu(void) | |||
244 | 244 | ||
245 | if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, | 245 | if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0, |
246 | (void *) PTRACE_O_TRACESYSGOOD) < 0)) | 246 | (void *) PTRACE_O_TRACESYSGOOD) < 0)) |
247 | fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed"); | 247 | fatal_perror("check_sysemu: PTRACE_OLDSETOPTIONS failed"); |
248 | 248 | ||
249 | while (1) { | 249 | while (1) { |
250 | count++; | 250 | count++; |
@@ -252,12 +252,12 @@ static void __init check_sysemu(void) | |||
252 | goto fail; | 252 | goto fail; |
253 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | 253 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); |
254 | if (n < 0) | 254 | if (n < 0) |
255 | fatal_perror("check_ptrace : wait failed"); | 255 | fatal_perror("check_sysemu: wait failed"); |
256 | 256 | ||
257 | if (WIFSTOPPED(status) && | 257 | if (WIFSTOPPED(status) && |
258 | (WSTOPSIG(status) == (SIGTRAP|0x80))) { | 258 | (WSTOPSIG(status) == (SIGTRAP|0x80))) { |
259 | if (!count) { | 259 | if (!count) { |
260 | non_fatal("check_ptrace : SYSEMU_SINGLESTEP " | 260 | non_fatal("check_sysemu: SYSEMU_SINGLESTEP " |
261 | "doesn't singlestep"); | 261 | "doesn't singlestep"); |
262 | goto fail; | 262 | goto fail; |
263 | } | 263 | } |
@@ -271,7 +271,7 @@ static void __init check_sysemu(void) | |||
271 | else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) | 271 | else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) |
272 | count++; | 272 | count++; |
273 | else { | 273 | else { |
274 | non_fatal("check_ptrace : expected SIGTRAP or " | 274 | non_fatal("check_sysemu: expected SIGTRAP or " |
275 | "(SIGTRAP | 0x80), got status = %d\n", | 275 | "(SIGTRAP | 0x80), got status = %d\n", |
276 | status); | 276 | status); |
277 | goto fail; | 277 | goto fail; |
diff --git a/arch/um/sys-i386/asm/archparam.h b/arch/um/sys-i386/asm/archparam.h index 93fd723344e..2a18a884ca1 100644 --- a/arch/um/sys-i386/asm/archparam.h +++ b/arch/um/sys-i386/asm/archparam.h | |||
@@ -14,13 +14,3 @@ | |||
14 | 14 | ||
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | /* | ||
18 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
19 | * Emacs will notice this stuff at the end of the file and automatically | ||
20 | * adjust the settings for this buffer only. This must remain at the end | ||
21 | * of the file. | ||
22 | * --------------------------------------------------------------------------- | ||
23 | * Local variables: | ||
24 | * c-file-style: "linux" | ||
25 | * End: | ||
26 | */ | ||
diff --git a/arch/um/sys-i386/shared/sysdep/checksum.h b/arch/um/sys-i386/shared/sysdep/checksum.h index 0cb4645cbeb..ed47445f390 100644 --- a/arch/um/sys-i386/shared/sysdep/checksum.h +++ b/arch/um/sys-i386/shared/sysdep/checksum.h | |||
@@ -199,13 +199,3 @@ static __inline__ __wsum csum_and_copy_to_user(const void *src, | |||
199 | 199 | ||
200 | #endif | 200 | #endif |
201 | 201 | ||
202 | /* | ||
203 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
204 | * Emacs will notice this stuff at the end of the file and automatically | ||
205 | * adjust the settings for this buffer only. This must remain at the end | ||
206 | * of the file. | ||
207 | * --------------------------------------------------------------------------- | ||
208 | * Local variables: | ||
209 | * c-file-style: "linux" | ||
210 | * End: | ||
211 | */ | ||
diff --git a/arch/um/sys-ia64/sysdep/ptrace.h b/arch/um/sys-ia64/sysdep/ptrace.h index 42dd8fb6f2f..0f0f4e6fd33 100644 --- a/arch/um/sys-ia64/sysdep/ptrace.h +++ b/arch/um/sys-ia64/sysdep/ptrace.h | |||
@@ -14,13 +14,3 @@ struct sys_pt_regs { | |||
14 | 14 | ||
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | /* | ||
18 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
19 | * Emacs will notice this stuff at the end of the file and automatically | ||
20 | * adjust the settings for this buffer only. This must remain at the end | ||
21 | * of the file. | ||
22 | * --------------------------------------------------------------------------- | ||
23 | * Local variables: | ||
24 | * c-file-style: "linux" | ||
25 | * End: | ||
26 | */ | ||
diff --git a/arch/um/sys-ia64/sysdep/sigcontext.h b/arch/um/sys-ia64/sysdep/sigcontext.h index f15fb25260b..76b43161e77 100644 --- a/arch/um/sys-ia64/sysdep/sigcontext.h +++ b/arch/um/sys-ia64/sysdep/sigcontext.h | |||
@@ -8,13 +8,3 @@ | |||
8 | 8 | ||
9 | #endif | 9 | #endif |
10 | 10 | ||
11 | /* | ||
12 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
13 | * Emacs will notice this stuff at the end of the file and automatically | ||
14 | * adjust the settings for this buffer only. This must remain at the end | ||
15 | * of the file. | ||
16 | * --------------------------------------------------------------------------- | ||
17 | * Local variables: | ||
18 | * c-file-style: "linux" | ||
19 | * End: | ||
20 | */ | ||
diff --git a/arch/um/sys-ia64/sysdep/syscalls.h b/arch/um/sys-ia64/sysdep/syscalls.h index 4a1f46ef1eb..5f6700c4155 100644 --- a/arch/um/sys-ia64/sysdep/syscalls.h +++ b/arch/um/sys-ia64/sysdep/syscalls.h | |||
@@ -8,13 +8,3 @@ | |||
8 | 8 | ||
9 | #endif | 9 | #endif |
10 | 10 | ||
11 | /* | ||
12 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
13 | * Emacs will notice this stuff at the end of the file and automatically | ||
14 | * adjust the settings for this buffer only. This must remain at the end | ||
15 | * of the file. | ||
16 | * --------------------------------------------------------------------------- | ||
17 | * Local variables: | ||
18 | * c-file-style: "linux" | ||
19 | * End: | ||
20 | */ | ||
diff --git a/arch/um/sys-ppc/miscthings.c b/arch/um/sys-ppc/miscthings.c index 373061c5012..1c11aed9c71 100644 --- a/arch/um/sys-ppc/miscthings.c +++ b/arch/um/sys-ppc/miscthings.c | |||
@@ -40,14 +40,3 @@ void shove_aux_table(unsigned long sp) | |||
40 | } | 40 | } |
41 | /* END stuff taken from arch/ppc/kernel/process.c */ | 41 | /* END stuff taken from arch/ppc/kernel/process.c */ |
42 | 42 | ||
43 | |||
44 | /* | ||
45 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
46 | * Emacs will notice this stuff at the end of the file and automatically | ||
47 | * adjust the settings for this buffer only. This must remain at the end | ||
48 | * of the file. | ||
49 | * --------------------------------------------------------------------------- | ||
50 | * Local variables: | ||
51 | * c-file-style: "linux" | ||
52 | * End: | ||
53 | */ | ||
diff --git a/arch/um/sys-ppc/ptrace.c b/arch/um/sys-ppc/ptrace.c index 8e71b47f2b8..66ef155248f 100644 --- a/arch/um/sys-ppc/ptrace.c +++ b/arch/um/sys-ppc/ptrace.c | |||
@@ -56,13 +56,3 @@ int peek_user(struct task_struct *child, long addr, long data) | |||
56 | return put_user(tmp, (unsigned long *) data); | 56 | return put_user(tmp, (unsigned long *) data); |
57 | } | 57 | } |
58 | 58 | ||
59 | /* | ||
60 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
61 | * Emacs will notice this stuff at the end of the file and automatically | ||
62 | * adjust the settings for this buffer only. This must remain at the end | ||
63 | * of the file. | ||
64 | * --------------------------------------------------------------------------- | ||
65 | * Local variables: | ||
66 | * c-file-style: "linux" | ||
67 | * End: | ||
68 | */ | ||
diff --git a/arch/um/sys-ppc/ptrace_user.c b/arch/um/sys-ppc/ptrace_user.c index ff0b9c077a1..224d2403c37 100644 --- a/arch/um/sys-ppc/ptrace_user.c +++ b/arch/um/sys-ppc/ptrace_user.c | |||
@@ -27,13 +27,3 @@ int ptrace_setregs(long pid, unsigned long *regs_in) | |||
27 | } | 27 | } |
28 | return 0; | 28 | return 0; |
29 | } | 29 | } |
30 | /* | ||
31 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
32 | * Emacs will notice this stuff at the end of the file and automatically | ||
33 | * adjust the settings for this buffer only. This must remain at the end | ||
34 | * of the file. | ||
35 | * --------------------------------------------------------------------------- | ||
36 | * Local variables: | ||
37 | * c-file-style: "linux" | ||
38 | * End: | ||
39 | */ | ||
diff --git a/arch/um/sys-ppc/shared/sysdep/ptrace.h b/arch/um/sys-ppc/shared/sysdep/ptrace.h index df2397dba3e..0e3230e937e 100644 --- a/arch/um/sys-ppc/shared/sysdep/ptrace.h +++ b/arch/um/sys-ppc/shared/sysdep/ptrace.h | |||
@@ -91,13 +91,3 @@ extern void shove_aux_table(unsigned long sp); | |||
91 | 91 | ||
92 | #endif | 92 | #endif |
93 | 93 | ||
94 | /* | ||
95 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
96 | * Emacs will notice this stuff at the end of the file and automatically | ||
97 | * adjust the settings for this buffer only. This must remain at the end | ||
98 | * of the file. | ||
99 | * --------------------------------------------------------------------------- | ||
100 | * Local variables: | ||
101 | * c-file-style: "linux" | ||
102 | * End: | ||
103 | */ | ||
diff --git a/arch/um/sys-ppc/shared/sysdep/sigcontext.h b/arch/um/sys-ppc/shared/sysdep/sigcontext.h index f20d965de9c..b7286f0a1e0 100644 --- a/arch/um/sys-ppc/shared/sysdep/sigcontext.h +++ b/arch/um/sys-ppc/shared/sysdep/sigcontext.h | |||
@@ -50,13 +50,3 @@ | |||
50 | 50 | ||
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | /* | ||
54 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
55 | * Emacs will notice this stuff at the end of the file and automatically | ||
56 | * adjust the settings for this buffer only. This must remain at the end | ||
57 | * of the file. | ||
58 | * --------------------------------------------------------------------------- | ||
59 | * Local variables: | ||
60 | * c-file-style: "linux" | ||
61 | * End: | ||
62 | */ | ||
diff --git a/arch/um/sys-ppc/shared/sysdep/syscalls.h b/arch/um/sys-ppc/shared/sysdep/syscalls.h index 679df351e19..1ff81552251 100644 --- a/arch/um/sys-ppc/shared/sysdep/syscalls.h +++ b/arch/um/sys-ppc/shared/sysdep/syscalls.h | |||
@@ -41,13 +41,3 @@ int old_mmap(unsigned long addr, unsigned long len, | |||
41 | 41 | ||
42 | #define LAST_ARCH_SYSCALL __NR_fadvise64 | 42 | #define LAST_ARCH_SYSCALL __NR_fadvise64 |
43 | 43 | ||
44 | /* | ||
45 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
46 | * Emacs will notice this stuff at the end of the file and automatically | ||
47 | * adjust the settings for this buffer only. This must remain at the end | ||
48 | * of the file. | ||
49 | * --------------------------------------------------------------------------- | ||
50 | * Local variables: | ||
51 | * c-file-style: "linux" | ||
52 | * End: | ||
53 | */ | ||
diff --git a/arch/um/sys-ppc/sigcontext.c b/arch/um/sys-ppc/sigcontext.c index 4bdc15c89ed..40694d0f3d1 100644 --- a/arch/um/sys-ppc/sigcontext.c +++ b/arch/um/sys-ppc/sigcontext.c | |||
@@ -2,13 +2,3 @@ | |||
2 | #include "asm/sigcontext.h" | 2 | #include "asm/sigcontext.h" |
3 | #include "sysdep/ptrace.h" | 3 | #include "sysdep/ptrace.h" |
4 | 4 | ||
5 | /* | ||
6 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
7 | * Emacs will notice this stuff at the end of the file and automatically | ||
8 | * adjust the settings for this buffer only. This must remain at the end | ||
9 | * of the file. | ||
10 | * --------------------------------------------------------------------------- | ||
11 | * Local variables: | ||
12 | * c-file-style: "linux" | ||
13 | * End: | ||
14 | */ | ||
diff --git a/arch/um/sys-x86_64/asm/archparam.h b/arch/um/sys-x86_64/asm/archparam.h index 270ed9586b6..6c083663b8d 100644 --- a/arch/um/sys-x86_64/asm/archparam.h +++ b/arch/um/sys-x86_64/asm/archparam.h | |||
@@ -14,13 +14,3 @@ | |||
14 | 14 | ||
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | /* | ||
18 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
19 | * Emacs will notice this stuff at the end of the file and automatically | ||
20 | * adjust the settings for this buffer only. This must remain at the end | ||
21 | * of the file. | ||
22 | * --------------------------------------------------------------------------- | ||
23 | * Local variables: | ||
24 | * c-file-style: "linux" | ||
25 | * End: | ||
26 | */ | ||
diff --git a/arch/um/sys-x86_64/asm/module.h b/arch/um/sys-x86_64/asm/module.h index 35b5491d3e9..8eb79c2d07d 100644 --- a/arch/um/sys-x86_64/asm/module.h +++ b/arch/um/sys-x86_64/asm/module.h | |||
@@ -18,13 +18,3 @@ struct mod_arch_specific | |||
18 | 18 | ||
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | /* | ||
22 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
23 | * Emacs will notice this stuff at the end of the file and automatically | ||
24 | * adjust the settings for this buffer only. This must remain at the end | ||
25 | * of the file. | ||
26 | * --------------------------------------------------------------------------- | ||
27 | * Local variables: | ||
28 | * c-file-style: "linux" | ||
29 | * End: | ||
30 | */ | ||
diff --git a/arch/um/sys-x86_64/mem.c b/arch/um/sys-x86_64/mem.c index 3f59a0a4f15..3f8df8abf34 100644 --- a/arch/um/sys-x86_64/mem.c +++ b/arch/um/sys-x86_64/mem.c | |||
@@ -14,12 +14,3 @@ unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS; | |||
14 | unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS; | 14 | unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS; |
15 | unsigned long vm_force_exec32 = PROT_EXEC; | 15 | unsigned long vm_force_exec32 = PROT_EXEC; |
16 | 16 | ||
17 | /* Overrides for Emacs so that we follow Linus's tabbing style. | ||
18 | * Emacs will notice this stuff at the end of the file and automatically | ||
19 | * adjust the settings for this buffer only. This must remain at the end | ||
20 | * of the file. | ||
21 | * --------------------------------------------------------------------------- | ||
22 | * Local variables: | ||
23 | * c-file-style: "linux" | ||
24 | * End: | ||
25 | */ | ||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 45161b81631..748e50a1a15 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -165,6 +165,9 @@ config AUDIT_ARCH | |||
165 | config ARCH_SUPPORTS_OPTIMIZED_INLINING | 165 | config ARCH_SUPPORTS_OPTIMIZED_INLINING |
166 | def_bool y | 166 | def_bool y |
167 | 167 | ||
168 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC | ||
169 | def_bool y | ||
170 | |||
168 | # Use the generic interrupt handling code in kernel/irq/: | 171 | # Use the generic interrupt handling code in kernel/irq/: |
169 | config GENERIC_HARDIRQS | 172 | config GENERIC_HARDIRQS |
170 | bool | 173 | bool |
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index fdb45df608b..a345cb5447a 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug | |||
@@ -75,6 +75,7 @@ config DEBUG_STACK_USAGE | |||
75 | config DEBUG_PAGEALLOC | 75 | config DEBUG_PAGEALLOC |
76 | bool "Debug page memory allocations" | 76 | bool "Debug page memory allocations" |
77 | depends on DEBUG_KERNEL | 77 | depends on DEBUG_KERNEL |
78 | depends on ARCH_SUPPORTS_DEBUG_PAGEALLOC | ||
78 | ---help--- | 79 | ---help--- |
79 | Unmap pages from the kernel linear mapping after free_pages(). | 80 | Unmap pages from the kernel linear mapping after free_pages(). |
80 | This results in a large slowdown, but helps to find certain types | 81 | This results in a large slowdown, but helps to find certain types |
diff --git a/arch/x86/include/asm/suspend_32.h b/arch/x86/include/asm/suspend_32.h index a5074bd0f8b..48dcfa62ea0 100644 --- a/arch/x86/include/asm/suspend_32.h +++ b/arch/x86/include/asm/suspend_32.h | |||
@@ -24,28 +24,4 @@ struct saved_context { | |||
24 | unsigned long return_address; | 24 | unsigned long return_address; |
25 | } __attribute__((packed)); | 25 | } __attribute__((packed)); |
26 | 26 | ||
27 | #ifdef CONFIG_ACPI | ||
28 | extern unsigned long saved_eip; | ||
29 | extern unsigned long saved_esp; | ||
30 | extern unsigned long saved_ebp; | ||
31 | extern unsigned long saved_ebx; | ||
32 | extern unsigned long saved_esi; | ||
33 | extern unsigned long saved_edi; | ||
34 | |||
35 | static inline void acpi_save_register_state(unsigned long return_point) | ||
36 | { | ||
37 | saved_eip = return_point; | ||
38 | asm volatile("movl %%esp,%0" : "=m" (saved_esp)); | ||
39 | asm volatile("movl %%ebp,%0" : "=m" (saved_ebp)); | ||
40 | asm volatile("movl %%ebx,%0" : "=m" (saved_ebx)); | ||
41 | asm volatile("movl %%edi,%0" : "=m" (saved_edi)); | ||
42 | asm volatile("movl %%esi,%0" : "=m" (saved_esi)); | ||
43 | } | ||
44 | |||
45 | #define acpi_restore_register_state() do {} while (0) | ||
46 | |||
47 | /* routines for saving/restoring kernel state */ | ||
48 | extern int acpi_save_state_mem(void); | ||
49 | #endif | ||
50 | |||
51 | #endif /* _ASM_X86_SUSPEND_32_H */ | 27 | #endif /* _ASM_X86_SUSPEND_32_H */ |
diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c index fbf2f33e308..5a6aa1c1162 100644 --- a/arch/x86/kernel/asm-offsets_32.c +++ b/arch/x86/kernel/asm-offsets_32.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/thread_info.h> | 18 | #include <asm/thread_info.h> |
19 | #include <asm/bootparam.h> | 19 | #include <asm/bootparam.h> |
20 | #include <asm/elf.h> | 20 | #include <asm/elf.h> |
21 | #include <asm/suspend.h> | ||
21 | 22 | ||
22 | #include <xen/interface/xen.h> | 23 | #include <xen/interface/xen.h> |
23 | 24 | ||
diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 8793ab33e2c..e72f062fb4b 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <asm/thread_info.h> | 16 | #include <asm/thread_info.h> |
17 | #include <asm/ia32.h> | 17 | #include <asm/ia32.h> |
18 | #include <asm/bootparam.h> | 18 | #include <asm/bootparam.h> |
19 | #include <asm/suspend.h> | ||
19 | 20 | ||
20 | #include <xen/interface/xen.h> | 21 | #include <xen/interface/xen.h> |
21 | 22 | ||
diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c index 522db5e3d0b..5bc5d1688c1 100644 --- a/arch/x86/mm/highmem_32.c +++ b/arch/x86/mm/highmem_32.c | |||
@@ -19,49 +19,6 @@ void kunmap(struct page *page) | |||
19 | kunmap_high(page); | 19 | kunmap_high(page); |
20 | } | 20 | } |
21 | 21 | ||
22 | static void debug_kmap_atomic_prot(enum km_type type) | ||
23 | { | ||
24 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
25 | static unsigned warn_count = 10; | ||
26 | |||
27 | if (unlikely(warn_count == 0)) | ||
28 | return; | ||
29 | |||
30 | if (unlikely(in_interrupt())) { | ||
31 | if (in_irq()) { | ||
32 | if (type != KM_IRQ0 && type != KM_IRQ1 && | ||
33 | type != KM_BIO_SRC_IRQ && type != KM_BIO_DST_IRQ && | ||
34 | type != KM_BOUNCE_READ) { | ||
35 | WARN_ON(1); | ||
36 | warn_count--; | ||
37 | } | ||
38 | } else if (!irqs_disabled()) { /* softirq */ | ||
39 | if (type != KM_IRQ0 && type != KM_IRQ1 && | ||
40 | type != KM_SOFTIRQ0 && type != KM_SOFTIRQ1 && | ||
41 | type != KM_SKB_SUNRPC_DATA && | ||
42 | type != KM_SKB_DATA_SOFTIRQ && | ||
43 | type != KM_BOUNCE_READ) { | ||
44 | WARN_ON(1); | ||
45 | warn_count--; | ||
46 | } | ||
47 | } | ||
48 | } | ||
49 | |||
50 | if (type == KM_IRQ0 || type == KM_IRQ1 || type == KM_BOUNCE_READ || | ||
51 | type == KM_BIO_SRC_IRQ || type == KM_BIO_DST_IRQ) { | ||
52 | if (!irqs_disabled()) { | ||
53 | WARN_ON(1); | ||
54 | warn_count--; | ||
55 | } | ||
56 | } else if (type == KM_SOFTIRQ0 || type == KM_SOFTIRQ1) { | ||
57 | if (irq_count() == 0 && !irqs_disabled()) { | ||
58 | WARN_ON(1); | ||
59 | warn_count--; | ||
60 | } | ||
61 | } | ||
62 | #endif | ||
63 | } | ||
64 | |||
65 | /* | 22 | /* |
66 | * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because | 23 | * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because |
67 | * no global lock is needed and because the kmap code must perform a global TLB | 24 | * no global lock is needed and because the kmap code must perform a global TLB |
@@ -81,8 +38,9 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | |||
81 | if (!PageHighMem(page)) | 38 | if (!PageHighMem(page)) |
82 | return page_address(page); | 39 | return page_address(page); |
83 | 40 | ||
84 | debug_kmap_atomic_prot(type); | 41 | debug_kmap_atomic(type); |
85 | 42 | ||
43 | debug_kmap_atomic(type); | ||
86 | idx = type + KM_TYPE_NR*smp_processor_id(); | 44 | idx = type + KM_TYPE_NR*smp_processor_id(); |
87 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 45 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
88 | BUG_ON(!pte_none(*(kmap_pte-idx))); | 46 | BUG_ON(!pte_none(*(kmap_pte-idx))); |
diff --git a/arch/x86/mm/iomap_32.c b/arch/x86/mm/iomap_32.c index 699c9b2895a..bff0c9032f8 100644 --- a/arch/x86/mm/iomap_32.c +++ b/arch/x86/mm/iomap_32.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/iomap.h> | 19 | #include <asm/iomap.h> |
20 | #include <asm/pat.h> | 20 | #include <asm/pat.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/highmem.h> | ||
22 | 23 | ||
23 | int is_io_mapping_possible(resource_size_t base, unsigned long size) | 24 | int is_io_mapping_possible(resource_size_t base, unsigned long size) |
24 | { | 25 | { |
@@ -71,6 +72,7 @@ iounmap_atomic(void *kvaddr, enum km_type type) | |||
71 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; | 72 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; |
72 | enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); | 73 | enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); |
73 | 74 | ||
75 | debug_kmap_atomic(type); | ||
74 | /* | 76 | /* |
75 | * Force other mappings to Oops if they'll try to access this pte | 77 | * Force other mappings to Oops if they'll try to access this pte |
76 | * without first remap it. Keeping stale mappings around is a bad idea | 78 | * without first remap it. Keeping stale mappings around is a bad idea |
diff --git a/arch/x86/power/cpu_32.c b/arch/x86/power/cpu_32.c index 274d06082f4..ce702c5b3a2 100644 --- a/arch/x86/power/cpu_32.c +++ b/arch/x86/power/cpu_32.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <asm/mtrr.h> | 12 | #include <asm/mtrr.h> |
13 | #include <asm/mce.h> | 13 | #include <asm/mce.h> |
14 | #include <asm/xcr.h> | 14 | #include <asm/xcr.h> |
15 | #include <asm/suspend.h> | ||
15 | 16 | ||
16 | static struct saved_context saved_context; | 17 | static struct saved_context saved_context; |
17 | 18 | ||
diff --git a/arch/x86/power/cpu_64.c b/arch/x86/power/cpu_64.c index e3b6cf70d62..5343540f260 100644 --- a/arch/x86/power/cpu_64.c +++ b/arch/x86/power/cpu_64.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <asm/pgtable.h> | 15 | #include <asm/pgtable.h> |
16 | #include <asm/mtrr.h> | 16 | #include <asm/mtrr.h> |
17 | #include <asm/xcr.h> | 17 | #include <asm/xcr.h> |
18 | #include <asm/suspend.h> | ||
18 | 19 | ||
19 | static void fix_processor_context(void); | 20 | static void fix_processor_context(void); |
20 | 21 | ||
diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c index 6dd000dd793..65fdc86e923 100644 --- a/arch/x86/power/hibernate_64.c +++ b/arch/x86/power/hibernate_64.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <asm/page.h> | 14 | #include <asm/page.h> |
15 | #include <asm/pgtable.h> | 15 | #include <asm/pgtable.h> |
16 | #include <asm/mtrr.h> | 16 | #include <asm/mtrr.h> |
17 | #include <asm/suspend.h> | ||
17 | 18 | ||
18 | /* References to section boundaries */ | 19 | /* References to section boundaries */ |
19 | extern const void __nosave_begin, __nosave_end; | 20 | extern const void __nosave_begin, __nosave_end; |
diff --git a/arch/xtensa/platforms/iss/console.c b/arch/xtensa/platforms/iss/console.c index 25d46c84eb0..4c559cf7da2 100644 --- a/arch/xtensa/platforms/iss/console.c +++ b/arch/xtensa/platforms/iss/console.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | #include <linux/major.h> | 19 | #include <linux/major.h> |
20 | #include <linux/param.h> | 20 | #include <linux/param.h> |
21 | #include <linux/seq_file.h> | ||
21 | #include <linux/serial.h> | 22 | #include <linux/serial.h> |
22 | #include <linux/serialP.h> | 23 | #include <linux/serialP.h> |
23 | 24 | ||
@@ -176,22 +177,24 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
176 | /* Stub, once again.. */ | 177 | /* Stub, once again.. */ |
177 | } | 178 | } |
178 | 179 | ||
179 | static int rs_read_proc(char *page, char **start, off_t off, int count, | 180 | static int rs_proc_show(struct seq_file *m, void *v) |
180 | int *eof, void *data) | ||
181 | { | 181 | { |
182 | int len = 0; | 182 | seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version); |
183 | off_t begin = 0; | 183 | return 0; |
184 | 184 | } | |
185 | len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version); | ||
186 | *eof = 1; | ||
187 | |||
188 | if (off >= len + begin) | ||
189 | return 0; | ||
190 | 185 | ||
191 | *start = page + (off - begin); | 186 | static int rs_proc_open(struct inode *inode, struct file *file) |
192 | return ((count < begin + len - off) ? count : begin + len - off); | 187 | { |
188 | return single_open(file, rs_proc_show, NULL); | ||
193 | } | 189 | } |
194 | 190 | ||
191 | static const struct file_operations rs_proc_fops = { | ||
192 | .owner = THIS_MODULE, | ||
193 | .open = rs_proc_open, | ||
194 | .read = seq_read, | ||
195 | .llseek = seq_lseek, | ||
196 | .release = single_release, | ||
197 | }; | ||
195 | 198 | ||
196 | static struct tty_operations serial_ops = { | 199 | static struct tty_operations serial_ops = { |
197 | .open = rs_open, | 200 | .open = rs_open, |
@@ -203,7 +206,7 @@ static struct tty_operations serial_ops = { | |||
203 | .chars_in_buffer = rs_chars_in_buffer, | 206 | .chars_in_buffer = rs_chars_in_buffer, |
204 | .hangup = rs_hangup, | 207 | .hangup = rs_hangup, |
205 | .wait_until_sent = rs_wait_until_sent, | 208 | .wait_until_sent = rs_wait_until_sent, |
206 | .read_proc = rs_read_proc | 209 | .proc_fops = &rs_proc_fops, |
207 | }; | 210 | }; |
208 | 211 | ||
209 | int __init rs_init(void) | 212 | int __init rs_init(void) |
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig index 14b9d5f4c20..c07e725ea93 100644 --- a/drivers/auxdisplay/Kconfig +++ b/drivers/auxdisplay/Kconfig | |||
@@ -6,7 +6,6 @@ | |||
6 | # | 6 | # |
7 | 7 | ||
8 | menuconfig AUXDISPLAY | 8 | menuconfig AUXDISPLAY |
9 | depends on PARPORT | ||
10 | bool "Auxiliary Display support" | 9 | bool "Auxiliary Display support" |
11 | ---help--- | 10 | ---help--- |
12 | Say Y here to get to see options for auxiliary display drivers. | 11 | Say Y here to get to see options for auxiliary display drivers. |
@@ -14,7 +13,7 @@ menuconfig AUXDISPLAY | |||
14 | 13 | ||
15 | If you say N, all options in this submenu will be skipped and disabled. | 14 | If you say N, all options in this submenu will be skipped and disabled. |
16 | 15 | ||
17 | if AUXDISPLAY && PARPORT | 16 | if AUXDISPLAY |
18 | 17 | ||
19 | config KS0108 | 18 | config KS0108 |
20 | tristate "KS0108 LCD Controller" | 19 | tristate "KS0108 LCD Controller" |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 2621ed2ce6d..40b17d3b55a 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -1192,6 +1192,30 @@ loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg) { | |||
1192 | return err; | 1192 | return err; |
1193 | } | 1193 | } |
1194 | 1194 | ||
1195 | static int loop_set_capacity(struct loop_device *lo, struct block_device *bdev) | ||
1196 | { | ||
1197 | int err; | ||
1198 | sector_t sec; | ||
1199 | loff_t sz; | ||
1200 | |||
1201 | err = -ENXIO; | ||
1202 | if (unlikely(lo->lo_state != Lo_bound)) | ||
1203 | goto out; | ||
1204 | err = figure_loop_size(lo); | ||
1205 | if (unlikely(err)) | ||
1206 | goto out; | ||
1207 | sec = get_capacity(lo->lo_disk); | ||
1208 | /* the width of sector_t may be narrow for bit-shift */ | ||
1209 | sz = sec; | ||
1210 | sz <<= 9; | ||
1211 | mutex_lock(&bdev->bd_mutex); | ||
1212 | bd_set_size(bdev, sz); | ||
1213 | mutex_unlock(&bdev->bd_mutex); | ||
1214 | |||
1215 | out: | ||
1216 | return err; | ||
1217 | } | ||
1218 | |||
1195 | static int lo_ioctl(struct block_device *bdev, fmode_t mode, | 1219 | static int lo_ioctl(struct block_device *bdev, fmode_t mode, |
1196 | unsigned int cmd, unsigned long arg) | 1220 | unsigned int cmd, unsigned long arg) |
1197 | { | 1221 | { |
@@ -1224,6 +1248,11 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, | |||
1224 | case LOOP_GET_STATUS64: | 1248 | case LOOP_GET_STATUS64: |
1225 | err = loop_get_status64(lo, (struct loop_info64 __user *) arg); | 1249 | err = loop_get_status64(lo, (struct loop_info64 __user *) arg); |
1226 | break; | 1250 | break; |
1251 | case LOOP_SET_CAPACITY: | ||
1252 | err = -EPERM; | ||
1253 | if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) | ||
1254 | err = loop_set_capacity(lo, bdev); | ||
1255 | break; | ||
1227 | default: | 1256 | default: |
1228 | err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; | 1257 | err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; |
1229 | } | 1258 | } |
@@ -1371,6 +1400,7 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode, | |||
1371 | lo, (struct compat_loop_info __user *) arg); | 1400 | lo, (struct compat_loop_info __user *) arg); |
1372 | mutex_unlock(&lo->lo_ctl_mutex); | 1401 | mutex_unlock(&lo->lo_ctl_mutex); |
1373 | break; | 1402 | break; |
1403 | case LOOP_SET_CAPACITY: | ||
1374 | case LOOP_CLR_FD: | 1404 | case LOOP_CLR_FD: |
1375 | case LOOP_GET_STATUS64: | 1405 | case LOOP_GET_STATUS64: |
1376 | case LOOP_SET_STATUS64: | 1406 | case LOOP_SET_STATUS64: |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index a58869ea851..fd3ebd1be57 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -79,6 +79,7 @@ static char *serial_version = "4.30"; | |||
79 | #include <linux/ptrace.h> | 79 | #include <linux/ptrace.h> |
80 | #include <linux/ioport.h> | 80 | #include <linux/ioport.h> |
81 | #include <linux/mm.h> | 81 | #include <linux/mm.h> |
82 | #include <linux/seq_file.h> | ||
82 | #include <linux/slab.h> | 83 | #include <linux/slab.h> |
83 | #include <linux/init.h> | 84 | #include <linux/init.h> |
84 | #include <linux/bitops.h> | 85 | #include <linux/bitops.h> |
@@ -1825,14 +1826,13 @@ static int rs_open(struct tty_struct *tty, struct file * filp) | |||
1825 | * /proc fs routines.... | 1826 | * /proc fs routines.... |
1826 | */ | 1827 | */ |
1827 | 1828 | ||
1828 | static inline int line_info(char *buf, struct serial_state *state) | 1829 | static inline void line_info(struct seq_file *m, struct serial_state *state) |
1829 | { | 1830 | { |
1830 | struct async_struct *info = state->info, scr_info; | 1831 | struct async_struct *info = state->info, scr_info; |
1831 | char stat_buf[30], control, status; | 1832 | char stat_buf[30], control, status; |
1832 | int ret; | ||
1833 | unsigned long flags; | 1833 | unsigned long flags; |
1834 | 1834 | ||
1835 | ret = sprintf(buf, "%d: uart:amiga_builtin",state->line); | 1835 | seq_printf(m, "%d: uart:amiga_builtin",state->line); |
1836 | 1836 | ||
1837 | /* | 1837 | /* |
1838 | * Figure out the current RS-232 lines | 1838 | * Figure out the current RS-232 lines |
@@ -1864,55 +1864,49 @@ static inline int line_info(char *buf, struct serial_state *state) | |||
1864 | strcat(stat_buf, "|CD"); | 1864 | strcat(stat_buf, "|CD"); |
1865 | 1865 | ||
1866 | if (info->quot) { | 1866 | if (info->quot) { |
1867 | ret += sprintf(buf+ret, " baud:%d", | 1867 | seq_printf(m, " baud:%d", state->baud_base / info->quot); |
1868 | state->baud_base / info->quot); | ||
1869 | } | 1868 | } |
1870 | 1869 | ||
1871 | ret += sprintf(buf+ret, " tx:%d rx:%d", | 1870 | seq_printf(m, " tx:%d rx:%d", state->icount.tx, state->icount.rx); |
1872 | state->icount.tx, state->icount.rx); | ||
1873 | 1871 | ||
1874 | if (state->icount.frame) | 1872 | if (state->icount.frame) |
1875 | ret += sprintf(buf+ret, " fe:%d", state->icount.frame); | 1873 | seq_printf(m, " fe:%d", state->icount.frame); |
1876 | 1874 | ||
1877 | if (state->icount.parity) | 1875 | if (state->icount.parity) |
1878 | ret += sprintf(buf+ret, " pe:%d", state->icount.parity); | 1876 | seq_printf(m, " pe:%d", state->icount.parity); |
1879 | 1877 | ||
1880 | if (state->icount.brk) | 1878 | if (state->icount.brk) |
1881 | ret += sprintf(buf+ret, " brk:%d", state->icount.brk); | 1879 | seq_printf(m, " brk:%d", state->icount.brk); |
1882 | 1880 | ||
1883 | if (state->icount.overrun) | 1881 | if (state->icount.overrun) |
1884 | ret += sprintf(buf+ret, " oe:%d", state->icount.overrun); | 1882 | seq_printf(m, " oe:%d", state->icount.overrun); |
1885 | 1883 | ||
1886 | /* | 1884 | /* |
1887 | * Last thing is the RS-232 status lines | 1885 | * Last thing is the RS-232 status lines |
1888 | */ | 1886 | */ |
1889 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 1887 | seq_printf(m, " %s\n", stat_buf+1); |
1890 | return ret; | ||
1891 | } | 1888 | } |
1892 | 1889 | ||
1893 | static int rs_read_proc(char *page, char **start, off_t off, int count, | 1890 | static int rs_proc_show(struct seq_file *m, void *v) |
1894 | int *eof, void *data) | ||
1895 | { | 1891 | { |
1896 | int len = 0, l; | 1892 | seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version); |
1897 | off_t begin = 0; | 1893 | line_info(m, &rs_table[0]); |
1898 | 1894 | return 0; | |
1899 | len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version); | ||
1900 | l = line_info(page + len, &rs_table[0]); | ||
1901 | len += l; | ||
1902 | if (len+begin > off+count) | ||
1903 | goto done; | ||
1904 | if (len+begin < off) { | ||
1905 | begin += len; | ||
1906 | len = 0; | ||
1907 | } | ||
1908 | *eof = 1; | ||
1909 | done: | ||
1910 | if (off >= len+begin) | ||
1911 | return 0; | ||
1912 | *start = page + (off-begin); | ||
1913 | return ((count < begin+len-off) ? count : begin+len-off); | ||
1914 | } | 1895 | } |
1915 | 1896 | ||
1897 | static int rs_proc_open(struct inode *inode, struct file *file) | ||
1898 | { | ||
1899 | return single_open(file, rs_proc_show, NULL); | ||
1900 | } | ||
1901 | |||
1902 | static const struct file_operations rs_proc_fops = { | ||
1903 | .owner = THIS_MODULE, | ||
1904 | .open = rs_proc_open, | ||
1905 | .read = seq_read, | ||
1906 | .llseek = seq_lseek, | ||
1907 | .release = single_release, | ||
1908 | }; | ||
1909 | |||
1916 | /* | 1910 | /* |
1917 | * --------------------------------------------------------------------- | 1911 | * --------------------------------------------------------------------- |
1918 | * rs_init() and friends | 1912 | * rs_init() and friends |
@@ -1951,9 +1945,9 @@ static const struct tty_operations serial_ops = { | |||
1951 | .break_ctl = rs_break, | 1945 | .break_ctl = rs_break, |
1952 | .send_xchar = rs_send_xchar, | 1946 | .send_xchar = rs_send_xchar, |
1953 | .wait_until_sent = rs_wait_until_sent, | 1947 | .wait_until_sent = rs_wait_until_sent, |
1954 | .read_proc = rs_read_proc, | ||
1955 | .tiocmget = rs_tiocmget, | 1948 | .tiocmget = rs_tiocmget, |
1956 | .tiocmset = rs_tiocmset, | 1949 | .tiocmset = rs_tiocmset, |
1950 | .proc_fops = &rs_proc_fops, | ||
1957 | }; | 1951 | }; |
1958 | 1952 | ||
1959 | /* | 1953 | /* |
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 6a59f72a9c2..272db0e2b49 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -657,6 +657,7 @@ | |||
657 | 657 | ||
658 | #include <linux/stat.h> | 658 | #include <linux/stat.h> |
659 | #include <linux/proc_fs.h> | 659 | #include <linux/proc_fs.h> |
660 | #include <linux/seq_file.h> | ||
660 | 661 | ||
661 | static void cy_throttle(struct tty_struct *tty); | 662 | static void cy_throttle(struct tty_struct *tty); |
662 | static void cy_send_xchar(struct tty_struct *tty, char ch); | 663 | static void cy_send_xchar(struct tty_struct *tty, char ch); |
@@ -868,8 +869,6 @@ static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32); | |||
868 | static unsigned detect_isa_irq(void __iomem *); | 869 | static unsigned detect_isa_irq(void __iomem *); |
869 | #endif /* CONFIG_ISA */ | 870 | #endif /* CONFIG_ISA */ |
870 | 871 | ||
871 | static int cyclades_get_proc_info(char *, char **, off_t, int, int *, void *); | ||
872 | |||
873 | #ifndef CONFIG_CYZ_INTR | 872 | #ifndef CONFIG_CYZ_INTR |
874 | static void cyz_poll(unsigned long); | 873 | static void cyz_poll(unsigned long); |
875 | 874 | ||
@@ -5216,31 +5215,22 @@ static struct pci_driver cy_pci_driver = { | |||
5216 | }; | 5215 | }; |
5217 | #endif | 5216 | #endif |
5218 | 5217 | ||
5219 | static int | 5218 | static int cyclades_proc_show(struct seq_file *m, void *v) |
5220 | cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, | ||
5221 | int *eof, void *data) | ||
5222 | { | 5219 | { |
5223 | struct cyclades_port *info; | 5220 | struct cyclades_port *info; |
5224 | unsigned int i, j; | 5221 | unsigned int i, j; |
5225 | int len = 0; | ||
5226 | off_t begin = 0; | ||
5227 | off_t pos = 0; | ||
5228 | int size; | ||
5229 | __u32 cur_jifs = jiffies; | 5222 | __u32 cur_jifs = jiffies; |
5230 | 5223 | ||
5231 | size = sprintf(buf, "Dev TimeOpen BytesOut IdleOut BytesIn " | 5224 | seq_puts(m, "Dev TimeOpen BytesOut IdleOut BytesIn " |
5232 | "IdleIn Overruns Ldisc\n"); | 5225 | "IdleIn Overruns Ldisc\n"); |
5233 | 5226 | ||
5234 | pos += size; | ||
5235 | len += size; | ||
5236 | |||
5237 | /* Output one line for each known port */ | 5227 | /* Output one line for each known port */ |
5238 | for (i = 0; i < NR_CARDS; i++) | 5228 | for (i = 0; i < NR_CARDS; i++) |
5239 | for (j = 0; j < cy_card[i].nports; j++) { | 5229 | for (j = 0; j < cy_card[i].nports; j++) { |
5240 | info = &cy_card[i].ports[j]; | 5230 | info = &cy_card[i].ports[j]; |
5241 | 5231 | ||
5242 | if (info->port.count) | 5232 | if (info->port.count) |
5243 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu " | 5233 | seq_printf(m, "%3d %8lu %10lu %8lu " |
5244 | "%10lu %8lu %9lu %6ld\n", info->line, | 5234 | "%10lu %8lu %9lu %6ld\n", info->line, |
5245 | (cur_jifs - info->idle_stats.in_use) / | 5235 | (cur_jifs - info->idle_stats.in_use) / |
5246 | HZ, info->idle_stats.xmit_bytes, | 5236 | HZ, info->idle_stats.xmit_bytes, |
@@ -5251,30 +5241,26 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, | |||
5251 | /* FIXME: double check locking */ | 5241 | /* FIXME: double check locking */ |
5252 | (long)info->port.tty->ldisc.ops->num); | 5242 | (long)info->port.tty->ldisc.ops->num); |
5253 | else | 5243 | else |
5254 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu " | 5244 | seq_printf(m, "%3d %8lu %10lu %8lu " |
5255 | "%10lu %8lu %9lu %6ld\n", | 5245 | "%10lu %8lu %9lu %6ld\n", |
5256 | info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); | 5246 | info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); |
5257 | len += size; | ||
5258 | pos = begin + len; | ||
5259 | |||
5260 | if (pos < offset) { | ||
5261 | len = 0; | ||
5262 | begin = pos; | ||
5263 | } | ||
5264 | if (pos > offset + length) | ||
5265 | goto done; | ||
5266 | } | 5247 | } |
5267 | *eof = 1; | 5248 | return 0; |
5268 | done: | 5249 | } |
5269 | *start = buf + (offset - begin); /* Start of wanted data */ | 5250 | |
5270 | len -= (offset - begin); /* Start slop */ | 5251 | static int cyclades_proc_open(struct inode *inode, struct file *file) |
5271 | if (len > length) | 5252 | { |
5272 | len = length; /* Ending slop */ | 5253 | return single_open(file, cyclades_proc_show, NULL); |
5273 | if (len < 0) | ||
5274 | len = 0; | ||
5275 | return len; | ||
5276 | } | 5254 | } |
5277 | 5255 | ||
5256 | static const struct file_operations cyclades_proc_fops = { | ||
5257 | .owner = THIS_MODULE, | ||
5258 | .open = cyclades_proc_open, | ||
5259 | .read = seq_read, | ||
5260 | .llseek = seq_lseek, | ||
5261 | .release = single_release, | ||
5262 | }; | ||
5263 | |||
5278 | /* The serial driver boot-time initialization code! | 5264 | /* The serial driver boot-time initialization code! |
5279 | Hardware I/O ports are mapped to character special devices on a | 5265 | Hardware I/O ports are mapped to character special devices on a |
5280 | first found, first allocated manner. That is, this code searches | 5266 | first found, first allocated manner. That is, this code searches |
@@ -5311,9 +5297,9 @@ static const struct tty_operations cy_ops = { | |||
5311 | .hangup = cy_hangup, | 5297 | .hangup = cy_hangup, |
5312 | .break_ctl = cy_break, | 5298 | .break_ctl = cy_break, |
5313 | .wait_until_sent = cy_wait_until_sent, | 5299 | .wait_until_sent = cy_wait_until_sent, |
5314 | .read_proc = cyclades_get_proc_info, | ||
5315 | .tiocmget = cy_tiocmget, | 5300 | .tiocmget = cy_tiocmget, |
5316 | .tiocmset = cy_tiocmset, | 5301 | .tiocmset = cy_tiocmset, |
5302 | .proc_fops = &cyclades_proc_fops, | ||
5317 | }; | 5303 | }; |
5318 | 5304 | ||
5319 | static int __init cy_init(void) | 5305 | static int __init cy_init(void) |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 70e0ebc30bd..afd9247cf08 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -139,7 +139,7 @@ | |||
139 | #include <linux/seq_file.h> | 139 | #include <linux/seq_file.h> |
140 | 140 | ||
141 | static const struct file_operations ip2mem_proc_fops; | 141 | static const struct file_operations ip2mem_proc_fops; |
142 | static int ip2_read_proc(char *, char **, off_t, int, int *, void * ); | 142 | static const struct file_operations ip2_proc_fops; |
143 | 143 | ||
144 | /********************/ | 144 | /********************/ |
145 | /* Type Definitions */ | 145 | /* Type Definitions */ |
@@ -446,9 +446,9 @@ static const struct tty_operations ip2_ops = { | |||
446 | .stop = ip2_stop, | 446 | .stop = ip2_stop, |
447 | .start = ip2_start, | 447 | .start = ip2_start, |
448 | .hangup = ip2_hangup, | 448 | .hangup = ip2_hangup, |
449 | .read_proc = ip2_read_proc, | ||
450 | .tiocmget = ip2_tiocmget, | 449 | .tiocmget = ip2_tiocmget, |
451 | .tiocmset = ip2_tiocmset, | 450 | .tiocmset = ip2_tiocmset, |
451 | .proc_fops = &ip2_proc_fops, | ||
452 | }; | 452 | }; |
453 | 453 | ||
454 | /******************************************************************************/ | 454 | /******************************************************************************/ |
@@ -3029,19 +3029,17 @@ static const struct file_operations ip2mem_proc_fops = { | |||
3029 | * different sources including ip2mkdev.c and a couple of other drivers. | 3029 | * different sources including ip2mkdev.c and a couple of other drivers. |
3030 | * The bugs are all mine. :-) =mhw= | 3030 | * The bugs are all mine. :-) =mhw= |
3031 | */ | 3031 | */ |
3032 | static int ip2_read_proc(char *page, char **start, off_t off, | 3032 | static int ip2_proc_show(struct seq_file *m, void *v) |
3033 | int count, int *eof, void *data) | ||
3034 | { | 3033 | { |
3035 | int i, j, box; | 3034 | int i, j, box; |
3036 | int len = 0; | ||
3037 | int boxes = 0; | 3035 | int boxes = 0; |
3038 | int ports = 0; | 3036 | int ports = 0; |
3039 | int tports = 0; | 3037 | int tports = 0; |
3040 | off_t begin = 0; | ||
3041 | i2eBordStrPtr pB; | 3038 | i2eBordStrPtr pB; |
3039 | char *sep; | ||
3042 | 3040 | ||
3043 | len += sprintf(page, "ip2info: 1.0 driver: %s\n", pcVersion ); | 3041 | seq_printf(m, "ip2info: 1.0 driver: %s\n", pcVersion); |
3044 | len += sprintf(page+len, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n", | 3042 | seq_printf(m, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n", |
3045 | IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR, | 3043 | IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR, |
3046 | IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX); | 3044 | IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX); |
3047 | 3045 | ||
@@ -3053,7 +3051,8 @@ static int ip2_read_proc(char *page, char **start, off_t off, | |||
3053 | switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) | 3051 | switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) |
3054 | { | 3052 | { |
3055 | case POR_ID_FIIEX: | 3053 | case POR_ID_FIIEX: |
3056 | len += sprintf( page+len, "Board %d: EX ports=", i ); | 3054 | seq_printf(m, "Board %d: EX ports=", i); |
3055 | sep = ""; | ||
3057 | for( box = 0; box < ABS_MAX_BOXES; ++box ) | 3056 | for( box = 0; box < ABS_MAX_BOXES; ++box ) |
3058 | { | 3057 | { |
3059 | ports = 0; | 3058 | ports = 0; |
@@ -3065,79 +3064,74 @@ static int ip2_read_proc(char *page, char **start, off_t off, | |||
3065 | ++ports; | 3064 | ++ports; |
3066 | } | 3065 | } |
3067 | } | 3066 | } |
3068 | len += sprintf( page+len, "%d,", ports ); | 3067 | seq_printf(m, "%s%d", sep, ports); |
3068 | sep = ","; | ||
3069 | tports += ports; | 3069 | tports += ports; |
3070 | } | 3070 | } |
3071 | 3071 | seq_printf(m, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8); | |
3072 | --len; /* Backup over that last comma */ | ||
3073 | |||
3074 | len += sprintf( page+len, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8 ); | ||
3075 | break; | 3072 | break; |
3076 | 3073 | ||
3077 | case POR_ID_II_4: | 3074 | case POR_ID_II_4: |
3078 | len += sprintf(page+len, "Board %d: ISA-4 ports=4 boxes=1", i ); | 3075 | seq_printf(m, "Board %d: ISA-4 ports=4 boxes=1", i); |
3079 | tports = ports = 4; | 3076 | tports = ports = 4; |
3080 | break; | 3077 | break; |
3081 | 3078 | ||
3082 | case POR_ID_II_8: | 3079 | case POR_ID_II_8: |
3083 | len += sprintf(page+len, "Board %d: ISA-8-std ports=8 boxes=1", i ); | 3080 | seq_printf(m, "Board %d: ISA-8-std ports=8 boxes=1", i); |
3084 | tports = ports = 8; | 3081 | tports = ports = 8; |
3085 | break; | 3082 | break; |
3086 | 3083 | ||
3087 | case POR_ID_II_8R: | 3084 | case POR_ID_II_8R: |
3088 | len += sprintf(page+len, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i ); | 3085 | seq_printf(m, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i); |
3089 | tports = ports = 8; | 3086 | tports = ports = 8; |
3090 | break; | 3087 | break; |
3091 | 3088 | ||
3092 | default: | 3089 | default: |
3093 | len += sprintf(page+len, "Board %d: unknown", i ); | 3090 | seq_printf(m, "Board %d: unknown", i); |
3094 | /* Don't try and probe for minor numbers */ | 3091 | /* Don't try and probe for minor numbers */ |
3095 | tports = ports = 0; | 3092 | tports = ports = 0; |
3096 | } | 3093 | } |
3097 | 3094 | ||
3098 | } else { | 3095 | } else { |
3099 | /* Don't try and probe for minor numbers */ | 3096 | /* Don't try and probe for minor numbers */ |
3100 | len += sprintf(page+len, "Board %d: vacant", i ); | 3097 | seq_printf(m, "Board %d: vacant", i); |
3101 | tports = ports = 0; | 3098 | tports = ports = 0; |
3102 | } | 3099 | } |
3103 | 3100 | ||
3104 | if( tports ) { | 3101 | if( tports ) { |
3105 | len += sprintf(page+len, " minors=" ); | 3102 | seq_puts(m, " minors="); |
3106 | 3103 | sep = ""; | |
3107 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) | 3104 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) |
3108 | { | 3105 | { |
3109 | for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) | 3106 | for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) |
3110 | { | 3107 | { |
3111 | if ( pB->i2eChannelMap[box] & (1 << j) ) | 3108 | if ( pB->i2eChannelMap[box] & (1 << j) ) |
3112 | { | 3109 | { |
3113 | len += sprintf (page+len,"%d,", | 3110 | seq_printf(m, "%s%d", sep, |
3114 | j + ABS_BIGGEST_BOX * | 3111 | j + ABS_BIGGEST_BOX * |
3115 | (box+i*ABS_MAX_BOXES)); | 3112 | (box+i*ABS_MAX_BOXES)); |
3113 | sep = ","; | ||
3116 | } | 3114 | } |
3117 | } | 3115 | } |
3118 | } | 3116 | } |
3119 | |||
3120 | page[ len - 1 ] = '\n'; /* Overwrite that last comma */ | ||
3121 | } else { | ||
3122 | len += sprintf (page+len,"\n" ); | ||
3123 | } | ||
3124 | |||
3125 | if (len+begin > off+count) | ||
3126 | break; | ||
3127 | if (len+begin < off) { | ||
3128 | begin += len; | ||
3129 | len = 0; | ||
3130 | } | 3117 | } |
3118 | seq_putc(m, '\n'); | ||
3131 | } | 3119 | } |
3120 | return 0; | ||
3121 | } | ||
3132 | 3122 | ||
3133 | if (i >= IP2_MAX_BOARDS) | 3123 | static int ip2_proc_open(struct inode *inode, struct file *file) |
3134 | *eof = 1; | 3124 | { |
3135 | if (off >= len+begin) | 3125 | return single_open(file, ip2_proc_show, NULL); |
3136 | return 0; | 3126 | } |
3137 | 3127 | ||
3138 | *start = page + (off-begin); | 3128 | static const struct file_operations ip2_proc_fops = { |
3139 | return ((count < begin+len-off) ? count : begin+len-off); | 3129 | .owner = THIS_MODULE, |
3140 | } | 3130 | .open = ip2_proc_open, |
3131 | .read = seq_read, | ||
3132 | .llseek = seq_lseek, | ||
3133 | .release = single_release, | ||
3134 | }; | ||
3141 | 3135 | ||
3142 | /******************************************************************************/ | 3136 | /******************************************************************************/ |
3143 | /* Function: ip2trace() */ | 3137 | /* Function: ip2trace() */ |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 5c3dc6b8411..fff19f7e29d 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/tty.h> | 24 | #include <linux/tty.h> |
25 | #include <linux/tty_flip.h> | 25 | #include <linux/tty_flip.h> |
26 | #include <linux/serial.h> | 26 | #include <linux/serial.h> |
27 | #include <linux/seq_file.h> | ||
27 | #include <linux/cdk.h> | 28 | #include <linux/cdk.h> |
28 | #include <linux/comstats.h> | 29 | #include <linux/comstats.h> |
29 | #include <linux/istallion.h> | 30 | #include <linux/istallion.h> |
@@ -613,7 +614,6 @@ static int stli_breakctl(struct tty_struct *tty, int state); | |||
613 | static void stli_waituntilsent(struct tty_struct *tty, int timeout); | 614 | static void stli_waituntilsent(struct tty_struct *tty, int timeout); |
614 | static void stli_sendxchar(struct tty_struct *tty, char ch); | 615 | static void stli_sendxchar(struct tty_struct *tty, char ch); |
615 | static void stli_hangup(struct tty_struct *tty); | 616 | static void stli_hangup(struct tty_struct *tty); |
616 | static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos); | ||
617 | 617 | ||
618 | static int stli_brdinit(struct stlibrd *brdp); | 618 | static int stli_brdinit(struct stlibrd *brdp); |
619 | static int stli_startbrd(struct stlibrd *brdp); | 619 | static int stli_startbrd(struct stlibrd *brdp); |
@@ -1893,20 +1893,10 @@ static void stli_sendxchar(struct tty_struct *tty, char ch) | |||
1893 | stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0); | 1893 | stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0); |
1894 | } | 1894 | } |
1895 | 1895 | ||
1896 | /*****************************************************************************/ | 1896 | static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stliport *portp, int portnr) |
1897 | |||
1898 | #define MAXLINE 80 | ||
1899 | |||
1900 | /* | ||
1901 | * Format info for a specified port. The line is deliberately limited | ||
1902 | * to 80 characters. (If it is too long it will be truncated, if too | ||
1903 | * short then padded with spaces). | ||
1904 | */ | ||
1905 | |||
1906 | static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos) | ||
1907 | { | 1897 | { |
1908 | char *sp, *uart; | 1898 | char *uart; |
1909 | int rc, cnt; | 1899 | int rc; |
1910 | 1900 | ||
1911 | rc = stli_portcmdstats(NULL, portp); | 1901 | rc = stli_portcmdstats(NULL, portp); |
1912 | 1902 | ||
@@ -1918,44 +1908,50 @@ static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portn | |||
1918 | default:uart = "CD1400"; break; | 1908 | default:uart = "CD1400"; break; |
1919 | } | 1909 | } |
1920 | } | 1910 | } |
1921 | 1911 | seq_printf(m, "%d: uart:%s ", portnr, uart); | |
1922 | sp = pos; | ||
1923 | sp += sprintf(sp, "%d: uart:%s ", portnr, uart); | ||
1924 | 1912 | ||
1925 | if ((brdp->state & BST_STARTED) && (rc >= 0)) { | 1913 | if ((brdp->state & BST_STARTED) && (rc >= 0)) { |
1926 | sp += sprintf(sp, "tx:%d rx:%d", (int) stli_comstats.txtotal, | 1914 | char sep; |
1915 | |||
1916 | seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal, | ||
1927 | (int) stli_comstats.rxtotal); | 1917 | (int) stli_comstats.rxtotal); |
1928 | 1918 | ||
1929 | if (stli_comstats.rxframing) | 1919 | if (stli_comstats.rxframing) |
1930 | sp += sprintf(sp, " fe:%d", | 1920 | seq_printf(m, " fe:%d", |
1931 | (int) stli_comstats.rxframing); | 1921 | (int) stli_comstats.rxframing); |
1932 | if (stli_comstats.rxparity) | 1922 | if (stli_comstats.rxparity) |
1933 | sp += sprintf(sp, " pe:%d", | 1923 | seq_printf(m, " pe:%d", |
1934 | (int) stli_comstats.rxparity); | 1924 | (int) stli_comstats.rxparity); |
1935 | if (stli_comstats.rxbreaks) | 1925 | if (stli_comstats.rxbreaks) |
1936 | sp += sprintf(sp, " brk:%d", | 1926 | seq_printf(m, " brk:%d", |
1937 | (int) stli_comstats.rxbreaks); | 1927 | (int) stli_comstats.rxbreaks); |
1938 | if (stli_comstats.rxoverrun) | 1928 | if (stli_comstats.rxoverrun) |
1939 | sp += sprintf(sp, " oe:%d", | 1929 | seq_printf(m, " oe:%d", |
1940 | (int) stli_comstats.rxoverrun); | 1930 | (int) stli_comstats.rxoverrun); |
1941 | 1931 | ||
1942 | cnt = sprintf(sp, "%s%s%s%s%s ", | 1932 | sep = ' '; |
1943 | (stli_comstats.signals & TIOCM_RTS) ? "|RTS" : "", | 1933 | if (stli_comstats.signals & TIOCM_RTS) { |
1944 | (stli_comstats.signals & TIOCM_CTS) ? "|CTS" : "", | 1934 | seq_printf(m, "%c%s", sep, "RTS"); |
1945 | (stli_comstats.signals & TIOCM_DTR) ? "|DTR" : "", | 1935 | sep = '|'; |
1946 | (stli_comstats.signals & TIOCM_CD) ? "|DCD" : "", | 1936 | } |
1947 | (stli_comstats.signals & TIOCM_DSR) ? "|DSR" : ""); | 1937 | if (stli_comstats.signals & TIOCM_CTS) { |
1948 | *sp = ' '; | 1938 | seq_printf(m, "%c%s", sep, "CTS"); |
1949 | sp += cnt; | 1939 | sep = '|'; |
1940 | } | ||
1941 | if (stli_comstats.signals & TIOCM_DTR) { | ||
1942 | seq_printf(m, "%c%s", sep, "DTR"); | ||
1943 | sep = '|'; | ||
1944 | } | ||
1945 | if (stli_comstats.signals & TIOCM_CD) { | ||
1946 | seq_printf(m, "%c%s", sep, "DCD"); | ||
1947 | sep = '|'; | ||
1948 | } | ||
1949 | if (stli_comstats.signals & TIOCM_DSR) { | ||
1950 | seq_printf(m, "%c%s", sep, "DSR"); | ||
1951 | sep = '|'; | ||
1952 | } | ||
1950 | } | 1953 | } |
1951 | 1954 | seq_putc(m, '\n'); | |
1952 | for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++) | ||
1953 | *sp++ = ' '; | ||
1954 | if (cnt >= MAXLINE) | ||
1955 | pos[(MAXLINE - 2)] = '+'; | ||
1956 | pos[(MAXLINE - 1)] = '\n'; | ||
1957 | |||
1958 | return(MAXLINE); | ||
1959 | } | 1955 | } |
1960 | 1956 | ||
1961 | /*****************************************************************************/ | 1957 | /*****************************************************************************/ |
@@ -1964,26 +1960,15 @@ static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portn | |||
1964 | * Port info, read from the /proc file system. | 1960 | * Port info, read from the /proc file system. |
1965 | */ | 1961 | */ |
1966 | 1962 | ||
1967 | static int stli_readproc(char *page, char **start, off_t off, int count, int *eof, void *data) | 1963 | static int stli_proc_show(struct seq_file *m, void *v) |
1968 | { | 1964 | { |
1969 | struct stlibrd *brdp; | 1965 | struct stlibrd *brdp; |
1970 | struct stliport *portp; | 1966 | struct stliport *portp; |
1971 | unsigned int brdnr, portnr, totalport; | 1967 | unsigned int brdnr, portnr, totalport; |
1972 | int curoff, maxoff; | ||
1973 | char *pos; | ||
1974 | 1968 | ||
1975 | pos = page; | ||
1976 | totalport = 0; | 1969 | totalport = 0; |
1977 | curoff = 0; | 1970 | |
1978 | 1971 | seq_printf(m, "%s: version %s\n", stli_drvtitle, stli_drvversion); | |
1979 | if (off == 0) { | ||
1980 | pos += sprintf(pos, "%s: version %s", stli_drvtitle, | ||
1981 | stli_drvversion); | ||
1982 | while (pos < (page + MAXLINE - 1)) | ||
1983 | *pos++ = ' '; | ||
1984 | *pos++ = '\n'; | ||
1985 | } | ||
1986 | curoff = MAXLINE; | ||
1987 | 1972 | ||
1988 | /* | 1973 | /* |
1989 | * We scan through for each board, panel and port. The offset is | 1974 | * We scan through for each board, panel and port. The offset is |
@@ -1996,33 +1981,31 @@ static int stli_readproc(char *page, char **start, off_t off, int count, int *eo | |||
1996 | if (brdp->state == 0) | 1981 | if (brdp->state == 0) |
1997 | continue; | 1982 | continue; |
1998 | 1983 | ||
1999 | maxoff = curoff + (brdp->nrports * MAXLINE); | ||
2000 | if (off >= maxoff) { | ||
2001 | curoff = maxoff; | ||
2002 | continue; | ||
2003 | } | ||
2004 | |||
2005 | totalport = brdnr * STL_MAXPORTS; | 1984 | totalport = brdnr * STL_MAXPORTS; |
2006 | for (portnr = 0; (portnr < brdp->nrports); portnr++, | 1985 | for (portnr = 0; (portnr < brdp->nrports); portnr++, |
2007 | totalport++) { | 1986 | totalport++) { |
2008 | portp = brdp->ports[portnr]; | 1987 | portp = brdp->ports[portnr]; |
2009 | if (portp == NULL) | 1988 | if (portp == NULL) |
2010 | continue; | 1989 | continue; |
2011 | if (off >= (curoff += MAXLINE)) | 1990 | stli_portinfo(m, brdp, portp, totalport); |
2012 | continue; | ||
2013 | if ((pos - page + MAXLINE) > count) | ||
2014 | goto stli_readdone; | ||
2015 | pos += stli_portinfo(brdp, portp, totalport, pos); | ||
2016 | } | 1991 | } |
2017 | } | 1992 | } |
1993 | return 0; | ||
1994 | } | ||
2018 | 1995 | ||
2019 | *eof = 1; | 1996 | static int stli_proc_open(struct inode *inode, struct file *file) |
2020 | 1997 | { | |
2021 | stli_readdone: | 1998 | return single_open(file, stli_proc_show, NULL); |
2022 | *start = page; | ||
2023 | return(pos - page); | ||
2024 | } | 1999 | } |
2025 | 2000 | ||
2001 | static const struct file_operations stli_proc_fops = { | ||
2002 | .owner = THIS_MODULE, | ||
2003 | .open = stli_proc_open, | ||
2004 | .read = seq_read, | ||
2005 | .llseek = seq_lseek, | ||
2006 | .release = single_release, | ||
2007 | }; | ||
2008 | |||
2026 | /*****************************************************************************/ | 2009 | /*****************************************************************************/ |
2027 | 2010 | ||
2028 | /* | 2011 | /* |
@@ -4427,9 +4410,9 @@ static const struct tty_operations stli_ops = { | |||
4427 | .break_ctl = stli_breakctl, | 4410 | .break_ctl = stli_breakctl, |
4428 | .wait_until_sent = stli_waituntilsent, | 4411 | .wait_until_sent = stli_waituntilsent, |
4429 | .send_xchar = stli_sendxchar, | 4412 | .send_xchar = stli_sendxchar, |
4430 | .read_proc = stli_readproc, | ||
4431 | .tiocmget = stli_tiocmget, | 4413 | .tiocmget = stli_tiocmget, |
4432 | .tiocmset = stli_tiocmset, | 4414 | .tiocmset = stli_tiocmset, |
4415 | .proc_fops = &stli_proc_fops, | ||
4433 | }; | 4416 | }; |
4434 | 4417 | ||
4435 | static const struct tty_port_operations stli_port_ops = { | 4418 | static const struct tty_port_operations stli_port_ops = { |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 5608a1e5a3b..19d79fc5446 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/ptrace.h> | 51 | #include <linux/ptrace.h> |
52 | #include <linux/ioport.h> | 52 | #include <linux/ioport.h> |
53 | #include <linux/mm.h> | 53 | #include <linux/mm.h> |
54 | #include <linux/seq_file.h> | ||
54 | #include <linux/slab.h> | 55 | #include <linux/slab.h> |
55 | #include <linux/netdevice.h> | 56 | #include <linux/netdevice.h> |
56 | #include <linux/vmalloc.h> | 57 | #include <linux/vmalloc.h> |
@@ -2619,13 +2620,12 @@ cleanup: | |||
2619 | * /proc fs routines.... | 2620 | * /proc fs routines.... |
2620 | */ | 2621 | */ |
2621 | 2622 | ||
2622 | static inline int line_info(char *buf, MGSLPC_INFO *info) | 2623 | static inline void line_info(struct seq_file *m, MGSLPC_INFO *info) |
2623 | { | 2624 | { |
2624 | char stat_buf[30]; | 2625 | char stat_buf[30]; |
2625 | int ret; | ||
2626 | unsigned long flags; | 2626 | unsigned long flags; |
2627 | 2627 | ||
2628 | ret = sprintf(buf, "%s:io:%04X irq:%d", | 2628 | seq_printf(m, "%s:io:%04X irq:%d", |
2629 | info->device_name, info->io_base, info->irq_level); | 2629 | info->device_name, info->io_base, info->irq_level); |
2630 | 2630 | ||
2631 | /* output current serial signal states */ | 2631 | /* output current serial signal states */ |
@@ -2649,75 +2649,70 @@ static inline int line_info(char *buf, MGSLPC_INFO *info) | |||
2649 | strcat(stat_buf, "|RI"); | 2649 | strcat(stat_buf, "|RI"); |
2650 | 2650 | ||
2651 | if (info->params.mode == MGSL_MODE_HDLC) { | 2651 | if (info->params.mode == MGSL_MODE_HDLC) { |
2652 | ret += sprintf(buf+ret, " HDLC txok:%d rxok:%d", | 2652 | seq_printf(m, " HDLC txok:%d rxok:%d", |
2653 | info->icount.txok, info->icount.rxok); | 2653 | info->icount.txok, info->icount.rxok); |
2654 | if (info->icount.txunder) | 2654 | if (info->icount.txunder) |
2655 | ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); | 2655 | seq_printf(m, " txunder:%d", info->icount.txunder); |
2656 | if (info->icount.txabort) | 2656 | if (info->icount.txabort) |
2657 | ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); | 2657 | seq_printf(m, " txabort:%d", info->icount.txabort); |
2658 | if (info->icount.rxshort) | 2658 | if (info->icount.rxshort) |
2659 | ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); | 2659 | seq_printf(m, " rxshort:%d", info->icount.rxshort); |
2660 | if (info->icount.rxlong) | 2660 | if (info->icount.rxlong) |
2661 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); | 2661 | seq_printf(m, " rxlong:%d", info->icount.rxlong); |
2662 | if (info->icount.rxover) | 2662 | if (info->icount.rxover) |
2663 | ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); | 2663 | seq_printf(m, " rxover:%d", info->icount.rxover); |
2664 | if (info->icount.rxcrc) | 2664 | if (info->icount.rxcrc) |
2665 | ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); | 2665 | seq_printf(m, " rxcrc:%d", info->icount.rxcrc); |
2666 | } else { | 2666 | } else { |
2667 | ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d", | 2667 | seq_printf(m, " ASYNC tx:%d rx:%d", |
2668 | info->icount.tx, info->icount.rx); | 2668 | info->icount.tx, info->icount.rx); |
2669 | if (info->icount.frame) | 2669 | if (info->icount.frame) |
2670 | ret += sprintf(buf+ret, " fe:%d", info->icount.frame); | 2670 | seq_printf(m, " fe:%d", info->icount.frame); |
2671 | if (info->icount.parity) | 2671 | if (info->icount.parity) |
2672 | ret += sprintf(buf+ret, " pe:%d", info->icount.parity); | 2672 | seq_printf(m, " pe:%d", info->icount.parity); |
2673 | if (info->icount.brk) | 2673 | if (info->icount.brk) |
2674 | ret += sprintf(buf+ret, " brk:%d", info->icount.brk); | 2674 | seq_printf(m, " brk:%d", info->icount.brk); |
2675 | if (info->icount.overrun) | 2675 | if (info->icount.overrun) |
2676 | ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); | 2676 | seq_printf(m, " oe:%d", info->icount.overrun); |
2677 | } | 2677 | } |
2678 | 2678 | ||
2679 | /* Append serial signal status to end */ | 2679 | /* Append serial signal status to end */ |
2680 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 2680 | seq_printf(m, " %s\n", stat_buf+1); |
2681 | 2681 | ||
2682 | ret += sprintf(buf+ret, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", | 2682 | seq_printf(m, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", |
2683 | info->tx_active,info->bh_requested,info->bh_running, | 2683 | info->tx_active,info->bh_requested,info->bh_running, |
2684 | info->pending_bh); | 2684 | info->pending_bh); |
2685 | |||
2686 | return ret; | ||
2687 | } | 2685 | } |
2688 | 2686 | ||
2689 | /* Called to print information about devices | 2687 | /* Called to print information about devices |
2690 | */ | 2688 | */ |
2691 | static int mgslpc_read_proc(char *page, char **start, off_t off, int count, | 2689 | static int mgslpc_proc_show(struct seq_file *m, void *v) |
2692 | int *eof, void *data) | ||
2693 | { | 2690 | { |
2694 | int len = 0, l; | ||
2695 | off_t begin = 0; | ||
2696 | MGSLPC_INFO *info; | 2691 | MGSLPC_INFO *info; |
2697 | 2692 | ||
2698 | len += sprintf(page, "synclink driver:%s\n", driver_version); | 2693 | seq_printf(m, "synclink driver:%s\n", driver_version); |
2699 | 2694 | ||
2700 | info = mgslpc_device_list; | 2695 | info = mgslpc_device_list; |
2701 | while( info ) { | 2696 | while( info ) { |
2702 | l = line_info(page + len, info); | 2697 | line_info(m, info); |
2703 | len += l; | ||
2704 | if (len+begin > off+count) | ||
2705 | goto done; | ||
2706 | if (len+begin < off) { | ||
2707 | begin += len; | ||
2708 | len = 0; | ||
2709 | } | ||
2710 | info = info->next_device; | 2698 | info = info->next_device; |
2711 | } | 2699 | } |
2700 | return 0; | ||
2701 | } | ||
2712 | 2702 | ||
2713 | *eof = 1; | 2703 | static int mgslpc_proc_open(struct inode *inode, struct file *file) |
2714 | done: | 2704 | { |
2715 | if (off >= len+begin) | 2705 | return single_open(file, mgslpc_proc_show, NULL); |
2716 | return 0; | ||
2717 | *start = page + (off-begin); | ||
2718 | return ((count < begin+len-off) ? count : begin+len-off); | ||
2719 | } | 2706 | } |
2720 | 2707 | ||
2708 | static const struct file_operations mgslpc_proc_fops = { | ||
2709 | .owner = THIS_MODULE, | ||
2710 | .open = mgslpc_proc_open, | ||
2711 | .read = seq_read, | ||
2712 | .llseek = seq_lseek, | ||
2713 | .release = single_release, | ||
2714 | }; | ||
2715 | |||
2721 | static int rx_alloc_buffers(MGSLPC_INFO *info) | 2716 | static int rx_alloc_buffers(MGSLPC_INFO *info) |
2722 | { | 2717 | { |
2723 | /* each buffer has header and data */ | 2718 | /* each buffer has header and data */ |
@@ -2861,13 +2856,13 @@ static const struct tty_operations mgslpc_ops = { | |||
2861 | .send_xchar = mgslpc_send_xchar, | 2856 | .send_xchar = mgslpc_send_xchar, |
2862 | .break_ctl = mgslpc_break, | 2857 | .break_ctl = mgslpc_break, |
2863 | .wait_until_sent = mgslpc_wait_until_sent, | 2858 | .wait_until_sent = mgslpc_wait_until_sent, |
2864 | .read_proc = mgslpc_read_proc, | ||
2865 | .set_termios = mgslpc_set_termios, | 2859 | .set_termios = mgslpc_set_termios, |
2866 | .stop = tx_pause, | 2860 | .stop = tx_pause, |
2867 | .start = tx_release, | 2861 | .start = tx_release, |
2868 | .hangup = mgslpc_hangup, | 2862 | .hangup = mgslpc_hangup, |
2869 | .tiocmget = tiocmget, | 2863 | .tiocmget = tiocmget, |
2870 | .tiocmset = tiocmset, | 2864 | .tiocmset = tiocmset, |
2865 | .proc_fops = &mgslpc_proc_fops, | ||
2871 | }; | 2866 | }; |
2872 | 2867 | ||
2873 | static void synclink_cs_cleanup(void) | 2868 | static void synclink_cs_cleanup(void) |
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index e1e0dd89ac9..2ad813a801d 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/tty.h> | 32 | #include <linux/tty.h> |
33 | #include <linux/tty_flip.h> | 33 | #include <linux/tty_flip.h> |
34 | #include <linux/serial.h> | 34 | #include <linux/serial.h> |
35 | #include <linux/seq_file.h> | ||
35 | #include <linux/cd1400.h> | 36 | #include <linux/cd1400.h> |
36 | #include <linux/sc26198.h> | 37 | #include <linux/sc26198.h> |
37 | #include <linux/comstats.h> | 38 | #include <linux/comstats.h> |
@@ -1379,52 +1380,47 @@ static void stl_sendxchar(struct tty_struct *tty, char ch) | |||
1379 | stl_putchar(tty, ch); | 1380 | stl_putchar(tty, ch); |
1380 | } | 1381 | } |
1381 | 1382 | ||
1382 | /*****************************************************************************/ | 1383 | static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr) |
1383 | |||
1384 | #define MAXLINE 80 | ||
1385 | |||
1386 | /* | ||
1387 | * Format info for a specified port. The line is deliberately limited | ||
1388 | * to 80 characters. (If it is too long it will be truncated, if too | ||
1389 | * short then padded with spaces). | ||
1390 | */ | ||
1391 | |||
1392 | static int stl_portinfo(struct stlport *portp, int portnr, char *pos) | ||
1393 | { | 1384 | { |
1394 | char *sp; | 1385 | int sigs; |
1395 | int sigs, cnt; | 1386 | char sep; |
1396 | 1387 | ||
1397 | sp = pos; | 1388 | seq_printf(m, "%d: uart:%s tx:%d rx:%d", |
1398 | sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d", | ||
1399 | portnr, (portp->hwid == 1) ? "SC26198" : "CD1400", | 1389 | portnr, (portp->hwid == 1) ? "SC26198" : "CD1400", |
1400 | (int) portp->stats.txtotal, (int) portp->stats.rxtotal); | 1390 | (int) portp->stats.txtotal, (int) portp->stats.rxtotal); |
1401 | 1391 | ||
1402 | if (portp->stats.rxframing) | 1392 | if (portp->stats.rxframing) |
1403 | sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing); | 1393 | seq_printf(m, " fe:%d", (int) portp->stats.rxframing); |
1404 | if (portp->stats.rxparity) | 1394 | if (portp->stats.rxparity) |
1405 | sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity); | 1395 | seq_printf(m, " pe:%d", (int) portp->stats.rxparity); |
1406 | if (portp->stats.rxbreaks) | 1396 | if (portp->stats.rxbreaks) |
1407 | sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks); | 1397 | seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks); |
1408 | if (portp->stats.rxoverrun) | 1398 | if (portp->stats.rxoverrun) |
1409 | sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun); | 1399 | seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun); |
1410 | 1400 | ||
1411 | sigs = stl_getsignals(portp); | 1401 | sigs = stl_getsignals(portp); |
1412 | cnt = sprintf(sp, "%s%s%s%s%s ", | 1402 | sep = ' '; |
1413 | (sigs & TIOCM_RTS) ? "|RTS" : "", | 1403 | if (sigs & TIOCM_RTS) { |
1414 | (sigs & TIOCM_CTS) ? "|CTS" : "", | 1404 | seq_printf(m, "%c%s", sep, "RTS"); |
1415 | (sigs & TIOCM_DTR) ? "|DTR" : "", | 1405 | sep = '|'; |
1416 | (sigs & TIOCM_CD) ? "|DCD" : "", | 1406 | } |
1417 | (sigs & TIOCM_DSR) ? "|DSR" : ""); | 1407 | if (sigs & TIOCM_CTS) { |
1418 | *sp = ' '; | 1408 | seq_printf(m, "%c%s", sep, "CTS"); |
1419 | sp += cnt; | 1409 | sep = '|'; |
1420 | 1410 | } | |
1421 | for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++) | 1411 | if (sigs & TIOCM_DTR) { |
1422 | *sp++ = ' '; | 1412 | seq_printf(m, "%c%s", sep, "DTR"); |
1423 | if (cnt >= MAXLINE) | 1413 | sep = '|'; |
1424 | pos[(MAXLINE - 2)] = '+'; | 1414 | } |
1425 | pos[(MAXLINE - 1)] = '\n'; | 1415 | if (sigs & TIOCM_CD) { |
1426 | 1416 | seq_printf(m, "%c%s", sep, "DCD"); | |
1427 | return MAXLINE; | 1417 | sep = '|'; |
1418 | } | ||
1419 | if (sigs & TIOCM_DSR) { | ||
1420 | seq_printf(m, "%c%s", sep, "DSR"); | ||
1421 | sep = '|'; | ||
1422 | } | ||
1423 | seq_putc(m, '\n'); | ||
1428 | } | 1424 | } |
1429 | 1425 | ||
1430 | /*****************************************************************************/ | 1426 | /*****************************************************************************/ |
@@ -1433,30 +1429,17 @@ static int stl_portinfo(struct stlport *portp, int portnr, char *pos) | |||
1433 | * Port info, read from the /proc file system. | 1429 | * Port info, read from the /proc file system. |
1434 | */ | 1430 | */ |
1435 | 1431 | ||
1436 | static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data) | 1432 | static int stl_proc_show(struct seq_file *m, void *v) |
1437 | { | 1433 | { |
1438 | struct stlbrd *brdp; | 1434 | struct stlbrd *brdp; |
1439 | struct stlpanel *panelp; | 1435 | struct stlpanel *panelp; |
1440 | struct stlport *portp; | 1436 | struct stlport *portp; |
1441 | unsigned int brdnr, panelnr, portnr; | 1437 | unsigned int brdnr, panelnr, portnr; |
1442 | int totalport, curoff, maxoff; | 1438 | int totalport; |
1443 | char *pos; | ||
1444 | 1439 | ||
1445 | pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p," | ||
1446 | "data=%p\n", page, start, off, count, eof, data); | ||
1447 | |||
1448 | pos = page; | ||
1449 | totalport = 0; | 1440 | totalport = 0; |
1450 | curoff = 0; | 1441 | |
1451 | 1442 | seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion); | |
1452 | if (off == 0) { | ||
1453 | pos += sprintf(pos, "%s: version %s", stl_drvtitle, | ||
1454 | stl_drvversion); | ||
1455 | while (pos < (page + MAXLINE - 1)) | ||
1456 | *pos++ = ' '; | ||
1457 | *pos++ = '\n'; | ||
1458 | } | ||
1459 | curoff = MAXLINE; | ||
1460 | 1443 | ||
1461 | /* | 1444 | /* |
1462 | * We scan through for each board, panel and port. The offset is | 1445 | * We scan through for each board, panel and port. The offset is |
@@ -1469,46 +1452,37 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof | |||
1469 | if (brdp->state == 0) | 1452 | if (brdp->state == 0) |
1470 | continue; | 1453 | continue; |
1471 | 1454 | ||
1472 | maxoff = curoff + (brdp->nrports * MAXLINE); | ||
1473 | if (off >= maxoff) { | ||
1474 | curoff = maxoff; | ||
1475 | continue; | ||
1476 | } | ||
1477 | |||
1478 | totalport = brdnr * STL_MAXPORTS; | 1455 | totalport = brdnr * STL_MAXPORTS; |
1479 | for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) { | 1456 | for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) { |
1480 | panelp = brdp->panels[panelnr]; | 1457 | panelp = brdp->panels[panelnr]; |
1481 | if (panelp == NULL) | 1458 | if (panelp == NULL) |
1482 | continue; | 1459 | continue; |
1483 | 1460 | ||
1484 | maxoff = curoff + (panelp->nrports * MAXLINE); | ||
1485 | if (off >= maxoff) { | ||
1486 | curoff = maxoff; | ||
1487 | totalport += panelp->nrports; | ||
1488 | continue; | ||
1489 | } | ||
1490 | |||
1491 | for (portnr = 0; portnr < panelp->nrports; portnr++, | 1461 | for (portnr = 0; portnr < panelp->nrports; portnr++, |
1492 | totalport++) { | 1462 | totalport++) { |
1493 | portp = panelp->ports[portnr]; | 1463 | portp = panelp->ports[portnr]; |
1494 | if (portp == NULL) | 1464 | if (portp == NULL) |
1495 | continue; | 1465 | continue; |
1496 | if (off >= (curoff += MAXLINE)) | 1466 | stl_portinfo(m, portp, totalport); |
1497 | continue; | ||
1498 | if ((pos - page + MAXLINE) > count) | ||
1499 | goto stl_readdone; | ||
1500 | pos += stl_portinfo(portp, totalport, pos); | ||
1501 | } | 1467 | } |
1502 | } | 1468 | } |
1503 | } | 1469 | } |
1470 | return 0; | ||
1471 | } | ||
1504 | 1472 | ||
1505 | *eof = 1; | 1473 | static int stl_proc_open(struct inode *inode, struct file *file) |
1506 | 1474 | { | |
1507 | stl_readdone: | 1475 | return single_open(file, stl_proc_show, NULL); |
1508 | *start = page; | ||
1509 | return pos - page; | ||
1510 | } | 1476 | } |
1511 | 1477 | ||
1478 | static const struct file_operations stl_proc_fops = { | ||
1479 | .owner = THIS_MODULE, | ||
1480 | .open = stl_proc_open, | ||
1481 | .read = seq_read, | ||
1482 | .llseek = seq_lseek, | ||
1483 | .release = single_release, | ||
1484 | }; | ||
1485 | |||
1512 | /*****************************************************************************/ | 1486 | /*****************************************************************************/ |
1513 | 1487 | ||
1514 | /* | 1488 | /* |
@@ -2566,9 +2540,9 @@ static const struct tty_operations stl_ops = { | |||
2566 | .break_ctl = stl_breakctl, | 2540 | .break_ctl = stl_breakctl, |
2567 | .wait_until_sent = stl_waituntilsent, | 2541 | .wait_until_sent = stl_waituntilsent, |
2568 | .send_xchar = stl_sendxchar, | 2542 | .send_xchar = stl_sendxchar, |
2569 | .read_proc = stl_readproc, | ||
2570 | .tiocmget = stl_tiocmget, | 2543 | .tiocmget = stl_tiocmget, |
2571 | .tiocmset = stl_tiocmset, | 2544 | .tiocmset = stl_tiocmset, |
2545 | .proc_fops = &stl_proc_fops, | ||
2572 | }; | 2546 | }; |
2573 | 2547 | ||
2574 | static const struct tty_port_operations stl_port_ops = { | 2548 | static const struct tty_port_operations stl_port_ops = { |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 0057a8f58cb..afd0b26ca05 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -79,6 +79,7 @@ | |||
79 | #include <linux/ptrace.h> | 79 | #include <linux/ptrace.h> |
80 | #include <linux/ioport.h> | 80 | #include <linux/ioport.h> |
81 | #include <linux/mm.h> | 81 | #include <linux/mm.h> |
82 | #include <linux/seq_file.h> | ||
82 | #include <linux/slab.h> | 83 | #include <linux/slab.h> |
83 | #include <linux/delay.h> | 84 | #include <linux/delay.h> |
84 | #include <linux/netdevice.h> | 85 | #include <linux/netdevice.h> |
@@ -3459,18 +3460,17 @@ cleanup: | |||
3459 | * /proc fs routines.... | 3460 | * /proc fs routines.... |
3460 | */ | 3461 | */ |
3461 | 3462 | ||
3462 | static inline int line_info(char *buf, struct mgsl_struct *info) | 3463 | static inline void line_info(struct seq_file *m, struct mgsl_struct *info) |
3463 | { | 3464 | { |
3464 | char stat_buf[30]; | 3465 | char stat_buf[30]; |
3465 | int ret; | ||
3466 | unsigned long flags; | 3466 | unsigned long flags; |
3467 | 3467 | ||
3468 | if (info->bus_type == MGSL_BUS_TYPE_PCI) { | 3468 | if (info->bus_type == MGSL_BUS_TYPE_PCI) { |
3469 | ret = sprintf(buf, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X", | 3469 | seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X", |
3470 | info->device_name, info->io_base, info->irq_level, | 3470 | info->device_name, info->io_base, info->irq_level, |
3471 | info->phys_memory_base, info->phys_lcr_base); | 3471 | info->phys_memory_base, info->phys_lcr_base); |
3472 | } else { | 3472 | } else { |
3473 | ret = sprintf(buf, "%s:(E)ISA io:%04X irq:%d dma:%d", | 3473 | seq_printf(m, "%s:(E)ISA io:%04X irq:%d dma:%d", |
3474 | info->device_name, info->io_base, | 3474 | info->device_name, info->io_base, |
3475 | info->irq_level, info->dma_level); | 3475 | info->irq_level, info->dma_level); |
3476 | } | 3476 | } |
@@ -3497,37 +3497,37 @@ static inline int line_info(char *buf, struct mgsl_struct *info) | |||
3497 | 3497 | ||
3498 | if (info->params.mode == MGSL_MODE_HDLC || | 3498 | if (info->params.mode == MGSL_MODE_HDLC || |
3499 | info->params.mode == MGSL_MODE_RAW ) { | 3499 | info->params.mode == MGSL_MODE_RAW ) { |
3500 | ret += sprintf(buf+ret, " HDLC txok:%d rxok:%d", | 3500 | seq_printf(m, " HDLC txok:%d rxok:%d", |
3501 | info->icount.txok, info->icount.rxok); | 3501 | info->icount.txok, info->icount.rxok); |
3502 | if (info->icount.txunder) | 3502 | if (info->icount.txunder) |
3503 | ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); | 3503 | seq_printf(m, " txunder:%d", info->icount.txunder); |
3504 | if (info->icount.txabort) | 3504 | if (info->icount.txabort) |
3505 | ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); | 3505 | seq_printf(m, " txabort:%d", info->icount.txabort); |
3506 | if (info->icount.rxshort) | 3506 | if (info->icount.rxshort) |
3507 | ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); | 3507 | seq_printf(m, " rxshort:%d", info->icount.rxshort); |
3508 | if (info->icount.rxlong) | 3508 | if (info->icount.rxlong) |
3509 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); | 3509 | seq_printf(m, " rxlong:%d", info->icount.rxlong); |
3510 | if (info->icount.rxover) | 3510 | if (info->icount.rxover) |
3511 | ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); | 3511 | seq_printf(m, " rxover:%d", info->icount.rxover); |
3512 | if (info->icount.rxcrc) | 3512 | if (info->icount.rxcrc) |
3513 | ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); | 3513 | seq_printf(m, " rxcrc:%d", info->icount.rxcrc); |
3514 | } else { | 3514 | } else { |
3515 | ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d", | 3515 | seq_printf(m, " ASYNC tx:%d rx:%d", |
3516 | info->icount.tx, info->icount.rx); | 3516 | info->icount.tx, info->icount.rx); |
3517 | if (info->icount.frame) | 3517 | if (info->icount.frame) |
3518 | ret += sprintf(buf+ret, " fe:%d", info->icount.frame); | 3518 | seq_printf(m, " fe:%d", info->icount.frame); |
3519 | if (info->icount.parity) | 3519 | if (info->icount.parity) |
3520 | ret += sprintf(buf+ret, " pe:%d", info->icount.parity); | 3520 | seq_printf(m, " pe:%d", info->icount.parity); |
3521 | if (info->icount.brk) | 3521 | if (info->icount.brk) |
3522 | ret += sprintf(buf+ret, " brk:%d", info->icount.brk); | 3522 | seq_printf(m, " brk:%d", info->icount.brk); |
3523 | if (info->icount.overrun) | 3523 | if (info->icount.overrun) |
3524 | ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); | 3524 | seq_printf(m, " oe:%d", info->icount.overrun); |
3525 | } | 3525 | } |
3526 | 3526 | ||
3527 | /* Append serial signal status to end */ | 3527 | /* Append serial signal status to end */ |
3528 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 3528 | seq_printf(m, " %s\n", stat_buf+1); |
3529 | 3529 | ||
3530 | ret += sprintf(buf+ret, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", | 3530 | seq_printf(m, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", |
3531 | info->tx_active,info->bh_requested,info->bh_running, | 3531 | info->tx_active,info->bh_requested,info->bh_running, |
3532 | info->pending_bh); | 3532 | info->pending_bh); |
3533 | 3533 | ||
@@ -3544,60 +3544,40 @@ static inline int line_info(char *buf, struct mgsl_struct *info) | |||
3544 | u16 Tmr = usc_InReg( info, TMR ); | 3544 | u16 Tmr = usc_InReg( info, TMR ); |
3545 | u16 Tccr = usc_InReg( info, TCCR ); | 3545 | u16 Tccr = usc_InReg( info, TCCR ); |
3546 | u16 Ccar = inw( info->io_base + CCAR ); | 3546 | u16 Ccar = inw( info->io_base + CCAR ); |
3547 | ret += sprintf(buf+ret, "tcsr=%04X tdmr=%04X ticr=%04X rcsr=%04X rdmr=%04X\n" | 3547 | seq_printf(m, "tcsr=%04X tdmr=%04X ticr=%04X rcsr=%04X rdmr=%04X\n" |
3548 | "ricr=%04X icr =%04X dccr=%04X tmr=%04X tccr=%04X ccar=%04X\n", | 3548 | "ricr=%04X icr =%04X dccr=%04X tmr=%04X tccr=%04X ccar=%04X\n", |
3549 | Tcsr,Tdmr,Ticr,Rscr,Rdmr,Ricr,Icr,Dccr,Tmr,Tccr,Ccar ); | 3549 | Tcsr,Tdmr,Ticr,Rscr,Rdmr,Ricr,Icr,Dccr,Tmr,Tccr,Ccar ); |
3550 | } | 3550 | } |
3551 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | 3551 | spin_unlock_irqrestore(&info->irq_spinlock,flags); |
3552 | 3552 | } | |
3553 | return ret; | ||
3554 | |||
3555 | } /* end of line_info() */ | ||
3556 | 3553 | ||
3557 | /* mgsl_read_proc() | 3554 | /* Called to print information about devices */ |
3558 | * | 3555 | static int mgsl_proc_show(struct seq_file *m, void *v) |
3559 | * Called to print information about devices | ||
3560 | * | ||
3561 | * Arguments: | ||
3562 | * page page of memory to hold returned info | ||
3563 | * start | ||
3564 | * off | ||
3565 | * count | ||
3566 | * eof | ||
3567 | * data | ||
3568 | * | ||
3569 | * Return Value: | ||
3570 | */ | ||
3571 | static int mgsl_read_proc(char *page, char **start, off_t off, int count, | ||
3572 | int *eof, void *data) | ||
3573 | { | 3556 | { |
3574 | int len = 0, l; | ||
3575 | off_t begin = 0; | ||
3576 | struct mgsl_struct *info; | 3557 | struct mgsl_struct *info; |
3577 | 3558 | ||
3578 | len += sprintf(page, "synclink driver:%s\n", driver_version); | 3559 | seq_printf(m, "synclink driver:%s\n", driver_version); |
3579 | 3560 | ||
3580 | info = mgsl_device_list; | 3561 | info = mgsl_device_list; |
3581 | while( info ) { | 3562 | while( info ) { |
3582 | l = line_info(page + len, info); | 3563 | line_info(m, info); |
3583 | len += l; | ||
3584 | if (len+begin > off+count) | ||
3585 | goto done; | ||
3586 | if (len+begin < off) { | ||
3587 | begin += len; | ||
3588 | len = 0; | ||
3589 | } | ||
3590 | info = info->next_device; | 3564 | info = info->next_device; |
3591 | } | 3565 | } |
3566 | return 0; | ||
3567 | } | ||
3592 | 3568 | ||
3593 | *eof = 1; | 3569 | static int mgsl_proc_open(struct inode *inode, struct file *file) |
3594 | done: | 3570 | { |
3595 | if (off >= len+begin) | 3571 | return single_open(file, mgsl_proc_show, NULL); |
3596 | return 0; | 3572 | } |
3597 | *start = page + (off-begin); | 3573 | |
3598 | return ((count < begin+len-off) ? count : begin+len-off); | 3574 | static const struct file_operations mgsl_proc_fops = { |
3599 | 3575 | .owner = THIS_MODULE, | |
3600 | } /* end of mgsl_read_proc() */ | 3576 | .open = mgsl_proc_open, |
3577 | .read = seq_read, | ||
3578 | .llseek = seq_lseek, | ||
3579 | .release = single_release, | ||
3580 | }; | ||
3601 | 3581 | ||
3602 | /* mgsl_allocate_dma_buffers() | 3582 | /* mgsl_allocate_dma_buffers() |
3603 | * | 3583 | * |
@@ -4335,13 +4315,13 @@ static const struct tty_operations mgsl_ops = { | |||
4335 | .send_xchar = mgsl_send_xchar, | 4315 | .send_xchar = mgsl_send_xchar, |
4336 | .break_ctl = mgsl_break, | 4316 | .break_ctl = mgsl_break, |
4337 | .wait_until_sent = mgsl_wait_until_sent, | 4317 | .wait_until_sent = mgsl_wait_until_sent, |
4338 | .read_proc = mgsl_read_proc, | ||
4339 | .set_termios = mgsl_set_termios, | 4318 | .set_termios = mgsl_set_termios, |
4340 | .stop = mgsl_stop, | 4319 | .stop = mgsl_stop, |
4341 | .start = mgsl_start, | 4320 | .start = mgsl_start, |
4342 | .hangup = mgsl_hangup, | 4321 | .hangup = mgsl_hangup, |
4343 | .tiocmget = tiocmget, | 4322 | .tiocmget = tiocmget, |
4344 | .tiocmset = tiocmset, | 4323 | .tiocmset = tiocmset, |
4324 | .proc_fops = &mgsl_proc_fops, | ||
4345 | }; | 4325 | }; |
4346 | 4326 | ||
4347 | /* | 4327 | /* |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index efb3dc928a4..6ec6e13d47d 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #include <linux/ptrace.h> | 60 | #include <linux/ptrace.h> |
61 | #include <linux/ioport.h> | 61 | #include <linux/ioport.h> |
62 | #include <linux/mm.h> | 62 | #include <linux/mm.h> |
63 | #include <linux/seq_file.h> | ||
63 | #include <linux/slab.h> | 64 | #include <linux/slab.h> |
64 | #include <linux/netdevice.h> | 65 | #include <linux/netdevice.h> |
65 | #include <linux/vmalloc.h> | 66 | #include <linux/vmalloc.h> |
@@ -154,7 +155,6 @@ static void tx_hold(struct tty_struct *tty); | |||
154 | static void tx_release(struct tty_struct *tty); | 155 | static void tx_release(struct tty_struct *tty); |
155 | 156 | ||
156 | static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); | 157 | static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); |
157 | static int read_proc(char *page, char **start, off_t off, int count,int *eof, void *data); | ||
158 | static int chars_in_buffer(struct tty_struct *tty); | 158 | static int chars_in_buffer(struct tty_struct *tty); |
159 | static void throttle(struct tty_struct * tty); | 159 | static void throttle(struct tty_struct * tty); |
160 | static void unthrottle(struct tty_struct * tty); | 160 | static void unthrottle(struct tty_struct * tty); |
@@ -1229,13 +1229,12 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file, | |||
1229 | /* | 1229 | /* |
1230 | * proc fs support | 1230 | * proc fs support |
1231 | */ | 1231 | */ |
1232 | static inline int line_info(char *buf, struct slgt_info *info) | 1232 | static inline void line_info(struct seq_file *m, struct slgt_info *info) |
1233 | { | 1233 | { |
1234 | char stat_buf[30]; | 1234 | char stat_buf[30]; |
1235 | int ret; | ||
1236 | unsigned long flags; | 1235 | unsigned long flags; |
1237 | 1236 | ||
1238 | ret = sprintf(buf, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n", | 1237 | seq_printf(m, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n", |
1239 | info->device_name, info->phys_reg_addr, | 1238 | info->device_name, info->phys_reg_addr, |
1240 | info->irq_level, info->max_frame_size); | 1239 | info->irq_level, info->max_frame_size); |
1241 | 1240 | ||
@@ -1260,75 +1259,70 @@ static inline int line_info(char *buf, struct slgt_info *info) | |||
1260 | strcat(stat_buf, "|RI"); | 1259 | strcat(stat_buf, "|RI"); |
1261 | 1260 | ||
1262 | if (info->params.mode != MGSL_MODE_ASYNC) { | 1261 | if (info->params.mode != MGSL_MODE_ASYNC) { |
1263 | ret += sprintf(buf+ret, "\tHDLC txok:%d rxok:%d", | 1262 | seq_printf(m, "\tHDLC txok:%d rxok:%d", |
1264 | info->icount.txok, info->icount.rxok); | 1263 | info->icount.txok, info->icount.rxok); |
1265 | if (info->icount.txunder) | 1264 | if (info->icount.txunder) |
1266 | ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); | 1265 | seq_printf(m, " txunder:%d", info->icount.txunder); |
1267 | if (info->icount.txabort) | 1266 | if (info->icount.txabort) |
1268 | ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); | 1267 | seq_printf(m, " txabort:%d", info->icount.txabort); |
1269 | if (info->icount.rxshort) | 1268 | if (info->icount.rxshort) |
1270 | ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); | 1269 | seq_printf(m, " rxshort:%d", info->icount.rxshort); |
1271 | if (info->icount.rxlong) | 1270 | if (info->icount.rxlong) |
1272 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); | 1271 | seq_printf(m, " rxlong:%d", info->icount.rxlong); |
1273 | if (info->icount.rxover) | 1272 | if (info->icount.rxover) |
1274 | ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); | 1273 | seq_printf(m, " rxover:%d", info->icount.rxover); |
1275 | if (info->icount.rxcrc) | 1274 | if (info->icount.rxcrc) |
1276 | ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); | 1275 | seq_printf(m, " rxcrc:%d", info->icount.rxcrc); |
1277 | } else { | 1276 | } else { |
1278 | ret += sprintf(buf+ret, "\tASYNC tx:%d rx:%d", | 1277 | seq_printf(m, "\tASYNC tx:%d rx:%d", |
1279 | info->icount.tx, info->icount.rx); | 1278 | info->icount.tx, info->icount.rx); |
1280 | if (info->icount.frame) | 1279 | if (info->icount.frame) |
1281 | ret += sprintf(buf+ret, " fe:%d", info->icount.frame); | 1280 | seq_printf(m, " fe:%d", info->icount.frame); |
1282 | if (info->icount.parity) | 1281 | if (info->icount.parity) |
1283 | ret += sprintf(buf+ret, " pe:%d", info->icount.parity); | 1282 | seq_printf(m, " pe:%d", info->icount.parity); |
1284 | if (info->icount.brk) | 1283 | if (info->icount.brk) |
1285 | ret += sprintf(buf+ret, " brk:%d", info->icount.brk); | 1284 | seq_printf(m, " brk:%d", info->icount.brk); |
1286 | if (info->icount.overrun) | 1285 | if (info->icount.overrun) |
1287 | ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); | 1286 | seq_printf(m, " oe:%d", info->icount.overrun); |
1288 | } | 1287 | } |
1289 | 1288 | ||
1290 | /* Append serial signal status to end */ | 1289 | /* Append serial signal status to end */ |
1291 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 1290 | seq_printf(m, " %s\n", stat_buf+1); |
1292 | 1291 | ||
1293 | ret += sprintf(buf+ret, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", | 1292 | seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", |
1294 | info->tx_active,info->bh_requested,info->bh_running, | 1293 | info->tx_active,info->bh_requested,info->bh_running, |
1295 | info->pending_bh); | 1294 | info->pending_bh); |
1296 | |||
1297 | return ret; | ||
1298 | } | 1295 | } |
1299 | 1296 | ||
1300 | /* Called to print information about devices | 1297 | /* Called to print information about devices |
1301 | */ | 1298 | */ |
1302 | static int read_proc(char *page, char **start, off_t off, int count, | 1299 | static int synclink_gt_proc_show(struct seq_file *m, void *v) |
1303 | int *eof, void *data) | ||
1304 | { | 1300 | { |
1305 | int len = 0, l; | ||
1306 | off_t begin = 0; | ||
1307 | struct slgt_info *info; | 1301 | struct slgt_info *info; |
1308 | 1302 | ||
1309 | len += sprintf(page, "synclink_gt driver\n"); | 1303 | seq_puts(m, "synclink_gt driver\n"); |
1310 | 1304 | ||
1311 | info = slgt_device_list; | 1305 | info = slgt_device_list; |
1312 | while( info ) { | 1306 | while( info ) { |
1313 | l = line_info(page + len, info); | 1307 | line_info(m, info); |
1314 | len += l; | ||
1315 | if (len+begin > off+count) | ||
1316 | goto done; | ||
1317 | if (len+begin < off) { | ||
1318 | begin += len; | ||
1319 | len = 0; | ||
1320 | } | ||
1321 | info = info->next_device; | 1308 | info = info->next_device; |
1322 | } | 1309 | } |
1310 | return 0; | ||
1311 | } | ||
1323 | 1312 | ||
1324 | *eof = 1; | 1313 | static int synclink_gt_proc_open(struct inode *inode, struct file *file) |
1325 | done: | 1314 | { |
1326 | if (off >= len+begin) | 1315 | return single_open(file, synclink_gt_proc_show, NULL); |
1327 | return 0; | ||
1328 | *start = page + (off-begin); | ||
1329 | return ((count < begin+len-off) ? count : begin+len-off); | ||
1330 | } | 1316 | } |
1331 | 1317 | ||
1318 | static const struct file_operations synclink_gt_proc_fops = { | ||
1319 | .owner = THIS_MODULE, | ||
1320 | .open = synclink_gt_proc_open, | ||
1321 | .read = seq_read, | ||
1322 | .llseek = seq_lseek, | ||
1323 | .release = single_release, | ||
1324 | }; | ||
1325 | |||
1332 | /* | 1326 | /* |
1333 | * return count of bytes in transmit buffer | 1327 | * return count of bytes in transmit buffer |
1334 | */ | 1328 | */ |
@@ -3562,13 +3556,13 @@ static const struct tty_operations ops = { | |||
3562 | .send_xchar = send_xchar, | 3556 | .send_xchar = send_xchar, |
3563 | .break_ctl = set_break, | 3557 | .break_ctl = set_break, |
3564 | .wait_until_sent = wait_until_sent, | 3558 | .wait_until_sent = wait_until_sent, |
3565 | .read_proc = read_proc, | ||
3566 | .set_termios = set_termios, | 3559 | .set_termios = set_termios, |
3567 | .stop = tx_hold, | 3560 | .stop = tx_hold, |
3568 | .start = tx_release, | 3561 | .start = tx_release, |
3569 | .hangup = hangup, | 3562 | .hangup = hangup, |
3570 | .tiocmget = tiocmget, | 3563 | .tiocmget = tiocmget, |
3571 | .tiocmset = tiocmset, | 3564 | .tiocmset = tiocmset, |
3565 | .proc_fops = &synclink_gt_proc_fops, | ||
3572 | }; | 3566 | }; |
3573 | 3567 | ||
3574 | static void slgt_cleanup(void) | 3568 | static void slgt_cleanup(void) |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 8eb6c89a980..26de60efe4b 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/ptrace.h> | 50 | #include <linux/ptrace.h> |
51 | #include <linux/ioport.h> | 51 | #include <linux/ioport.h> |
52 | #include <linux/mm.h> | 52 | #include <linux/mm.h> |
53 | #include <linux/seq_file.h> | ||
53 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
54 | #include <linux/netdevice.h> | 55 | #include <linux/netdevice.h> |
55 | #include <linux/vmalloc.h> | 56 | #include <linux/vmalloc.h> |
@@ -520,7 +521,6 @@ static void tx_hold(struct tty_struct *tty); | |||
520 | static void tx_release(struct tty_struct *tty); | 521 | static void tx_release(struct tty_struct *tty); |
521 | 522 | ||
522 | static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); | 523 | static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); |
523 | static int read_proc(char *page, char **start, off_t off, int count,int *eof, void *data); | ||
524 | static int chars_in_buffer(struct tty_struct *tty); | 524 | static int chars_in_buffer(struct tty_struct *tty); |
525 | static void throttle(struct tty_struct * tty); | 525 | static void throttle(struct tty_struct * tty); |
526 | static void unthrottle(struct tty_struct * tty); | 526 | static void unthrottle(struct tty_struct * tty); |
@@ -1354,13 +1354,12 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
1354 | * /proc fs routines.... | 1354 | * /proc fs routines.... |
1355 | */ | 1355 | */ |
1356 | 1356 | ||
1357 | static inline int line_info(char *buf, SLMP_INFO *info) | 1357 | static inline void line_info(struct seq_file *m, SLMP_INFO *info) |
1358 | { | 1358 | { |
1359 | char stat_buf[30]; | 1359 | char stat_buf[30]; |
1360 | int ret; | ||
1361 | unsigned long flags; | 1360 | unsigned long flags; |
1362 | 1361 | ||
1363 | ret = sprintf(buf, "%s: SCABase=%08x Mem=%08X StatusControl=%08x LCR=%08X\n" | 1362 | seq_printf(m, "%s: SCABase=%08x Mem=%08X StatusControl=%08x LCR=%08X\n" |
1364 | "\tIRQ=%d MaxFrameSize=%u\n", | 1363 | "\tIRQ=%d MaxFrameSize=%u\n", |
1365 | info->device_name, | 1364 | info->device_name, |
1366 | info->phys_sca_base, | 1365 | info->phys_sca_base, |
@@ -1391,75 +1390,70 @@ static inline int line_info(char *buf, SLMP_INFO *info) | |||
1391 | strcat(stat_buf, "|RI"); | 1390 | strcat(stat_buf, "|RI"); |
1392 | 1391 | ||
1393 | if (info->params.mode == MGSL_MODE_HDLC) { | 1392 | if (info->params.mode == MGSL_MODE_HDLC) { |
1394 | ret += sprintf(buf+ret, "\tHDLC txok:%d rxok:%d", | 1393 | seq_printf(m, "\tHDLC txok:%d rxok:%d", |
1395 | info->icount.txok, info->icount.rxok); | 1394 | info->icount.txok, info->icount.rxok); |
1396 | if (info->icount.txunder) | 1395 | if (info->icount.txunder) |
1397 | ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); | 1396 | seq_printf(m, " txunder:%d", info->icount.txunder); |
1398 | if (info->icount.txabort) | 1397 | if (info->icount.txabort) |
1399 | ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); | 1398 | seq_printf(m, " txabort:%d", info->icount.txabort); |
1400 | if (info->icount.rxshort) | 1399 | if (info->icount.rxshort) |
1401 | ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); | 1400 | seq_printf(m, " rxshort:%d", info->icount.rxshort); |
1402 | if (info->icount.rxlong) | 1401 | if (info->icount.rxlong) |
1403 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); | 1402 | seq_printf(m, " rxlong:%d", info->icount.rxlong); |
1404 | if (info->icount.rxover) | 1403 | if (info->icount.rxover) |
1405 | ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); | 1404 | seq_printf(m, " rxover:%d", info->icount.rxover); |
1406 | if (info->icount.rxcrc) | 1405 | if (info->icount.rxcrc) |
1407 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxcrc); | 1406 | seq_printf(m, " rxlong:%d", info->icount.rxcrc); |
1408 | } else { | 1407 | } else { |
1409 | ret += sprintf(buf+ret, "\tASYNC tx:%d rx:%d", | 1408 | seq_printf(m, "\tASYNC tx:%d rx:%d", |
1410 | info->icount.tx, info->icount.rx); | 1409 | info->icount.tx, info->icount.rx); |
1411 | if (info->icount.frame) | 1410 | if (info->icount.frame) |
1412 | ret += sprintf(buf+ret, " fe:%d", info->icount.frame); | 1411 | seq_printf(m, " fe:%d", info->icount.frame); |
1413 | if (info->icount.parity) | 1412 | if (info->icount.parity) |
1414 | ret += sprintf(buf+ret, " pe:%d", info->icount.parity); | 1413 | seq_printf(m, " pe:%d", info->icount.parity); |
1415 | if (info->icount.brk) | 1414 | if (info->icount.brk) |
1416 | ret += sprintf(buf+ret, " brk:%d", info->icount.brk); | 1415 | seq_printf(m, " brk:%d", info->icount.brk); |
1417 | if (info->icount.overrun) | 1416 | if (info->icount.overrun) |
1418 | ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); | 1417 | seq_printf(m, " oe:%d", info->icount.overrun); |
1419 | } | 1418 | } |
1420 | 1419 | ||
1421 | /* Append serial signal status to end */ | 1420 | /* Append serial signal status to end */ |
1422 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 1421 | seq_printf(m, " %s\n", stat_buf+1); |
1423 | 1422 | ||
1424 | ret += sprintf(buf+ret, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", | 1423 | seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", |
1425 | info->tx_active,info->bh_requested,info->bh_running, | 1424 | info->tx_active,info->bh_requested,info->bh_running, |
1426 | info->pending_bh); | 1425 | info->pending_bh); |
1427 | |||
1428 | return ret; | ||
1429 | } | 1426 | } |
1430 | 1427 | ||
1431 | /* Called to print information about devices | 1428 | /* Called to print information about devices |
1432 | */ | 1429 | */ |
1433 | static int read_proc(char *page, char **start, off_t off, int count, | 1430 | static int synclinkmp_proc_show(struct seq_file *m, void *v) |
1434 | int *eof, void *data) | ||
1435 | { | 1431 | { |
1436 | int len = 0, l; | ||
1437 | off_t begin = 0; | ||
1438 | SLMP_INFO *info; | 1432 | SLMP_INFO *info; |
1439 | 1433 | ||
1440 | len += sprintf(page, "synclinkmp driver:%s\n", driver_version); | 1434 | seq_printf(m, "synclinkmp driver:%s\n", driver_version); |
1441 | 1435 | ||
1442 | info = synclinkmp_device_list; | 1436 | info = synclinkmp_device_list; |
1443 | while( info ) { | 1437 | while( info ) { |
1444 | l = line_info(page + len, info); | 1438 | line_info(m, info); |
1445 | len += l; | ||
1446 | if (len+begin > off+count) | ||
1447 | goto done; | ||
1448 | if (len+begin < off) { | ||
1449 | begin += len; | ||
1450 | len = 0; | ||
1451 | } | ||
1452 | info = info->next_device; | 1439 | info = info->next_device; |
1453 | } | 1440 | } |
1441 | return 0; | ||
1442 | } | ||
1454 | 1443 | ||
1455 | *eof = 1; | 1444 | static int synclinkmp_proc_open(struct inode *inode, struct file *file) |
1456 | done: | 1445 | { |
1457 | if (off >= len+begin) | 1446 | return single_open(file, synclinkmp_proc_show, NULL); |
1458 | return 0; | ||
1459 | *start = page + (off-begin); | ||
1460 | return ((count < begin+len-off) ? count : begin+len-off); | ||
1461 | } | 1447 | } |
1462 | 1448 | ||
1449 | static const struct file_operations synclinkmp_proc_fops = { | ||
1450 | .owner = THIS_MODULE, | ||
1451 | .open = synclinkmp_proc_open, | ||
1452 | .read = seq_read, | ||
1453 | .llseek = seq_lseek, | ||
1454 | .release = single_release, | ||
1455 | }; | ||
1456 | |||
1463 | /* Return the count of bytes in transmit buffer | 1457 | /* Return the count of bytes in transmit buffer |
1464 | */ | 1458 | */ |
1465 | static int chars_in_buffer(struct tty_struct *tty) | 1459 | static int chars_in_buffer(struct tty_struct *tty) |
@@ -3905,13 +3899,13 @@ static const struct tty_operations ops = { | |||
3905 | .send_xchar = send_xchar, | 3899 | .send_xchar = send_xchar, |
3906 | .break_ctl = set_break, | 3900 | .break_ctl = set_break, |
3907 | .wait_until_sent = wait_until_sent, | 3901 | .wait_until_sent = wait_until_sent, |
3908 | .read_proc = read_proc, | ||
3909 | .set_termios = set_termios, | 3902 | .set_termios = set_termios, |
3910 | .stop = tx_hold, | 3903 | .stop = tx_hold, |
3911 | .start = tx_release, | 3904 | .start = tx_release, |
3912 | .hangup = hangup, | 3905 | .hangup = hangup, |
3913 | .tiocmget = tiocmget, | 3906 | .tiocmget = tiocmget, |
3914 | .tiocmset = tiocmset, | 3907 | .tiocmset = tiocmset, |
3908 | .proc_fops = &synclinkmp_proc_fops, | ||
3915 | }; | 3909 | }; |
3916 | 3910 | ||
3917 | 3911 | ||
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 3df694e5454..ebea9b2c30a 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
@@ -346,6 +346,19 @@ static struct sysrq_key_op sysrq_moom_op = { | |||
346 | .enable_mask = SYSRQ_ENABLE_SIGNAL, | 346 | .enable_mask = SYSRQ_ENABLE_SIGNAL, |
347 | }; | 347 | }; |
348 | 348 | ||
349 | #ifdef CONFIG_BLOCK | ||
350 | static void sysrq_handle_thaw(int key, struct tty_struct *tty) | ||
351 | { | ||
352 | emergency_thaw_all(); | ||
353 | } | ||
354 | static struct sysrq_key_op sysrq_thaw_op = { | ||
355 | .handler = sysrq_handle_thaw, | ||
356 | .help_msg = "thaw-filesystems(J)", | ||
357 | .action_msg = "Emergency Thaw of all frozen filesystems", | ||
358 | .enable_mask = SYSRQ_ENABLE_SIGNAL, | ||
359 | }; | ||
360 | #endif | ||
361 | |||
349 | static void sysrq_handle_kill(int key, struct tty_struct *tty) | 362 | static void sysrq_handle_kill(int key, struct tty_struct *tty) |
350 | { | 363 | { |
351 | send_sig_all(SIGKILL); | 364 | send_sig_all(SIGKILL); |
@@ -396,9 +409,13 @@ static struct sysrq_key_op *sysrq_key_table[36] = { | |||
396 | &sysrq_moom_op, /* f */ | 409 | &sysrq_moom_op, /* f */ |
397 | /* g: May be registered by ppc for kgdb */ | 410 | /* g: May be registered by ppc for kgdb */ |
398 | NULL, /* g */ | 411 | NULL, /* g */ |
399 | NULL, /* h */ | 412 | NULL, /* h - reserved for help */ |
400 | &sysrq_kill_op, /* i */ | 413 | &sysrq_kill_op, /* i */ |
414 | #ifdef CONFIG_BLOCK | ||
415 | &sysrq_thaw_op, /* j */ | ||
416 | #else | ||
401 | NULL, /* j */ | 417 | NULL, /* j */ |
418 | #endif | ||
402 | &sysrq_SAK_op, /* k */ | 419 | &sysrq_SAK_op, /* k */ |
403 | #ifdef CONFIG_SMP | 420 | #ifdef CONFIG_SMP |
404 | &sysrq_showallcpus_op, /* l */ | 421 | &sysrq_showallcpus_op, /* l */ |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 224f271d8cb..33dac94922a 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -464,7 +464,7 @@ void tty_wakeup(struct tty_struct *tty) | |||
464 | tty_ldisc_deref(ld); | 464 | tty_ldisc_deref(ld); |
465 | } | 465 | } |
466 | } | 466 | } |
467 | wake_up_interruptible(&tty->write_wait); | 467 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); |
468 | } | 468 | } |
469 | 469 | ||
470 | EXPORT_SYMBOL_GPL(tty_wakeup); | 470 | EXPORT_SYMBOL_GPL(tty_wakeup); |
@@ -587,8 +587,8 @@ static void do_tty_hangup(struct work_struct *work) | |||
587 | * FIXME: Once we trust the LDISC code better we can wait here for | 587 | * FIXME: Once we trust the LDISC code better we can wait here for |
588 | * ldisc completion and fix the driver call race | 588 | * ldisc completion and fix the driver call race |
589 | */ | 589 | */ |
590 | wake_up_interruptible(&tty->write_wait); | 590 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); |
591 | wake_up_interruptible(&tty->read_wait); | 591 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); |
592 | /* | 592 | /* |
593 | * Shutdown the current line discipline, and reset it to | 593 | * Shutdown the current line discipline, and reset it to |
594 | * N_TTY. | 594 | * N_TTY. |
@@ -879,7 +879,7 @@ void stop_tty(struct tty_struct *tty) | |||
879 | if (tty->link && tty->link->packet) { | 879 | if (tty->link && tty->link->packet) { |
880 | tty->ctrl_status &= ~TIOCPKT_START; | 880 | tty->ctrl_status &= ~TIOCPKT_START; |
881 | tty->ctrl_status |= TIOCPKT_STOP; | 881 | tty->ctrl_status |= TIOCPKT_STOP; |
882 | wake_up_interruptible(&tty->link->read_wait); | 882 | wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); |
883 | } | 883 | } |
884 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 884 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
885 | if (tty->ops->stop) | 885 | if (tty->ops->stop) |
@@ -913,7 +913,7 @@ void start_tty(struct tty_struct *tty) | |||
913 | if (tty->link && tty->link->packet) { | 913 | if (tty->link && tty->link->packet) { |
914 | tty->ctrl_status &= ~TIOCPKT_STOP; | 914 | tty->ctrl_status &= ~TIOCPKT_STOP; |
915 | tty->ctrl_status |= TIOCPKT_START; | 915 | tty->ctrl_status |= TIOCPKT_START; |
916 | wake_up_interruptible(&tty->link->read_wait); | 916 | wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); |
917 | } | 917 | } |
918 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 918 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
919 | if (tty->ops->start) | 919 | if (tty->ops->start) |
@@ -970,7 +970,7 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, | |||
970 | void tty_write_unlock(struct tty_struct *tty) | 970 | void tty_write_unlock(struct tty_struct *tty) |
971 | { | 971 | { |
972 | mutex_unlock(&tty->atomic_write_lock); | 972 | mutex_unlock(&tty->atomic_write_lock); |
973 | wake_up_interruptible(&tty->write_wait); | 973 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); |
974 | } | 974 | } |
975 | 975 | ||
976 | int tty_write_lock(struct tty_struct *tty, int ndelay) | 976 | int tty_write_lock(struct tty_struct *tty, int ndelay) |
@@ -1623,21 +1623,21 @@ void tty_release_dev(struct file *filp) | |||
1623 | 1623 | ||
1624 | if (tty_closing) { | 1624 | if (tty_closing) { |
1625 | if (waitqueue_active(&tty->read_wait)) { | 1625 | if (waitqueue_active(&tty->read_wait)) { |
1626 | wake_up(&tty->read_wait); | 1626 | wake_up_poll(&tty->read_wait, POLLIN); |
1627 | do_sleep++; | 1627 | do_sleep++; |
1628 | } | 1628 | } |
1629 | if (waitqueue_active(&tty->write_wait)) { | 1629 | if (waitqueue_active(&tty->write_wait)) { |
1630 | wake_up(&tty->write_wait); | 1630 | wake_up_poll(&tty->write_wait, POLLOUT); |
1631 | do_sleep++; | 1631 | do_sleep++; |
1632 | } | 1632 | } |
1633 | } | 1633 | } |
1634 | if (o_tty_closing) { | 1634 | if (o_tty_closing) { |
1635 | if (waitqueue_active(&o_tty->read_wait)) { | 1635 | if (waitqueue_active(&o_tty->read_wait)) { |
1636 | wake_up(&o_tty->read_wait); | 1636 | wake_up_poll(&o_tty->read_wait, POLLIN); |
1637 | do_sleep++; | 1637 | do_sleep++; |
1638 | } | 1638 | } |
1639 | if (waitqueue_active(&o_tty->write_wait)) { | 1639 | if (waitqueue_active(&o_tty->write_wait)) { |
1640 | wake_up(&o_tty->write_wait); | 1640 | wake_up_poll(&o_tty->write_wait, POLLOUT); |
1641 | do_sleep++; | 1641 | do_sleep++; |
1642 | } | 1642 | } |
1643 | } | 1643 | } |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 51ff9b3d7ea..ce52bf2f235 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -571,6 +571,17 @@ config SENSORS_LM93 | |||
571 | This driver can also be built as a module. If so, the module | 571 | This driver can also be built as a module. If so, the module |
572 | will be called lm93. | 572 | will be called lm93. |
573 | 573 | ||
574 | config SENSORS_LTC4215 | ||
575 | tristate "Linear Technology LTC4215" | ||
576 | depends on I2C && EXPERIMENTAL | ||
577 | default n | ||
578 | help | ||
579 | If you say yes here you get support for Linear Technology LTC4215 | ||
580 | Hot Swap Controller I2C interface. | ||
581 | |||
582 | This driver can also be built as a module. If so, the module will | ||
583 | be called ltc4215. | ||
584 | |||
574 | config SENSORS_LTC4245 | 585 | config SENSORS_LTC4245 |
575 | tristate "Linear Technology LTC4245" | 586 | tristate "Linear Technology LTC4245" |
576 | depends on I2C && EXPERIMENTAL | 587 | depends on I2C && EXPERIMENTAL |
@@ -582,6 +593,15 @@ config SENSORS_LTC4245 | |||
582 | This driver can also be built as a module. If so, the module will | 593 | This driver can also be built as a module. If so, the module will |
583 | be called ltc4245. | 594 | be called ltc4245. |
584 | 595 | ||
596 | config SENSORS_LM95241 | ||
597 | tristate "National Semiconductor LM95241 sensor chip" | ||
598 | depends on I2C | ||
599 | help | ||
600 | If you say yes here you get support for LM95241 sensor chip. | ||
601 | |||
602 | This driver can also be built as a module. If so, the module | ||
603 | will be called lm95241. | ||
604 | |||
585 | config SENSORS_MAX1111 | 605 | config SENSORS_MAX1111 |
586 | tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" | 606 | tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" |
587 | depends on SPI_MASTER | 607 | depends on SPI_MASTER |
@@ -912,6 +932,22 @@ config SENSORS_LIS3LV02D | |||
912 | Say Y here if you have an applicable laptop and want to experience | 932 | Say Y here if you have an applicable laptop and want to experience |
913 | the awesome power of lis3lv02d. | 933 | the awesome power of lis3lv02d. |
914 | 934 | ||
935 | config SENSORS_LIS3_SPI | ||
936 | tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)" | ||
937 | depends on !ACPI && SPI_MASTER && INPUT | ||
938 | default n | ||
939 | help | ||
940 | This driver provides support for the LIS3LV02Dx accelerometer connected | ||
941 | via SPI. The accelerometer data is readable via | ||
942 | /sys/devices/platform/lis3lv02d. | ||
943 | |||
944 | This driver also provides an absolute input class device, allowing | ||
945 | the laptop to act as a pinball machine-esque joystick. | ||
946 | |||
947 | This driver can also be built as modules. If so, the core module | ||
948 | will be called lis3lv02d and a specific module for the SPI transport | ||
949 | is called lis3lv02d_spi. | ||
950 | |||
915 | config SENSORS_APPLESMC | 951 | config SENSORS_APPLESMC |
916 | tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)" | 952 | tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)" |
917 | depends on INPUT && X86 | 953 | depends on INPUT && X86 |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index e332d626792..3a6b1f06f8f 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -52,6 +52,7 @@ obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o | |||
52 | obj-$(CONFIG_SENSORS_IT87) += it87.o | 52 | obj-$(CONFIG_SENSORS_IT87) += it87.o |
53 | obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o | 53 | obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o |
54 | obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o | 54 | obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o |
55 | obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o | ||
55 | obj-$(CONFIG_SENSORS_LM63) += lm63.o | 56 | obj-$(CONFIG_SENSORS_LM63) += lm63.o |
56 | obj-$(CONFIG_SENSORS_LM70) += lm70.o | 57 | obj-$(CONFIG_SENSORS_LM70) += lm70.o |
57 | obj-$(CONFIG_SENSORS_LM75) += lm75.o | 58 | obj-$(CONFIG_SENSORS_LM75) += lm75.o |
@@ -64,6 +65,8 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o | |||
64 | obj-$(CONFIG_SENSORS_LM90) += lm90.o | 65 | obj-$(CONFIG_SENSORS_LM90) += lm90.o |
65 | obj-$(CONFIG_SENSORS_LM92) += lm92.o | 66 | obj-$(CONFIG_SENSORS_LM92) += lm92.o |
66 | obj-$(CONFIG_SENSORS_LM93) += lm93.o | 67 | obj-$(CONFIG_SENSORS_LM93) += lm93.o |
68 | obj-$(CONFIG_SENSORS_LM95241) += lm95241.o | ||
69 | obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o | ||
67 | obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o | 70 | obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o |
68 | obj-$(CONFIG_SENSORS_MAX1111) += max1111.o | 71 | obj-$(CONFIG_SENSORS_MAX1111) += max1111.o |
69 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o | 72 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o |
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index 29c83b5b969..55d3dc565be 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c | |||
@@ -85,25 +85,31 @@ MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids); | |||
85 | 85 | ||
86 | /** | 86 | /** |
87 | * lis3lv02d_acpi_init - ACPI _INI method: initialize the device. | 87 | * lis3lv02d_acpi_init - ACPI _INI method: initialize the device. |
88 | * @handle: the handle of the device | 88 | * @lis3: pointer to the device struct |
89 | * | 89 | * |
90 | * Returns AE_OK on success. | 90 | * Returns 0 on success. |
91 | */ | 91 | */ |
92 | acpi_status lis3lv02d_acpi_init(acpi_handle handle) | 92 | int lis3lv02d_acpi_init(struct lis3lv02d *lis3) |
93 | { | 93 | { |
94 | return acpi_evaluate_object(handle, METHOD_NAME__INI, NULL, NULL); | 94 | struct acpi_device *dev = lis3->bus_priv; |
95 | if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI, | ||
96 | NULL, NULL) != AE_OK) | ||
97 | return -EINVAL; | ||
98 | |||
99 | return 0; | ||
95 | } | 100 | } |
96 | 101 | ||
97 | /** | 102 | /** |
98 | * lis3lv02d_acpi_read - ACPI ALRD method: read a register | 103 | * lis3lv02d_acpi_read - ACPI ALRD method: read a register |
99 | * @handle: the handle of the device | 104 | * @lis3: pointer to the device struct |
100 | * @reg: the register to read | 105 | * @reg: the register to read |
101 | * @ret: result of the operation | 106 | * @ret: result of the operation |
102 | * | 107 | * |
103 | * Returns AE_OK on success. | 108 | * Returns 0 on success. |
104 | */ | 109 | */ |
105 | acpi_status lis3lv02d_acpi_read(acpi_handle handle, int reg, u8 *ret) | 110 | int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret) |
106 | { | 111 | { |
112 | struct acpi_device *dev = lis3->bus_priv; | ||
107 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | 113 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; |
108 | struct acpi_object_list args = { 1, &arg0 }; | 114 | struct acpi_object_list args = { 1, &arg0 }; |
109 | unsigned long long lret; | 115 | unsigned long long lret; |
@@ -111,21 +117,22 @@ acpi_status lis3lv02d_acpi_read(acpi_handle handle, int reg, u8 *ret) | |||
111 | 117 | ||
112 | arg0.integer.value = reg; | 118 | arg0.integer.value = reg; |
113 | 119 | ||
114 | status = acpi_evaluate_integer(handle, "ALRD", &args, &lret); | 120 | status = acpi_evaluate_integer(dev->handle, "ALRD", &args, &lret); |
115 | *ret = lret; | 121 | *ret = lret; |
116 | return status; | 122 | return (status != AE_OK) ? -EINVAL : 0; |
117 | } | 123 | } |
118 | 124 | ||
119 | /** | 125 | /** |
120 | * lis3lv02d_acpi_write - ACPI ALWR method: write to a register | 126 | * lis3lv02d_acpi_write - ACPI ALWR method: write to a register |
121 | * @handle: the handle of the device | 127 | * @lis3: pointer to the device struct |
122 | * @reg: the register to write to | 128 | * @reg: the register to write to |
123 | * @val: the value to write | 129 | * @val: the value to write |
124 | * | 130 | * |
125 | * Returns AE_OK on success. | 131 | * Returns 0 on success. |
126 | */ | 132 | */ |
127 | acpi_status lis3lv02d_acpi_write(acpi_handle handle, int reg, u8 val) | 133 | int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val) |
128 | { | 134 | { |
135 | struct acpi_device *dev = lis3->bus_priv; | ||
129 | unsigned long long ret; /* Not used when writting */ | 136 | unsigned long long ret; /* Not used when writting */ |
130 | union acpi_object in_obj[2]; | 137 | union acpi_object in_obj[2]; |
131 | struct acpi_object_list args = { 2, in_obj }; | 138 | struct acpi_object_list args = { 2, in_obj }; |
@@ -135,12 +142,15 @@ acpi_status lis3lv02d_acpi_write(acpi_handle handle, int reg, u8 val) | |||
135 | in_obj[1].type = ACPI_TYPE_INTEGER; | 142 | in_obj[1].type = ACPI_TYPE_INTEGER; |
136 | in_obj[1].integer.value = val; | 143 | in_obj[1].integer.value = val; |
137 | 144 | ||
138 | return acpi_evaluate_integer(handle, "ALWR", &args, &ret); | 145 | if (acpi_evaluate_integer(dev->handle, "ALWR", &args, &ret) != AE_OK) |
146 | return -EINVAL; | ||
147 | |||
148 | return 0; | ||
139 | } | 149 | } |
140 | 150 | ||
141 | static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi) | 151 | static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi) |
142 | { | 152 | { |
143 | adev.ac = *((struct axis_conversion *)dmi->driver_data); | 153 | lis3_dev.ac = *((struct axis_conversion *)dmi->driver_data); |
144 | printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident); | 154 | printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident); |
145 | 155 | ||
146 | return 1; | 156 | return 1; |
@@ -187,6 +197,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { | |||
187 | AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted), | 197 | AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted), |
188 | AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted), | 198 | AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted), |
189 | AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left), | 199 | AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left), |
200 | AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted), | ||
190 | AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd), | 201 | AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd), |
191 | AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd), | 202 | AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd), |
192 | AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right), | 203 | AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right), |
@@ -201,6 +212,8 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { | |||
201 | PRODUCT_NAME, "HP Pavilion dv5", | 212 | PRODUCT_NAME, "HP Pavilion dv5", |
202 | BOARD_NAME, "3600", | 213 | BOARD_NAME, "3600", |
203 | y_inverted), | 214 | y_inverted), |
215 | AXIS_DMI_MATCH("DV7", "HP Pavilion dv7", x_inverted), | ||
216 | AXIS_DMI_MATCH("HP8710", "HP Compaq 8710", y_inverted), | ||
204 | { NULL, } | 217 | { NULL, } |
205 | /* Laptop models without axis info (yet): | 218 | /* Laptop models without axis info (yet): |
206 | * "NC6910" "HP Compaq 6910" | 219 | * "NC6910" "HP Compaq 6910" |
@@ -214,7 +227,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { | |||
214 | 227 | ||
215 | static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value) | 228 | static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value) |
216 | { | 229 | { |
217 | acpi_handle handle = adev.device->handle; | 230 | struct acpi_device *dev = lis3_dev.bus_priv; |
218 | unsigned long long ret; /* Not used when writing */ | 231 | unsigned long long ret; /* Not used when writing */ |
219 | union acpi_object in_obj[1]; | 232 | union acpi_object in_obj[1]; |
220 | struct acpi_object_list args = { 1, in_obj }; | 233 | struct acpi_object_list args = { 1, in_obj }; |
@@ -222,7 +235,7 @@ static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness | |||
222 | in_obj[0].type = ACPI_TYPE_INTEGER; | 235 | in_obj[0].type = ACPI_TYPE_INTEGER; |
223 | in_obj[0].integer.value = !!value; | 236 | in_obj[0].integer.value = !!value; |
224 | 237 | ||
225 | acpi_evaluate_integer(handle, "ALED", &args, &ret); | 238 | acpi_evaluate_integer(dev->handle, "ALED", &args, &ret); |
226 | } | 239 | } |
227 | 240 | ||
228 | static struct delayed_led_classdev hpled_led = { | 241 | static struct delayed_led_classdev hpled_led = { |
@@ -254,28 +267,11 @@ static void lis3lv02d_enum_resources(struct acpi_device *device) | |||
254 | acpi_status status; | 267 | acpi_status status; |
255 | 268 | ||
256 | status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, | 269 | status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, |
257 | lis3lv02d_get_resource, &adev.irq); | 270 | lis3lv02d_get_resource, &lis3_dev.irq); |
258 | if (ACPI_FAILURE(status)) | 271 | if (ACPI_FAILURE(status)) |
259 | printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n"); | 272 | printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n"); |
260 | } | 273 | } |
261 | 274 | ||
262 | static s16 lis3lv02d_read_16(acpi_handle handle, int reg) | ||
263 | { | ||
264 | u8 lo, hi; | ||
265 | |||
266 | adev.read(handle, reg - 1, &lo); | ||
267 | adev.read(handle, reg, &hi); | ||
268 | /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */ | ||
269 | return (s16)((hi << 8) | lo); | ||
270 | } | ||
271 | |||
272 | static s16 lis3lv02d_read_8(acpi_handle handle, int reg) | ||
273 | { | ||
274 | s8 lo; | ||
275 | adev.read(handle, reg, &lo); | ||
276 | return lo; | ||
277 | } | ||
278 | |||
279 | static int lis3lv02d_add(struct acpi_device *device) | 275 | static int lis3lv02d_add(struct acpi_device *device) |
280 | { | 276 | { |
281 | int ret; | 277 | int ret; |
@@ -283,51 +279,35 @@ static int lis3lv02d_add(struct acpi_device *device) | |||
283 | if (!device) | 279 | if (!device) |
284 | return -EINVAL; | 280 | return -EINVAL; |
285 | 281 | ||
286 | adev.device = device; | 282 | lis3_dev.bus_priv = device; |
287 | adev.init = lis3lv02d_acpi_init; | 283 | lis3_dev.init = lis3lv02d_acpi_init; |
288 | adev.read = lis3lv02d_acpi_read; | 284 | lis3_dev.read = lis3lv02d_acpi_read; |
289 | adev.write = lis3lv02d_acpi_write; | 285 | lis3_dev.write = lis3lv02d_acpi_write; |
290 | strcpy(acpi_device_name(device), DRIVER_NAME); | 286 | strcpy(acpi_device_name(device), DRIVER_NAME); |
291 | strcpy(acpi_device_class(device), ACPI_MDPS_CLASS); | 287 | strcpy(acpi_device_class(device), ACPI_MDPS_CLASS); |
292 | device->driver_data = &adev; | 288 | device->driver_data = &lis3_dev; |
293 | 289 | ||
294 | lis3lv02d_acpi_read(device->handle, WHO_AM_I, &adev.whoami); | 290 | /* obtain IRQ number of our device from ACPI */ |
295 | switch (adev.whoami) { | 291 | lis3lv02d_enum_resources(device); |
296 | case LIS_DOUBLE_ID: | ||
297 | printk(KERN_INFO DRIVER_NAME ": 2-byte sensor found\n"); | ||
298 | adev.read_data = lis3lv02d_read_16; | ||
299 | adev.mdps_max_val = 2048; | ||
300 | break; | ||
301 | case LIS_SINGLE_ID: | ||
302 | printk(KERN_INFO DRIVER_NAME ": 1-byte sensor found\n"); | ||
303 | adev.read_data = lis3lv02d_read_8; | ||
304 | adev.mdps_max_val = 128; | ||
305 | break; | ||
306 | default: | ||
307 | printk(KERN_ERR DRIVER_NAME | ||
308 | ": unknown sensor type 0x%X\n", adev.whoami); | ||
309 | return -EINVAL; | ||
310 | } | ||
311 | 292 | ||
312 | /* If possible use a "standard" axes order */ | 293 | /* If possible use a "standard" axes order */ |
313 | if (dmi_check_system(lis3lv02d_dmi_ids) == 0) { | 294 | if (dmi_check_system(lis3lv02d_dmi_ids) == 0) { |
314 | printk(KERN_INFO DRIVER_NAME ": laptop model unknown, " | 295 | printk(KERN_INFO DRIVER_NAME ": laptop model unknown, " |
315 | "using default axes configuration\n"); | 296 | "using default axes configuration\n"); |
316 | adev.ac = lis3lv02d_axis_normal; | 297 | lis3_dev.ac = lis3lv02d_axis_normal; |
317 | } | 298 | } |
318 | 299 | ||
319 | INIT_WORK(&hpled_led.work, delayed_set_status_worker); | 300 | /* call the core layer do its init */ |
320 | ret = led_classdev_register(NULL, &hpled_led.led_classdev); | 301 | ret = lis3lv02d_init_device(&lis3_dev); |
321 | if (ret) | 302 | if (ret) |
322 | return ret; | 303 | return ret; |
323 | 304 | ||
324 | /* obtain IRQ number of our device from ACPI */ | 305 | INIT_WORK(&hpled_led.work, delayed_set_status_worker); |
325 | lis3lv02d_enum_resources(adev.device); | 306 | ret = led_classdev_register(NULL, &hpled_led.led_classdev); |
326 | |||
327 | ret = lis3lv02d_init_device(&adev); | ||
328 | if (ret) { | 307 | if (ret) { |
308 | lis3lv02d_joystick_disable(); | ||
309 | lis3lv02d_poweroff(&lis3_dev); | ||
329 | flush_work(&hpled_led.work); | 310 | flush_work(&hpled_led.work); |
330 | led_classdev_unregister(&hpled_led.led_classdev); | ||
331 | return ret; | 311 | return ret; |
332 | } | 312 | } |
333 | 313 | ||
@@ -340,7 +320,7 @@ static int lis3lv02d_remove(struct acpi_device *device, int type) | |||
340 | return -EINVAL; | 320 | return -EINVAL; |
341 | 321 | ||
342 | lis3lv02d_joystick_disable(); | 322 | lis3lv02d_joystick_disable(); |
343 | lis3lv02d_poweroff(device->handle); | 323 | lis3lv02d_poweroff(&lis3_dev); |
344 | 324 | ||
345 | flush_work(&hpled_led.work); | 325 | flush_work(&hpled_led.work); |
346 | led_classdev_unregister(&hpled_led.led_classdev); | 326 | led_classdev_unregister(&hpled_led.led_classdev); |
@@ -353,19 +333,19 @@ static int lis3lv02d_remove(struct acpi_device *device, int type) | |||
353 | static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state) | 333 | static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state) |
354 | { | 334 | { |
355 | /* make sure the device is off when we suspend */ | 335 | /* make sure the device is off when we suspend */ |
356 | lis3lv02d_poweroff(device->handle); | 336 | lis3lv02d_poweroff(&lis3_dev); |
357 | return 0; | 337 | return 0; |
358 | } | 338 | } |
359 | 339 | ||
360 | static int lis3lv02d_resume(struct acpi_device *device) | 340 | static int lis3lv02d_resume(struct acpi_device *device) |
361 | { | 341 | { |
362 | /* put back the device in the right state (ACPI might turn it on) */ | 342 | /* put back the device in the right state (ACPI might turn it on) */ |
363 | mutex_lock(&adev.lock); | 343 | mutex_lock(&lis3_dev.lock); |
364 | if (adev.usage > 0) | 344 | if (lis3_dev.usage > 0) |
365 | lis3lv02d_poweron(device->handle); | 345 | lis3lv02d_poweron(&lis3_dev); |
366 | else | 346 | else |
367 | lis3lv02d_poweroff(device->handle); | 347 | lis3lv02d_poweroff(&lis3_dev); |
368 | mutex_unlock(&adev.lock); | 348 | mutex_unlock(&lis3_dev.lock); |
369 | return 0; | 349 | return 0; |
370 | } | 350 | } |
371 | #else | 351 | #else |
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c index 8bb2158f045..778eb779598 100644 --- a/drivers/hwmon/lis3lv02d.c +++ b/drivers/hwmon/lis3lv02d.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <linux/freezer.h> | 36 | #include <linux/freezer.h> |
37 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
38 | #include <linux/miscdevice.h> | 38 | #include <linux/miscdevice.h> |
39 | #include <acpi/acpi_drivers.h> | ||
40 | #include <asm/atomic.h> | 39 | #include <asm/atomic.h> |
41 | #include "lis3lv02d.h" | 40 | #include "lis3lv02d.h" |
42 | 41 | ||
@@ -53,13 +52,30 @@ | |||
53 | * joystick. | 52 | * joystick. |
54 | */ | 53 | */ |
55 | 54 | ||
56 | struct acpi_lis3lv02d adev = { | 55 | struct lis3lv02d lis3_dev = { |
57 | .misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(adev.misc_wait), | 56 | .misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait), |
58 | }; | 57 | }; |
59 | 58 | ||
60 | EXPORT_SYMBOL_GPL(adev); | 59 | EXPORT_SYMBOL_GPL(lis3_dev); |
61 | 60 | ||
62 | static int lis3lv02d_add_fs(struct acpi_device *device); | 61 | static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg) |
62 | { | ||
63 | s8 lo; | ||
64 | if (lis3->read(lis3, reg, &lo) < 0) | ||
65 | return 0; | ||
66 | |||
67 | return lo; | ||
68 | } | ||
69 | |||
70 | static s16 lis3lv02d_read_16(struct lis3lv02d *lis3, int reg) | ||
71 | { | ||
72 | u8 lo, hi; | ||
73 | |||
74 | lis3->read(lis3, reg - 1, &lo); | ||
75 | lis3->read(lis3, reg, &hi); | ||
76 | /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */ | ||
77 | return (s16)((hi << 8) | lo); | ||
78 | } | ||
63 | 79 | ||
64 | /** | 80 | /** |
65 | * lis3lv02d_get_axis - For the given axis, give the value converted | 81 | * lis3lv02d_get_axis - For the given axis, give the value converted |
@@ -78,36 +94,36 @@ static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3]) | |||
78 | 94 | ||
79 | /** | 95 | /** |
80 | * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer | 96 | * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer |
81 | * @handle: the handle to the device | 97 | * @lis3: pointer to the device struct |
82 | * @x: where to store the X axis value | 98 | * @x: where to store the X axis value |
83 | * @y: where to store the Y axis value | 99 | * @y: where to store the Y axis value |
84 | * @z: where to store the Z axis value | 100 | * @z: where to store the Z axis value |
85 | * | 101 | * |
86 | * Note that 40Hz input device can eat up about 10% CPU at 800MHZ | 102 | * Note that 40Hz input device can eat up about 10% CPU at 800MHZ |
87 | */ | 103 | */ |
88 | static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z) | 104 | static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z) |
89 | { | 105 | { |
90 | int position[3]; | 106 | int position[3]; |
91 | 107 | ||
92 | position[0] = adev.read_data(handle, OUTX); | 108 | position[0] = lis3_dev.read_data(lis3, OUTX); |
93 | position[1] = adev.read_data(handle, OUTY); | 109 | position[1] = lis3_dev.read_data(lis3, OUTY); |
94 | position[2] = adev.read_data(handle, OUTZ); | 110 | position[2] = lis3_dev.read_data(lis3, OUTZ); |
95 | 111 | ||
96 | *x = lis3lv02d_get_axis(adev.ac.x, position); | 112 | *x = lis3lv02d_get_axis(lis3_dev.ac.x, position); |
97 | *y = lis3lv02d_get_axis(adev.ac.y, position); | 113 | *y = lis3lv02d_get_axis(lis3_dev.ac.y, position); |
98 | *z = lis3lv02d_get_axis(adev.ac.z, position); | 114 | *z = lis3lv02d_get_axis(lis3_dev.ac.z, position); |
99 | } | 115 | } |
100 | 116 | ||
101 | void lis3lv02d_poweroff(acpi_handle handle) | 117 | void lis3lv02d_poweroff(struct lis3lv02d *lis3) |
102 | { | 118 | { |
103 | adev.is_on = 0; | 119 | lis3_dev.is_on = 0; |
104 | } | 120 | } |
105 | EXPORT_SYMBOL_GPL(lis3lv02d_poweroff); | 121 | EXPORT_SYMBOL_GPL(lis3lv02d_poweroff); |
106 | 122 | ||
107 | void lis3lv02d_poweron(acpi_handle handle) | 123 | void lis3lv02d_poweron(struct lis3lv02d *lis3) |
108 | { | 124 | { |
109 | adev.is_on = 1; | 125 | lis3_dev.is_on = 1; |
110 | adev.init(handle); | 126 | lis3_dev.init(lis3); |
111 | } | 127 | } |
112 | EXPORT_SYMBOL_GPL(lis3lv02d_poweron); | 128 | EXPORT_SYMBOL_GPL(lis3lv02d_poweron); |
113 | 129 | ||
@@ -116,13 +132,13 @@ EXPORT_SYMBOL_GPL(lis3lv02d_poweron); | |||
116 | * device will always be on until a call to lis3lv02d_decrease_use(). Not to be | 132 | * device will always be on until a call to lis3lv02d_decrease_use(). Not to be |
117 | * used from interrupt context. | 133 | * used from interrupt context. |
118 | */ | 134 | */ |
119 | static void lis3lv02d_increase_use(struct acpi_lis3lv02d *dev) | 135 | static void lis3lv02d_increase_use(struct lis3lv02d *dev) |
120 | { | 136 | { |
121 | mutex_lock(&dev->lock); | 137 | mutex_lock(&dev->lock); |
122 | dev->usage++; | 138 | dev->usage++; |
123 | if (dev->usage == 1) { | 139 | if (dev->usage == 1) { |
124 | if (!dev->is_on) | 140 | if (!dev->is_on) |
125 | lis3lv02d_poweron(dev->device->handle); | 141 | lis3lv02d_poweron(dev); |
126 | } | 142 | } |
127 | mutex_unlock(&dev->lock); | 143 | mutex_unlock(&dev->lock); |
128 | } | 144 | } |
@@ -131,12 +147,12 @@ static void lis3lv02d_increase_use(struct acpi_lis3lv02d *dev) | |||
131 | * To be called whenever a usage of the device is stopped. | 147 | * To be called whenever a usage of the device is stopped. |
132 | * It will make sure to turn off the device when there is not usage. | 148 | * It will make sure to turn off the device when there is not usage. |
133 | */ | 149 | */ |
134 | static void lis3lv02d_decrease_use(struct acpi_lis3lv02d *dev) | 150 | static void lis3lv02d_decrease_use(struct lis3lv02d *dev) |
135 | { | 151 | { |
136 | mutex_lock(&dev->lock); | 152 | mutex_lock(&dev->lock); |
137 | dev->usage--; | 153 | dev->usage--; |
138 | if (dev->usage == 0) | 154 | if (dev->usage == 0) |
139 | lis3lv02d_poweroff(dev->device->handle); | 155 | lis3lv02d_poweroff(dev); |
140 | mutex_unlock(&dev->lock); | 156 | mutex_unlock(&dev->lock); |
141 | } | 157 | } |
142 | 158 | ||
@@ -147,10 +163,10 @@ static irqreturn_t lis302dl_interrupt(int irq, void *dummy) | |||
147 | * the lid is closed. This leads to interrupts as soon as a little move | 163 | * the lid is closed. This leads to interrupts as soon as a little move |
148 | * is done. | 164 | * is done. |
149 | */ | 165 | */ |
150 | atomic_inc(&adev.count); | 166 | atomic_inc(&lis3_dev.count); |
151 | 167 | ||
152 | wake_up_interruptible(&adev.misc_wait); | 168 | wake_up_interruptible(&lis3_dev.misc_wait); |
153 | kill_fasync(&adev.async_queue, SIGIO, POLL_IN); | 169 | kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN); |
154 | return IRQ_HANDLED; | 170 | return IRQ_HANDLED; |
155 | } | 171 | } |
156 | 172 | ||
@@ -158,10 +174,10 @@ static int lis3lv02d_misc_open(struct inode *inode, struct file *file) | |||
158 | { | 174 | { |
159 | int ret; | 175 | int ret; |
160 | 176 | ||
161 | if (test_and_set_bit(0, &adev.misc_opened)) | 177 | if (test_and_set_bit(0, &lis3_dev.misc_opened)) |
162 | return -EBUSY; /* already open */ | 178 | return -EBUSY; /* already open */ |
163 | 179 | ||
164 | atomic_set(&adev.count, 0); | 180 | atomic_set(&lis3_dev.count, 0); |
165 | 181 | ||
166 | /* | 182 | /* |
167 | * The sensor can generate interrupts for free-fall and direction | 183 | * The sensor can generate interrupts for free-fall and direction |
@@ -174,25 +190,25 @@ static int lis3lv02d_misc_open(struct inode *inode, struct file *file) | |||
174 | * io-apic is not configurable (and generates a warning) but I keep it | 190 | * io-apic is not configurable (and generates a warning) but I keep it |
175 | * in case of support for other hardware. | 191 | * in case of support for other hardware. |
176 | */ | 192 | */ |
177 | ret = request_irq(adev.irq, lis302dl_interrupt, IRQF_TRIGGER_RISING, | 193 | ret = request_irq(lis3_dev.irq, lis302dl_interrupt, IRQF_TRIGGER_RISING, |
178 | DRIVER_NAME, &adev); | 194 | DRIVER_NAME, &lis3_dev); |
179 | 195 | ||
180 | if (ret) { | 196 | if (ret) { |
181 | clear_bit(0, &adev.misc_opened); | 197 | clear_bit(0, &lis3_dev.misc_opened); |
182 | printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", adev.irq); | 198 | printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", lis3_dev.irq); |
183 | return -EBUSY; | 199 | return -EBUSY; |
184 | } | 200 | } |
185 | lis3lv02d_increase_use(&adev); | 201 | lis3lv02d_increase_use(&lis3_dev); |
186 | printk("lis3: registered interrupt %d\n", adev.irq); | 202 | printk("lis3: registered interrupt %d\n", lis3_dev.irq); |
187 | return 0; | 203 | return 0; |
188 | } | 204 | } |
189 | 205 | ||
190 | static int lis3lv02d_misc_release(struct inode *inode, struct file *file) | 206 | static int lis3lv02d_misc_release(struct inode *inode, struct file *file) |
191 | { | 207 | { |
192 | fasync_helper(-1, file, 0, &adev.async_queue); | 208 | fasync_helper(-1, file, 0, &lis3_dev.async_queue); |
193 | lis3lv02d_decrease_use(&adev); | 209 | lis3lv02d_decrease_use(&lis3_dev); |
194 | free_irq(adev.irq, &adev); | 210 | free_irq(lis3_dev.irq, &lis3_dev); |
195 | clear_bit(0, &adev.misc_opened); /* release the device */ | 211 | clear_bit(0, &lis3_dev.misc_opened); /* release the device */ |
196 | return 0; | 212 | return 0; |
197 | } | 213 | } |
198 | 214 | ||
@@ -207,10 +223,10 @@ static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf, | |||
207 | if (count < 1) | 223 | if (count < 1) |
208 | return -EINVAL; | 224 | return -EINVAL; |
209 | 225 | ||
210 | add_wait_queue(&adev.misc_wait, &wait); | 226 | add_wait_queue(&lis3_dev.misc_wait, &wait); |
211 | while (true) { | 227 | while (true) { |
212 | set_current_state(TASK_INTERRUPTIBLE); | 228 | set_current_state(TASK_INTERRUPTIBLE); |
213 | data = atomic_xchg(&adev.count, 0); | 229 | data = atomic_xchg(&lis3_dev.count, 0); |
214 | if (data) | 230 | if (data) |
215 | break; | 231 | break; |
216 | 232 | ||
@@ -240,22 +256,22 @@ static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf, | |||
240 | 256 | ||
241 | out: | 257 | out: |
242 | __set_current_state(TASK_RUNNING); | 258 | __set_current_state(TASK_RUNNING); |
243 | remove_wait_queue(&adev.misc_wait, &wait); | 259 | remove_wait_queue(&lis3_dev.misc_wait, &wait); |
244 | 260 | ||
245 | return retval; | 261 | return retval; |
246 | } | 262 | } |
247 | 263 | ||
248 | static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait) | 264 | static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait) |
249 | { | 265 | { |
250 | poll_wait(file, &adev.misc_wait, wait); | 266 | poll_wait(file, &lis3_dev.misc_wait, wait); |
251 | if (atomic_read(&adev.count)) | 267 | if (atomic_read(&lis3_dev.count)) |
252 | return POLLIN | POLLRDNORM; | 268 | return POLLIN | POLLRDNORM; |
253 | return 0; | 269 | return 0; |
254 | } | 270 | } |
255 | 271 | ||
256 | static int lis3lv02d_misc_fasync(int fd, struct file *file, int on) | 272 | static int lis3lv02d_misc_fasync(int fd, struct file *file, int on) |
257 | { | 273 | { |
258 | return fasync_helper(fd, file, on, &adev.async_queue); | 274 | return fasync_helper(fd, file, on, &lis3_dev.async_queue); |
259 | } | 275 | } |
260 | 276 | ||
261 | static const struct file_operations lis3lv02d_misc_fops = { | 277 | static const struct file_operations lis3lv02d_misc_fops = { |
@@ -283,12 +299,12 @@ static int lis3lv02d_joystick_kthread(void *data) | |||
283 | int x, y, z; | 299 | int x, y, z; |
284 | 300 | ||
285 | while (!kthread_should_stop()) { | 301 | while (!kthread_should_stop()) { |
286 | lis3lv02d_get_xyz(adev.device->handle, &x, &y, &z); | 302 | lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); |
287 | input_report_abs(adev.idev, ABS_X, x - adev.xcalib); | 303 | input_report_abs(lis3_dev.idev, ABS_X, x - lis3_dev.xcalib); |
288 | input_report_abs(adev.idev, ABS_Y, y - adev.ycalib); | 304 | input_report_abs(lis3_dev.idev, ABS_Y, y - lis3_dev.ycalib); |
289 | input_report_abs(adev.idev, ABS_Z, z - adev.zcalib); | 305 | input_report_abs(lis3_dev.idev, ABS_Z, z - lis3_dev.zcalib); |
290 | 306 | ||
291 | input_sync(adev.idev); | 307 | input_sync(lis3_dev.idev); |
292 | 308 | ||
293 | try_to_freeze(); | 309 | try_to_freeze(); |
294 | msleep_interruptible(MDPS_POLL_INTERVAL); | 310 | msleep_interruptible(MDPS_POLL_INTERVAL); |
@@ -299,11 +315,11 @@ static int lis3lv02d_joystick_kthread(void *data) | |||
299 | 315 | ||
300 | static int lis3lv02d_joystick_open(struct input_dev *input) | 316 | static int lis3lv02d_joystick_open(struct input_dev *input) |
301 | { | 317 | { |
302 | lis3lv02d_increase_use(&adev); | 318 | lis3lv02d_increase_use(&lis3_dev); |
303 | adev.kthread = kthread_run(lis3lv02d_joystick_kthread, NULL, "klis3lv02d"); | 319 | lis3_dev.kthread = kthread_run(lis3lv02d_joystick_kthread, NULL, "klis3lv02d"); |
304 | if (IS_ERR(adev.kthread)) { | 320 | if (IS_ERR(lis3_dev.kthread)) { |
305 | lis3lv02d_decrease_use(&adev); | 321 | lis3lv02d_decrease_use(&lis3_dev); |
306 | return PTR_ERR(adev.kthread); | 322 | return PTR_ERR(lis3_dev.kthread); |
307 | } | 323 | } |
308 | 324 | ||
309 | return 0; | 325 | return 0; |
@@ -311,45 +327,46 @@ static int lis3lv02d_joystick_open(struct input_dev *input) | |||
311 | 327 | ||
312 | static void lis3lv02d_joystick_close(struct input_dev *input) | 328 | static void lis3lv02d_joystick_close(struct input_dev *input) |
313 | { | 329 | { |
314 | kthread_stop(adev.kthread); | 330 | kthread_stop(lis3_dev.kthread); |
315 | lis3lv02d_decrease_use(&adev); | 331 | lis3lv02d_decrease_use(&lis3_dev); |
316 | } | 332 | } |
317 | 333 | ||
318 | static inline void lis3lv02d_calibrate_joystick(void) | 334 | static inline void lis3lv02d_calibrate_joystick(void) |
319 | { | 335 | { |
320 | lis3lv02d_get_xyz(adev.device->handle, &adev.xcalib, &adev.ycalib, &adev.zcalib); | 336 | lis3lv02d_get_xyz(&lis3_dev, |
337 | &lis3_dev.xcalib, &lis3_dev.ycalib, &lis3_dev.zcalib); | ||
321 | } | 338 | } |
322 | 339 | ||
323 | int lis3lv02d_joystick_enable(void) | 340 | int lis3lv02d_joystick_enable(void) |
324 | { | 341 | { |
325 | int err; | 342 | int err; |
326 | 343 | ||
327 | if (adev.idev) | 344 | if (lis3_dev.idev) |
328 | return -EINVAL; | 345 | return -EINVAL; |
329 | 346 | ||
330 | adev.idev = input_allocate_device(); | 347 | lis3_dev.idev = input_allocate_device(); |
331 | if (!adev.idev) | 348 | if (!lis3_dev.idev) |
332 | return -ENOMEM; | 349 | return -ENOMEM; |
333 | 350 | ||
334 | lis3lv02d_calibrate_joystick(); | 351 | lis3lv02d_calibrate_joystick(); |
335 | 352 | ||
336 | adev.idev->name = "ST LIS3LV02DL Accelerometer"; | 353 | lis3_dev.idev->name = "ST LIS3LV02DL Accelerometer"; |
337 | adev.idev->phys = DRIVER_NAME "/input0"; | 354 | lis3_dev.idev->phys = DRIVER_NAME "/input0"; |
338 | adev.idev->id.bustype = BUS_HOST; | 355 | lis3_dev.idev->id.bustype = BUS_HOST; |
339 | adev.idev->id.vendor = 0; | 356 | lis3_dev.idev->id.vendor = 0; |
340 | adev.idev->dev.parent = &adev.pdev->dev; | 357 | lis3_dev.idev->dev.parent = &lis3_dev.pdev->dev; |
341 | adev.idev->open = lis3lv02d_joystick_open; | 358 | lis3_dev.idev->open = lis3lv02d_joystick_open; |
342 | adev.idev->close = lis3lv02d_joystick_close; | 359 | lis3_dev.idev->close = lis3lv02d_joystick_close; |
343 | 360 | ||
344 | set_bit(EV_ABS, adev.idev->evbit); | 361 | set_bit(EV_ABS, lis3_dev.idev->evbit); |
345 | input_set_abs_params(adev.idev, ABS_X, -adev.mdps_max_val, adev.mdps_max_val, 3, 3); | 362 | input_set_abs_params(lis3_dev.idev, ABS_X, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3); |
346 | input_set_abs_params(adev.idev, ABS_Y, -adev.mdps_max_val, adev.mdps_max_val, 3, 3); | 363 | input_set_abs_params(lis3_dev.idev, ABS_Y, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3); |
347 | input_set_abs_params(adev.idev, ABS_Z, -adev.mdps_max_val, adev.mdps_max_val, 3, 3); | 364 | input_set_abs_params(lis3_dev.idev, ABS_Z, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3); |
348 | 365 | ||
349 | err = input_register_device(adev.idev); | 366 | err = input_register_device(lis3_dev.idev); |
350 | if (err) { | 367 | if (err) { |
351 | input_free_device(adev.idev); | 368 | input_free_device(lis3_dev.idev); |
352 | adev.idev = NULL; | 369 | lis3_dev.idev = NULL; |
353 | } | 370 | } |
354 | 371 | ||
355 | return err; | 372 | return err; |
@@ -358,71 +375,40 @@ EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable); | |||
358 | 375 | ||
359 | void lis3lv02d_joystick_disable(void) | 376 | void lis3lv02d_joystick_disable(void) |
360 | { | 377 | { |
361 | if (!adev.idev) | 378 | if (!lis3_dev.idev) |
362 | return; | 379 | return; |
363 | 380 | ||
364 | misc_deregister(&lis3lv02d_misc_device); | 381 | misc_deregister(&lis3lv02d_misc_device); |
365 | input_unregister_device(adev.idev); | 382 | input_unregister_device(lis3_dev.idev); |
366 | adev.idev = NULL; | 383 | lis3_dev.idev = NULL; |
367 | } | 384 | } |
368 | EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable); | 385 | EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable); |
369 | 386 | ||
370 | /* | ||
371 | * Initialise the accelerometer and the various subsystems. | ||
372 | * Should be rather independant of the bus system. | ||
373 | */ | ||
374 | int lis3lv02d_init_device(struct acpi_lis3lv02d *dev) | ||
375 | { | ||
376 | mutex_init(&dev->lock); | ||
377 | lis3lv02d_add_fs(dev->device); | ||
378 | lis3lv02d_increase_use(dev); | ||
379 | |||
380 | if (lis3lv02d_joystick_enable()) | ||
381 | printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n"); | ||
382 | |||
383 | printk("lis3_init_device: irq %d\n", dev->irq); | ||
384 | |||
385 | /* if we did not get an IRQ from ACPI - we have nothing more to do */ | ||
386 | if (!dev->irq) { | ||
387 | printk(KERN_ERR DRIVER_NAME | ||
388 | ": No IRQ in ACPI. Disabling /dev/freefall\n"); | ||
389 | goto out; | ||
390 | } | ||
391 | |||
392 | printk("lis3: registering device\n"); | ||
393 | if (misc_register(&lis3lv02d_misc_device)) | ||
394 | printk(KERN_ERR DRIVER_NAME ": misc_register failed\n"); | ||
395 | out: | ||
396 | lis3lv02d_decrease_use(dev); | ||
397 | return 0; | ||
398 | } | ||
399 | EXPORT_SYMBOL_GPL(lis3lv02d_init_device); | ||
400 | |||
401 | /* Sysfs stuff */ | 387 | /* Sysfs stuff */ |
402 | static ssize_t lis3lv02d_position_show(struct device *dev, | 388 | static ssize_t lis3lv02d_position_show(struct device *dev, |
403 | struct device_attribute *attr, char *buf) | 389 | struct device_attribute *attr, char *buf) |
404 | { | 390 | { |
405 | int x, y, z; | 391 | int x, y, z; |
406 | 392 | ||
407 | lis3lv02d_increase_use(&adev); | 393 | lis3lv02d_increase_use(&lis3_dev); |
408 | lis3lv02d_get_xyz(adev.device->handle, &x, &y, &z); | 394 | lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); |
409 | lis3lv02d_decrease_use(&adev); | 395 | lis3lv02d_decrease_use(&lis3_dev); |
410 | return sprintf(buf, "(%d,%d,%d)\n", x, y, z); | 396 | return sprintf(buf, "(%d,%d,%d)\n", x, y, z); |
411 | } | 397 | } |
412 | 398 | ||
413 | static ssize_t lis3lv02d_calibrate_show(struct device *dev, | 399 | static ssize_t lis3lv02d_calibrate_show(struct device *dev, |
414 | struct device_attribute *attr, char *buf) | 400 | struct device_attribute *attr, char *buf) |
415 | { | 401 | { |
416 | return sprintf(buf, "(%d,%d,%d)\n", adev.xcalib, adev.ycalib, adev.zcalib); | 402 | return sprintf(buf, "(%d,%d,%d)\n", lis3_dev.xcalib, lis3_dev.ycalib, lis3_dev.zcalib); |
417 | } | 403 | } |
418 | 404 | ||
419 | static ssize_t lis3lv02d_calibrate_store(struct device *dev, | 405 | static ssize_t lis3lv02d_calibrate_store(struct device *dev, |
420 | struct device_attribute *attr, | 406 | struct device_attribute *attr, |
421 | const char *buf, size_t count) | 407 | const char *buf, size_t count) |
422 | { | 408 | { |
423 | lis3lv02d_increase_use(&adev); | 409 | lis3lv02d_increase_use(&lis3_dev); |
424 | lis3lv02d_calibrate_joystick(); | 410 | lis3lv02d_calibrate_joystick(); |
425 | lis3lv02d_decrease_use(&adev); | 411 | lis3lv02d_decrease_use(&lis3_dev); |
426 | return count; | 412 | return count; |
427 | } | 413 | } |
428 | 414 | ||
@@ -434,9 +420,9 @@ static ssize_t lis3lv02d_rate_show(struct device *dev, | |||
434 | u8 ctrl; | 420 | u8 ctrl; |
435 | int val; | 421 | int val; |
436 | 422 | ||
437 | lis3lv02d_increase_use(&adev); | 423 | lis3lv02d_increase_use(&lis3_dev); |
438 | adev.read(adev.device->handle, CTRL_REG1, &ctrl); | 424 | lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl); |
439 | lis3lv02d_decrease_use(&adev); | 425 | lis3lv02d_decrease_use(&lis3_dev); |
440 | val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4; | 426 | val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4; |
441 | return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]); | 427 | return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]); |
442 | } | 428 | } |
@@ -458,23 +444,73 @@ static struct attribute_group lis3lv02d_attribute_group = { | |||
458 | }; | 444 | }; |
459 | 445 | ||
460 | 446 | ||
461 | static int lis3lv02d_add_fs(struct acpi_device *device) | 447 | static int lis3lv02d_add_fs(struct lis3lv02d *lis3) |
462 | { | 448 | { |
463 | adev.pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); | 449 | lis3_dev.pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); |
464 | if (IS_ERR(adev.pdev)) | 450 | if (IS_ERR(lis3_dev.pdev)) |
465 | return PTR_ERR(adev.pdev); | 451 | return PTR_ERR(lis3_dev.pdev); |
466 | 452 | ||
467 | return sysfs_create_group(&adev.pdev->dev.kobj, &lis3lv02d_attribute_group); | 453 | return sysfs_create_group(&lis3_dev.pdev->dev.kobj, &lis3lv02d_attribute_group); |
468 | } | 454 | } |
469 | 455 | ||
470 | int lis3lv02d_remove_fs(void) | 456 | int lis3lv02d_remove_fs(void) |
471 | { | 457 | { |
472 | sysfs_remove_group(&adev.pdev->dev.kobj, &lis3lv02d_attribute_group); | 458 | sysfs_remove_group(&lis3_dev.pdev->dev.kobj, &lis3lv02d_attribute_group); |
473 | platform_device_unregister(adev.pdev); | 459 | platform_device_unregister(lis3_dev.pdev); |
474 | return 0; | 460 | return 0; |
475 | } | 461 | } |
476 | EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); | 462 | EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); |
477 | 463 | ||
464 | /* | ||
465 | * Initialise the accelerometer and the various subsystems. | ||
466 | * Should be rather independant of the bus system. | ||
467 | */ | ||
468 | int lis3lv02d_init_device(struct lis3lv02d *dev) | ||
469 | { | ||
470 | dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I); | ||
471 | |||
472 | switch (dev->whoami) { | ||
473 | case LIS_DOUBLE_ID: | ||
474 | printk(KERN_INFO DRIVER_NAME ": 2-byte sensor found\n"); | ||
475 | dev->read_data = lis3lv02d_read_16; | ||
476 | dev->mdps_max_val = 2048; | ||
477 | break; | ||
478 | case LIS_SINGLE_ID: | ||
479 | printk(KERN_INFO DRIVER_NAME ": 1-byte sensor found\n"); | ||
480 | dev->read_data = lis3lv02d_read_8; | ||
481 | dev->mdps_max_val = 128; | ||
482 | break; | ||
483 | default: | ||
484 | printk(KERN_ERR DRIVER_NAME | ||
485 | ": unknown sensor type 0x%X\n", lis3_dev.whoami); | ||
486 | return -EINVAL; | ||
487 | } | ||
488 | |||
489 | mutex_init(&dev->lock); | ||
490 | lis3lv02d_add_fs(dev); | ||
491 | lis3lv02d_increase_use(dev); | ||
492 | |||
493 | if (lis3lv02d_joystick_enable()) | ||
494 | printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n"); | ||
495 | |||
496 | printk("lis3_init_device: irq %d\n", dev->irq); | ||
497 | |||
498 | /* bail if we did not get an IRQ from the bus layer */ | ||
499 | if (!dev->irq) { | ||
500 | printk(KERN_ERR DRIVER_NAME | ||
501 | ": No IRQ. Disabling /dev/freefall\n"); | ||
502 | goto out; | ||
503 | } | ||
504 | |||
505 | printk("lis3: registering device\n"); | ||
506 | if (misc_register(&lis3lv02d_misc_device)) | ||
507 | printk(KERN_ERR DRIVER_NAME ": misc_register failed\n"); | ||
508 | out: | ||
509 | lis3lv02d_decrease_use(dev); | ||
510 | return 0; | ||
511 | } | ||
512 | EXPORT_SYMBOL_GPL(lis3lv02d_init_device); | ||
513 | |||
478 | MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver"); | 514 | MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver"); |
479 | MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek"); | 515 | MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek"); |
480 | MODULE_LICENSE("GPL"); | 516 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h index 75972bf372f..745ec96806d 100644 --- a/drivers/hwmon/lis3lv02d.h +++ b/drivers/hwmon/lis3lv02d.h | |||
@@ -159,14 +159,14 @@ struct axis_conversion { | |||
159 | s8 z; | 159 | s8 z; |
160 | }; | 160 | }; |
161 | 161 | ||
162 | struct acpi_lis3lv02d { | 162 | struct lis3lv02d { |
163 | struct acpi_device *device; /* The ACPI device */ | 163 | void *bus_priv; /* used by the bus layer only */ |
164 | acpi_status (*init) (acpi_handle handle); | 164 | int (*init) (struct lis3lv02d *lis3); |
165 | acpi_status (*write) (acpi_handle handle, int reg, u8 val); | 165 | int (*write) (struct lis3lv02d *lis3, int reg, u8 val); |
166 | acpi_status (*read) (acpi_handle handle, int reg, u8 *ret); | 166 | int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret); |
167 | 167 | ||
168 | u8 whoami; /* 3Ah: 2-byte registries, 3Bh: 1-byte registries */ | 168 | u8 whoami; /* 3Ah: 2-byte registries, 3Bh: 1-byte registries */ |
169 | s16 (*read_data) (acpi_handle handle, int reg); | 169 | s16 (*read_data) (struct lis3lv02d *lis3, int reg); |
170 | int mdps_max_val; | 170 | int mdps_max_val; |
171 | 171 | ||
172 | struct input_dev *idev; /* input device */ | 172 | struct input_dev *idev; /* input device */ |
@@ -187,11 +187,11 @@ struct acpi_lis3lv02d { | |||
187 | unsigned long misc_opened; /* bit0: whether the device is open */ | 187 | unsigned long misc_opened; /* bit0: whether the device is open */ |
188 | }; | 188 | }; |
189 | 189 | ||
190 | int lis3lv02d_init_device(struct acpi_lis3lv02d *dev); | 190 | int lis3lv02d_init_device(struct lis3lv02d *lis3); |
191 | int lis3lv02d_joystick_enable(void); | 191 | int lis3lv02d_joystick_enable(void); |
192 | void lis3lv02d_joystick_disable(void); | 192 | void lis3lv02d_joystick_disable(void); |
193 | void lis3lv02d_poweroff(acpi_handle handle); | 193 | void lis3lv02d_poweroff(struct lis3lv02d *lis3); |
194 | void lis3lv02d_poweron(acpi_handle handle); | 194 | void lis3lv02d_poweron(struct lis3lv02d *lis3); |
195 | int lis3lv02d_remove_fs(void); | 195 | int lis3lv02d_remove_fs(void); |
196 | 196 | ||
197 | extern struct acpi_lis3lv02d adev; | 197 | extern struct lis3lv02d lis3_dev; |
diff --git a/drivers/hwmon/lis3lv02d_spi.c b/drivers/hwmon/lis3lv02d_spi.c new file mode 100644 index 00000000000..07ae74b0e19 --- /dev/null +++ b/drivers/hwmon/lis3lv02d_spi.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * lis3lv02d_spi - SPI glue layer for lis3lv02d | ||
3 | * | ||
4 | * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * publishhed by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/input.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/workqueue.h> | ||
18 | #include <linux/spi/spi.h> | ||
19 | |||
20 | #include "lis3lv02d.h" | ||
21 | |||
22 | #define DRV_NAME "lis3lv02d_spi" | ||
23 | #define LIS3_SPI_READ 0x80 | ||
24 | |||
25 | static int lis3_spi_read(struct lis3lv02d *lis3, int reg, u8 *v) | ||
26 | { | ||
27 | struct spi_device *spi = lis3->bus_priv; | ||
28 | int ret = spi_w8r8(spi, reg | LIS3_SPI_READ); | ||
29 | if (ret < 0) | ||
30 | return -EINVAL; | ||
31 | |||
32 | *v = (u8) ret; | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static int lis3_spi_write(struct lis3lv02d *lis3, int reg, u8 val) | ||
37 | { | ||
38 | u8 tmp[2] = { reg, val }; | ||
39 | struct spi_device *spi = lis3->bus_priv; | ||
40 | return spi_write(spi, tmp, sizeof(tmp)); | ||
41 | } | ||
42 | |||
43 | static int lis3_spi_init(struct lis3lv02d *lis3) | ||
44 | { | ||
45 | u8 reg; | ||
46 | int ret; | ||
47 | |||
48 | /* power up the device */ | ||
49 | ret = lis3->read(lis3, CTRL_REG1, ®); | ||
50 | if (ret < 0) | ||
51 | return ret; | ||
52 | |||
53 | reg |= CTRL1_PD0; | ||
54 | return lis3->write(lis3, CTRL_REG1, reg); | ||
55 | } | ||
56 | |||
57 | static struct axis_conversion lis3lv02d_axis_normal = { 1, 2, 3 }; | ||
58 | |||
59 | static int __devinit lis302dl_spi_probe(struct spi_device *spi) | ||
60 | { | ||
61 | int ret; | ||
62 | |||
63 | spi->bits_per_word = 8; | ||
64 | spi->mode = SPI_MODE_0; | ||
65 | ret = spi_setup(spi); | ||
66 | if (ret < 0) | ||
67 | return ret; | ||
68 | |||
69 | lis3_dev.bus_priv = spi; | ||
70 | lis3_dev.init = lis3_spi_init; | ||
71 | lis3_dev.read = lis3_spi_read; | ||
72 | lis3_dev.write = lis3_spi_write; | ||
73 | lis3_dev.irq = spi->irq; | ||
74 | lis3_dev.ac = lis3lv02d_axis_normal; | ||
75 | spi_set_drvdata(spi, &lis3_dev); | ||
76 | |||
77 | ret = lis3lv02d_init_device(&lis3_dev); | ||
78 | return ret; | ||
79 | } | ||
80 | |||
81 | static int __devexit lis302dl_spi_remove(struct spi_device *spi) | ||
82 | { | ||
83 | struct lis3lv02d *lis3 = spi_get_drvdata(spi); | ||
84 | lis3lv02d_joystick_disable(); | ||
85 | lis3lv02d_poweroff(lis3); | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static struct spi_driver lis302dl_spi_driver = { | ||
90 | .driver = { | ||
91 | .name = DRV_NAME, | ||
92 | .owner = THIS_MODULE, | ||
93 | }, | ||
94 | .probe = lis302dl_spi_probe, | ||
95 | .remove = __devexit_p(lis302dl_spi_remove), | ||
96 | }; | ||
97 | |||
98 | static int __init lis302dl_init(void) | ||
99 | { | ||
100 | return spi_register_driver(&lis302dl_spi_driver); | ||
101 | } | ||
102 | |||
103 | static void __exit lis302dl_exit(void) | ||
104 | { | ||
105 | spi_unregister_driver(&lis302dl_spi_driver); | ||
106 | } | ||
107 | |||
108 | module_init(lis302dl_init); | ||
109 | module_exit(lis302dl_exit); | ||
110 | |||
111 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | ||
112 | MODULE_DESCRIPTION("lis3lv02d SPI glue layer"); | ||
113 | MODULE_LICENSE("GPL"); | ||
114 | |||
diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c new file mode 100644 index 00000000000..091d95f38aa --- /dev/null +++ b/drivers/hwmon/lm95241.c | |||
@@ -0,0 +1,527 @@ | |||
1 | /* | ||
2 | * lm95241.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | * monitoring | ||
4 | * Copyright (C) 2008 Davide Rizzo <elpa-rizzo@gmail.com> | ||
5 | * | ||
6 | * Based on the max1619 driver. The LM95241 is a sensor chip made by National | ||
7 | * Semiconductors. | ||
8 | * It reports up to three temperatures (its own plus up to | ||
9 | * two external ones). Complete datasheet can be | ||
10 | * obtained from National's website at: | ||
11 | * http://www.national.com/ds.cgi/LM/LM95241.pdf | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/jiffies.h> | ||
32 | #include <linux/i2c.h> | ||
33 | #include <linux/hwmon.h> | ||
34 | #include <linux/hwmon-sysfs.h> | ||
35 | #include <linux/err.h> | ||
36 | #include <linux/mutex.h> | ||
37 | #include <linux/sysfs.h> | ||
38 | |||
39 | static const unsigned short normal_i2c[] = { | ||
40 | 0x19, 0x2a, 0x2b, I2C_CLIENT_END}; | ||
41 | |||
42 | /* Insmod parameters */ | ||
43 | I2C_CLIENT_INSMOD_1(lm95241); | ||
44 | |||
45 | /* LM95241 registers */ | ||
46 | #define LM95241_REG_R_MAN_ID 0xFE | ||
47 | #define LM95241_REG_R_CHIP_ID 0xFF | ||
48 | #define LM95241_REG_R_STATUS 0x02 | ||
49 | #define LM95241_REG_RW_CONFIG 0x03 | ||
50 | #define LM95241_REG_RW_REM_FILTER 0x06 | ||
51 | #define LM95241_REG_RW_TRUTHERM 0x07 | ||
52 | #define LM95241_REG_W_ONE_SHOT 0x0F | ||
53 | #define LM95241_REG_R_LOCAL_TEMPH 0x10 | ||
54 | #define LM95241_REG_R_REMOTE1_TEMPH 0x11 | ||
55 | #define LM95241_REG_R_REMOTE2_TEMPH 0x12 | ||
56 | #define LM95241_REG_R_LOCAL_TEMPL 0x20 | ||
57 | #define LM95241_REG_R_REMOTE1_TEMPL 0x21 | ||
58 | #define LM95241_REG_R_REMOTE2_TEMPL 0x22 | ||
59 | #define LM95241_REG_RW_REMOTE_MODEL 0x30 | ||
60 | |||
61 | /* LM95241 specific bitfields */ | ||
62 | #define CFG_STOP 0x40 | ||
63 | #define CFG_CR0076 0x00 | ||
64 | #define CFG_CR0182 0x10 | ||
65 | #define CFG_CR1000 0x20 | ||
66 | #define CFG_CR2700 0x30 | ||
67 | #define R1MS_SHIFT 0 | ||
68 | #define R2MS_SHIFT 2 | ||
69 | #define R1MS_MASK (0x01 << (R1MS_SHIFT)) | ||
70 | #define R2MS_MASK (0x01 << (R2MS_SHIFT)) | ||
71 | #define R1DF_SHIFT 1 | ||
72 | #define R2DF_SHIFT 2 | ||
73 | #define R1DF_MASK (0x01 << (R1DF_SHIFT)) | ||
74 | #define R2DF_MASK (0x01 << (R2DF_SHIFT)) | ||
75 | #define R1FE_MASK 0x01 | ||
76 | #define R2FE_MASK 0x05 | ||
77 | #define TT1_SHIFT 0 | ||
78 | #define TT2_SHIFT 4 | ||
79 | #define TT_OFF 0 | ||
80 | #define TT_ON 1 | ||
81 | #define TT_MASK 7 | ||
82 | #define MANUFACTURER_ID 0x01 | ||
83 | #define DEFAULT_REVISION 0xA4 | ||
84 | |||
85 | /* Conversions and various macros */ | ||
86 | #define TEMP_FROM_REG(val_h, val_l) (((val_h) & 0x80 ? (val_h) - 0x100 : \ | ||
87 | (val_h)) * 1000 + (val_l) * 1000 / 256) | ||
88 | |||
89 | /* Functions declaration */ | ||
90 | static int lm95241_attach_adapter(struct i2c_adapter *adapter); | ||
91 | static int lm95241_detect(struct i2c_adapter *adapter, int address, | ||
92 | int kind); | ||
93 | static void lm95241_init_client(struct i2c_client *client); | ||
94 | static int lm95241_detach_client(struct i2c_client *client); | ||
95 | static struct lm95241_data *lm95241_update_device(struct device *dev); | ||
96 | |||
97 | /* Driver data (common to all clients) */ | ||
98 | static struct i2c_driver lm95241_driver = { | ||
99 | .driver = { | ||
100 | .name = "lm95241", | ||
101 | }, | ||
102 | .attach_adapter = lm95241_attach_adapter, | ||
103 | .detach_client = lm95241_detach_client, | ||
104 | }; | ||
105 | |||
106 | /* Client data (each client gets its own) */ | ||
107 | struct lm95241_data { | ||
108 | struct i2c_client client; | ||
109 | struct device *hwmon_dev; | ||
110 | struct mutex update_lock; | ||
111 | unsigned long last_updated, rate; /* in jiffies */ | ||
112 | char valid; /* zero until following fields are valid */ | ||
113 | /* registers values */ | ||
114 | u8 local_h, local_l; /* local */ | ||
115 | u8 remote1_h, remote1_l; /* remote1 */ | ||
116 | u8 remote2_h, remote2_l; /* remote2 */ | ||
117 | u8 config, model, trutherm; | ||
118 | }; | ||
119 | |||
120 | /* Sysfs stuff */ | ||
121 | #define show_temp(value) \ | ||
122 | static ssize_t show_##value(struct device *dev, \ | ||
123 | struct device_attribute *attr, char *buf) \ | ||
124 | { \ | ||
125 | struct lm95241_data *data = lm95241_update_device(dev); \ | ||
126 | snprintf(buf, PAGE_SIZE - 1, "%d\n", \ | ||
127 | TEMP_FROM_REG(data->value##_h, data->value##_l)); \ | ||
128 | return strlen(buf); \ | ||
129 | } | ||
130 | show_temp(local); | ||
131 | show_temp(remote1); | ||
132 | show_temp(remote2); | ||
133 | |||
134 | static ssize_t show_rate(struct device *dev, struct device_attribute *attr, | ||
135 | char *buf) | ||
136 | { | ||
137 | struct lm95241_data *data = lm95241_update_device(dev); | ||
138 | |||
139 | snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->rate / HZ); | ||
140 | return strlen(buf); | ||
141 | } | ||
142 | |||
143 | static ssize_t set_rate(struct device *dev, struct device_attribute *attr, | ||
144 | const char *buf, size_t count) | ||
145 | { | ||
146 | struct i2c_client *client = to_i2c_client(dev); | ||
147 | struct lm95241_data *data = i2c_get_clientdata(client); | ||
148 | |||
149 | strict_strtol(buf, 10, &data->rate); | ||
150 | data->rate = data->rate * HZ / 1000; | ||
151 | |||
152 | return count; | ||
153 | } | ||
154 | |||
155 | #define show_type(flag) \ | ||
156 | static ssize_t show_type##flag(struct device *dev, \ | ||
157 | struct device_attribute *attr, char *buf) \ | ||
158 | { \ | ||
159 | struct i2c_client *client = to_i2c_client(dev); \ | ||
160 | struct lm95241_data *data = i2c_get_clientdata(client); \ | ||
161 | \ | ||
162 | snprintf(buf, PAGE_SIZE - 1, \ | ||
163 | data->model & R##flag##MS_MASK ? "1\n" : "2\n"); \ | ||
164 | return strlen(buf); \ | ||
165 | } | ||
166 | show_type(1); | ||
167 | show_type(2); | ||
168 | |||
169 | #define show_min(flag) \ | ||
170 | static ssize_t show_min##flag(struct device *dev, \ | ||
171 | struct device_attribute *attr, char *buf) \ | ||
172 | { \ | ||
173 | struct i2c_client *client = to_i2c_client(dev); \ | ||
174 | struct lm95241_data *data = i2c_get_clientdata(client); \ | ||
175 | \ | ||
176 | snprintf(buf, PAGE_SIZE - 1, \ | ||
177 | data->config & R##flag##DF_MASK ? \ | ||
178 | "-127000\n" : "0\n"); \ | ||
179 | return strlen(buf); \ | ||
180 | } | ||
181 | show_min(1); | ||
182 | show_min(2); | ||
183 | |||
184 | #define show_max(flag) \ | ||
185 | static ssize_t show_max##flag(struct device *dev, \ | ||
186 | struct device_attribute *attr, char *buf) \ | ||
187 | { \ | ||
188 | struct i2c_client *client = to_i2c_client(dev); \ | ||
189 | struct lm95241_data *data = i2c_get_clientdata(client); \ | ||
190 | \ | ||
191 | snprintf(buf, PAGE_SIZE - 1, \ | ||
192 | data->config & R##flag##DF_MASK ? \ | ||
193 | "127000\n" : "255000\n"); \ | ||
194 | return strlen(buf); \ | ||
195 | } | ||
196 | show_max(1); | ||
197 | show_max(2); | ||
198 | |||
199 | #define set_type(flag) \ | ||
200 | static ssize_t set_type##flag(struct device *dev, \ | ||
201 | struct device_attribute *attr, \ | ||
202 | const char *buf, size_t count) \ | ||
203 | { \ | ||
204 | struct i2c_client *client = to_i2c_client(dev); \ | ||
205 | struct lm95241_data *data = i2c_get_clientdata(client); \ | ||
206 | \ | ||
207 | long val; \ | ||
208 | strict_strtol(buf, 10, &val); \ | ||
209 | \ | ||
210 | if ((val == 1) || (val == 2)) { \ | ||
211 | \ | ||
212 | mutex_lock(&data->update_lock); \ | ||
213 | \ | ||
214 | data->trutherm &= ~(TT_MASK << TT##flag##_SHIFT); \ | ||
215 | if (val == 1) { \ | ||
216 | data->model |= R##flag##MS_MASK; \ | ||
217 | data->trutherm |= (TT_ON << TT##flag##_SHIFT); \ | ||
218 | } \ | ||
219 | else { \ | ||
220 | data->model &= ~R##flag##MS_MASK; \ | ||
221 | data->trutherm |= (TT_OFF << TT##flag##_SHIFT); \ | ||
222 | } \ | ||
223 | \ | ||
224 | data->valid = 0; \ | ||
225 | \ | ||
226 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, \ | ||
227 | data->model); \ | ||
228 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, \ | ||
229 | data->trutherm); \ | ||
230 | \ | ||
231 | mutex_unlock(&data->update_lock); \ | ||
232 | \ | ||
233 | } \ | ||
234 | return count; \ | ||
235 | } | ||
236 | set_type(1); | ||
237 | set_type(2); | ||
238 | |||
239 | #define set_min(flag) \ | ||
240 | static ssize_t set_min##flag(struct device *dev, \ | ||
241 | struct device_attribute *devattr, const char *buf, size_t count) \ | ||
242 | { \ | ||
243 | struct i2c_client *client = to_i2c_client(dev); \ | ||
244 | struct lm95241_data *data = i2c_get_clientdata(client); \ | ||
245 | \ | ||
246 | long val; \ | ||
247 | strict_strtol(buf, 10, &val); \ | ||
248 | \ | ||
249 | mutex_lock(&data->update_lock); \ | ||
250 | \ | ||
251 | if (val < 0) \ | ||
252 | data->config |= R##flag##DF_MASK; \ | ||
253 | else \ | ||
254 | data->config &= ~R##flag##DF_MASK; \ | ||
255 | \ | ||
256 | data->valid = 0; \ | ||
257 | \ | ||
258 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \ | ||
259 | data->config); \ | ||
260 | \ | ||
261 | mutex_unlock(&data->update_lock); \ | ||
262 | \ | ||
263 | return count; \ | ||
264 | } | ||
265 | set_min(1); | ||
266 | set_min(2); | ||
267 | |||
268 | #define set_max(flag) \ | ||
269 | static ssize_t set_max##flag(struct device *dev, \ | ||
270 | struct device_attribute *devattr, const char *buf, size_t count) \ | ||
271 | { \ | ||
272 | struct i2c_client *client = to_i2c_client(dev); \ | ||
273 | struct lm95241_data *data = i2c_get_clientdata(client); \ | ||
274 | \ | ||
275 | long val; \ | ||
276 | strict_strtol(buf, 10, &val); \ | ||
277 | \ | ||
278 | mutex_lock(&data->update_lock); \ | ||
279 | \ | ||
280 | if (val <= 127000) \ | ||
281 | data->config |= R##flag##DF_MASK; \ | ||
282 | else \ | ||
283 | data->config &= ~R##flag##DF_MASK; \ | ||
284 | \ | ||
285 | data->valid = 0; \ | ||
286 | \ | ||
287 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \ | ||
288 | data->config); \ | ||
289 | \ | ||
290 | mutex_unlock(&data->update_lock); \ | ||
291 | \ | ||
292 | return count; \ | ||
293 | } | ||
294 | set_max(1); | ||
295 | set_max(2); | ||
296 | |||
297 | static DEVICE_ATTR(temp1_input, S_IRUGO, show_local, NULL); | ||
298 | static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote1, NULL); | ||
299 | static DEVICE_ATTR(temp3_input, S_IRUGO, show_remote2, NULL); | ||
300 | static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type1, set_type1); | ||
301 | static DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type2, set_type2); | ||
302 | static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min1, set_min1); | ||
303 | static DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min2, set_min2); | ||
304 | static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max1, set_max1); | ||
305 | static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max2, set_max2); | ||
306 | static DEVICE_ATTR(rate, S_IWUSR | S_IRUGO, show_rate, set_rate); | ||
307 | |||
308 | static struct attribute *lm95241_attributes[] = { | ||
309 | &dev_attr_temp1_input.attr, | ||
310 | &dev_attr_temp2_input.attr, | ||
311 | &dev_attr_temp3_input.attr, | ||
312 | &dev_attr_temp2_type.attr, | ||
313 | &dev_attr_temp3_type.attr, | ||
314 | &dev_attr_temp2_min.attr, | ||
315 | &dev_attr_temp3_min.attr, | ||
316 | &dev_attr_temp2_max.attr, | ||
317 | &dev_attr_temp3_max.attr, | ||
318 | &dev_attr_rate.attr, | ||
319 | NULL | ||
320 | }; | ||
321 | |||
322 | static const struct attribute_group lm95241_group = { | ||
323 | .attrs = lm95241_attributes, | ||
324 | }; | ||
325 | |||
326 | /* Init/exit code */ | ||
327 | static int lm95241_attach_adapter(struct i2c_adapter *adapter) | ||
328 | { | ||
329 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
330 | return 0; | ||
331 | return i2c_probe(adapter, &addr_data, lm95241_detect); | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * The following function does more than just detection. If detection | ||
336 | * succeeds, it also registers the new chip. | ||
337 | */ | ||
338 | static int lm95241_detect(struct i2c_adapter *adapter, int address, int kind) | ||
339 | { | ||
340 | struct i2c_client *new_client; | ||
341 | struct lm95241_data *data; | ||
342 | int err = 0; | ||
343 | const char *name = ""; | ||
344 | |||
345 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
346 | goto exit; | ||
347 | |||
348 | data = kzalloc(sizeof(struct lm95241_data), GFP_KERNEL); | ||
349 | if (!data) { | ||
350 | err = -ENOMEM; | ||
351 | goto exit; | ||
352 | } | ||
353 | |||
354 | /* The common I2C client data is placed right before the | ||
355 | LM95241-specific data. */ | ||
356 | new_client = &data->client; | ||
357 | i2c_set_clientdata(new_client, data); | ||
358 | new_client->addr = address; | ||
359 | new_client->adapter = adapter; | ||
360 | new_client->driver = &lm95241_driver; | ||
361 | new_client->flags = 0; | ||
362 | |||
363 | /* | ||
364 | * Now we do the remaining detection. A negative kind means that | ||
365 | * the driver was loaded with no force parameter (default), so we | ||
366 | * must both detect and identify the chip. A zero kind means that | ||
367 | * the driver was loaded with the force parameter, the detection | ||
368 | * step shall be skipped. A positive kind means that the driver | ||
369 | * was loaded with the force parameter and a given kind of chip is | ||
370 | * requested, so both the detection and the identification steps | ||
371 | * are skipped. | ||
372 | */ | ||
373 | if (kind < 0) { /* detection */ | ||
374 | if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) | ||
375 | != MANUFACTURER_ID) | ||
376 | || (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) | ||
377 | < DEFAULT_REVISION)) { | ||
378 | dev_dbg(&adapter->dev, | ||
379 | "LM95241 detection failed at 0x%02x.\n", | ||
380 | address); | ||
381 | goto exit_free; | ||
382 | } | ||
383 | } | ||
384 | |||
385 | if (kind <= 0) { /* identification */ | ||
386 | if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) | ||
387 | == MANUFACTURER_ID) | ||
388 | && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) | ||
389 | >= DEFAULT_REVISION)) { | ||
390 | |||
391 | kind = lm95241; | ||
392 | |||
393 | if (kind <= 0) { /* identification failed */ | ||
394 | dev_info(&adapter->dev, "Unsupported chip\n"); | ||
395 | goto exit_free; | ||
396 | } | ||
397 | } | ||
398 | } | ||
399 | |||
400 | if (kind == lm95241) | ||
401 | name = "lm95241"; | ||
402 | |||
403 | /* We can fill in the remaining client fields */ | ||
404 | strlcpy(new_client->name, name, I2C_NAME_SIZE); | ||
405 | data->valid = 0; | ||
406 | mutex_init(&data->update_lock); | ||
407 | |||
408 | /* Tell the I2C layer a new client has arrived */ | ||
409 | err = i2c_attach_client(new_client); | ||
410 | if (err) | ||
411 | goto exit_free; | ||
412 | |||
413 | /* Initialize the LM95241 chip */ | ||
414 | lm95241_init_client(new_client); | ||
415 | |||
416 | /* Register sysfs hooks */ | ||
417 | err = sysfs_create_group(&new_client->dev.kobj, &lm95241_group); | ||
418 | if (err) | ||
419 | goto exit_detach; | ||
420 | |||
421 | data->hwmon_dev = hwmon_device_register(&new_client->dev); | ||
422 | if (IS_ERR(data->hwmon_dev)) { | ||
423 | err = PTR_ERR(data->hwmon_dev); | ||
424 | goto exit_remove_files; | ||
425 | } | ||
426 | |||
427 | return 0; | ||
428 | |||
429 | exit_remove_files: | ||
430 | sysfs_remove_group(&new_client->dev.kobj, &lm95241_group); | ||
431 | exit_detach: | ||
432 | i2c_detach_client(new_client); | ||
433 | exit_free: | ||
434 | kfree(data); | ||
435 | exit: | ||
436 | return err; | ||
437 | } | ||
438 | |||
439 | static void lm95241_init_client(struct i2c_client *client) | ||
440 | { | ||
441 | struct lm95241_data *data = i2c_get_clientdata(client); | ||
442 | |||
443 | data->rate = HZ; /* 1 sec default */ | ||
444 | data->valid = 0; | ||
445 | data->config = CFG_CR0076; | ||
446 | data->model = 0; | ||
447 | data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT); | ||
448 | |||
449 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, | ||
450 | data->config); | ||
451 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER, | ||
452 | R1FE_MASK | R2FE_MASK); | ||
453 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, | ||
454 | data->trutherm); | ||
455 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, | ||
456 | data->model); | ||
457 | } | ||
458 | |||
459 | static int lm95241_detach_client(struct i2c_client *client) | ||
460 | { | ||
461 | struct lm95241_data *data = i2c_get_clientdata(client); | ||
462 | int err; | ||
463 | |||
464 | hwmon_device_unregister(data->hwmon_dev); | ||
465 | sysfs_remove_group(&client->dev.kobj, &lm95241_group); | ||
466 | |||
467 | err = i2c_detach_client(client); | ||
468 | if (err) | ||
469 | return err; | ||
470 | |||
471 | kfree(data); | ||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | static struct lm95241_data *lm95241_update_device(struct device *dev) | ||
476 | { | ||
477 | struct i2c_client *client = to_i2c_client(dev); | ||
478 | struct lm95241_data *data = i2c_get_clientdata(client); | ||
479 | |||
480 | mutex_lock(&data->update_lock); | ||
481 | |||
482 | if (time_after(jiffies, data->last_updated + data->rate) || | ||
483 | !data->valid) { | ||
484 | dev_dbg(&client->dev, "Updating lm95241 data.\n"); | ||
485 | data->local_h = | ||
486 | i2c_smbus_read_byte_data(client, | ||
487 | LM95241_REG_R_LOCAL_TEMPH); | ||
488 | data->local_l = | ||
489 | i2c_smbus_read_byte_data(client, | ||
490 | LM95241_REG_R_LOCAL_TEMPL); | ||
491 | data->remote1_h = | ||
492 | i2c_smbus_read_byte_data(client, | ||
493 | LM95241_REG_R_REMOTE1_TEMPH); | ||
494 | data->remote1_l = | ||
495 | i2c_smbus_read_byte_data(client, | ||
496 | LM95241_REG_R_REMOTE1_TEMPL); | ||
497 | data->remote2_h = | ||
498 | i2c_smbus_read_byte_data(client, | ||
499 | LM95241_REG_R_REMOTE2_TEMPH); | ||
500 | data->remote2_l = | ||
501 | i2c_smbus_read_byte_data(client, | ||
502 | LM95241_REG_R_REMOTE2_TEMPL); | ||
503 | data->last_updated = jiffies; | ||
504 | data->valid = 1; | ||
505 | } | ||
506 | |||
507 | mutex_unlock(&data->update_lock); | ||
508 | |||
509 | return data; | ||
510 | } | ||
511 | |||
512 | static int __init sensors_lm95241_init(void) | ||
513 | { | ||
514 | return i2c_add_driver(&lm95241_driver); | ||
515 | } | ||
516 | |||
517 | static void __exit sensors_lm95241_exit(void) | ||
518 | { | ||
519 | i2c_del_driver(&lm95241_driver); | ||
520 | } | ||
521 | |||
522 | MODULE_AUTHOR("Davide Rizzo <elpa-rizzo@gmail.com>"); | ||
523 | MODULE_DESCRIPTION("LM95241 sensor driver"); | ||
524 | MODULE_LICENSE("GPL"); | ||
525 | |||
526 | module_init(sensors_lm95241_init); | ||
527 | module_exit(sensors_lm95241_exit); | ||
diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c new file mode 100644 index 00000000000..9386e2a3921 --- /dev/null +++ b/drivers/hwmon/ltc4215.c | |||
@@ -0,0 +1,364 @@ | |||
1 | /* | ||
2 | * Driver for Linear Technology LTC4215 I2C Hot Swap Controller | ||
3 | * | ||
4 | * Copyright (C) 2009 Ira W. Snyder <iws@ovro.caltech.edu> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * Datasheet: | ||
11 | * http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1006,C1163,P17572,D12697 | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/hwmon.h> | ||
21 | #include <linux/hwmon-sysfs.h> | ||
22 | |||
23 | static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
24 | |||
25 | /* Insmod parameters */ | ||
26 | I2C_CLIENT_INSMOD_1(ltc4215); | ||
27 | |||
28 | /* Here are names of the chip's registers (a.k.a. commands) */ | ||
29 | enum ltc4215_cmd { | ||
30 | LTC4215_CONTROL = 0x00, /* rw */ | ||
31 | LTC4215_ALERT = 0x01, /* rw */ | ||
32 | LTC4215_STATUS = 0x02, /* ro */ | ||
33 | LTC4215_FAULT = 0x03, /* rw */ | ||
34 | LTC4215_SENSE = 0x04, /* rw */ | ||
35 | LTC4215_SOURCE = 0x05, /* rw */ | ||
36 | LTC4215_ADIN = 0x06, /* rw */ | ||
37 | }; | ||
38 | |||
39 | struct ltc4215_data { | ||
40 | struct device *hwmon_dev; | ||
41 | |||
42 | struct mutex update_lock; | ||
43 | bool valid; | ||
44 | unsigned long last_updated; /* in jiffies */ | ||
45 | |||
46 | /* Registers */ | ||
47 | u8 regs[7]; | ||
48 | }; | ||
49 | |||
50 | static struct ltc4215_data *ltc4215_update_device(struct device *dev) | ||
51 | { | ||
52 | struct i2c_client *client = to_i2c_client(dev); | ||
53 | struct ltc4215_data *data = i2c_get_clientdata(client); | ||
54 | s32 val; | ||
55 | int i; | ||
56 | |||
57 | mutex_lock(&data->update_lock); | ||
58 | |||
59 | /* The chip's A/D updates 10 times per second */ | ||
60 | if (time_after(jiffies, data->last_updated + HZ / 10) || !data->valid) { | ||
61 | |||
62 | dev_dbg(&client->dev, "Starting ltc4215 update\n"); | ||
63 | |||
64 | /* Read all registers */ | ||
65 | for (i = 0; i < ARRAY_SIZE(data->regs); i++) { | ||
66 | val = i2c_smbus_read_byte_data(client, i); | ||
67 | if (unlikely(val < 0)) | ||
68 | data->regs[i] = 0; | ||
69 | else | ||
70 | data->regs[i] = val; | ||
71 | } | ||
72 | |||
73 | data->last_updated = jiffies; | ||
74 | data->valid = 1; | ||
75 | } | ||
76 | |||
77 | mutex_unlock(&data->update_lock); | ||
78 | |||
79 | return data; | ||
80 | } | ||
81 | |||
82 | /* Return the voltage from the given register in millivolts */ | ||
83 | static int ltc4215_get_voltage(struct device *dev, u8 reg) | ||
84 | { | ||
85 | struct ltc4215_data *data = ltc4215_update_device(dev); | ||
86 | const u8 regval = data->regs[reg]; | ||
87 | u32 voltage = 0; | ||
88 | |||
89 | switch (reg) { | ||
90 | case LTC4215_SENSE: | ||
91 | /* 151 uV per increment */ | ||
92 | voltage = regval * 151 / 1000; | ||
93 | break; | ||
94 | case LTC4215_SOURCE: | ||
95 | /* 60.5 mV per increment */ | ||
96 | voltage = regval * 605 / 10; | ||
97 | break; | ||
98 | case LTC4215_ADIN: | ||
99 | /* The ADIN input is divided by 12.5, and has 4.82 mV | ||
100 | * per increment, so we have the additional multiply */ | ||
101 | voltage = regval * 482 * 125 / 1000; | ||
102 | break; | ||
103 | default: | ||
104 | /* If we get here, the developer messed up */ | ||
105 | WARN_ON_ONCE(1); | ||
106 | break; | ||
107 | } | ||
108 | |||
109 | return voltage; | ||
110 | } | ||
111 | |||
112 | /* Return the current from the sense resistor in mA */ | ||
113 | static unsigned int ltc4215_get_current(struct device *dev) | ||
114 | { | ||
115 | struct ltc4215_data *data = ltc4215_update_device(dev); | ||
116 | |||
117 | /* The strange looking conversions that follow are fixed-point | ||
118 | * math, since we cannot do floating point in the kernel. | ||
119 | * | ||
120 | * Step 1: convert sense register to microVolts | ||
121 | * Step 2: convert voltage to milliAmperes | ||
122 | * | ||
123 | * If you play around with the V=IR equation, you come up with | ||
124 | * the following: X uV / Y mOhm == Z mA | ||
125 | * | ||
126 | * With the resistors that are fractions of a milliOhm, we multiply | ||
127 | * the voltage and resistance by 10, to shift the decimal point. | ||
128 | * Now we can use the normal division operator again. | ||
129 | */ | ||
130 | |||
131 | /* Calculate voltage in microVolts (151 uV per increment) */ | ||
132 | const unsigned int voltage = data->regs[LTC4215_SENSE] * 151; | ||
133 | |||
134 | /* Calculate current in milliAmperes (4 milliOhm sense resistor) */ | ||
135 | const unsigned int curr = voltage / 4; | ||
136 | |||
137 | return curr; | ||
138 | } | ||
139 | |||
140 | static ssize_t ltc4215_show_voltage(struct device *dev, | ||
141 | struct device_attribute *da, | ||
142 | char *buf) | ||
143 | { | ||
144 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
145 | const int voltage = ltc4215_get_voltage(dev, attr->index); | ||
146 | |||
147 | return snprintf(buf, PAGE_SIZE, "%d\n", voltage); | ||
148 | } | ||
149 | |||
150 | static ssize_t ltc4215_show_current(struct device *dev, | ||
151 | struct device_attribute *da, | ||
152 | char *buf) | ||
153 | { | ||
154 | const unsigned int curr = ltc4215_get_current(dev); | ||
155 | |||
156 | return snprintf(buf, PAGE_SIZE, "%u\n", curr); | ||
157 | } | ||
158 | |||
159 | static ssize_t ltc4215_show_power(struct device *dev, | ||
160 | struct device_attribute *da, | ||
161 | char *buf) | ||
162 | { | ||
163 | const unsigned int curr = ltc4215_get_current(dev); | ||
164 | const int output_voltage = ltc4215_get_voltage(dev, LTC4215_ADIN); | ||
165 | |||
166 | /* current in mA * voltage in mV == power in uW */ | ||
167 | const unsigned int power = abs(output_voltage * curr); | ||
168 | |||
169 | return snprintf(buf, PAGE_SIZE, "%u\n", power); | ||
170 | } | ||
171 | |||
172 | static ssize_t ltc4215_show_alarm(struct device *dev, | ||
173 | struct device_attribute *da, | ||
174 | char *buf) | ||
175 | { | ||
176 | struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da); | ||
177 | struct ltc4215_data *data = ltc4215_update_device(dev); | ||
178 | const u8 reg = data->regs[attr->index]; | ||
179 | const u32 mask = attr->nr; | ||
180 | |||
181 | return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0); | ||
182 | } | ||
183 | |||
184 | /* These macros are used below in constructing device attribute objects | ||
185 | * for use with sysfs_create_group() to make a sysfs device file | ||
186 | * for each register. | ||
187 | */ | ||
188 | |||
189 | #define LTC4215_VOLTAGE(name, ltc4215_cmd_idx) \ | ||
190 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ | ||
191 | ltc4215_show_voltage, NULL, ltc4215_cmd_idx) | ||
192 | |||
193 | #define LTC4215_CURRENT(name) \ | ||
194 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ | ||
195 | ltc4215_show_current, NULL, 0); | ||
196 | |||
197 | #define LTC4215_POWER(name) \ | ||
198 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ | ||
199 | ltc4215_show_power, NULL, 0); | ||
200 | |||
201 | #define LTC4215_ALARM(name, mask, reg) \ | ||
202 | static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \ | ||
203 | ltc4215_show_alarm, NULL, (mask), reg) | ||
204 | |||
205 | /* Construct a sensor_device_attribute structure for each register */ | ||
206 | |||
207 | /* Current */ | ||
208 | LTC4215_CURRENT(curr1_input); | ||
209 | LTC4215_ALARM(curr1_max_alarm, (1 << 2), LTC4215_STATUS); | ||
210 | |||
211 | /* Power (virtual) */ | ||
212 | LTC4215_POWER(power1_input); | ||
213 | LTC4215_ALARM(power1_alarm, (1 << 3), LTC4215_STATUS); | ||
214 | |||
215 | /* Input Voltage */ | ||
216 | LTC4215_VOLTAGE(in1_input, LTC4215_ADIN); | ||
217 | LTC4215_ALARM(in1_max_alarm, (1 << 0), LTC4215_STATUS); | ||
218 | LTC4215_ALARM(in1_min_alarm, (1 << 1), LTC4215_STATUS); | ||
219 | |||
220 | /* Output Voltage */ | ||
221 | LTC4215_VOLTAGE(in2_input, LTC4215_SOURCE); | ||
222 | |||
223 | /* Finally, construct an array of pointers to members of the above objects, | ||
224 | * as required for sysfs_create_group() | ||
225 | */ | ||
226 | static struct attribute *ltc4215_attributes[] = { | ||
227 | &sensor_dev_attr_curr1_input.dev_attr.attr, | ||
228 | &sensor_dev_attr_curr1_max_alarm.dev_attr.attr, | ||
229 | |||
230 | &sensor_dev_attr_power1_input.dev_attr.attr, | ||
231 | &sensor_dev_attr_power1_alarm.dev_attr.attr, | ||
232 | |||
233 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
234 | &sensor_dev_attr_in1_max_alarm.dev_attr.attr, | ||
235 | &sensor_dev_attr_in1_min_alarm.dev_attr.attr, | ||
236 | |||
237 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
238 | |||
239 | NULL, | ||
240 | }; | ||
241 | |||
242 | static const struct attribute_group ltc4215_group = { | ||
243 | .attrs = ltc4215_attributes, | ||
244 | }; | ||
245 | |||
246 | static int ltc4215_probe(struct i2c_client *client, | ||
247 | const struct i2c_device_id *id) | ||
248 | { | ||
249 | struct ltc4215_data *data; | ||
250 | int ret; | ||
251 | |||
252 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
253 | if (!data) { | ||
254 | ret = -ENOMEM; | ||
255 | goto out_kzalloc; | ||
256 | } | ||
257 | |||
258 | i2c_set_clientdata(client, data); | ||
259 | mutex_init(&data->update_lock); | ||
260 | |||
261 | /* Initialize the LTC4215 chip */ | ||
262 | /* TODO */ | ||
263 | |||
264 | /* Register sysfs hooks */ | ||
265 | ret = sysfs_create_group(&client->dev.kobj, <c4215_group); | ||
266 | if (ret) | ||
267 | goto out_sysfs_create_group; | ||
268 | |||
269 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
270 | if (IS_ERR(data->hwmon_dev)) { | ||
271 | ret = PTR_ERR(data->hwmon_dev); | ||
272 | goto out_hwmon_device_register; | ||
273 | } | ||
274 | |||
275 | return 0; | ||
276 | |||
277 | out_hwmon_device_register: | ||
278 | sysfs_remove_group(&client->dev.kobj, <c4215_group); | ||
279 | out_sysfs_create_group: | ||
280 | kfree(data); | ||
281 | out_kzalloc: | ||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | static int ltc4215_remove(struct i2c_client *client) | ||
286 | { | ||
287 | struct ltc4215_data *data = i2c_get_clientdata(client); | ||
288 | |||
289 | hwmon_device_unregister(data->hwmon_dev); | ||
290 | sysfs_remove_group(&client->dev.kobj, <c4215_group); | ||
291 | |||
292 | kfree(data); | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static int ltc4215_detect(struct i2c_client *client, | ||
298 | int kind, | ||
299 | struct i2c_board_info *info) | ||
300 | { | ||
301 | struct i2c_adapter *adapter = client->adapter; | ||
302 | |||
303 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
304 | return -ENODEV; | ||
305 | |||
306 | if (kind < 0) { /* probed detection - check the chip type */ | ||
307 | s32 v; /* 8 bits from the chip, or -ERRNO */ | ||
308 | |||
309 | /* | ||
310 | * Register 0x01 bit b7 is reserved, expect 0 | ||
311 | * Register 0x03 bit b6 and b7 are reserved, expect 0 | ||
312 | */ | ||
313 | v = i2c_smbus_read_byte_data(client, LTC4215_ALERT); | ||
314 | if (v < 0 || (v & (1 << 7)) != 0) | ||
315 | return -ENODEV; | ||
316 | |||
317 | v = i2c_smbus_read_byte_data(client, LTC4215_FAULT); | ||
318 | if (v < 0 || (v & ((1 << 6) | (1 << 7))) != 0) | ||
319 | return -ENODEV; | ||
320 | } | ||
321 | |||
322 | strlcpy(info->type, "ltc4215", I2C_NAME_SIZE); | ||
323 | dev_info(&adapter->dev, "ltc4215 %s at address 0x%02x\n", | ||
324 | kind < 0 ? "probed" : "forced", | ||
325 | client->addr); | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static const struct i2c_device_id ltc4215_id[] = { | ||
331 | { "ltc4215", ltc4215 }, | ||
332 | { } | ||
333 | }; | ||
334 | MODULE_DEVICE_TABLE(i2c, ltc4215_id); | ||
335 | |||
336 | /* This is the driver that will be inserted */ | ||
337 | static struct i2c_driver ltc4215_driver = { | ||
338 | .class = I2C_CLASS_HWMON, | ||
339 | .driver = { | ||
340 | .name = "ltc4215", | ||
341 | }, | ||
342 | .probe = ltc4215_probe, | ||
343 | .remove = ltc4215_remove, | ||
344 | .id_table = ltc4215_id, | ||
345 | .detect = ltc4215_detect, | ||
346 | .address_data = &addr_data, | ||
347 | }; | ||
348 | |||
349 | static int __init ltc4215_init(void) | ||
350 | { | ||
351 | return i2c_add_driver(<c4215_driver); | ||
352 | } | ||
353 | |||
354 | static void __exit ltc4215_exit(void) | ||
355 | { | ||
356 | i2c_del_driver(<c4215_driver); | ||
357 | } | ||
358 | |||
359 | MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>"); | ||
360 | MODULE_DESCRIPTION("LTC4215 driver"); | ||
361 | MODULE_LICENSE("GPL"); | ||
362 | |||
363 | module_init(ltc4215_init); | ||
364 | module_exit(ltc4215_exit); | ||
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 3e468d2cf73..2d8352419c0 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c | |||
@@ -1331,12 +1331,6 @@ static void capinc_tty_send_xchar(struct tty_struct *tty, char ch) | |||
1331 | #endif | 1331 | #endif |
1332 | } | 1332 | } |
1333 | 1333 | ||
1334 | static int capinc_tty_read_proc(char *page, char **start, off_t off, | ||
1335 | int count, int *eof, void *data) | ||
1336 | { | ||
1337 | return 0; | ||
1338 | } | ||
1339 | |||
1340 | static struct tty_driver *capinc_tty_driver; | 1334 | static struct tty_driver *capinc_tty_driver; |
1341 | 1335 | ||
1342 | static const struct tty_operations capinc_ops = { | 1336 | static const struct tty_operations capinc_ops = { |
@@ -1358,7 +1352,6 @@ static const struct tty_operations capinc_ops = { | |||
1358 | .flush_buffer = capinc_tty_flush_buffer, | 1352 | .flush_buffer = capinc_tty_flush_buffer, |
1359 | .set_ldisc = capinc_tty_set_ldisc, | 1353 | .set_ldisc = capinc_tty_set_ldisc, |
1360 | .send_xchar = capinc_tty_send_xchar, | 1354 | .send_xchar = capinc_tty_send_xchar, |
1361 | .read_proc = capinc_tty_read_proc, | ||
1362 | }; | 1355 | }; |
1363 | 1356 | ||
1364 | static int capinc_tty_init(void) | 1357 | static int capinc_tty_init(void) |
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 1c484084ed4..5f3bff43462 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -223,6 +223,16 @@ config DELL_LAPTOP | |||
223 | This driver adds support for rfkill and backlight control to Dell | 223 | This driver adds support for rfkill and backlight control to Dell |
224 | laptops. | 224 | laptops. |
225 | 225 | ||
226 | config ISL29003 | ||
227 | tristate "Intersil ISL29003 ambient light sensor" | ||
228 | depends on I2C && SYSFS | ||
229 | help | ||
230 | If you say yes here you get support for the Intersil ISL29003 | ||
231 | ambient light sensor. | ||
232 | |||
233 | This driver can also be built as a module. If so, the module | ||
234 | will be called isl29003. | ||
235 | |||
226 | source "drivers/misc/c2port/Kconfig" | 236 | source "drivers/misc/c2port/Kconfig" |
227 | source "drivers/misc/eeprom/Kconfig" | 237 | source "drivers/misc/eeprom/Kconfig" |
228 | 238 | ||
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index bc119983055..7871f05dcb9 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
@@ -18,5 +18,6 @@ obj-$(CONFIG_KGDB_TESTS) += kgdbts.o | |||
18 | obj-$(CONFIG_SGI_XP) += sgi-xp/ | 18 | obj-$(CONFIG_SGI_XP) += sgi-xp/ |
19 | obj-$(CONFIG_SGI_GRU) += sgi-gru/ | 19 | obj-$(CONFIG_SGI_GRU) += sgi-gru/ |
20 | obj-$(CONFIG_HP_ILO) += hpilo.o | 20 | obj-$(CONFIG_HP_ILO) += hpilo.o |
21 | obj-$(CONFIG_ISL29003) += isl29003.o | ||
21 | obj-$(CONFIG_C2PORT) += c2port/ | 22 | obj-$(CONFIG_C2PORT) += c2port/ |
22 | obj-y += eeprom/ | 23 | obj-y += eeprom/ |
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c index cf991850f01..880ccf39e23 100644 --- a/drivers/misc/hpilo.c +++ b/drivers/misc/hpilo.c | |||
@@ -209,7 +209,7 @@ static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data) | |||
209 | /* give iLO some time to process stop request */ | 209 | /* give iLO some time to process stop request */ |
210 | for (retries = MAX_WAIT; retries > 0; retries--) { | 210 | for (retries = MAX_WAIT; retries > 0; retries--) { |
211 | doorbell_set(driver_ccb); | 211 | doorbell_set(driver_ccb); |
212 | udelay(1); | 212 | udelay(WAIT_TIME); |
213 | if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A)) | 213 | if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A)) |
214 | && | 214 | && |
215 | !(ioread32(&device_ccb->recv_ctrl) & (1 << CTRL_BITPOS_A))) | 215 | !(ioread32(&device_ccb->recv_ctrl) & (1 << CTRL_BITPOS_A))) |
@@ -312,7 +312,7 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot) | |||
312 | for (i = MAX_WAIT; i > 0; i--) { | 312 | for (i = MAX_WAIT; i > 0; i--) { |
313 | if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL)) | 313 | if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL)) |
314 | break; | 314 | break; |
315 | udelay(1); | 315 | udelay(WAIT_TIME); |
316 | } | 316 | } |
317 | 317 | ||
318 | if (i) { | 318 | if (i) { |
@@ -759,7 +759,7 @@ static void __exit ilo_exit(void) | |||
759 | class_destroy(ilo_class); | 759 | class_destroy(ilo_class); |
760 | } | 760 | } |
761 | 761 | ||
762 | MODULE_VERSION("1.0"); | 762 | MODULE_VERSION("1.1"); |
763 | MODULE_ALIAS(ILO_NAME); | 763 | MODULE_ALIAS(ILO_NAME); |
764 | MODULE_DESCRIPTION(ILO_NAME); | 764 | MODULE_DESCRIPTION(ILO_NAME); |
765 | MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>"); | 765 | MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>"); |
diff --git a/drivers/misc/hpilo.h b/drivers/misc/hpilo.h index b64a20ef07e..03a14c82aad 100644 --- a/drivers/misc/hpilo.h +++ b/drivers/misc/hpilo.h | |||
@@ -19,8 +19,12 @@ | |||
19 | #define MAX_ILO_DEV 1 | 19 | #define MAX_ILO_DEV 1 |
20 | /* max number of files */ | 20 | /* max number of files */ |
21 | #define MAX_OPEN (MAX_CCB * MAX_ILO_DEV) | 21 | #define MAX_OPEN (MAX_CCB * MAX_ILO_DEV) |
22 | /* total wait time in usec */ | ||
23 | #define MAX_WAIT_TIME 10000 | ||
24 | /* per spin wait time in usec */ | ||
25 | #define WAIT_TIME 10 | ||
22 | /* spin counter for open/close delay */ | 26 | /* spin counter for open/close delay */ |
23 | #define MAX_WAIT 10000 | 27 | #define MAX_WAIT (MAX_WAIT_TIME / WAIT_TIME) |
24 | 28 | ||
25 | /* | 29 | /* |
26 | * Per device, used to track global memory allocations. | 30 | * Per device, used to track global memory allocations. |
diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c new file mode 100644 index 00000000000..2e2a5923d4c --- /dev/null +++ b/drivers/misc/isl29003.c | |||
@@ -0,0 +1,470 @@ | |||
1 | /* | ||
2 | * isl29003.c - Linux kernel module for | ||
3 | * Intersil ISL29003 ambient light sensor | ||
4 | * | ||
5 | * See file:Documentation/misc-devices/isl29003 | ||
6 | * | ||
7 | * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> | ||
8 | * | ||
9 | * Based on code written by | ||
10 | * Rodolfo Giometti <giometti@linux.it> | ||
11 | * Eurotech S.p.A. <info@eurotech.it> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/i2c.h> | ||
32 | #include <linux/mutex.h> | ||
33 | #include <linux/delay.h> | ||
34 | |||
35 | #define ISL29003_DRV_NAME "isl29003" | ||
36 | #define DRIVER_VERSION "1.0" | ||
37 | |||
38 | #define ISL29003_REG_COMMAND 0x00 | ||
39 | #define ISL29003_ADC_ENABLED (1 << 7) | ||
40 | #define ISL29003_ADC_PD (1 << 6) | ||
41 | #define ISL29003_TIMING_INT (1 << 5) | ||
42 | #define ISL29003_MODE_SHIFT (2) | ||
43 | #define ISL29003_MODE_MASK (0x3 << ISL29003_MODE_SHIFT) | ||
44 | #define ISL29003_RES_SHIFT (0) | ||
45 | #define ISL29003_RES_MASK (0x3 << ISL29003_RES_SHIFT) | ||
46 | |||
47 | #define ISL29003_REG_CONTROL 0x01 | ||
48 | #define ISL29003_INT_FLG (1 << 5) | ||
49 | #define ISL29003_RANGE_SHIFT (2) | ||
50 | #define ISL29003_RANGE_MASK (0x3 << ISL29003_RANGE_SHIFT) | ||
51 | #define ISL29003_INT_PERSISTS_SHIFT (0) | ||
52 | #define ISL29003_INT_PERSISTS_MASK (0xf << ISL29003_INT_PERSISTS_SHIFT) | ||
53 | |||
54 | #define ISL29003_REG_IRQ_THRESH_HI 0x02 | ||
55 | #define ISL29003_REG_IRQ_THRESH_LO 0x03 | ||
56 | #define ISL29003_REG_LSB_SENSOR 0x04 | ||
57 | #define ISL29003_REG_MSB_SENSOR 0x05 | ||
58 | #define ISL29003_REG_LSB_TIMER 0x06 | ||
59 | #define ISL29003_REG_MSB_TIMER 0x07 | ||
60 | |||
61 | #define ISL29003_NUM_CACHABLE_REGS 4 | ||
62 | |||
63 | struct isl29003_data { | ||
64 | struct i2c_client *client; | ||
65 | struct mutex lock; | ||
66 | u8 reg_cache[ISL29003_NUM_CACHABLE_REGS]; | ||
67 | }; | ||
68 | |||
69 | static int gain_range[] = { | ||
70 | 1000, 4000, 16000, 64000 | ||
71 | }; | ||
72 | |||
73 | /* | ||
74 | * register access helpers | ||
75 | */ | ||
76 | |||
77 | static int __isl29003_read_reg(struct i2c_client *client, | ||
78 | u32 reg, u8 mask, u8 shift) | ||
79 | { | ||
80 | struct isl29003_data *data = i2c_get_clientdata(client); | ||
81 | return (data->reg_cache[reg] & mask) >> shift; | ||
82 | } | ||
83 | |||
84 | static int __isl29003_write_reg(struct i2c_client *client, | ||
85 | u32 reg, u8 mask, u8 shift, u8 val) | ||
86 | { | ||
87 | struct isl29003_data *data = i2c_get_clientdata(client); | ||
88 | int ret = 0; | ||
89 | u8 tmp; | ||
90 | |||
91 | if (reg >= ISL29003_NUM_CACHABLE_REGS) | ||
92 | return -EINVAL; | ||
93 | |||
94 | mutex_lock(&data->lock); | ||
95 | |||
96 | tmp = data->reg_cache[reg]; | ||
97 | tmp &= ~mask; | ||
98 | tmp |= val << shift; | ||
99 | |||
100 | ret = i2c_smbus_write_byte_data(client, reg, tmp); | ||
101 | if (!ret) | ||
102 | data->reg_cache[reg] = tmp; | ||
103 | |||
104 | mutex_unlock(&data->lock); | ||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * internally used functions | ||
110 | */ | ||
111 | |||
112 | /* range */ | ||
113 | static int isl29003_get_range(struct i2c_client *client) | ||
114 | { | ||
115 | return __isl29003_read_reg(client, ISL29003_REG_CONTROL, | ||
116 | ISL29003_RANGE_MASK, ISL29003_RANGE_SHIFT); | ||
117 | } | ||
118 | |||
119 | static int isl29003_set_range(struct i2c_client *client, int range) | ||
120 | { | ||
121 | return __isl29003_write_reg(client, ISL29003_REG_CONTROL, | ||
122 | ISL29003_RANGE_MASK, ISL29003_RANGE_SHIFT, range); | ||
123 | } | ||
124 | |||
125 | /* resolution */ | ||
126 | static int isl29003_get_resolution(struct i2c_client *client) | ||
127 | { | ||
128 | return __isl29003_read_reg(client, ISL29003_REG_COMMAND, | ||
129 | ISL29003_RES_MASK, ISL29003_RES_SHIFT); | ||
130 | } | ||
131 | |||
132 | static int isl29003_set_resolution(struct i2c_client *client, int res) | ||
133 | { | ||
134 | return __isl29003_write_reg(client, ISL29003_REG_COMMAND, | ||
135 | ISL29003_RES_MASK, ISL29003_RES_SHIFT, res); | ||
136 | } | ||
137 | |||
138 | /* mode */ | ||
139 | static int isl29003_get_mode(struct i2c_client *client) | ||
140 | { | ||
141 | return __isl29003_read_reg(client, ISL29003_REG_COMMAND, | ||
142 | ISL29003_RES_MASK, ISL29003_RES_SHIFT); | ||
143 | } | ||
144 | |||
145 | static int isl29003_set_mode(struct i2c_client *client, int mode) | ||
146 | { | ||
147 | return __isl29003_write_reg(client, ISL29003_REG_COMMAND, | ||
148 | ISL29003_RES_MASK, ISL29003_RES_SHIFT, mode); | ||
149 | } | ||
150 | |||
151 | /* power_state */ | ||
152 | static int isl29003_set_power_state(struct i2c_client *client, int state) | ||
153 | { | ||
154 | return __isl29003_write_reg(client, ISL29003_REG_COMMAND, | ||
155 | ISL29003_ADC_ENABLED | ISL29003_ADC_PD, 0, | ||
156 | state ? ISL29003_ADC_ENABLED : ISL29003_ADC_PD); | ||
157 | } | ||
158 | |||
159 | static int isl29003_get_power_state(struct i2c_client *client) | ||
160 | { | ||
161 | struct isl29003_data *data = i2c_get_clientdata(client); | ||
162 | u8 cmdreg = data->reg_cache[ISL29003_REG_COMMAND]; | ||
163 | return ~cmdreg & ISL29003_ADC_PD; | ||
164 | } | ||
165 | |||
166 | static int isl29003_get_adc_value(struct i2c_client *client) | ||
167 | { | ||
168 | struct isl29003_data *data = i2c_get_clientdata(client); | ||
169 | int lsb, msb, range, bitdepth; | ||
170 | |||
171 | mutex_lock(&data->lock); | ||
172 | lsb = i2c_smbus_read_byte_data(client, ISL29003_REG_LSB_SENSOR); | ||
173 | |||
174 | if (lsb < 0) { | ||
175 | mutex_unlock(&data->lock); | ||
176 | return lsb; | ||
177 | } | ||
178 | |||
179 | msb = i2c_smbus_read_byte_data(client, ISL29003_REG_MSB_SENSOR); | ||
180 | mutex_unlock(&data->lock); | ||
181 | |||
182 | if (msb < 0) | ||
183 | return msb; | ||
184 | |||
185 | range = isl29003_get_range(client); | ||
186 | bitdepth = (4 - isl29003_get_resolution(client)) * 4; | ||
187 | return (((msb << 8) | lsb) * gain_range[range]) >> bitdepth; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * sysfs layer | ||
192 | */ | ||
193 | |||
194 | /* range */ | ||
195 | static ssize_t isl29003_show_range(struct device *dev, | ||
196 | struct device_attribute *attr, char *buf) | ||
197 | { | ||
198 | struct i2c_client *client = to_i2c_client(dev); | ||
199 | return sprintf(buf, "%i\n", isl29003_get_range(client)); | ||
200 | } | ||
201 | |||
202 | static ssize_t isl29003_store_range(struct device *dev, | ||
203 | struct device_attribute *attr, | ||
204 | const char *buf, size_t count) | ||
205 | { | ||
206 | struct i2c_client *client = to_i2c_client(dev); | ||
207 | unsigned long val; | ||
208 | int ret; | ||
209 | |||
210 | if ((strict_strtoul(buf, 10, &val) < 0) || (val > 3)) | ||
211 | return -EINVAL; | ||
212 | |||
213 | ret = isl29003_set_range(client, val); | ||
214 | if (ret < 0) | ||
215 | return ret; | ||
216 | |||
217 | return count; | ||
218 | } | ||
219 | |||
220 | static DEVICE_ATTR(range, S_IWUSR | S_IRUGO, | ||
221 | isl29003_show_range, isl29003_store_range); | ||
222 | |||
223 | |||
224 | /* resolution */ | ||
225 | static ssize_t isl29003_show_resolution(struct device *dev, | ||
226 | struct device_attribute *attr, | ||
227 | char *buf) | ||
228 | { | ||
229 | struct i2c_client *client = to_i2c_client(dev); | ||
230 | return sprintf(buf, "%d\n", isl29003_get_resolution(client)); | ||
231 | } | ||
232 | |||
233 | static ssize_t isl29003_store_resolution(struct device *dev, | ||
234 | struct device_attribute *attr, | ||
235 | const char *buf, size_t count) | ||
236 | { | ||
237 | struct i2c_client *client = to_i2c_client(dev); | ||
238 | unsigned long val; | ||
239 | int ret; | ||
240 | |||
241 | if ((strict_strtoul(buf, 10, &val) < 0) || (val > 3)) | ||
242 | return -EINVAL; | ||
243 | |||
244 | ret = isl29003_set_resolution(client, val); | ||
245 | if (ret < 0) | ||
246 | return ret; | ||
247 | |||
248 | return count; | ||
249 | } | ||
250 | |||
251 | static DEVICE_ATTR(resolution, S_IWUSR | S_IRUGO, | ||
252 | isl29003_show_resolution, isl29003_store_resolution); | ||
253 | |||
254 | /* mode */ | ||
255 | static ssize_t isl29003_show_mode(struct device *dev, | ||
256 | struct device_attribute *attr, char *buf) | ||
257 | { | ||
258 | struct i2c_client *client = to_i2c_client(dev); | ||
259 | return sprintf(buf, "%d\n", isl29003_get_mode(client)); | ||
260 | } | ||
261 | |||
262 | static ssize_t isl29003_store_mode(struct device *dev, | ||
263 | struct device_attribute *attr, const char *buf, size_t count) | ||
264 | { | ||
265 | struct i2c_client *client = to_i2c_client(dev); | ||
266 | unsigned long val; | ||
267 | int ret; | ||
268 | |||
269 | if ((strict_strtoul(buf, 10, &val) < 0) || (val > 2)) | ||
270 | return -EINVAL; | ||
271 | |||
272 | ret = isl29003_set_mode(client, val); | ||
273 | if (ret < 0) | ||
274 | return ret; | ||
275 | |||
276 | return count; | ||
277 | } | ||
278 | |||
279 | static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, | ||
280 | isl29003_show_mode, isl29003_store_mode); | ||
281 | |||
282 | |||
283 | /* power state */ | ||
284 | static ssize_t isl29003_show_power_state(struct device *dev, | ||
285 | struct device_attribute *attr, | ||
286 | char *buf) | ||
287 | { | ||
288 | struct i2c_client *client = to_i2c_client(dev); | ||
289 | return sprintf(buf, "%d\n", isl29003_get_power_state(client)); | ||
290 | } | ||
291 | |||
292 | static ssize_t isl29003_store_power_state(struct device *dev, | ||
293 | struct device_attribute *attr, | ||
294 | const char *buf, size_t count) | ||
295 | { | ||
296 | struct i2c_client *client = to_i2c_client(dev); | ||
297 | unsigned long val; | ||
298 | int ret; | ||
299 | |||
300 | if ((strict_strtoul(buf, 10, &val) < 0) || (val > 1)) | ||
301 | return -EINVAL; | ||
302 | |||
303 | ret = isl29003_set_power_state(client, val); | ||
304 | return ret ? ret : count; | ||
305 | } | ||
306 | |||
307 | static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO, | ||
308 | isl29003_show_power_state, isl29003_store_power_state); | ||
309 | |||
310 | |||
311 | /* lux */ | ||
312 | static ssize_t isl29003_show_lux(struct device *dev, | ||
313 | struct device_attribute *attr, char *buf) | ||
314 | { | ||
315 | struct i2c_client *client = to_i2c_client(dev); | ||
316 | |||
317 | /* No LUX data if not operational */ | ||
318 | if (!isl29003_get_power_state(client)) | ||
319 | return -EBUSY; | ||
320 | |||
321 | return sprintf(buf, "%d\n", isl29003_get_adc_value(client)); | ||
322 | } | ||
323 | |||
324 | static DEVICE_ATTR(lux, S_IRUGO, isl29003_show_lux, NULL); | ||
325 | |||
326 | static struct attribute *isl29003_attributes[] = { | ||
327 | &dev_attr_range.attr, | ||
328 | &dev_attr_resolution.attr, | ||
329 | &dev_attr_mode.attr, | ||
330 | &dev_attr_power_state.attr, | ||
331 | &dev_attr_lux.attr, | ||
332 | NULL | ||
333 | }; | ||
334 | |||
335 | static const struct attribute_group isl29003_attr_group = { | ||
336 | .attrs = isl29003_attributes, | ||
337 | }; | ||
338 | |||
339 | static int isl29003_init_client(struct i2c_client *client) | ||
340 | { | ||
341 | struct isl29003_data *data = i2c_get_clientdata(client); | ||
342 | int i; | ||
343 | |||
344 | /* read all the registers once to fill the cache. | ||
345 | * if one of the reads fails, we consider the init failed */ | ||
346 | for (i = 0; i < ARRAY_SIZE(data->reg_cache); i++) { | ||
347 | int v = i2c_smbus_read_byte_data(client, i); | ||
348 | if (v < 0) | ||
349 | return -ENODEV; | ||
350 | |||
351 | data->reg_cache[i] = v; | ||
352 | } | ||
353 | |||
354 | /* set defaults */ | ||
355 | isl29003_set_range(client, 0); | ||
356 | isl29003_set_resolution(client, 0); | ||
357 | isl29003_set_mode(client, 0); | ||
358 | isl29003_set_power_state(client, 0); | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | /* | ||
364 | * I2C layer | ||
365 | */ | ||
366 | |||
367 | static int __devinit isl29003_probe(struct i2c_client *client, | ||
368 | const struct i2c_device_id *id) | ||
369 | { | ||
370 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
371 | struct isl29003_data *data; | ||
372 | int err = 0; | ||
373 | |||
374 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) | ||
375 | return -EIO; | ||
376 | |||
377 | data = kzalloc(sizeof(struct isl29003_data), GFP_KERNEL); | ||
378 | if (!data) | ||
379 | return -ENOMEM; | ||
380 | |||
381 | data->client = client; | ||
382 | i2c_set_clientdata(client, data); | ||
383 | mutex_init(&data->lock); | ||
384 | |||
385 | /* initialize the ISL29003 chip */ | ||
386 | err = isl29003_init_client(client); | ||
387 | if (err) | ||
388 | goto exit_kfree; | ||
389 | |||
390 | /* register sysfs hooks */ | ||
391 | err = sysfs_create_group(&client->dev.kobj, &isl29003_attr_group); | ||
392 | if (err) | ||
393 | goto exit_kfree; | ||
394 | |||
395 | dev_info(&client->dev, "driver version %s enabled\n", DRIVER_VERSION); | ||
396 | return 0; | ||
397 | |||
398 | exit_kfree: | ||
399 | kfree(data); | ||
400 | return err; | ||
401 | } | ||
402 | |||
403 | static int __devexit isl29003_remove(struct i2c_client *client) | ||
404 | { | ||
405 | sysfs_remove_group(&client->dev.kobj, &isl29003_attr_group); | ||
406 | isl29003_set_power_state(client, 0); | ||
407 | kfree(i2c_get_clientdata(client)); | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | #ifdef CONFIG_PM | ||
412 | static int isl29003_suspend(struct i2c_client *client, pm_message_t mesg) | ||
413 | { | ||
414 | return isl29003_set_power_state(client, 0); | ||
415 | } | ||
416 | |||
417 | static int isl29003_resume(struct i2c_client *client) | ||
418 | { | ||
419 | int i; | ||
420 | struct isl29003_data *data = i2c_get_clientdata(client); | ||
421 | |||
422 | /* restore registers from cache */ | ||
423 | for (i = 0; i < ARRAY_SIZE(data->reg_cache); i++) | ||
424 | if (!i2c_smbus_write_byte_data(client, i, data->reg_cache[i])) | ||
425 | return -EIO; | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | #else | ||
431 | #define isl29003_suspend NULL | ||
432 | #define isl29003_resume NULL | ||
433 | #endif /* CONFIG_PM */ | ||
434 | |||
435 | static const struct i2c_device_id isl29003_id[] = { | ||
436 | { "isl29003", 0 }, | ||
437 | {} | ||
438 | }; | ||
439 | MODULE_DEVICE_TABLE(i2c, isl29003_id); | ||
440 | |||
441 | static struct i2c_driver isl29003_driver = { | ||
442 | .driver = { | ||
443 | .name = ISL29003_DRV_NAME, | ||
444 | .owner = THIS_MODULE, | ||
445 | }, | ||
446 | .suspend = isl29003_suspend, | ||
447 | .resume = isl29003_resume, | ||
448 | .probe = isl29003_probe, | ||
449 | .remove = __devexit_p(isl29003_remove), | ||
450 | .id_table = isl29003_id, | ||
451 | }; | ||
452 | |||
453 | static int __init isl29003_init(void) | ||
454 | { | ||
455 | return i2c_add_driver(&isl29003_driver); | ||
456 | } | ||
457 | |||
458 | static void __exit isl29003_exit(void) | ||
459 | { | ||
460 | i2c_del_driver(&isl29003_driver); | ||
461 | } | ||
462 | |||
463 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | ||
464 | MODULE_DESCRIPTION("ISL29003 ambient light sensor driver"); | ||
465 | MODULE_LICENSE("GPL v2"); | ||
466 | MODULE_VERSION(DRIVER_VERSION); | ||
467 | |||
468 | module_init(isl29003_init); | ||
469 | module_exit(isl29003_exit); | ||
470 | |||
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index 78ad48718ab..36a8d53ad2a 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
33 | #include <linux/seq_file.h> | ||
33 | #include <linux/serial_reg.h> | 34 | #include <linux/serial_reg.h> |
34 | #include <linux/circ_buf.h> | 35 | #include <linux/circ_buf.h> |
35 | #include <linux/gfp.h> | 36 | #include <linux/gfp.h> |
@@ -933,67 +934,64 @@ static int sdio_uart_tiocmset(struct tty_struct *tty, struct file *file, | |||
933 | return result; | 934 | return result; |
934 | } | 935 | } |
935 | 936 | ||
936 | static int sdio_uart_read_proc(char *page, char **start, off_t off, | 937 | static int sdio_uart_proc_show(struct seq_file *m, void *v) |
937 | int count, int *eof, void *data) | ||
938 | { | 938 | { |
939 | int i, len = 0; | 939 | int i; |
940 | off_t begin = 0; | ||
941 | 940 | ||
942 | len += sprintf(page, "serinfo:1.0 driver%s%s revision:%s\n", | 941 | seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n", |
943 | "", "", ""); | 942 | "", "", ""); |
944 | for (i = 0; i < UART_NR && len < PAGE_SIZE - 96; i++) { | 943 | for (i = 0; i < UART_NR; i++) { |
945 | struct sdio_uart_port *port = sdio_uart_port_get(i); | 944 | struct sdio_uart_port *port = sdio_uart_port_get(i); |
946 | if (port) { | 945 | if (port) { |
947 | len += sprintf(page+len, "%d: uart:SDIO", i); | 946 | seq_printf(m, "%d: uart:SDIO", i); |
948 | if(capable(CAP_SYS_ADMIN)) { | 947 | if(capable(CAP_SYS_ADMIN)) { |
949 | len += sprintf(page + len, " tx:%d rx:%d", | 948 | seq_printf(m, " tx:%d rx:%d", |
950 | port->icount.tx, port->icount.rx); | 949 | port->icount.tx, port->icount.rx); |
951 | if (port->icount.frame) | 950 | if (port->icount.frame) |
952 | len += sprintf(page + len, " fe:%d", | 951 | seq_printf(m, " fe:%d", |
953 | port->icount.frame); | 952 | port->icount.frame); |
954 | if (port->icount.parity) | 953 | if (port->icount.parity) |
955 | len += sprintf(page + len, " pe:%d", | 954 | seq_printf(m, " pe:%d", |
956 | port->icount.parity); | 955 | port->icount.parity); |
957 | if (port->icount.brk) | 956 | if (port->icount.brk) |
958 | len += sprintf(page + len, " brk:%d", | 957 | seq_printf(m, " brk:%d", |
959 | port->icount.brk); | 958 | port->icount.brk); |
960 | if (port->icount.overrun) | 959 | if (port->icount.overrun) |
961 | len += sprintf(page + len, " oe:%d", | 960 | seq_printf(m, " oe:%d", |
962 | port->icount.overrun); | 961 | port->icount.overrun); |
963 | if (port->icount.cts) | 962 | if (port->icount.cts) |
964 | len += sprintf(page + len, " cts:%d", | 963 | seq_printf(m, " cts:%d", |
965 | port->icount.cts); | 964 | port->icount.cts); |
966 | if (port->icount.dsr) | 965 | if (port->icount.dsr) |
967 | len += sprintf(page + len, " dsr:%d", | 966 | seq_printf(m, " dsr:%d", |
968 | port->icount.dsr); | 967 | port->icount.dsr); |
969 | if (port->icount.rng) | 968 | if (port->icount.rng) |
970 | len += sprintf(page + len, " rng:%d", | 969 | seq_printf(m, " rng:%d", |
971 | port->icount.rng); | 970 | port->icount.rng); |
972 | if (port->icount.dcd) | 971 | if (port->icount.dcd) |
973 | len += sprintf(page + len, " dcd:%d", | 972 | seq_printf(m, " dcd:%d", |
974 | port->icount.dcd); | 973 | port->icount.dcd); |
975 | } | 974 | } |
976 | strcat(page, "\n"); | ||
977 | len++; | ||
978 | sdio_uart_port_put(port); | 975 | sdio_uart_port_put(port); |
979 | } | 976 | seq_putc(m, '\n'); |
980 | |||
981 | if (len + begin > off + count) | ||
982 | goto done; | ||
983 | if (len + begin < off) { | ||
984 | begin += len; | ||
985 | len = 0; | ||
986 | } | 977 | } |
987 | } | 978 | } |
988 | *eof = 1; | 979 | return 0; |
980 | } | ||
989 | 981 | ||
990 | done: | 982 | static int sdio_uart_proc_open(struct inode *inode, struct file *file) |
991 | if (off >= len + begin) | 983 | { |
992 | return 0; | 984 | return single_open(file, sdio_uart_proc_show, NULL); |
993 | *start = page + (off - begin); | ||
994 | return (count < begin + len - off) ? count : (begin + len - off); | ||
995 | } | 985 | } |
996 | 986 | ||
987 | static const struct file_operations sdio_uart_proc_fops = { | ||
988 | .owner = THIS_MODULE, | ||
989 | .open = sdio_uart_proc_open, | ||
990 | .read = seq_read, | ||
991 | .llseek = seq_lseek, | ||
992 | .release = single_release, | ||
993 | }; | ||
994 | |||
997 | static const struct tty_operations sdio_uart_ops = { | 995 | static const struct tty_operations sdio_uart_ops = { |
998 | .open = sdio_uart_open, | 996 | .open = sdio_uart_open, |
999 | .close = sdio_uart_close, | 997 | .close = sdio_uart_close, |
@@ -1007,7 +1005,7 @@ static const struct tty_operations sdio_uart_ops = { | |||
1007 | .break_ctl = sdio_uart_break_ctl, | 1005 | .break_ctl = sdio_uart_break_ctl, |
1008 | .tiocmget = sdio_uart_tiocmget, | 1006 | .tiocmget = sdio_uart_tiocmget, |
1009 | .tiocmset = sdio_uart_tiocmset, | 1007 | .tiocmset = sdio_uart_tiocmset, |
1010 | .read_proc = sdio_uart_read_proc, | 1008 | .proc_fops = &sdio_uart_proc_fops, |
1011 | }; | 1009 | }; |
1012 | 1010 | ||
1013 | static struct tty_driver *sdio_uart_tty_driver; | 1011 | static struct tty_driver *sdio_uart_tty_driver; |
diff --git a/drivers/of/base.c b/drivers/of/base.c index cd17092b82b..41c5dfd8535 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -446,6 +446,7 @@ struct of_modalias_table { | |||
446 | }; | 446 | }; |
447 | static struct of_modalias_table of_modalias_table[] = { | 447 | static struct of_modalias_table of_modalias_table[] = { |
448 | { "fsl,mcu-mpc8349emitx", "mcu-mpc8349emitx" }, | 448 | { "fsl,mcu-mpc8349emitx", "mcu-mpc8349emitx" }, |
449 | { "mmc-spi-slot", "mmc_spi" }, | ||
449 | }; | 450 | }; |
450 | 451 | ||
451 | /** | 452 | /** |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 81450fbd8b1..09d5cd33a3f 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -129,13 +129,14 @@ comment "I2C RTC drivers" | |||
129 | if I2C | 129 | if I2C |
130 | 130 | ||
131 | config RTC_DRV_DS1307 | 131 | config RTC_DRV_DS1307 |
132 | tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00" | 132 | tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025" |
133 | help | 133 | help |
134 | If you say yes here you get support for various compatible RTC | 134 | If you say yes here you get support for various compatible RTC |
135 | chips (often with battery backup) connected with I2C. This driver | 135 | chips (often with battery backup) connected with I2C. This driver |
136 | should handle DS1307, DS1337, DS1338, DS1339, DS1340, ST M41T00, | 136 | should handle DS1307, DS1337, DS1338, DS1339, DS1340, ST M41T00, |
137 | and probably other chips. In some cases the RTC must already | 137 | EPSON RX-8025 and probably other chips. In some cases the RTC |
138 | have been initialized (by manufacturing or a bootloader). | 138 | must already have been initialized (by manufacturing or a |
139 | bootloader). | ||
139 | 140 | ||
140 | The first seven registers on these chips hold an RTC, and other | 141 | The first seven registers on these chips hold an RTC, and other |
141 | registers may add features such as NVRAM, a trickle charger for | 142 | registers may add features such as NVRAM, a trickle charger for |
@@ -440,6 +441,16 @@ config RTC_DRV_DS1742 | |||
440 | This driver can also be built as a module. If so, the module | 441 | This driver can also be built as a module. If so, the module |
441 | will be called rtc-ds1742. | 442 | will be called rtc-ds1742. |
442 | 443 | ||
444 | config RTC_DRV_EFI | ||
445 | tristate "EFI RTC" | ||
446 | depends on IA64 | ||
447 | help | ||
448 | If you say yes here you will get support for the EFI | ||
449 | Real Time Clock. | ||
450 | |||
451 | This driver can also be built as a module. If so, the module | ||
452 | will be called rtc-efi. | ||
453 | |||
443 | config RTC_DRV_STK17TA8 | 454 | config RTC_DRV_STK17TA8 |
444 | tristate "Simtek STK17TA8" | 455 | tristate "Simtek STK17TA8" |
445 | depends on RTC_CLASS | 456 | depends on RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 0e697aa51ca..e7b09986d26 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -36,6 +36,7 @@ obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | |||
36 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 36 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
37 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | 37 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o |
38 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o | 38 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o |
39 | obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o | ||
39 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | 40 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o |
40 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o | 41 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o |
41 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o | 42 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o |
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 7e5155e88ac..2c4a65302a9 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2005 James Chapman (ds1337 core) | 4 | * Copyright (C) 2005 James Chapman (ds1337 core) |
5 | * Copyright (C) 2006 David Brownell | 5 | * Copyright (C) 2006 David Brownell |
6 | * Copyright (C) 2009 Matthias Fuchs (rx8025 support) | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -31,6 +32,7 @@ enum ds_type { | |||
31 | ds_1339, | 32 | ds_1339, |
32 | ds_1340, | 33 | ds_1340, |
33 | m41t00, | 34 | m41t00, |
35 | rx_8025, | ||
34 | // rs5c372 too? different address... | 36 | // rs5c372 too? different address... |
35 | }; | 37 | }; |
36 | 38 | ||
@@ -83,6 +85,12 @@ enum ds_type { | |||
83 | #define DS1339_REG_ALARM1_SECS 0x07 | 85 | #define DS1339_REG_ALARM1_SECS 0x07 |
84 | #define DS1339_REG_TRICKLE 0x10 | 86 | #define DS1339_REG_TRICKLE 0x10 |
85 | 87 | ||
88 | #define RX8025_REG_CTRL1 0x0e | ||
89 | # define RX8025_BIT_2412 0x20 | ||
90 | #define RX8025_REG_CTRL2 0x0f | ||
91 | # define RX8025_BIT_PON 0x10 | ||
92 | # define RX8025_BIT_VDET 0x40 | ||
93 | # define RX8025_BIT_XST 0x20 | ||
86 | 94 | ||
87 | 95 | ||
88 | struct ds1307 { | 96 | struct ds1307 { |
@@ -94,6 +102,10 @@ struct ds1307 { | |||
94 | struct i2c_client *client; | 102 | struct i2c_client *client; |
95 | struct rtc_device *rtc; | 103 | struct rtc_device *rtc; |
96 | struct work_struct work; | 104 | struct work_struct work; |
105 | s32 (*read_block_data)(struct i2c_client *client, u8 command, | ||
106 | u8 length, u8 *values); | ||
107 | s32 (*write_block_data)(struct i2c_client *client, u8 command, | ||
108 | u8 length, const u8 *values); | ||
97 | }; | 109 | }; |
98 | 110 | ||
99 | struct chip_desc { | 111 | struct chip_desc { |
@@ -117,6 +129,8 @@ static const struct chip_desc chips[] = { | |||
117 | [ds_1340] = { | 129 | [ds_1340] = { |
118 | }, | 130 | }, |
119 | [m41t00] = { | 131 | [m41t00] = { |
132 | }, | ||
133 | [rx_8025] = { | ||
120 | }, }; | 134 | }, }; |
121 | 135 | ||
122 | static const struct i2c_device_id ds1307_id[] = { | 136 | static const struct i2c_device_id ds1307_id[] = { |
@@ -126,12 +140,86 @@ static const struct i2c_device_id ds1307_id[] = { | |||
126 | { "ds1339", ds_1339 }, | 140 | { "ds1339", ds_1339 }, |
127 | { "ds1340", ds_1340 }, | 141 | { "ds1340", ds_1340 }, |
128 | { "m41t00", m41t00 }, | 142 | { "m41t00", m41t00 }, |
143 | { "rx8025", rx_8025 }, | ||
129 | { } | 144 | { } |
130 | }; | 145 | }; |
131 | MODULE_DEVICE_TABLE(i2c, ds1307_id); | 146 | MODULE_DEVICE_TABLE(i2c, ds1307_id); |
132 | 147 | ||
133 | /*----------------------------------------------------------------------*/ | 148 | /*----------------------------------------------------------------------*/ |
134 | 149 | ||
150 | #define BLOCK_DATA_MAX_TRIES 10 | ||
151 | |||
152 | static s32 ds1307_read_block_data_once(struct i2c_client *client, u8 command, | ||
153 | u8 length, u8 *values) | ||
154 | { | ||
155 | s32 i, data; | ||
156 | |||
157 | for (i = 0; i < length; i++) { | ||
158 | data = i2c_smbus_read_byte_data(client, command + i); | ||
159 | if (data < 0) | ||
160 | return data; | ||
161 | values[i] = data; | ||
162 | } | ||
163 | return i; | ||
164 | } | ||
165 | |||
166 | static s32 ds1307_read_block_data(struct i2c_client *client, u8 command, | ||
167 | u8 length, u8 *values) | ||
168 | { | ||
169 | u8 oldvalues[I2C_SMBUS_BLOCK_MAX]; | ||
170 | s32 ret; | ||
171 | int tries = 0; | ||
172 | |||
173 | dev_dbg(&client->dev, "ds1307_read_block_data (length=%d)\n", length); | ||
174 | ret = ds1307_read_block_data_once(client, command, length, values); | ||
175 | if (ret < 0) | ||
176 | return ret; | ||
177 | do { | ||
178 | if (++tries > BLOCK_DATA_MAX_TRIES) { | ||
179 | dev_err(&client->dev, | ||
180 | "ds1307_read_block_data failed\n"); | ||
181 | return -EIO; | ||
182 | } | ||
183 | memcpy(oldvalues, values, length); | ||
184 | ret = ds1307_read_block_data_once(client, command, length, | ||
185 | values); | ||
186 | if (ret < 0) | ||
187 | return ret; | ||
188 | } while (memcmp(oldvalues, values, length)); | ||
189 | return length; | ||
190 | } | ||
191 | |||
192 | static s32 ds1307_write_block_data(struct i2c_client *client, u8 command, | ||
193 | u8 length, const u8 *values) | ||
194 | { | ||
195 | u8 currvalues[I2C_SMBUS_BLOCK_MAX]; | ||
196 | int tries = 0; | ||
197 | |||
198 | dev_dbg(&client->dev, "ds1307_write_block_data (length=%d)\n", length); | ||
199 | do { | ||
200 | s32 i, ret; | ||
201 | |||
202 | if (++tries > BLOCK_DATA_MAX_TRIES) { | ||
203 | dev_err(&client->dev, | ||
204 | "ds1307_write_block_data failed\n"); | ||
205 | return -EIO; | ||
206 | } | ||
207 | for (i = 0; i < length; i++) { | ||
208 | ret = i2c_smbus_write_byte_data(client, command + i, | ||
209 | values[i]); | ||
210 | if (ret < 0) | ||
211 | return ret; | ||
212 | } | ||
213 | ret = ds1307_read_block_data_once(client, command, length, | ||
214 | currvalues); | ||
215 | if (ret < 0) | ||
216 | return ret; | ||
217 | } while (memcmp(currvalues, values, length)); | ||
218 | return length; | ||
219 | } | ||
220 | |||
221 | /*----------------------------------------------------------------------*/ | ||
222 | |||
135 | /* | 223 | /* |
136 | * The IRQ logic includes a "real" handler running in IRQ context just | 224 | * The IRQ logic includes a "real" handler running in IRQ context just |
137 | * long enough to schedule this workqueue entry. We need a task context | 225 | * long enough to schedule this workqueue entry. We need a task context |
@@ -202,7 +290,7 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) | |||
202 | int tmp; | 290 | int tmp; |
203 | 291 | ||
204 | /* read the RTC date and time registers all at once */ | 292 | /* read the RTC date and time registers all at once */ |
205 | tmp = i2c_smbus_read_i2c_block_data(ds1307->client, | 293 | tmp = ds1307->read_block_data(ds1307->client, |
206 | DS1307_REG_SECS, 7, ds1307->regs); | 294 | DS1307_REG_SECS, 7, ds1307->regs); |
207 | if (tmp != 7) { | 295 | if (tmp != 7) { |
208 | dev_err(dev, "%s error %d\n", "read", tmp); | 296 | dev_err(dev, "%s error %d\n", "read", tmp); |
@@ -279,7 +367,7 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) | |||
279 | "write", buf[0], buf[1], buf[2], buf[3], | 367 | "write", buf[0], buf[1], buf[2], buf[3], |
280 | buf[4], buf[5], buf[6]); | 368 | buf[4], buf[5], buf[6]); |
281 | 369 | ||
282 | result = i2c_smbus_write_i2c_block_data(ds1307->client, 0, 7, buf); | 370 | result = ds1307->write_block_data(ds1307->client, 0, 7, buf); |
283 | if (result < 0) { | 371 | if (result < 0) { |
284 | dev_err(dev, "%s error %d\n", "write", result); | 372 | dev_err(dev, "%s error %d\n", "write", result); |
285 | return result; | 373 | return result; |
@@ -297,7 +385,7 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
297 | return -EINVAL; | 385 | return -EINVAL; |
298 | 386 | ||
299 | /* read all ALARM1, ALARM2, and status registers at once */ | 387 | /* read all ALARM1, ALARM2, and status registers at once */ |
300 | ret = i2c_smbus_read_i2c_block_data(client, | 388 | ret = ds1307->read_block_data(client, |
301 | DS1339_REG_ALARM1_SECS, 9, ds1307->regs); | 389 | DS1339_REG_ALARM1_SECS, 9, ds1307->regs); |
302 | if (ret != 9) { | 390 | if (ret != 9) { |
303 | dev_err(dev, "%s error %d\n", "alarm read", ret); | 391 | dev_err(dev, "%s error %d\n", "alarm read", ret); |
@@ -356,7 +444,7 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
356 | t->enabled, t->pending); | 444 | t->enabled, t->pending); |
357 | 445 | ||
358 | /* read current status of both alarms and the chip */ | 446 | /* read current status of both alarms and the chip */ |
359 | ret = i2c_smbus_read_i2c_block_data(client, | 447 | ret = ds1307->read_block_data(client, |
360 | DS1339_REG_ALARM1_SECS, 9, buf); | 448 | DS1339_REG_ALARM1_SECS, 9, buf); |
361 | if (ret != 9) { | 449 | if (ret != 9) { |
362 | dev_err(dev, "%s error %d\n", "alarm write", ret); | 450 | dev_err(dev, "%s error %d\n", "alarm write", ret); |
@@ -391,7 +479,7 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
391 | } | 479 | } |
392 | buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I); | 480 | buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I); |
393 | 481 | ||
394 | ret = i2c_smbus_write_i2c_block_data(client, | 482 | ret = ds1307->write_block_data(client, |
395 | DS1339_REG_ALARM1_SECS, 9, buf); | 483 | DS1339_REG_ALARM1_SECS, 9, buf); |
396 | if (ret < 0) { | 484 | if (ret < 0) { |
397 | dev_err(dev, "can't set alarm time\n"); | 485 | dev_err(dev, "can't set alarm time\n"); |
@@ -479,7 +567,7 @@ ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | |||
479 | if (unlikely(!count)) | 567 | if (unlikely(!count)) |
480 | return count; | 568 | return count; |
481 | 569 | ||
482 | result = i2c_smbus_read_i2c_block_data(client, 8 + off, count, buf); | 570 | result = ds1307->read_block_data(client, 8 + off, count, buf); |
483 | if (result < 0) | 571 | if (result < 0) |
484 | dev_err(&client->dev, "%s error %d\n", "nvram read", result); | 572 | dev_err(&client->dev, "%s error %d\n", "nvram read", result); |
485 | return result; | 573 | return result; |
@@ -490,9 +578,11 @@ ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | |||
490 | char *buf, loff_t off, size_t count) | 578 | char *buf, loff_t off, size_t count) |
491 | { | 579 | { |
492 | struct i2c_client *client; | 580 | struct i2c_client *client; |
581 | struct ds1307 *ds1307; | ||
493 | int result; | 582 | int result; |
494 | 583 | ||
495 | client = kobj_to_i2c_client(kobj); | 584 | client = kobj_to_i2c_client(kobj); |
585 | ds1307 = i2c_get_clientdata(client); | ||
496 | 586 | ||
497 | if (unlikely(off >= NVRAM_SIZE)) | 587 | if (unlikely(off >= NVRAM_SIZE)) |
498 | return -EFBIG; | 588 | return -EFBIG; |
@@ -501,7 +591,7 @@ ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | |||
501 | if (unlikely(!count)) | 591 | if (unlikely(!count)) |
502 | return count; | 592 | return count; |
503 | 593 | ||
504 | result = i2c_smbus_write_i2c_block_data(client, 8 + off, count, buf); | 594 | result = ds1307->write_block_data(client, 8 + off, count, buf); |
505 | if (result < 0) { | 595 | if (result < 0) { |
506 | dev_err(&client->dev, "%s error %d\n", "nvram write", result); | 596 | dev_err(&client->dev, "%s error %d\n", "nvram write", result); |
507 | return result; | 597 | return result; |
@@ -535,9 +625,8 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
535 | int want_irq = false; | 625 | int want_irq = false; |
536 | unsigned char *buf; | 626 | unsigned char *buf; |
537 | 627 | ||
538 | if (!i2c_check_functionality(adapter, | 628 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA) |
539 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA | | 629 | && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) |
540 | I2C_FUNC_SMBUS_I2C_BLOCK)) | ||
541 | return -EIO; | 630 | return -EIO; |
542 | 631 | ||
543 | if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL))) | 632 | if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL))) |
@@ -547,6 +636,13 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
547 | i2c_set_clientdata(client, ds1307); | 636 | i2c_set_clientdata(client, ds1307); |
548 | ds1307->type = id->driver_data; | 637 | ds1307->type = id->driver_data; |
549 | buf = ds1307->regs; | 638 | buf = ds1307->regs; |
639 | if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { | ||
640 | ds1307->read_block_data = i2c_smbus_read_i2c_block_data; | ||
641 | ds1307->write_block_data = i2c_smbus_write_i2c_block_data; | ||
642 | } else { | ||
643 | ds1307->read_block_data = ds1307_read_block_data; | ||
644 | ds1307->write_block_data = ds1307_write_block_data; | ||
645 | } | ||
550 | 646 | ||
551 | switch (ds1307->type) { | 647 | switch (ds1307->type) { |
552 | case ds_1337: | 648 | case ds_1337: |
@@ -557,7 +653,7 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
557 | want_irq = true; | 653 | want_irq = true; |
558 | } | 654 | } |
559 | /* get registers that the "rtc" read below won't read... */ | 655 | /* get registers that the "rtc" read below won't read... */ |
560 | tmp = i2c_smbus_read_i2c_block_data(ds1307->client, | 656 | tmp = ds1307->read_block_data(ds1307->client, |
561 | DS1337_REG_CONTROL, 2, buf); | 657 | DS1337_REG_CONTROL, 2, buf); |
562 | if (tmp != 2) { | 658 | if (tmp != 2) { |
563 | pr_debug("read error %d\n", tmp); | 659 | pr_debug("read error %d\n", tmp); |
@@ -589,13 +685,79 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
589 | dev_warn(&client->dev, "SET TIME!\n"); | 685 | dev_warn(&client->dev, "SET TIME!\n"); |
590 | } | 686 | } |
591 | break; | 687 | break; |
688 | |||
689 | case rx_8025: | ||
690 | tmp = i2c_smbus_read_i2c_block_data(ds1307->client, | ||
691 | RX8025_REG_CTRL1 << 4 | 0x08, 2, buf); | ||
692 | if (tmp != 2) { | ||
693 | pr_debug("read error %d\n", tmp); | ||
694 | err = -EIO; | ||
695 | goto exit_free; | ||
696 | } | ||
697 | |||
698 | /* oscillator off? turn it on, so clock can tick. */ | ||
699 | if (!(ds1307->regs[1] & RX8025_BIT_XST)) { | ||
700 | ds1307->regs[1] |= RX8025_BIT_XST; | ||
701 | i2c_smbus_write_byte_data(client, | ||
702 | RX8025_REG_CTRL2 << 4 | 0x08, | ||
703 | ds1307->regs[1]); | ||
704 | dev_warn(&client->dev, | ||
705 | "oscillator stop detected - SET TIME!\n"); | ||
706 | } | ||
707 | |||
708 | if (ds1307->regs[1] & RX8025_BIT_PON) { | ||
709 | ds1307->regs[1] &= ~RX8025_BIT_PON; | ||
710 | i2c_smbus_write_byte_data(client, | ||
711 | RX8025_REG_CTRL2 << 4 | 0x08, | ||
712 | ds1307->regs[1]); | ||
713 | dev_warn(&client->dev, "power-on detected\n"); | ||
714 | } | ||
715 | |||
716 | if (ds1307->regs[1] & RX8025_BIT_VDET) { | ||
717 | ds1307->regs[1] &= ~RX8025_BIT_VDET; | ||
718 | i2c_smbus_write_byte_data(client, | ||
719 | RX8025_REG_CTRL2 << 4 | 0x08, | ||
720 | ds1307->regs[1]); | ||
721 | dev_warn(&client->dev, "voltage drop detected\n"); | ||
722 | } | ||
723 | |||
724 | /* make sure we are running in 24hour mode */ | ||
725 | if (!(ds1307->regs[0] & RX8025_BIT_2412)) { | ||
726 | u8 hour; | ||
727 | |||
728 | /* switch to 24 hour mode */ | ||
729 | i2c_smbus_write_byte_data(client, | ||
730 | RX8025_REG_CTRL1 << 4 | 0x08, | ||
731 | ds1307->regs[0] | | ||
732 | RX8025_BIT_2412); | ||
733 | |||
734 | tmp = i2c_smbus_read_i2c_block_data(ds1307->client, | ||
735 | RX8025_REG_CTRL1 << 4 | 0x08, 2, buf); | ||
736 | if (tmp != 2) { | ||
737 | pr_debug("read error %d\n", tmp); | ||
738 | err = -EIO; | ||
739 | goto exit_free; | ||
740 | } | ||
741 | |||
742 | /* correct hour */ | ||
743 | hour = bcd2bin(ds1307->regs[DS1307_REG_HOUR]); | ||
744 | if (hour == 12) | ||
745 | hour = 0; | ||
746 | if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM) | ||
747 | hour += 12; | ||
748 | |||
749 | i2c_smbus_write_byte_data(client, | ||
750 | DS1307_REG_HOUR << 4 | 0x08, | ||
751 | hour); | ||
752 | } | ||
753 | break; | ||
592 | default: | 754 | default: |
593 | break; | 755 | break; |
594 | } | 756 | } |
595 | 757 | ||
596 | read_rtc: | 758 | read_rtc: |
597 | /* read RTC registers */ | 759 | /* read RTC registers */ |
598 | tmp = i2c_smbus_read_i2c_block_data(ds1307->client, 0, 8, buf); | 760 | tmp = ds1307->read_block_data(ds1307->client, 0, 8, buf); |
599 | if (tmp != 8) { | 761 | if (tmp != 8) { |
600 | pr_debug("read error %d\n", tmp); | 762 | pr_debug("read error %d\n", tmp); |
601 | err = -EIO; | 763 | err = -EIO; |
@@ -649,6 +811,7 @@ read_rtc: | |||
649 | dev_warn(&client->dev, "SET TIME!\n"); | 811 | dev_warn(&client->dev, "SET TIME!\n"); |
650 | } | 812 | } |
651 | break; | 813 | break; |
814 | case rx_8025: | ||
652 | case ds_1337: | 815 | case ds_1337: |
653 | case ds_1339: | 816 | case ds_1339: |
654 | break; | 817 | break; |
@@ -662,6 +825,8 @@ read_rtc: | |||
662 | * systems that will run through year 2100. | 825 | * systems that will run through year 2100. |
663 | */ | 826 | */ |
664 | break; | 827 | break; |
828 | case rx_8025: | ||
829 | break; | ||
665 | default: | 830 | default: |
666 | if (!(tmp & DS1307_BIT_12HR)) | 831 | if (!(tmp & DS1307_BIT_12HR)) |
667 | break; | 832 | break; |
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index a5b0fc09f0c..4d32e328f6c 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c | |||
@@ -222,16 +222,16 @@ static int ds1374_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
222 | rtc_tm_to_time(&alarm->time, &new_alarm); | 222 | rtc_tm_to_time(&alarm->time, &new_alarm); |
223 | rtc_tm_to_time(&now, &itime); | 223 | rtc_tm_to_time(&now, &itime); |
224 | 224 | ||
225 | new_alarm -= itime; | ||
226 | |||
227 | /* This can happen due to races, in addition to dates that are | 225 | /* This can happen due to races, in addition to dates that are |
228 | * truly in the past. To avoid requiring the caller to check for | 226 | * truly in the past. To avoid requiring the caller to check for |
229 | * races, dates in the past are assumed to be in the recent past | 227 | * races, dates in the past are assumed to be in the recent past |
230 | * (i.e. not something that we'd rather the caller know about via | 228 | * (i.e. not something that we'd rather the caller know about via |
231 | * an error), and the alarm is set to go off as soon as possible. | 229 | * an error), and the alarm is set to go off as soon as possible. |
232 | */ | 230 | */ |
233 | if (new_alarm <= 0) | 231 | if (time_before_eq(new_alarm, itime)) |
234 | new_alarm = 1; | 232 | new_alarm = 1; |
233 | else | ||
234 | new_alarm -= itime; | ||
235 | 235 | ||
236 | mutex_lock(&ds1374->mutex); | 236 | mutex_lock(&ds1374->mutex); |
237 | 237 | ||
diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c new file mode 100644 index 00000000000..550292304b0 --- /dev/null +++ b/drivers/rtc/rtc-efi.c | |||
@@ -0,0 +1,235 @@ | |||
1 | /* | ||
2 | * rtc-efi: RTC Class Driver for EFI-based systems | ||
3 | * | ||
4 | * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. | ||
5 | * | ||
6 | * Author: dann frazier <dannf@hp.com> | ||
7 | * Based on efirtc.c by Stephane Eranian | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/time.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/rtc.h> | ||
21 | #include <linux/efi.h> | ||
22 | |||
23 | #define EFI_ISDST (EFI_TIME_ADJUST_DAYLIGHT|EFI_TIME_IN_DAYLIGHT) | ||
24 | /* | ||
25 | * EFI Epoch is 1/1/1998 | ||
26 | */ | ||
27 | #define EFI_RTC_EPOCH 1998 | ||
28 | |||
29 | /* | ||
30 | * returns day of the year [0-365] | ||
31 | */ | ||
32 | static inline int | ||
33 | compute_yday(efi_time_t *eft) | ||
34 | { | ||
35 | /* efi_time_t.month is in the [1-12] so, we need -1 */ | ||
36 | return rtc_year_days(eft->day - 1, eft->month - 1, eft->year); | ||
37 | } | ||
38 | /* | ||
39 | * returns day of the week [0-6] 0=Sunday | ||
40 | * | ||
41 | * Don't try to provide a year that's before 1998, please ! | ||
42 | */ | ||
43 | static int | ||
44 | compute_wday(efi_time_t *eft) | ||
45 | { | ||
46 | int y; | ||
47 | int ndays = 0; | ||
48 | |||
49 | if (eft->year < 1998) { | ||
50 | printk(KERN_ERR "efirtc: EFI year < 1998, invalid date\n"); | ||
51 | return -1; | ||
52 | } | ||
53 | |||
54 | for (y = EFI_RTC_EPOCH; y < eft->year; y++) | ||
55 | ndays += 365 + (is_leap_year(y) ? 1 : 0); | ||
56 | |||
57 | ndays += compute_yday(eft); | ||
58 | |||
59 | /* | ||
60 | * 4=1/1/1998 was a Thursday | ||
61 | */ | ||
62 | return (ndays + 4) % 7; | ||
63 | } | ||
64 | |||
65 | static void | ||
66 | convert_to_efi_time(struct rtc_time *wtime, efi_time_t *eft) | ||
67 | { | ||
68 | eft->year = wtime->tm_year + 1900; | ||
69 | eft->month = wtime->tm_mon + 1; | ||
70 | eft->day = wtime->tm_mday; | ||
71 | eft->hour = wtime->tm_hour; | ||
72 | eft->minute = wtime->tm_min; | ||
73 | eft->second = wtime->tm_sec; | ||
74 | eft->nanosecond = 0; | ||
75 | eft->daylight = wtime->tm_isdst ? EFI_ISDST : 0; | ||
76 | eft->timezone = EFI_UNSPECIFIED_TIMEZONE; | ||
77 | } | ||
78 | |||
79 | static void | ||
80 | convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime) | ||
81 | { | ||
82 | memset(wtime, 0, sizeof(*wtime)); | ||
83 | wtime->tm_sec = eft->second; | ||
84 | wtime->tm_min = eft->minute; | ||
85 | wtime->tm_hour = eft->hour; | ||
86 | wtime->tm_mday = eft->day; | ||
87 | wtime->tm_mon = eft->month - 1; | ||
88 | wtime->tm_year = eft->year - 1900; | ||
89 | |||
90 | /* day of the week [0-6], Sunday=0 */ | ||
91 | wtime->tm_wday = compute_wday(eft); | ||
92 | |||
93 | /* day in the year [1-365]*/ | ||
94 | wtime->tm_yday = compute_yday(eft); | ||
95 | |||
96 | |||
97 | switch (eft->daylight & EFI_ISDST) { | ||
98 | case EFI_ISDST: | ||
99 | wtime->tm_isdst = 1; | ||
100 | break; | ||
101 | case EFI_TIME_ADJUST_DAYLIGHT: | ||
102 | wtime->tm_isdst = 0; | ||
103 | break; | ||
104 | default: | ||
105 | wtime->tm_isdst = -1; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static int efi_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | ||
110 | { | ||
111 | efi_time_t eft; | ||
112 | efi_status_t status; | ||
113 | |||
114 | /* | ||
115 | * As of EFI v1.10, this call always returns an unsupported status | ||
116 | */ | ||
117 | status = efi.get_wakeup_time((efi_bool_t *)&wkalrm->enabled, | ||
118 | (efi_bool_t *)&wkalrm->pending, &eft); | ||
119 | |||
120 | if (status != EFI_SUCCESS) | ||
121 | return -EINVAL; | ||
122 | |||
123 | convert_from_efi_time(&eft, &wkalrm->time); | ||
124 | |||
125 | return rtc_valid_tm(&wkalrm->time); | ||
126 | } | ||
127 | |||
128 | static int efi_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | ||
129 | { | ||
130 | efi_time_t eft; | ||
131 | efi_status_t status; | ||
132 | |||
133 | convert_to_efi_time(&wkalrm->time, &eft); | ||
134 | |||
135 | /* | ||
136 | * XXX Fixme: | ||
137 | * As of EFI 0.92 with the firmware I have on my | ||
138 | * machine this call does not seem to work quite | ||
139 | * right | ||
140 | * | ||
141 | * As of v1.10, this call always returns an unsupported status | ||
142 | */ | ||
143 | status = efi.set_wakeup_time((efi_bool_t)wkalrm->enabled, &eft); | ||
144 | |||
145 | printk(KERN_WARNING "write status is %d\n", (int)status); | ||
146 | |||
147 | return status == EFI_SUCCESS ? 0 : -EINVAL; | ||
148 | } | ||
149 | |||
150 | static int efi_read_time(struct device *dev, struct rtc_time *tm) | ||
151 | { | ||
152 | efi_status_t status; | ||
153 | efi_time_t eft; | ||
154 | efi_time_cap_t cap; | ||
155 | |||
156 | status = efi.get_time(&eft, &cap); | ||
157 | |||
158 | if (status != EFI_SUCCESS) { | ||
159 | /* should never happen */ | ||
160 | printk(KERN_ERR "efitime: can't read time\n"); | ||
161 | return -EINVAL; | ||
162 | } | ||
163 | |||
164 | convert_from_efi_time(&eft, tm); | ||
165 | |||
166 | return rtc_valid_tm(tm); | ||
167 | } | ||
168 | |||
169 | static int efi_set_time(struct device *dev, struct rtc_time *tm) | ||
170 | { | ||
171 | efi_status_t status; | ||
172 | efi_time_t eft; | ||
173 | |||
174 | convert_to_efi_time(tm, &eft); | ||
175 | |||
176 | status = efi.set_time(&eft); | ||
177 | |||
178 | return status == EFI_SUCCESS ? 0 : -EINVAL; | ||
179 | } | ||
180 | |||
181 | static const struct rtc_class_ops efi_rtc_ops = { | ||
182 | .read_time = efi_read_time, | ||
183 | .set_time = efi_set_time, | ||
184 | .read_alarm = efi_read_alarm, | ||
185 | .set_alarm = efi_set_alarm, | ||
186 | }; | ||
187 | |||
188 | static int __init efi_rtc_probe(struct platform_device *dev) | ||
189 | { | ||
190 | struct rtc_device *rtc; | ||
191 | |||
192 | rtc = rtc_device_register("rtc-efi", &dev->dev, &efi_rtc_ops, | ||
193 | THIS_MODULE); | ||
194 | if (IS_ERR(rtc)) | ||
195 | return PTR_ERR(rtc); | ||
196 | |||
197 | platform_set_drvdata(dev, rtc); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int __exit efi_rtc_remove(struct platform_device *dev) | ||
203 | { | ||
204 | struct rtc_device *rtc = platform_get_drvdata(dev); | ||
205 | |||
206 | rtc_device_unregister(rtc); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static struct platform_driver efi_rtc_driver = { | ||
212 | .driver = { | ||
213 | .name = "rtc-efi", | ||
214 | .owner = THIS_MODULE, | ||
215 | }, | ||
216 | .probe = efi_rtc_probe, | ||
217 | .remove = __exit_p(efi_rtc_remove), | ||
218 | }; | ||
219 | |||
220 | static int __init efi_rtc_init(void) | ||
221 | { | ||
222 | return platform_driver_probe(&efi_rtc_driver, efi_rtc_probe); | ||
223 | } | ||
224 | |||
225 | static void __exit efi_rtc_exit(void) | ||
226 | { | ||
227 | platform_driver_unregister(&efi_rtc_driver); | ||
228 | } | ||
229 | |||
230 | module_init(efi_rtc_init); | ||
231 | module_exit(efi_rtc_exit); | ||
232 | |||
233 | MODULE_AUTHOR("dann frazier <dannf@hp.com>"); | ||
234 | MODULE_LICENSE("GPL"); | ||
235 | MODULE_DESCRIPTION("EFI RTC driver"); | ||
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index dd70bf73ce9..773851f338b 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c | |||
@@ -26,14 +26,13 @@ static const unsigned short rtc_ydays[2][13] = { | |||
26 | }; | 26 | }; |
27 | 27 | ||
28 | #define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) | 28 | #define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) |
29 | #define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400)) | ||
30 | 29 | ||
31 | /* | 30 | /* |
32 | * The number of days in the month. | 31 | * The number of days in the month. |
33 | */ | 32 | */ |
34 | int rtc_month_days(unsigned int month, unsigned int year) | 33 | int rtc_month_days(unsigned int month, unsigned int year) |
35 | { | 34 | { |
36 | return rtc_days_in_month[month] + (LEAP_YEAR(year) && month == 1); | 35 | return rtc_days_in_month[month] + (is_leap_year(year) && month == 1); |
37 | } | 36 | } |
38 | EXPORT_SYMBOL(rtc_month_days); | 37 | EXPORT_SYMBOL(rtc_month_days); |
39 | 38 | ||
@@ -42,7 +41,7 @@ EXPORT_SYMBOL(rtc_month_days); | |||
42 | */ | 41 | */ |
43 | int rtc_year_days(unsigned int day, unsigned int month, unsigned int year) | 42 | int rtc_year_days(unsigned int day, unsigned int month, unsigned int year) |
44 | { | 43 | { |
45 | return rtc_ydays[LEAP_YEAR(year)][month] + day-1; | 44 | return rtc_ydays[is_leap_year(year)][month] + day-1; |
46 | } | 45 | } |
47 | EXPORT_SYMBOL(rtc_year_days); | 46 | EXPORT_SYMBOL(rtc_year_days); |
48 | 47 | ||
@@ -66,7 +65,7 @@ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) | |||
66 | - LEAPS_THRU_END_OF(1970 - 1); | 65 | - LEAPS_THRU_END_OF(1970 - 1); |
67 | if (days < 0) { | 66 | if (days < 0) { |
68 | year -= 1; | 67 | year -= 1; |
69 | days += 365 + LEAP_YEAR(year); | 68 | days += 365 + is_leap_year(year); |
70 | } | 69 | } |
71 | tm->tm_year = year - 1900; | 70 | tm->tm_year = year - 1900; |
72 | tm->tm_yday = days + 1; | 71 | tm->tm_yday = days + 1; |
diff --git a/drivers/rtc/rtc-parisc.c b/drivers/rtc/rtc-parisc.c index c6bfa6fe1a2..b966f56da97 100644 --- a/drivers/rtc/rtc-parisc.c +++ b/drivers/rtc/rtc-parisc.c | |||
@@ -7,41 +7,25 @@ | |||
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <linux/time.h> | 8 | #include <linux/time.h> |
9 | #include <linux/platform_device.h> | 9 | #include <linux/platform_device.h> |
10 | #include <linux/rtc.h> | ||
10 | 11 | ||
11 | #include <asm/rtc.h> | 12 | #include <asm/rtc.h> |
12 | 13 | ||
13 | /* as simple as can be, and no simpler. */ | ||
14 | struct parisc_rtc { | ||
15 | struct rtc_device *rtc; | ||
16 | spinlock_t lock; | ||
17 | }; | ||
18 | |||
19 | static int parisc_get_time(struct device *dev, struct rtc_time *tm) | 14 | static int parisc_get_time(struct device *dev, struct rtc_time *tm) |
20 | { | 15 | { |
21 | struct parisc_rtc *p = dev_get_drvdata(dev); | 16 | unsigned long ret; |
22 | unsigned long flags, ret; | ||
23 | 17 | ||
24 | spin_lock_irqsave(&p->lock, flags); | ||
25 | ret = get_rtc_time(tm); | 18 | ret = get_rtc_time(tm); |
26 | spin_unlock_irqrestore(&p->lock, flags); | ||
27 | 19 | ||
28 | if (ret & RTC_BATT_BAD) | 20 | if (ret & RTC_BATT_BAD) |
29 | return -EOPNOTSUPP; | 21 | return -EOPNOTSUPP; |
30 | 22 | ||
31 | return 0; | 23 | return rtc_valid_tm(tm); |
32 | } | 24 | } |
33 | 25 | ||
34 | static int parisc_set_time(struct device *dev, struct rtc_time *tm) | 26 | static int parisc_set_time(struct device *dev, struct rtc_time *tm) |
35 | { | 27 | { |
36 | struct parisc_rtc *p = dev_get_drvdata(dev); | 28 | if (set_rtc_time(tm) < 0) |
37 | unsigned long flags; | ||
38 | int ret; | ||
39 | |||
40 | spin_lock_irqsave(&p->lock, flags); | ||
41 | ret = set_rtc_time(tm); | ||
42 | spin_unlock_irqrestore(&p->lock, flags); | ||
43 | |||
44 | if (ret < 0) | ||
45 | return -EOPNOTSUPP; | 29 | return -EOPNOTSUPP; |
46 | 30 | ||
47 | return 0; | 31 | return 0; |
@@ -52,35 +36,25 @@ static const struct rtc_class_ops parisc_rtc_ops = { | |||
52 | .set_time = parisc_set_time, | 36 | .set_time = parisc_set_time, |
53 | }; | 37 | }; |
54 | 38 | ||
55 | static int __devinit parisc_rtc_probe(struct platform_device *dev) | 39 | static int __init parisc_rtc_probe(struct platform_device *dev) |
56 | { | 40 | { |
57 | struct parisc_rtc *p; | 41 | struct rtc_device *rtc; |
58 | |||
59 | p = kzalloc(sizeof (*p), GFP_KERNEL); | ||
60 | if (!p) | ||
61 | return -ENOMEM; | ||
62 | |||
63 | spin_lock_init(&p->lock); | ||
64 | 42 | ||
65 | p->rtc = rtc_device_register("rtc-parisc", &dev->dev, &parisc_rtc_ops, | 43 | rtc = rtc_device_register("rtc-parisc", &dev->dev, &parisc_rtc_ops, |
66 | THIS_MODULE); | 44 | THIS_MODULE); |
67 | if (IS_ERR(p->rtc)) { | 45 | if (IS_ERR(rtc)) |
68 | int err = PTR_ERR(p->rtc); | 46 | return PTR_ERR(rtc); |
69 | kfree(p); | ||
70 | return err; | ||
71 | } | ||
72 | 47 | ||
73 | platform_set_drvdata(dev, p); | 48 | platform_set_drvdata(dev, rtc); |
74 | 49 | ||
75 | return 0; | 50 | return 0; |
76 | } | 51 | } |
77 | 52 | ||
78 | static int __devexit parisc_rtc_remove(struct platform_device *dev) | 53 | static int __exit parisc_rtc_remove(struct platform_device *dev) |
79 | { | 54 | { |
80 | struct parisc_rtc *p = platform_get_drvdata(dev); | 55 | struct rtc_device *rtc = platform_get_drvdata(dev); |
81 | 56 | ||
82 | rtc_device_unregister(p->rtc); | 57 | rtc_device_unregister(rtc); |
83 | kfree(p); | ||
84 | 58 | ||
85 | return 0; | 59 | return 0; |
86 | } | 60 | } |
@@ -96,7 +70,7 @@ static struct platform_driver parisc_rtc_driver = { | |||
96 | 70 | ||
97 | static int __init parisc_rtc_init(void) | 71 | static int __init parisc_rtc_init(void) |
98 | { | 72 | { |
99 | return platform_driver_register(&parisc_rtc_driver); | 73 | return platform_driver_probe(&parisc_rtc_driver, parisc_rtc_probe); |
100 | } | 74 | } |
101 | 75 | ||
102 | static void __exit parisc_rtc_fini(void) | 76 | static void __exit parisc_rtc_fini(void) |
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index 14d4f036a76..66955cc9c74 100644 --- a/drivers/rtc/rtc-v3020.c +++ b/drivers/rtc/rtc-v3020.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/rtc-v3020.h> | 28 | #include <linux/rtc-v3020.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | 30 | ||
31 | #include <asm/io.h> | 31 | #include <linux/io.h> |
32 | 32 | ||
33 | #undef DEBUG | 33 | #undef DEBUG |
34 | 34 | ||
@@ -63,7 +63,7 @@ static void v3020_set_reg(struct v3020 *chip, unsigned char address, | |||
63 | 63 | ||
64 | static unsigned char v3020_get_reg(struct v3020 *chip, unsigned char address) | 64 | static unsigned char v3020_get_reg(struct v3020 *chip, unsigned char address) |
65 | { | 65 | { |
66 | unsigned int data=0; | 66 | unsigned int data = 0; |
67 | int i; | 67 | int i; |
68 | 68 | ||
69 | for (i = 0; i < 4; i++) { | 69 | for (i = 0; i < 4; i++) { |
@@ -106,16 +106,14 @@ static int v3020_read_time(struct device *dev, struct rtc_time *dt) | |||
106 | tmp = v3020_get_reg(chip, V3020_YEAR); | 106 | tmp = v3020_get_reg(chip, V3020_YEAR); |
107 | dt->tm_year = bcd2bin(tmp)+100; | 107 | dt->tm_year = bcd2bin(tmp)+100; |
108 | 108 | ||
109 | #ifdef DEBUG | 109 | dev_dbg(dev, "\n%s : Read RTC values\n", __func__); |
110 | printk("\n%s : Read RTC values\n",__func__); | 110 | dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour); |
111 | printk("tm_hour: %i\n",dt->tm_hour); | 111 | dev_dbg(dev, "tm_min : %i\n", dt->tm_min); |
112 | printk("tm_min : %i\n",dt->tm_min); | 112 | dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec); |
113 | printk("tm_sec : %i\n",dt->tm_sec); | 113 | dev_dbg(dev, "tm_year: %i\n", dt->tm_year); |
114 | printk("tm_year: %i\n",dt->tm_year); | 114 | dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon); |
115 | printk("tm_mon : %i\n",dt->tm_mon); | 115 | dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday); |
116 | printk("tm_mday: %i\n",dt->tm_mday); | 116 | dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday); |
117 | printk("tm_wday: %i\n",dt->tm_wday); | ||
118 | #endif | ||
119 | 117 | ||
120 | return 0; | 118 | return 0; |
121 | } | 119 | } |
@@ -125,15 +123,13 @@ static int v3020_set_time(struct device *dev, struct rtc_time *dt) | |||
125 | { | 123 | { |
126 | struct v3020 *chip = dev_get_drvdata(dev); | 124 | struct v3020 *chip = dev_get_drvdata(dev); |
127 | 125 | ||
128 | #ifdef DEBUG | 126 | dev_dbg(dev, "\n%s : Setting RTC values\n", __func__); |
129 | printk("\n%s : Setting RTC values\n",__func__); | 127 | dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec); |
130 | printk("tm_sec : %i\n",dt->tm_sec); | 128 | dev_dbg(dev, "tm_min : %i\n", dt->tm_min); |
131 | printk("tm_min : %i\n",dt->tm_min); | 129 | dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour); |
132 | printk("tm_hour: %i\n",dt->tm_hour); | 130 | dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday); |
133 | printk("tm_mday: %i\n",dt->tm_mday); | 131 | dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday); |
134 | printk("tm_wday: %i\n",dt->tm_wday); | 132 | dev_dbg(dev, "tm_year: %i\n", dt->tm_year); |
135 | printk("tm_year: %i\n",dt->tm_year); | ||
136 | #endif | ||
137 | 133 | ||
138 | /* Write all the values to ram... */ | 134 | /* Write all the values to ram... */ |
139 | v3020_set_reg(chip, V3020_SECONDS, bin2bcd(dt->tm_sec)); | 135 | v3020_set_reg(chip, V3020_SECONDS, bin2bcd(dt->tm_sec)); |
@@ -191,7 +187,7 @@ static int rtc_probe(struct platform_device *pdev) | |||
191 | /* Test chip by doing a write/read sequence | 187 | /* Test chip by doing a write/read sequence |
192 | * to the chip ram */ | 188 | * to the chip ram */ |
193 | v3020_set_reg(chip, V3020_SECONDS, 0x33); | 189 | v3020_set_reg(chip, V3020_SECONDS, 0x33); |
194 | if(v3020_get_reg(chip, V3020_SECONDS) != 0x33) { | 190 | if (v3020_get_reg(chip, V3020_SECONDS) != 0x33) { |
195 | retval = -ENODEV; | 191 | retval = -ENODEV; |
196 | goto err_io; | 192 | goto err_io; |
197 | } | 193 | } |
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index 5c5e3aa9138..c91edc572eb 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c | |||
@@ -122,7 +122,7 @@ static int wm8350_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
122 | do { | 122 | do { |
123 | rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); | 123 | rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); |
124 | schedule_timeout_uninterruptible(msecs_to_jiffies(1)); | 124 | schedule_timeout_uninterruptible(msecs_to_jiffies(1)); |
125 | } while (retries-- && !(rtc_ctrl & WM8350_RTC_STS)); | 125 | } while (--retries && !(rtc_ctrl & WM8350_RTC_STS)); |
126 | 126 | ||
127 | if (!retries) { | 127 | if (!retries) { |
128 | dev_err(dev, "timed out on set confirmation\n"); | 128 | dev_err(dev, "timed out on set confirmation\n"); |
@@ -236,6 +236,17 @@ static int wm8350_rtc_start_alarm(struct wm8350 *wm8350) | |||
236 | return 0; | 236 | return 0; |
237 | } | 237 | } |
238 | 238 | ||
239 | static int wm8350_rtc_alarm_irq_enable(struct device *dev, | ||
240 | unsigned int enabled) | ||
241 | { | ||
242 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | ||
243 | |||
244 | if (enabled) | ||
245 | return wm8350_rtc_start_alarm(wm8350); | ||
246 | else | ||
247 | return wm8350_rtc_stop_alarm(wm8350); | ||
248 | } | ||
249 | |||
239 | static int wm8350_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | 250 | static int wm8350_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) |
240 | { | 251 | { |
241 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | 252 | struct wm8350 *wm8350 = dev_get_drvdata(dev); |
@@ -291,30 +302,15 @@ static int wm8350_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
291 | return ret; | 302 | return ret; |
292 | } | 303 | } |
293 | 304 | ||
294 | /* | 305 | static int wm8350_rtc_update_irq_enable(struct device *dev, |
295 | * Handle commands from user-space | 306 | unsigned int enabled) |
296 | */ | ||
297 | static int wm8350_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
298 | unsigned long arg) | ||
299 | { | 307 | { |
300 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | 308 | struct wm8350 *wm8350 = dev_get_drvdata(dev); |
301 | 309 | ||
302 | switch (cmd) { | 310 | if (enabled) |
303 | case RTC_AIE_OFF: | ||
304 | return wm8350_rtc_stop_alarm(wm8350); | ||
305 | case RTC_AIE_ON: | ||
306 | return wm8350_rtc_start_alarm(wm8350); | ||
307 | |||
308 | case RTC_UIE_OFF: | ||
309 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
310 | break; | ||
311 | case RTC_UIE_ON: | ||
312 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); | 311 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); |
313 | break; | 312 | else |
314 | 313 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | |
315 | default: | ||
316 | return -ENOIOCTLCMD; | ||
317 | } | ||
318 | 314 | ||
319 | return 0; | 315 | return 0; |
320 | } | 316 | } |
@@ -345,11 +341,12 @@ static void wm8350_rtc_update_handler(struct wm8350 *wm8350, int irq, | |||
345 | } | 341 | } |
346 | 342 | ||
347 | static const struct rtc_class_ops wm8350_rtc_ops = { | 343 | static const struct rtc_class_ops wm8350_rtc_ops = { |
348 | .ioctl = wm8350_rtc_ioctl, | ||
349 | .read_time = wm8350_rtc_readtime, | 344 | .read_time = wm8350_rtc_readtime, |
350 | .set_time = wm8350_rtc_settime, | 345 | .set_time = wm8350_rtc_settime, |
351 | .read_alarm = wm8350_rtc_readalarm, | 346 | .read_alarm = wm8350_rtc_readalarm, |
352 | .set_alarm = wm8350_rtc_setalarm, | 347 | .set_alarm = wm8350_rtc_setalarm, |
348 | .alarm_irq_enable = wm8350_rtc_alarm_irq_enable, | ||
349 | .update_irq_enable = wm8350_rtc_update_irq_enable, | ||
353 | }; | 350 | }; |
354 | 351 | ||
355 | #ifdef CONFIG_PM | 352 | #ifdef CONFIG_PM |
@@ -440,7 +437,7 @@ static int wm8350_rtc_probe(struct platform_device *pdev) | |||
440 | do { | 437 | do { |
441 | timectl = wm8350_reg_read(wm8350, | 438 | timectl = wm8350_reg_read(wm8350, |
442 | WM8350_RTC_TIME_CONTROL); | 439 | WM8350_RTC_TIME_CONTROL); |
443 | } while (timectl & WM8350_RTC_STS && retries--); | 440 | } while (timectl & WM8350_RTC_STS && --retries); |
444 | 441 | ||
445 | if (retries == 0) { | 442 | if (retries == 0) { |
446 | dev_err(&pdev->dev, "failed to start: timeout\n"); | 443 | dev_err(&pdev->dev, "failed to start: timeout\n"); |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 42f4e66fcca..bf3c0e32a33 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/console.h> | 29 | #include <linux/console.h> |
30 | #include <linux/proc_fs.h> | ||
31 | #include <linux/seq_file.h> | ||
30 | #include <linux/serial_core.h> | 32 | #include <linux/serial_core.h> |
31 | #include <linux/smp_lock.h> | 33 | #include <linux/smp_lock.h> |
32 | #include <linux/device.h> | 34 | #include <linux/device.h> |
@@ -1682,20 +1684,20 @@ static const char *uart_type(struct uart_port *port) | |||
1682 | 1684 | ||
1683 | #ifdef CONFIG_PROC_FS | 1685 | #ifdef CONFIG_PROC_FS |
1684 | 1686 | ||
1685 | static int uart_line_info(char *buf, struct uart_driver *drv, int i) | 1687 | static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i) |
1686 | { | 1688 | { |
1687 | struct uart_state *state = drv->state + i; | 1689 | struct uart_state *state = drv->state + i; |
1688 | int pm_state; | 1690 | int pm_state; |
1689 | struct uart_port *port = state->port; | 1691 | struct uart_port *port = state->port; |
1690 | char stat_buf[32]; | 1692 | char stat_buf[32]; |
1691 | unsigned int status; | 1693 | unsigned int status; |
1692 | int mmio, ret; | 1694 | int mmio; |
1693 | 1695 | ||
1694 | if (!port) | 1696 | if (!port) |
1695 | return 0; | 1697 | return; |
1696 | 1698 | ||
1697 | mmio = port->iotype >= UPIO_MEM; | 1699 | mmio = port->iotype >= UPIO_MEM; |
1698 | ret = sprintf(buf, "%d: uart:%s %s%08llX irq:%d", | 1700 | seq_printf(m, "%d: uart:%s %s%08llX irq:%d", |
1699 | port->line, uart_type(port), | 1701 | port->line, uart_type(port), |
1700 | mmio ? "mmio:0x" : "port:", | 1702 | mmio ? "mmio:0x" : "port:", |
1701 | mmio ? (unsigned long long)port->mapbase | 1703 | mmio ? (unsigned long long)port->mapbase |
@@ -1703,8 +1705,8 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i) | |||
1703 | port->irq); | 1705 | port->irq); |
1704 | 1706 | ||
1705 | if (port->type == PORT_UNKNOWN) { | 1707 | if (port->type == PORT_UNKNOWN) { |
1706 | strcat(buf, "\n"); | 1708 | seq_putc(m, '\n'); |
1707 | return ret + 1; | 1709 | return; |
1708 | } | 1710 | } |
1709 | 1711 | ||
1710 | if (capable(CAP_SYS_ADMIN)) { | 1712 | if (capable(CAP_SYS_ADMIN)) { |
@@ -1719,19 +1721,19 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i) | |||
1719 | uart_change_pm(state, pm_state); | 1721 | uart_change_pm(state, pm_state); |
1720 | mutex_unlock(&state->mutex); | 1722 | mutex_unlock(&state->mutex); |
1721 | 1723 | ||
1722 | ret += sprintf(buf + ret, " tx:%d rx:%d", | 1724 | seq_printf(m, " tx:%d rx:%d", |
1723 | port->icount.tx, port->icount.rx); | 1725 | port->icount.tx, port->icount.rx); |
1724 | if (port->icount.frame) | 1726 | if (port->icount.frame) |
1725 | ret += sprintf(buf + ret, " fe:%d", | 1727 | seq_printf(m, " fe:%d", |
1726 | port->icount.frame); | 1728 | port->icount.frame); |
1727 | if (port->icount.parity) | 1729 | if (port->icount.parity) |
1728 | ret += sprintf(buf + ret, " pe:%d", | 1730 | seq_printf(m, " pe:%d", |
1729 | port->icount.parity); | 1731 | port->icount.parity); |
1730 | if (port->icount.brk) | 1732 | if (port->icount.brk) |
1731 | ret += sprintf(buf + ret, " brk:%d", | 1733 | seq_printf(m, " brk:%d", |
1732 | port->icount.brk); | 1734 | port->icount.brk); |
1733 | if (port->icount.overrun) | 1735 | if (port->icount.overrun) |
1734 | ret += sprintf(buf + ret, " oe:%d", | 1736 | seq_printf(m, " oe:%d", |
1735 | port->icount.overrun); | 1737 | port->icount.overrun); |
1736 | 1738 | ||
1737 | #define INFOBIT(bit, str) \ | 1739 | #define INFOBIT(bit, str) \ |
@@ -1753,45 +1755,39 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i) | |||
1753 | STATBIT(TIOCM_RNG, "|RI"); | 1755 | STATBIT(TIOCM_RNG, "|RI"); |
1754 | if (stat_buf[0]) | 1756 | if (stat_buf[0]) |
1755 | stat_buf[0] = ' '; | 1757 | stat_buf[0] = ' '; |
1756 | strcat(stat_buf, "\n"); | ||
1757 | 1758 | ||
1758 | ret += sprintf(buf + ret, stat_buf); | 1759 | seq_puts(m, stat_buf); |
1759 | } else { | ||
1760 | strcat(buf, "\n"); | ||
1761 | ret++; | ||
1762 | } | 1760 | } |
1761 | seq_putc(m, '\n'); | ||
1763 | #undef STATBIT | 1762 | #undef STATBIT |
1764 | #undef INFOBIT | 1763 | #undef INFOBIT |
1765 | return ret; | ||
1766 | } | 1764 | } |
1767 | 1765 | ||
1768 | static int uart_read_proc(char *page, char **start, off_t off, | 1766 | static int uart_proc_show(struct seq_file *m, void *v) |
1769 | int count, int *eof, void *data) | ||
1770 | { | 1767 | { |
1771 | struct tty_driver *ttydrv = data; | 1768 | struct tty_driver *ttydrv = v; |
1772 | struct uart_driver *drv = ttydrv->driver_state; | 1769 | struct uart_driver *drv = ttydrv->driver_state; |
1773 | int i, len = 0, l; | 1770 | int i; |
1774 | off_t begin = 0; | ||
1775 | 1771 | ||
1776 | len += sprintf(page, "serinfo:1.0 driver%s%s revision:%s\n", | 1772 | seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n", |
1777 | "", "", ""); | 1773 | "", "", ""); |
1778 | for (i = 0; i < drv->nr && len < PAGE_SIZE - 96; i++) { | 1774 | for (i = 0; i < drv->nr; i++) |
1779 | l = uart_line_info(page + len, drv, i); | 1775 | uart_line_info(m, drv, i); |
1780 | len += l; | 1776 | return 0; |
1781 | if (len + begin > off + count) | ||
1782 | goto done; | ||
1783 | if (len + begin < off) { | ||
1784 | begin += len; | ||
1785 | len = 0; | ||
1786 | } | ||
1787 | } | ||
1788 | *eof = 1; | ||
1789 | done: | ||
1790 | if (off >= len + begin) | ||
1791 | return 0; | ||
1792 | *start = page + (off - begin); | ||
1793 | return (count < begin + len - off) ? count : (begin + len - off); | ||
1794 | } | 1777 | } |
1778 | |||
1779 | static int uart_proc_open(struct inode *inode, struct file *file) | ||
1780 | { | ||
1781 | return single_open(file, uart_proc_show, PDE(inode)->data); | ||
1782 | } | ||
1783 | |||
1784 | static const struct file_operations uart_proc_fops = { | ||
1785 | .owner = THIS_MODULE, | ||
1786 | .open = uart_proc_open, | ||
1787 | .read = seq_read, | ||
1788 | .llseek = seq_lseek, | ||
1789 | .release = single_release, | ||
1790 | }; | ||
1795 | #endif | 1791 | #endif |
1796 | 1792 | ||
1797 | #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL) | 1793 | #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL) |
@@ -2299,7 +2295,7 @@ static const struct tty_operations uart_ops = { | |||
2299 | .break_ctl = uart_break_ctl, | 2295 | .break_ctl = uart_break_ctl, |
2300 | .wait_until_sent= uart_wait_until_sent, | 2296 | .wait_until_sent= uart_wait_until_sent, |
2301 | #ifdef CONFIG_PROC_FS | 2297 | #ifdef CONFIG_PROC_FS |
2302 | .read_proc = uart_read_proc, | 2298 | .proc_fops = &uart_proc_fops, |
2303 | #endif | 2299 | #endif |
2304 | .tiocmget = uart_tiocmget, | 2300 | .tiocmget = uart_tiocmget, |
2305 | .tiocmset = uart_tiocmset, | 2301 | .tiocmset = uart_tiocmset, |
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c index 44a2b46ccb7..f4573a96af2 100644 --- a/drivers/spi/spi_mpc83xx.c +++ b/drivers/spi/spi_mpc83xx.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/errno.h> | ||
18 | #include <linux/err.h> | ||
17 | #include <linux/completion.h> | 19 | #include <linux/completion.h> |
18 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
19 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
@@ -23,7 +25,13 @@ | |||
23 | #include <linux/spi/spi_bitbang.h> | 25 | #include <linux/spi/spi_bitbang.h> |
24 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
25 | #include <linux/fsl_devices.h> | 27 | #include <linux/fsl_devices.h> |
28 | #include <linux/of.h> | ||
29 | #include <linux/of_platform.h> | ||
30 | #include <linux/gpio.h> | ||
31 | #include <linux/of_gpio.h> | ||
32 | #include <linux/of_spi.h> | ||
26 | 33 | ||
34 | #include <sysdev/fsl_soc.h> | ||
27 | #include <asm/irq.h> | 35 | #include <asm/irq.h> |
28 | #include <asm/io.h> | 36 | #include <asm/io.h> |
29 | 37 | ||
@@ -79,7 +87,7 @@ struct mpc83xx_spi { | |||
79 | u32(*get_tx) (struct mpc83xx_spi *); | 87 | u32(*get_tx) (struct mpc83xx_spi *); |
80 | 88 | ||
81 | unsigned int count; | 89 | unsigned int count; |
82 | int irq; | 90 | unsigned int irq; |
83 | 91 | ||
84 | unsigned nsecs; /* (clock cycle time)/2 */ | 92 | unsigned nsecs; /* (clock cycle time)/2 */ |
85 | 93 | ||
@@ -89,9 +97,6 @@ struct mpc83xx_spi { | |||
89 | 97 | ||
90 | bool qe_mode; | 98 | bool qe_mode; |
91 | 99 | ||
92 | void (*activate_cs) (u8 cs, u8 polarity); | ||
93 | void (*deactivate_cs) (u8 cs, u8 polarity); | ||
94 | |||
95 | u8 busy; | 100 | u8 busy; |
96 | 101 | ||
97 | struct workqueue_struct *workqueue; | 102 | struct workqueue_struct *workqueue; |
@@ -123,6 +128,7 @@ static inline u32 mpc83xx_spi_read_reg(__be32 __iomem * reg) | |||
123 | } | 128 | } |
124 | 129 | ||
125 | #define MPC83XX_SPI_RX_BUF(type) \ | 130 | #define MPC83XX_SPI_RX_BUF(type) \ |
131 | static \ | ||
126 | void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \ | 132 | void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \ |
127 | { \ | 133 | { \ |
128 | type * rx = mpc83xx_spi->rx; \ | 134 | type * rx = mpc83xx_spi->rx; \ |
@@ -131,6 +137,7 @@ void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \ | |||
131 | } | 137 | } |
132 | 138 | ||
133 | #define MPC83XX_SPI_TX_BUF(type) \ | 139 | #define MPC83XX_SPI_TX_BUF(type) \ |
140 | static \ | ||
134 | u32 mpc83xx_spi_tx_buf_##type(struct mpc83xx_spi *mpc83xx_spi) \ | 141 | u32 mpc83xx_spi_tx_buf_##type(struct mpc83xx_spi *mpc83xx_spi) \ |
135 | { \ | 142 | { \ |
136 | u32 data; \ | 143 | u32 data; \ |
@@ -151,15 +158,14 @@ MPC83XX_SPI_TX_BUF(u32) | |||
151 | 158 | ||
152 | static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) | 159 | static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) |
153 | { | 160 | { |
154 | struct mpc83xx_spi *mpc83xx_spi; | 161 | struct mpc83xx_spi *mpc83xx_spi = spi_master_get_devdata(spi->master); |
155 | u8 pol = spi->mode & SPI_CS_HIGH ? 1 : 0; | 162 | struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data; |
163 | bool pol = spi->mode & SPI_CS_HIGH; | ||
156 | struct spi_mpc83xx_cs *cs = spi->controller_state; | 164 | struct spi_mpc83xx_cs *cs = spi->controller_state; |
157 | 165 | ||
158 | mpc83xx_spi = spi_master_get_devdata(spi->master); | ||
159 | |||
160 | if (value == BITBANG_CS_INACTIVE) { | 166 | if (value == BITBANG_CS_INACTIVE) { |
161 | if (mpc83xx_spi->deactivate_cs) | 167 | if (pdata->cs_control) |
162 | mpc83xx_spi->deactivate_cs(spi->chip_select, pol); | 168 | pdata->cs_control(spi, !pol); |
163 | } | 169 | } |
164 | 170 | ||
165 | if (value == BITBANG_CS_ACTIVE) { | 171 | if (value == BITBANG_CS_ACTIVE) { |
@@ -172,7 +178,7 @@ static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) | |||
172 | 178 | ||
173 | if (cs->hw_mode != regval) { | 179 | if (cs->hw_mode != regval) { |
174 | unsigned long flags; | 180 | unsigned long flags; |
175 | void *tmp_ptr = &mpc83xx_spi->base->mode; | 181 | __be32 __iomem *mode = &mpc83xx_spi->base->mode; |
176 | 182 | ||
177 | regval = cs->hw_mode; | 183 | regval = cs->hw_mode; |
178 | /* Turn off IRQs locally to minimize time that | 184 | /* Turn off IRQs locally to minimize time that |
@@ -180,12 +186,12 @@ static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) | |||
180 | */ | 186 | */ |
181 | local_irq_save(flags); | 187 | local_irq_save(flags); |
182 | /* Turn off SPI unit prior changing mode */ | 188 | /* Turn off SPI unit prior changing mode */ |
183 | mpc83xx_spi_write_reg(tmp_ptr, regval & ~SPMODE_ENABLE); | 189 | mpc83xx_spi_write_reg(mode, regval & ~SPMODE_ENABLE); |
184 | mpc83xx_spi_write_reg(tmp_ptr, regval); | 190 | mpc83xx_spi_write_reg(mode, regval); |
185 | local_irq_restore(flags); | 191 | local_irq_restore(flags); |
186 | } | 192 | } |
187 | if (mpc83xx_spi->activate_cs) | 193 | if (pdata->cs_control) |
188 | mpc83xx_spi->activate_cs(spi->chip_select, pol); | 194 | pdata->cs_control(spi, pol); |
189 | } | 195 | } |
190 | } | 196 | } |
191 | 197 | ||
@@ -284,7 +290,7 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
284 | regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode); | 290 | regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode); |
285 | if (cs->hw_mode != regval) { | 291 | if (cs->hw_mode != regval) { |
286 | unsigned long flags; | 292 | unsigned long flags; |
287 | void *tmp_ptr = &mpc83xx_spi->base->mode; | 293 | __be32 __iomem *mode = &mpc83xx_spi->base->mode; |
288 | 294 | ||
289 | regval = cs->hw_mode; | 295 | regval = cs->hw_mode; |
290 | /* Turn off IRQs locally to minimize time | 296 | /* Turn off IRQs locally to minimize time |
@@ -292,8 +298,8 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
292 | */ | 298 | */ |
293 | local_irq_save(flags); | 299 | local_irq_save(flags); |
294 | /* Turn off SPI unit prior changing mode */ | 300 | /* Turn off SPI unit prior changing mode */ |
295 | mpc83xx_spi_write_reg(tmp_ptr, regval & ~SPMODE_ENABLE); | 301 | mpc83xx_spi_write_reg(mode, regval & ~SPMODE_ENABLE); |
296 | mpc83xx_spi_write_reg(tmp_ptr, regval); | 302 | mpc83xx_spi_write_reg(mode, regval); |
297 | local_irq_restore(flags); | 303 | local_irq_restore(flags); |
298 | } | 304 | } |
299 | return 0; | 305 | return 0; |
@@ -483,7 +489,7 @@ static int mpc83xx_spi_setup(struct spi_device *spi) | |||
483 | return 0; | 489 | return 0; |
484 | } | 490 | } |
485 | 491 | ||
486 | irqreturn_t mpc83xx_spi_irq(s32 irq, void *context_data) | 492 | static irqreturn_t mpc83xx_spi_irq(s32 irq, void *context_data) |
487 | { | 493 | { |
488 | struct mpc83xx_spi *mpc83xx_spi = context_data; | 494 | struct mpc83xx_spi *mpc83xx_spi = context_data; |
489 | u32 event; | 495 | u32 event; |
@@ -545,43 +551,28 @@ static void mpc83xx_spi_cleanup(struct spi_device *spi) | |||
545 | kfree(spi->controller_state); | 551 | kfree(spi->controller_state); |
546 | } | 552 | } |
547 | 553 | ||
548 | static int __init mpc83xx_spi_probe(struct platform_device *dev) | 554 | static struct spi_master * __devinit |
555 | mpc83xx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) | ||
549 | { | 556 | { |
557 | struct fsl_spi_platform_data *pdata = dev->platform_data; | ||
550 | struct spi_master *master; | 558 | struct spi_master *master; |
551 | struct mpc83xx_spi *mpc83xx_spi; | 559 | struct mpc83xx_spi *mpc83xx_spi; |
552 | struct fsl_spi_platform_data *pdata; | ||
553 | struct resource *r; | ||
554 | u32 regval; | 560 | u32 regval; |
555 | int ret = 0; | 561 | int ret = 0; |
556 | 562 | ||
557 | /* Get resources(memory, IRQ) associated with the device */ | 563 | master = spi_alloc_master(dev, sizeof(struct mpc83xx_spi)); |
558 | master = spi_alloc_master(&dev->dev, sizeof(struct mpc83xx_spi)); | ||
559 | |||
560 | if (master == NULL) { | 564 | if (master == NULL) { |
561 | ret = -ENOMEM; | 565 | ret = -ENOMEM; |
562 | goto err; | 566 | goto err; |
563 | } | 567 | } |
564 | 568 | ||
565 | platform_set_drvdata(dev, master); | 569 | dev_set_drvdata(dev, master); |
566 | pdata = dev->dev.platform_data; | ||
567 | 570 | ||
568 | if (pdata == NULL) { | ||
569 | ret = -ENODEV; | ||
570 | goto free_master; | ||
571 | } | ||
572 | |||
573 | r = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
574 | if (r == NULL) { | ||
575 | ret = -ENODEV; | ||
576 | goto free_master; | ||
577 | } | ||
578 | master->setup = mpc83xx_spi_setup; | 571 | master->setup = mpc83xx_spi_setup; |
579 | master->transfer = mpc83xx_spi_transfer; | 572 | master->transfer = mpc83xx_spi_transfer; |
580 | master->cleanup = mpc83xx_spi_cleanup; | 573 | master->cleanup = mpc83xx_spi_cleanup; |
581 | 574 | ||
582 | mpc83xx_spi = spi_master_get_devdata(master); | 575 | mpc83xx_spi = spi_master_get_devdata(master); |
583 | mpc83xx_spi->activate_cs = pdata->activate_cs; | ||
584 | mpc83xx_spi->deactivate_cs = pdata->deactivate_cs; | ||
585 | mpc83xx_spi->qe_mode = pdata->qe_mode; | 576 | mpc83xx_spi->qe_mode = pdata->qe_mode; |
586 | mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8; | 577 | mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8; |
587 | mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8; | 578 | mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8; |
@@ -596,18 +587,13 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) | |||
596 | 587 | ||
597 | init_completion(&mpc83xx_spi->done); | 588 | init_completion(&mpc83xx_spi->done); |
598 | 589 | ||
599 | mpc83xx_spi->base = ioremap(r->start, r->end - r->start + 1); | 590 | mpc83xx_spi->base = ioremap(mem->start, mem->end - mem->start + 1); |
600 | if (mpc83xx_spi->base == NULL) { | 591 | if (mpc83xx_spi->base == NULL) { |
601 | ret = -ENOMEM; | 592 | ret = -ENOMEM; |
602 | goto put_master; | 593 | goto put_master; |
603 | } | 594 | } |
604 | 595 | ||
605 | mpc83xx_spi->irq = platform_get_irq(dev, 0); | 596 | mpc83xx_spi->irq = irq; |
606 | |||
607 | if (mpc83xx_spi->irq < 0) { | ||
608 | ret = -ENXIO; | ||
609 | goto unmap_io; | ||
610 | } | ||
611 | 597 | ||
612 | /* Register for SPI Interrupt */ | 598 | /* Register for SPI Interrupt */ |
613 | ret = request_irq(mpc83xx_spi->irq, mpc83xx_spi_irq, | 599 | ret = request_irq(mpc83xx_spi->irq, mpc83xx_spi_irq, |
@@ -649,9 +635,9 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) | |||
649 | 635 | ||
650 | printk(KERN_INFO | 636 | printk(KERN_INFO |
651 | "%s: MPC83xx SPI Controller driver at 0x%p (irq = %d)\n", | 637 | "%s: MPC83xx SPI Controller driver at 0x%p (irq = %d)\n", |
652 | dev_name(&dev->dev), mpc83xx_spi->base, mpc83xx_spi->irq); | 638 | dev_name(dev), mpc83xx_spi->base, mpc83xx_spi->irq); |
653 | 639 | ||
654 | return ret; | 640 | return master; |
655 | 641 | ||
656 | unreg_master: | 642 | unreg_master: |
657 | destroy_workqueue(mpc83xx_spi->workqueue); | 643 | destroy_workqueue(mpc83xx_spi->workqueue); |
@@ -661,18 +647,16 @@ unmap_io: | |||
661 | iounmap(mpc83xx_spi->base); | 647 | iounmap(mpc83xx_spi->base); |
662 | put_master: | 648 | put_master: |
663 | spi_master_put(master); | 649 | spi_master_put(master); |
664 | free_master: | ||
665 | kfree(master); | ||
666 | err: | 650 | err: |
667 | return ret; | 651 | return ERR_PTR(ret); |
668 | } | 652 | } |
669 | 653 | ||
670 | static int __exit mpc83xx_spi_remove(struct platform_device *dev) | 654 | static int __devexit mpc83xx_spi_remove(struct device *dev) |
671 | { | 655 | { |
672 | struct mpc83xx_spi *mpc83xx_spi; | 656 | struct mpc83xx_spi *mpc83xx_spi; |
673 | struct spi_master *master; | 657 | struct spi_master *master; |
674 | 658 | ||
675 | master = platform_get_drvdata(dev); | 659 | master = dev_get_drvdata(dev); |
676 | mpc83xx_spi = spi_master_get_devdata(master); | 660 | mpc83xx_spi = spi_master_get_devdata(master); |
677 | 661 | ||
678 | flush_workqueue(mpc83xx_spi->workqueue); | 662 | flush_workqueue(mpc83xx_spi->workqueue); |
@@ -685,23 +669,293 @@ static int __exit mpc83xx_spi_remove(struct platform_device *dev) | |||
685 | return 0; | 669 | return 0; |
686 | } | 670 | } |
687 | 671 | ||
672 | struct mpc83xx_spi_probe_info { | ||
673 | struct fsl_spi_platform_data pdata; | ||
674 | int *gpios; | ||
675 | bool *alow_flags; | ||
676 | }; | ||
677 | |||
678 | static struct mpc83xx_spi_probe_info * | ||
679 | to_of_pinfo(struct fsl_spi_platform_data *pdata) | ||
680 | { | ||
681 | return container_of(pdata, struct mpc83xx_spi_probe_info, pdata); | ||
682 | } | ||
683 | |||
684 | static void mpc83xx_spi_cs_control(struct spi_device *spi, bool on) | ||
685 | { | ||
686 | struct device *dev = spi->dev.parent; | ||
687 | struct mpc83xx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data); | ||
688 | u16 cs = spi->chip_select; | ||
689 | int gpio = pinfo->gpios[cs]; | ||
690 | bool alow = pinfo->alow_flags[cs]; | ||
691 | |||
692 | gpio_set_value(gpio, on ^ alow); | ||
693 | } | ||
694 | |||
695 | static int of_mpc83xx_spi_get_chipselects(struct device *dev) | ||
696 | { | ||
697 | struct device_node *np = dev_archdata_get_node(&dev->archdata); | ||
698 | struct fsl_spi_platform_data *pdata = dev->platform_data; | ||
699 | struct mpc83xx_spi_probe_info *pinfo = to_of_pinfo(pdata); | ||
700 | unsigned int ngpios; | ||
701 | int i = 0; | ||
702 | int ret; | ||
703 | |||
704 | ngpios = of_gpio_count(np); | ||
705 | if (!ngpios) { | ||
706 | /* | ||
707 | * SPI w/o chip-select line. One SPI device is still permitted | ||
708 | * though. | ||
709 | */ | ||
710 | pdata->max_chipselect = 1; | ||
711 | return 0; | ||
712 | } | ||
713 | |||
714 | pinfo->gpios = kmalloc(ngpios * sizeof(pinfo->gpios), GFP_KERNEL); | ||
715 | if (!pinfo->gpios) | ||
716 | return -ENOMEM; | ||
717 | memset(pinfo->gpios, -1, ngpios * sizeof(pinfo->gpios)); | ||
718 | |||
719 | pinfo->alow_flags = kzalloc(ngpios * sizeof(pinfo->alow_flags), | ||
720 | GFP_KERNEL); | ||
721 | if (!pinfo->alow_flags) { | ||
722 | ret = -ENOMEM; | ||
723 | goto err_alloc_flags; | ||
724 | } | ||
725 | |||
726 | for (; i < ngpios; i++) { | ||
727 | int gpio; | ||
728 | enum of_gpio_flags flags; | ||
729 | |||
730 | gpio = of_get_gpio_flags(np, i, &flags); | ||
731 | if (!gpio_is_valid(gpio)) { | ||
732 | dev_err(dev, "invalid gpio #%d: %d\n", i, gpio); | ||
733 | goto err_loop; | ||
734 | } | ||
735 | |||
736 | ret = gpio_request(gpio, dev_name(dev)); | ||
737 | if (ret) { | ||
738 | dev_err(dev, "can't request gpio #%d: %d\n", i, ret); | ||
739 | goto err_loop; | ||
740 | } | ||
741 | |||
742 | pinfo->gpios[i] = gpio; | ||
743 | pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW; | ||
744 | |||
745 | ret = gpio_direction_output(pinfo->gpios[i], | ||
746 | pinfo->alow_flags[i]); | ||
747 | if (ret) { | ||
748 | dev_err(dev, "can't set output direction for gpio " | ||
749 | "#%d: %d\n", i, ret); | ||
750 | goto err_loop; | ||
751 | } | ||
752 | } | ||
753 | |||
754 | pdata->max_chipselect = ngpios; | ||
755 | pdata->cs_control = mpc83xx_spi_cs_control; | ||
756 | |||
757 | return 0; | ||
758 | |||
759 | err_loop: | ||
760 | while (i >= 0) { | ||
761 | if (gpio_is_valid(pinfo->gpios[i])) | ||
762 | gpio_free(pinfo->gpios[i]); | ||
763 | i--; | ||
764 | } | ||
765 | |||
766 | kfree(pinfo->alow_flags); | ||
767 | pinfo->alow_flags = NULL; | ||
768 | err_alloc_flags: | ||
769 | kfree(pinfo->gpios); | ||
770 | pinfo->gpios = NULL; | ||
771 | return ret; | ||
772 | } | ||
773 | |||
774 | static int of_mpc83xx_spi_free_chipselects(struct device *dev) | ||
775 | { | ||
776 | struct fsl_spi_platform_data *pdata = dev->platform_data; | ||
777 | struct mpc83xx_spi_probe_info *pinfo = to_of_pinfo(pdata); | ||
778 | int i; | ||
779 | |||
780 | if (!pinfo->gpios) | ||
781 | return 0; | ||
782 | |||
783 | for (i = 0; i < pdata->max_chipselect; i++) { | ||
784 | if (gpio_is_valid(pinfo->gpios[i])) | ||
785 | gpio_free(pinfo->gpios[i]); | ||
786 | } | ||
787 | |||
788 | kfree(pinfo->gpios); | ||
789 | kfree(pinfo->alow_flags); | ||
790 | return 0; | ||
791 | } | ||
792 | |||
793 | static int __devinit of_mpc83xx_spi_probe(struct of_device *ofdev, | ||
794 | const struct of_device_id *ofid) | ||
795 | { | ||
796 | struct device *dev = &ofdev->dev; | ||
797 | struct device_node *np = ofdev->node; | ||
798 | struct mpc83xx_spi_probe_info *pinfo; | ||
799 | struct fsl_spi_platform_data *pdata; | ||
800 | struct spi_master *master; | ||
801 | struct resource mem; | ||
802 | struct resource irq; | ||
803 | const void *prop; | ||
804 | int ret = -ENOMEM; | ||
805 | |||
806 | pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL); | ||
807 | if (!pinfo) | ||
808 | return -ENOMEM; | ||
809 | |||
810 | pdata = &pinfo->pdata; | ||
811 | dev->platform_data = pdata; | ||
812 | |||
813 | /* Allocate bus num dynamically. */ | ||
814 | pdata->bus_num = -1; | ||
815 | |||
816 | /* SPI controller is either clocked from QE or SoC clock. */ | ||
817 | pdata->sysclk = get_brgfreq(); | ||
818 | if (pdata->sysclk == -1) { | ||
819 | pdata->sysclk = fsl_get_sys_freq(); | ||
820 | if (pdata->sysclk == -1) { | ||
821 | ret = -ENODEV; | ||
822 | goto err_clk; | ||
823 | } | ||
824 | } | ||
825 | |||
826 | prop = of_get_property(np, "mode", NULL); | ||
827 | if (prop && !strcmp(prop, "cpu-qe")) | ||
828 | pdata->qe_mode = 1; | ||
829 | |||
830 | ret = of_mpc83xx_spi_get_chipselects(dev); | ||
831 | if (ret) | ||
832 | goto err; | ||
833 | |||
834 | ret = of_address_to_resource(np, 0, &mem); | ||
835 | if (ret) | ||
836 | goto err; | ||
837 | |||
838 | ret = of_irq_to_resource(np, 0, &irq); | ||
839 | if (!ret) { | ||
840 | ret = -EINVAL; | ||
841 | goto err; | ||
842 | } | ||
843 | |||
844 | master = mpc83xx_spi_probe(dev, &mem, irq.start); | ||
845 | if (IS_ERR(master)) { | ||
846 | ret = PTR_ERR(master); | ||
847 | goto err; | ||
848 | } | ||
849 | |||
850 | of_register_spi_devices(master, np); | ||
851 | |||
852 | return 0; | ||
853 | |||
854 | err: | ||
855 | of_mpc83xx_spi_free_chipselects(dev); | ||
856 | err_clk: | ||
857 | kfree(pinfo); | ||
858 | return ret; | ||
859 | } | ||
860 | |||
861 | static int __devexit of_mpc83xx_spi_remove(struct of_device *ofdev) | ||
862 | { | ||
863 | int ret; | ||
864 | |||
865 | ret = mpc83xx_spi_remove(&ofdev->dev); | ||
866 | if (ret) | ||
867 | return ret; | ||
868 | of_mpc83xx_spi_free_chipselects(&ofdev->dev); | ||
869 | return 0; | ||
870 | } | ||
871 | |||
872 | static const struct of_device_id of_mpc83xx_spi_match[] = { | ||
873 | { .compatible = "fsl,spi" }, | ||
874 | {}, | ||
875 | }; | ||
876 | MODULE_DEVICE_TABLE(of, of_mpc83xx_spi_match); | ||
877 | |||
878 | static struct of_platform_driver of_mpc83xx_spi_driver = { | ||
879 | .name = "mpc83xx_spi", | ||
880 | .match_table = of_mpc83xx_spi_match, | ||
881 | .probe = of_mpc83xx_spi_probe, | ||
882 | .remove = __devexit_p(of_mpc83xx_spi_remove), | ||
883 | }; | ||
884 | |||
885 | #ifdef CONFIG_MPC832x_RDB | ||
886 | /* | ||
887 | * XXX XXX XXX | ||
888 | * This is "legacy" platform driver, was used by the MPC8323E-RDB boards | ||
889 | * only. The driver should go away soon, since newer MPC8323E-RDB's device | ||
890 | * tree can work with OpenFirmware driver. But for now we support old trees | ||
891 | * as well. | ||
892 | */ | ||
893 | static int __devinit plat_mpc83xx_spi_probe(struct platform_device *pdev) | ||
894 | { | ||
895 | struct resource *mem; | ||
896 | unsigned int irq; | ||
897 | struct spi_master *master; | ||
898 | |||
899 | if (!pdev->dev.platform_data) | ||
900 | return -EINVAL; | ||
901 | |||
902 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
903 | if (!mem) | ||
904 | return -EINVAL; | ||
905 | |||
906 | irq = platform_get_irq(pdev, 0); | ||
907 | if (!irq) | ||
908 | return -EINVAL; | ||
909 | |||
910 | master = mpc83xx_spi_probe(&pdev->dev, mem, irq); | ||
911 | if (IS_ERR(master)) | ||
912 | return PTR_ERR(master); | ||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | static int __devexit plat_mpc83xx_spi_remove(struct platform_device *pdev) | ||
917 | { | ||
918 | return mpc83xx_spi_remove(&pdev->dev); | ||
919 | } | ||
920 | |||
688 | MODULE_ALIAS("platform:mpc83xx_spi"); | 921 | MODULE_ALIAS("platform:mpc83xx_spi"); |
689 | static struct platform_driver mpc83xx_spi_driver = { | 922 | static struct platform_driver mpc83xx_spi_driver = { |
690 | .remove = __exit_p(mpc83xx_spi_remove), | 923 | .probe = plat_mpc83xx_spi_probe, |
924 | .remove = __exit_p(plat_mpc83xx_spi_remove), | ||
691 | .driver = { | 925 | .driver = { |
692 | .name = "mpc83xx_spi", | 926 | .name = "mpc83xx_spi", |
693 | .owner = THIS_MODULE, | 927 | .owner = THIS_MODULE, |
694 | }, | 928 | }, |
695 | }; | 929 | }; |
696 | 930 | ||
931 | static bool legacy_driver_failed; | ||
932 | |||
933 | static void __init legacy_driver_register(void) | ||
934 | { | ||
935 | legacy_driver_failed = platform_driver_register(&mpc83xx_spi_driver); | ||
936 | } | ||
937 | |||
938 | static void __exit legacy_driver_unregister(void) | ||
939 | { | ||
940 | if (legacy_driver_failed) | ||
941 | return; | ||
942 | platform_driver_unregister(&mpc83xx_spi_driver); | ||
943 | } | ||
944 | #else | ||
945 | static void __init legacy_driver_register(void) {} | ||
946 | static void __exit legacy_driver_unregister(void) {} | ||
947 | #endif /* CONFIG_MPC832x_RDB */ | ||
948 | |||
697 | static int __init mpc83xx_spi_init(void) | 949 | static int __init mpc83xx_spi_init(void) |
698 | { | 950 | { |
699 | return platform_driver_probe(&mpc83xx_spi_driver, mpc83xx_spi_probe); | 951 | legacy_driver_register(); |
952 | return of_register_platform_driver(&of_mpc83xx_spi_driver); | ||
700 | } | 953 | } |
701 | 954 | ||
702 | static void __exit mpc83xx_spi_exit(void) | 955 | static void __exit mpc83xx_spi_exit(void) |
703 | { | 956 | { |
704 | platform_driver_unregister(&mpc83xx_spi_driver); | 957 | of_unregister_platform_driver(&of_mpc83xx_spi_driver); |
958 | legacy_driver_unregister(); | ||
705 | } | 959 | } |
706 | 960 | ||
707 | module_init(mpc83xx_spi_init); | 961 | module_init(mpc83xx_spi_init); |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 742a5bc44be..2a70563bbee 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/tty_flip.h> | 26 | #include <linux/tty_flip.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
29 | #include <linux/seq_file.h> | ||
29 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
30 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
31 | #include <linux/list.h> | 32 | #include <linux/list.h> |
@@ -421,57 +422,52 @@ static int serial_break(struct tty_struct *tty, int break_state) | |||
421 | return 0; | 422 | return 0; |
422 | } | 423 | } |
423 | 424 | ||
424 | static int serial_read_proc(char *page, char **start, off_t off, int count, | 425 | static int serial_proc_show(struct seq_file *m, void *v) |
425 | int *eof, void *data) | ||
426 | { | 426 | { |
427 | struct usb_serial *serial; | 427 | struct usb_serial *serial; |
428 | int length = 0; | ||
429 | int i; | 428 | int i; |
430 | off_t begin = 0; | ||
431 | char tmp[40]; | 429 | char tmp[40]; |
432 | 430 | ||
433 | dbg("%s", __func__); | 431 | dbg("%s", __func__); |
434 | length += sprintf(page, "usbserinfo:1.0 driver:2.0\n"); | 432 | seq_puts(m, "usbserinfo:1.0 driver:2.0\n"); |
435 | for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) { | 433 | for (i = 0; i < SERIAL_TTY_MINORS; ++i) { |
436 | serial = usb_serial_get_by_index(i); | 434 | serial = usb_serial_get_by_index(i); |
437 | if (serial == NULL) | 435 | if (serial == NULL) |
438 | continue; | 436 | continue; |
439 | 437 | ||
440 | length += sprintf(page+length, "%d:", i); | 438 | seq_printf(m, "%d:", i); |
441 | if (serial->type->driver.owner) | 439 | if (serial->type->driver.owner) |
442 | length += sprintf(page+length, " module:%s", | 440 | seq_printf(m, " module:%s", |
443 | module_name(serial->type->driver.owner)); | 441 | module_name(serial->type->driver.owner)); |
444 | length += sprintf(page+length, " name:\"%s\"", | 442 | seq_printf(m, " name:\"%s\"", |
445 | serial->type->description); | 443 | serial->type->description); |
446 | length += sprintf(page+length, " vendor:%04x product:%04x", | 444 | seq_printf(m, " vendor:%04x product:%04x", |
447 | le16_to_cpu(serial->dev->descriptor.idVendor), | 445 | le16_to_cpu(serial->dev->descriptor.idVendor), |
448 | le16_to_cpu(serial->dev->descriptor.idProduct)); | 446 | le16_to_cpu(serial->dev->descriptor.idProduct)); |
449 | length += sprintf(page+length, " num_ports:%d", | 447 | seq_printf(m, " num_ports:%d", serial->num_ports); |
450 | serial->num_ports); | 448 | seq_printf(m, " port:%d", i - serial->minor + 1); |
451 | length += sprintf(page+length, " port:%d", | ||
452 | i - serial->minor + 1); | ||
453 | usb_make_path(serial->dev, tmp, sizeof(tmp)); | 449 | usb_make_path(serial->dev, tmp, sizeof(tmp)); |
454 | length += sprintf(page+length, " path:%s", tmp); | 450 | seq_printf(m, " path:%s", tmp); |
455 | 451 | ||
456 | length += sprintf(page+length, "\n"); | 452 | seq_putc(m, '\n'); |
457 | if ((length + begin) > (off + count)) { | ||
458 | usb_serial_put(serial); | ||
459 | goto done; | ||
460 | } | ||
461 | if ((length + begin) < off) { | ||
462 | begin += length; | ||
463 | length = 0; | ||
464 | } | ||
465 | usb_serial_put(serial); | 453 | usb_serial_put(serial); |
466 | } | 454 | } |
467 | *eof = 1; | 455 | return 0; |
468 | done: | ||
469 | if (off >= (length + begin)) | ||
470 | return 0; | ||
471 | *start = page + (off-begin); | ||
472 | return (count < begin+length-off) ? count : begin+length-off; | ||
473 | } | 456 | } |
474 | 457 | ||
458 | static int serial_proc_open(struct inode *inode, struct file *file) | ||
459 | { | ||
460 | return single_open(file, serial_proc_show, NULL); | ||
461 | } | ||
462 | |||
463 | static const struct file_operations serial_proc_fops = { | ||
464 | .owner = THIS_MODULE, | ||
465 | .open = serial_proc_open, | ||
466 | .read = seq_read, | ||
467 | .llseek = seq_lseek, | ||
468 | .release = single_release, | ||
469 | }; | ||
470 | |||
475 | static int serial_tiocmget(struct tty_struct *tty, struct file *file) | 471 | static int serial_tiocmget(struct tty_struct *tty, struct file *file) |
476 | { | 472 | { |
477 | struct usb_serial_port *port = tty->driver_data; | 473 | struct usb_serial_port *port = tty->driver_data; |
@@ -1113,9 +1109,9 @@ static const struct tty_operations serial_ops = { | |||
1113 | .unthrottle = serial_unthrottle, | 1109 | .unthrottle = serial_unthrottle, |
1114 | .break_ctl = serial_break, | 1110 | .break_ctl = serial_break, |
1115 | .chars_in_buffer = serial_chars_in_buffer, | 1111 | .chars_in_buffer = serial_chars_in_buffer, |
1116 | .read_proc = serial_read_proc, | ||
1117 | .tiocmget = serial_tiocmget, | 1112 | .tiocmget = serial_tiocmget, |
1118 | .tiocmset = serial_tiocmset, | 1113 | .tiocmset = serial_tiocmset, |
1114 | .proc_fops = &serial_proc_fops, | ||
1119 | }; | 1115 | }; |
1120 | 1116 | ||
1121 | struct tty_driver *usb_serial_tty_driver; | 1117 | struct tty_driver *usb_serial_tty_driver; |
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index 7f907fb23b8..0b17824b0eb 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c | |||
@@ -471,9 +471,11 @@ int __init mc68x328fb_init(void) | |||
471 | fb_info.pseudo_palette = &mc68x328fb_pseudo_palette; | 471 | fb_info.pseudo_palette = &mc68x328fb_pseudo_palette; |
472 | fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; | 472 | fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; |
473 | 473 | ||
474 | fb_alloc_cmap(&fb_info.cmap, 256, 0); | 474 | if (fb_alloc_cmap(&fb_info.cmap, 256, 0)) |
475 | return -ENOMEM; | ||
475 | 476 | ||
476 | if (register_framebuffer(&fb_info) < 0) { | 477 | if (register_framebuffer(&fb_info) < 0) { |
478 | fb_dealloc_cmap(&fb_info.cmap); | ||
477 | return -EINVAL; | 479 | return -EINVAL; |
478 | } | 480 | } |
479 | 481 | ||
@@ -494,6 +496,7 @@ module_init(mc68x328fb_init); | |||
494 | static void __exit mc68x328fb_cleanup(void) | 496 | static void __exit mc68x328fb_cleanup(void) |
495 | { | 497 | { |
496 | unregister_framebuffer(&fb_info); | 498 | unregister_framebuffer(&fb_info); |
499 | fb_dealloc_cmap(&fb_info.cmap); | ||
497 | } | 500 | } |
498 | 501 | ||
499 | module_exit(mc68x328fb_cleanup); | 502 | module_exit(mc68x328fb_cleanup); |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 41c27a44bd8..ffe2f2796e2 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -1597,32 +1597,8 @@ config FB_VT8623 | |||
1597 | Driver for CastleRock integrated graphics core in the | 1597 | Driver for CastleRock integrated graphics core in the |
1598 | VIA VT8623 [Apollo CLE266] chipset. | 1598 | VIA VT8623 [Apollo CLE266] chipset. |
1599 | 1599 | ||
1600 | config FB_CYBLA | ||
1601 | tristate "Cyberblade/i1 support" | ||
1602 | depends on FB && PCI && X86_32 && !64BIT | ||
1603 | select FB_CFB_IMAGEBLIT | ||
1604 | ---help--- | ||
1605 | This driver is supposed to support the Trident Cyberblade/i1 | ||
1606 | graphics core integrated in the VIA VT8601A North Bridge, | ||
1607 | also known as VIA Apollo PLE133. | ||
1608 | |||
1609 | Status: | ||
1610 | - Developed, tested and working on EPIA 5000 and EPIA 800. | ||
1611 | - Does work reliable on all systems with CRT/LCD connected to | ||
1612 | normal VGA ports. | ||
1613 | - Should work on systems that do use the internal LCD port, but | ||
1614 | this is absolutely not tested. | ||
1615 | |||
1616 | Character imageblit, copyarea and rectangle fill are hw accelerated, | ||
1617 | ypan scrolling is used by default. | ||
1618 | |||
1619 | Please do read <file:Documentation/fb/cyblafb/*>. | ||
1620 | |||
1621 | To compile this driver as a module, choose M here: the | ||
1622 | module will be called cyblafb. | ||
1623 | |||
1624 | config FB_TRIDENT | 1600 | config FB_TRIDENT |
1625 | tristate "Trident support" | 1601 | tristate "Trident/CyberXXX/CyberBlade support" |
1626 | depends on FB && PCI | 1602 | depends on FB && PCI |
1627 | select FB_CFB_FILLRECT | 1603 | select FB_CFB_FILLRECT |
1628 | select FB_CFB_COPYAREA | 1604 | select FB_CFB_COPYAREA |
@@ -1633,21 +1609,14 @@ config FB_TRIDENT | |||
1633 | and Blade XP. | 1609 | and Blade XP. |
1634 | There are also integrated versions of these chips called CyberXXXX, | 1610 | There are also integrated versions of these chips called CyberXXXX, |
1635 | CyberImage or CyberBlade. These chips are mostly found in laptops | 1611 | CyberImage or CyberBlade. These chips are mostly found in laptops |
1636 | but also on some motherboards. For more information, read | 1612 | but also on some motherboards including early VIA EPIA motherboards. |
1637 | <file:Documentation/fb/tridentfb.txt> | 1613 | For more information, read <file:Documentation/fb/tridentfb.txt> |
1638 | 1614 | ||
1639 | Say Y if you have such a graphics board. | 1615 | Say Y if you have such a graphics board. |
1640 | 1616 | ||
1641 | To compile this driver as a module, choose M here: the | 1617 | To compile this driver as a module, choose M here: the |
1642 | module will be called tridentfb. | 1618 | module will be called tridentfb. |
1643 | 1619 | ||
1644 | config FB_TRIDENT_ACCEL | ||
1645 | bool "Trident Acceleration functions (EXPERIMENTAL)" | ||
1646 | depends on FB_TRIDENT && EXPERIMENTAL | ||
1647 | ---help--- | ||
1648 | This will compile the Trident frame buffer device with | ||
1649 | acceleration functions. | ||
1650 | |||
1651 | config FB_ARK | 1620 | config FB_ARK |
1652 | tristate "ARK 2000PV support" | 1621 | tristate "ARK 2000PV support" |
1653 | depends on FB && PCI | 1622 | depends on FB && PCI |
@@ -1920,6 +1889,30 @@ config FB_TMIO_ACCELL | |||
1920 | depends on FB_TMIO | 1889 | depends on FB_TMIO |
1921 | default y | 1890 | default y |
1922 | 1891 | ||
1892 | config FB_S3C | ||
1893 | tristate "Samsung S3C framebuffer support" | ||
1894 | depends on FB && ARCH_S3C64XX | ||
1895 | select FB_CFB_FILLRECT | ||
1896 | select FB_CFB_COPYAREA | ||
1897 | select FB_CFB_IMAGEBLIT | ||
1898 | ---help--- | ||
1899 | Frame buffer driver for the built-in FB controller in the Samsung | ||
1900 | SoC line from the S3C2443 onwards, including the S3C2416, S3C2450, | ||
1901 | and the S3C64XX series such as the S3C6400 and S3C6410. | ||
1902 | |||
1903 | These chips all have the same basic framebuffer design with the | ||
1904 | actual capabilities depending on the chip. For instance the S3C6400 | ||
1905 | and S3C6410 support 4 hardware windows whereas the S3C24XX series | ||
1906 | currently only have two. | ||
1907 | |||
1908 | Currently the support is only for the S3C6400 and S3C6410 SoCs. | ||
1909 | |||
1910 | config FB_S3C_DEBUG_REGWRITE | ||
1911 | bool "Debug register writes" | ||
1912 | depends on FB_S3C | ||
1913 | ---help--- | ||
1914 | Show all register writes via printk(KERN_DEBUG) | ||
1915 | |||
1923 | config FB_S3C2410 | 1916 | config FB_S3C2410 |
1924 | tristate "S3C2410 LCD framebuffer support" | 1917 | tristate "S3C2410 LCD framebuffer support" |
1925 | depends on FB && ARCH_S3C2410 | 1918 | depends on FB && ARCH_S3C2410 |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index bb265eca7d5..0dbd6c68d76 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -76,6 +76,7 @@ obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \ | |||
76 | atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o | 76 | atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o |
77 | obj-$(CONFIG_FB_MAC) += macfb.o | 77 | obj-$(CONFIG_FB_MAC) += macfb.o |
78 | obj-$(CONFIG_FB_HECUBA) += hecubafb.o | 78 | obj-$(CONFIG_FB_HECUBA) += hecubafb.o |
79 | obj-$(CONFIG_FB_N411) += n411.o | ||
79 | obj-$(CONFIG_FB_HGA) += hgafb.o | 80 | obj-$(CONFIG_FB_HGA) += hgafb.o |
80 | obj-$(CONFIG_FB_XVR500) += sunxvr500.o | 81 | obj-$(CONFIG_FB_XVR500) += sunxvr500.o |
81 | obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o | 82 | obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o |
@@ -110,6 +111,7 @@ obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o | |||
110 | obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o | 111 | obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o |
111 | obj-$(CONFIG_FB_SH7760) += sh7760fb.o | 112 | obj-$(CONFIG_FB_SH7760) += sh7760fb.o |
112 | obj-$(CONFIG_FB_IMX) += imxfb.o | 113 | obj-$(CONFIG_FB_IMX) += imxfb.o |
114 | obj-$(CONFIG_FB_S3C) += s3c-fb.o | ||
113 | obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o | 115 | obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o |
114 | obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o | 116 | obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o |
115 | obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o | 117 | obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o |
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 4e046fed138..61050ab1412 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c | |||
@@ -408,7 +408,9 @@ static int clcdfb_register(struct clcd_fb *fb) | |||
408 | /* | 408 | /* |
409 | * Allocate colourmap. | 409 | * Allocate colourmap. |
410 | */ | 410 | */ |
411 | fb_alloc_cmap(&fb->fb.cmap, 256, 0); | 411 | ret = fb_alloc_cmap(&fb->fb.cmap, 256, 0); |
412 | if (ret) | ||
413 | goto unmap; | ||
412 | 414 | ||
413 | /* | 415 | /* |
414 | * Ensure interrupts are disabled. | 416 | * Ensure interrupts are disabled. |
@@ -426,6 +428,8 @@ static int clcdfb_register(struct clcd_fb *fb) | |||
426 | 428 | ||
427 | printk(KERN_ERR "CLCD: cannot register framebuffer (%d)\n", ret); | 429 | printk(KERN_ERR "CLCD: cannot register framebuffer (%d)\n", ret); |
428 | 430 | ||
431 | fb_dealloc_cmap(&fb->fb.cmap); | ||
432 | unmap: | ||
429 | iounmap(fb->regs); | 433 | iounmap(fb->regs); |
430 | free_clk: | 434 | free_clk: |
431 | clk_put(fb->clk); | 435 | clk_put(fb->clk); |
@@ -485,6 +489,8 @@ static int clcdfb_remove(struct amba_device *dev) | |||
485 | 489 | ||
486 | clcdfb_disable(fb); | 490 | clcdfb_disable(fb); |
487 | unregister_framebuffer(&fb->fb); | 491 | unregister_framebuffer(&fb->fb); |
492 | if (fb->fb.cmap.len) | ||
493 | fb_dealloc_cmap(&fb->fb.cmap); | ||
488 | iounmap(fb->regs); | 494 | iounmap(fb->regs); |
489 | clk_put(fb->clk); | 495 | clk_put(fb->clk); |
490 | 496 | ||
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 100f2366146..82bedd7f778 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c | |||
@@ -2437,7 +2437,9 @@ default_chipset: | |||
2437 | goto amifb_error; | 2437 | goto amifb_error; |
2438 | } | 2438 | } |
2439 | 2439 | ||
2440 | fb_alloc_cmap(&fb_info.cmap, 1<<fb_info.var.bits_per_pixel, 0); | 2440 | err = fb_alloc_cmap(&fb_info.cmap, 1<<fb_info.var.bits_per_pixel, 0); |
2441 | if (err) | ||
2442 | goto amifb_error; | ||
2441 | 2443 | ||
2442 | if (register_framebuffer(&fb_info) < 0) { | 2444 | if (register_framebuffer(&fb_info) < 0) { |
2443 | err = -EINVAL; | 2445 | err = -EINVAL; |
@@ -2456,7 +2458,8 @@ amifb_error: | |||
2456 | 2458 | ||
2457 | static void amifb_deinit(void) | 2459 | static void amifb_deinit(void) |
2458 | { | 2460 | { |
2459 | fb_dealloc_cmap(&fb_info.cmap); | 2461 | if (fb_info.cmap.len) |
2462 | fb_dealloc_cmap(&fb_info.cmap); | ||
2460 | chipfree(); | 2463 | chipfree(); |
2461 | if (videomemory) | 2464 | if (videomemory) |
2462 | iounmap((void*)videomemory); | 2465 | iounmap((void*)videomemory); |
diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c index 314d18694b6..d583bea608f 100644 --- a/drivers/video/arkfb.c +++ b/drivers/video/arkfb.c | |||
@@ -470,7 +470,7 @@ static void ark_dac_read_regs(void *data, u8 *code, int count) | |||
470 | 470 | ||
471 | while (count != 0) | 471 | while (count != 0) |
472 | { | 472 | { |
473 | vga_wseq(NULL, 0x1C, regval | (code[0] & 4) ? 0x80 : 0); | 473 | vga_wseq(NULL, 0x1C, regval | (code[0] & 4 ? 0x80 : 0)); |
474 | code[1] = vga_r(NULL, dac_regs[code[0] & 3]); | 474 | code[1] = vga_r(NULL, dac_regs[code[0] & 3]); |
475 | count--; | 475 | count--; |
476 | code += 2; | 476 | code += 2; |
@@ -485,7 +485,7 @@ static void ark_dac_write_regs(void *data, u8 *code, int count) | |||
485 | 485 | ||
486 | while (count != 0) | 486 | while (count != 0) |
487 | { | 487 | { |
488 | vga_wseq(NULL, 0x1C, regval | (code[0] & 4) ? 0x80 : 0); | 488 | vga_wseq(NULL, 0x1C, regval | (code[0] & 4 ? 0x80 : 0)); |
489 | vga_w(NULL, dac_regs[code[0] & 3], code[1]); | 489 | vga_w(NULL, dac_regs[code[0] & 3], code[1]); |
490 | count--; | 490 | count--; |
491 | code += 2; | 491 | code += 2; |
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index 1fd22f460b0..1a1f946d8fe 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c | |||
@@ -505,19 +505,27 @@ static struct fb_var_screeninfo asiliantfb_var __devinitdata = { | |||
505 | .vsync_len = 2, | 505 | .vsync_len = 2, |
506 | }; | 506 | }; |
507 | 507 | ||
508 | static void __devinit init_asiliant(struct fb_info *p, unsigned long addr) | 508 | static int __devinit init_asiliant(struct fb_info *p, unsigned long addr) |
509 | { | 509 | { |
510 | int err; | ||
511 | |||
510 | p->fix = asiliantfb_fix; | 512 | p->fix = asiliantfb_fix; |
511 | p->fix.smem_start = addr; | 513 | p->fix.smem_start = addr; |
512 | p->var = asiliantfb_var; | 514 | p->var = asiliantfb_var; |
513 | p->fbops = &asiliantfb_ops; | 515 | p->fbops = &asiliantfb_ops; |
514 | p->flags = FBINFO_DEFAULT; | 516 | p->flags = FBINFO_DEFAULT; |
515 | 517 | ||
516 | fb_alloc_cmap(&p->cmap, 256, 0); | 518 | err = fb_alloc_cmap(&p->cmap, 256, 0); |
519 | if (err) { | ||
520 | printk(KERN_ERR "C&T 69000 fb failed to alloc cmap memory\n"); | ||
521 | return err; | ||
522 | } | ||
517 | 523 | ||
518 | if (register_framebuffer(p) < 0) { | 524 | err = register_framebuffer(p); |
525 | if (err < 0) { | ||
519 | printk(KERN_ERR "C&T 69000 framebuffer failed to register\n"); | 526 | printk(KERN_ERR "C&T 69000 framebuffer failed to register\n"); |
520 | return; | 527 | fb_dealloc_cmap(&p->cmap); |
528 | return err; | ||
521 | } | 529 | } |
522 | 530 | ||
523 | printk(KERN_INFO "fb%d: Asiliant 69000 frame buffer (%dK RAM detected)\n", | 531 | printk(KERN_INFO "fb%d: Asiliant 69000 frame buffer (%dK RAM detected)\n", |
@@ -532,6 +540,7 @@ asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) | |||
532 | { | 540 | { |
533 | unsigned long addr, size; | 541 | unsigned long addr, size; |
534 | struct fb_info *p; | 542 | struct fb_info *p; |
543 | int err; | ||
535 | 544 | ||
536 | if ((dp->resource[0].flags & IORESOURCE_MEM) == 0) | 545 | if ((dp->resource[0].flags & IORESOURCE_MEM) == 0) |
537 | return -ENODEV; | 546 | return -ENODEV; |
@@ -560,7 +569,13 @@ asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) | |||
560 | pci_write_config_dword(dp, 4, 0x02800083); | 569 | pci_write_config_dword(dp, 4, 0x02800083); |
561 | writeb(3, p->screen_base + 0x400784); | 570 | writeb(3, p->screen_base + 0x400784); |
562 | 571 | ||
563 | init_asiliant(p, addr); | 572 | err = init_asiliant(p, addr); |
573 | if (err) { | ||
574 | iounmap(p->screen_base); | ||
575 | release_mem_region(addr, size); | ||
576 | framebuffer_release(p); | ||
577 | return err; | ||
578 | } | ||
564 | 579 | ||
565 | pci_set_drvdata(dp, p); | 580 | pci_set_drvdata(dp, p); |
566 | return 0; | 581 | return 0; |
@@ -571,6 +586,7 @@ static void __devexit asiliantfb_remove(struct pci_dev *dp) | |||
571 | struct fb_info *p = pci_get_drvdata(dp); | 586 | struct fb_info *p = pci_get_drvdata(dp); |
572 | 587 | ||
573 | unregister_framebuffer(p); | 588 | unregister_framebuffer(p); |
589 | fb_dealloc_cmap(&p->cmap); | ||
574 | iounmap(p->screen_base); | 590 | iounmap(p->screen_base); |
575 | release_mem_region(pci_resource_start(dp, 0), pci_resource_len(dp, 0)); | 591 | release_mem_region(pci_resource_start(dp, 0), pci_resource_len(dp, 0)); |
576 | pci_set_drvdata(dp, NULL); | 592 | pci_set_drvdata(dp, NULL); |
diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c index a8f60c33863..0cc9724e61a 100644 --- a/drivers/video/aty/mach64_accel.c +++ b/drivers/video/aty/mach64_accel.c | |||
@@ -39,7 +39,8 @@ void aty_reset_engine(const struct atyfb_par *par) | |||
39 | { | 39 | { |
40 | /* reset engine */ | 40 | /* reset engine */ |
41 | aty_st_le32(GEN_TEST_CNTL, | 41 | aty_st_le32(GEN_TEST_CNTL, |
42 | aty_ld_le32(GEN_TEST_CNTL, par) & ~GUI_ENGINE_ENABLE, par); | 42 | aty_ld_le32(GEN_TEST_CNTL, par) & |
43 | ~(GUI_ENGINE_ENABLE | HWCURSOR_ENABLE), par); | ||
43 | /* enable engine */ | 44 | /* enable engine */ |
44 | aty_st_le32(GEN_TEST_CNTL, | 45 | aty_st_le32(GEN_TEST_CNTL, |
45 | aty_ld_le32(GEN_TEST_CNTL, par) | GUI_ENGINE_ENABLE, par); | 46 | aty_ld_le32(GEN_TEST_CNTL, par) | GUI_ENGINE_ENABLE, par); |
diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c index faf95da8fcb..04c710804bb 100644 --- a/drivers/video/aty/mach64_cursor.c +++ b/drivers/video/aty/mach64_cursor.c | |||
@@ -77,9 +77,13 @@ static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
77 | if (par->asleep) | 77 | if (par->asleep) |
78 | return -EPERM; | 78 | return -EPERM; |
79 | 79 | ||
80 | /* Hide cursor */ | ||
81 | wait_for_fifo(1, par); | 80 | wait_for_fifo(1, par); |
82 | aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par) & ~HWCURSOR_ENABLE, par); | 81 | if (cursor->enable) |
82 | aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par) | ||
83 | | HWCURSOR_ENABLE, par); | ||
84 | else | ||
85 | aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par) | ||
86 | & ~HWCURSOR_ENABLE, par); | ||
83 | 87 | ||
84 | /* set position */ | 88 | /* set position */ |
85 | if (cursor->set & FB_CUR_SETPOS) { | 89 | if (cursor->set & FB_CUR_SETPOS) { |
@@ -109,7 +113,7 @@ static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
109 | y<<=1; | 113 | y<<=1; |
110 | h<<=1; | 114 | h<<=1; |
111 | } | 115 | } |
112 | wait_for_fifo(4, par); | 116 | wait_for_fifo(3, par); |
113 | aty_st_le32(CUR_OFFSET, (info->fix.smem_len >> 3) + (yoff << 1), par); | 117 | aty_st_le32(CUR_OFFSET, (info->fix.smem_len >> 3) + (yoff << 1), par); |
114 | aty_st_le32(CUR_HORZ_VERT_OFF, | 118 | aty_st_le32(CUR_HORZ_VERT_OFF, |
115 | ((u32) (64 - h + yoff) << 16) | xoff, par); | 119 | ((u32) (64 - h + yoff) << 16) | xoff, par); |
@@ -177,11 +181,6 @@ static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
177 | } | 181 | } |
178 | } | 182 | } |
179 | 183 | ||
180 | if (cursor->enable) { | ||
181 | wait_for_fifo(1, par); | ||
182 | aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par) | ||
183 | | HWCURSOR_ENABLE, par); | ||
184 | } | ||
185 | return 0; | 184 | return 0; |
186 | } | 185 | } |
187 | 186 | ||
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 1de0c003246..97a1f095f32 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c | |||
@@ -89,6 +89,9 @@ static struct radeon_device_id radeon_workaround_list[] = { | |||
89 | BUGFIX("Acer Aspire 2010", | 89 | BUGFIX("Acer Aspire 2010", |
90 | PCI_VENDOR_ID_AI, 0x0061, | 90 | PCI_VENDOR_ID_AI, 0x0061, |
91 | radeon_pm_off, radeon_reinitialize_M10), | 91 | radeon_pm_off, radeon_reinitialize_M10), |
92 | BUGFIX("Acer Travelmate 290D/292LMi", | ||
93 | PCI_VENDOR_ID_AI, 0x005a, | ||
94 | radeon_pm_off, radeon_reinitialize_M10), | ||
92 | { .ident = NULL } | 95 | { .ident = NULL } |
93 | }; | 96 | }; |
94 | 97 | ||
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 157057c79ca..dd37cbcaf8c 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c | |||
@@ -35,6 +35,8 @@ static int fb_notifier_callback(struct notifier_block *self, | |||
35 | return 0; | 35 | return 0; |
36 | 36 | ||
37 | bd = container_of(self, struct backlight_device, fb_notif); | 37 | bd = container_of(self, struct backlight_device, fb_notif); |
38 | if (!lock_fb_info(evdata->info)) | ||
39 | return -ENODEV; | ||
38 | mutex_lock(&bd->ops_lock); | 40 | mutex_lock(&bd->ops_lock); |
39 | if (bd->ops) | 41 | if (bd->ops) |
40 | if (!bd->ops->check_fb || | 42 | if (!bd->ops->check_fb || |
@@ -47,6 +49,7 @@ static int fb_notifier_callback(struct notifier_block *self, | |||
47 | backlight_update_status(bd); | 49 | backlight_update_status(bd); |
48 | } | 50 | } |
49 | mutex_unlock(&bd->ops_lock); | 51 | mutex_unlock(&bd->ops_lock); |
52 | unlock_fb_info(evdata->info); | ||
50 | return 0; | 53 | return 0; |
51 | } | 54 | } |
52 | 55 | ||
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index b6449470106..0bb13df0fa8 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c | |||
@@ -40,6 +40,8 @@ static int fb_notifier_callback(struct notifier_block *self, | |||
40 | if (!ld->ops) | 40 | if (!ld->ops) |
41 | return 0; | 41 | return 0; |
42 | 42 | ||
43 | if (!lock_fb_info(evdata->info)) | ||
44 | return -ENODEV; | ||
43 | mutex_lock(&ld->ops_lock); | 45 | mutex_lock(&ld->ops_lock); |
44 | if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) { | 46 | if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) { |
45 | if (event == FB_EVENT_BLANK) { | 47 | if (event == FB_EVENT_BLANK) { |
@@ -51,6 +53,7 @@ static int fb_notifier_callback(struct notifier_block *self, | |||
51 | } | 53 | } |
52 | } | 54 | } |
53 | mutex_unlock(&ld->ops_lock); | 55 | mutex_unlock(&ld->ops_lock); |
56 | unlock_fb_info(evdata->info); | ||
54 | return 0; | 57 | return 0; |
55 | } | 58 | } |
56 | 59 | ||
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index a2aa6ddffbe..d42e385f091 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c | |||
@@ -34,8 +34,6 @@ | |||
34 | * | 34 | * |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #define CIRRUSFB_VERSION "2.0-pre2" | ||
38 | |||
39 | #include <linux/module.h> | 37 | #include <linux/module.h> |
40 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
41 | #include <linux/errno.h> | 39 | #include <linux/errno.h> |
@@ -72,20 +70,9 @@ | |||
72 | * | 70 | * |
73 | */ | 71 | */ |
74 | 72 | ||
75 | /* enable debug output? */ | ||
76 | /* #define CIRRUSFB_DEBUG 1 */ | ||
77 | |||
78 | /* disable runtime assertions? */ | 73 | /* disable runtime assertions? */ |
79 | /* #define CIRRUSFB_NDEBUG */ | 74 | /* #define CIRRUSFB_NDEBUG */ |
80 | 75 | ||
81 | /* debug output */ | ||
82 | #ifdef CIRRUSFB_DEBUG | ||
83 | #define DPRINTK(fmt, args...) \ | ||
84 | printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) | ||
85 | #else | ||
86 | #define DPRINTK(fmt, args...) | ||
87 | #endif | ||
88 | |||
89 | /* debugging assertions */ | 76 | /* debugging assertions */ |
90 | #ifndef CIRRUSFB_NDEBUG | 77 | #ifndef CIRRUSFB_NDEBUG |
91 | #define assert(expr) \ | 78 | #define assert(expr) \ |
@@ -108,14 +95,15 @@ | |||
108 | /* board types */ | 95 | /* board types */ |
109 | enum cirrus_board { | 96 | enum cirrus_board { |
110 | BT_NONE = 0, | 97 | BT_NONE = 0, |
111 | BT_SD64, | 98 | BT_SD64, /* GD5434 */ |
112 | BT_PICCOLO, | 99 | BT_PICCOLO, /* GD5426 */ |
113 | BT_PICASSO, | 100 | BT_PICASSO, /* GD5426 or GD5428 */ |
114 | BT_SPECTRUM, | 101 | BT_SPECTRUM, /* GD5426 or GD5428 */ |
115 | BT_PICASSO4, /* GD5446 */ | 102 | BT_PICASSO4, /* GD5446 */ |
116 | BT_ALPINE, /* GD543x/4x */ | 103 | BT_ALPINE, /* GD543x/4x */ |
117 | BT_GD5480, | 104 | BT_GD5480, |
118 | BT_LAGUNA, /* GD546x */ | 105 | BT_LAGUNA, /* GD5462/64 */ |
106 | BT_LAGUNAB, /* GD5465 */ | ||
119 | }; | 107 | }; |
120 | 108 | ||
121 | /* | 109 | /* |
@@ -150,15 +138,17 @@ static const struct cirrusfb_board_info_rec { | |||
150 | .maxclock = { | 138 | .maxclock = { |
151 | /* guess */ | 139 | /* guess */ |
152 | /* the SD64/P4 have a higher max. videoclock */ | 140 | /* the SD64/P4 have a higher max. videoclock */ |
153 | 140000, 140000, 140000, 140000, 140000, | 141 | 135100, 135100, 85500, 85500, 0 |
154 | }, | 142 | }, |
155 | .init_sr07 = true, | 143 | .init_sr07 = true, |
156 | .init_sr1f = true, | 144 | .init_sr1f = true, |
157 | .scrn_start_bit19 = true, | 145 | .scrn_start_bit19 = true, |
158 | .sr07 = 0xF0, | 146 | .sr07 = 0xF0, |
159 | .sr07_1bpp = 0xF0, | 147 | .sr07_1bpp = 0xF0, |
148 | .sr07_1bpp_mux = 0xF6, | ||
160 | .sr07_8bpp = 0xF1, | 149 | .sr07_8bpp = 0xF1, |
161 | .sr1f = 0x20 | 150 | .sr07_8bpp_mux = 0xF7, |
151 | .sr1f = 0x1E | ||
162 | }, | 152 | }, |
163 | [BT_PICCOLO] = { | 153 | [BT_PICCOLO] = { |
164 | .name = "CL Piccolo", | 154 | .name = "CL Piccolo", |
@@ -210,9 +200,11 @@ static const struct cirrusfb_board_info_rec { | |||
210 | .init_sr07 = true, | 200 | .init_sr07 = true, |
211 | .init_sr1f = false, | 201 | .init_sr1f = false, |
212 | .scrn_start_bit19 = true, | 202 | .scrn_start_bit19 = true, |
213 | .sr07 = 0x20, | 203 | .sr07 = 0xA0, |
214 | .sr07_1bpp = 0x20, | 204 | .sr07_1bpp = 0xA0, |
215 | .sr07_8bpp = 0x21, | 205 | .sr07_1bpp_mux = 0xA6, |
206 | .sr07_8bpp = 0xA1, | ||
207 | .sr07_8bpp_mux = 0xA7, | ||
216 | .sr1f = 0 | 208 | .sr1f = 0 |
217 | }, | 209 | }, |
218 | [BT_ALPINE] = { | 210 | [BT_ALPINE] = { |
@@ -225,8 +217,8 @@ static const struct cirrusfb_board_info_rec { | |||
225 | .init_sr1f = true, | 217 | .init_sr1f = true, |
226 | .scrn_start_bit19 = true, | 218 | .scrn_start_bit19 = true, |
227 | .sr07 = 0xA0, | 219 | .sr07 = 0xA0, |
228 | .sr07_1bpp = 0xA1, | 220 | .sr07_1bpp = 0xA0, |
229 | .sr07_1bpp_mux = 0xA7, | 221 | .sr07_1bpp_mux = 0xA6, |
230 | .sr07_8bpp = 0xA1, | 222 | .sr07_8bpp = 0xA1, |
231 | .sr07_8bpp_mux = 0xA7, | 223 | .sr07_8bpp_mux = 0xA7, |
232 | .sr1f = 0x1C | 224 | .sr1f = 0x1C |
@@ -247,8 +239,18 @@ static const struct cirrusfb_board_info_rec { | |||
247 | [BT_LAGUNA] = { | 239 | [BT_LAGUNA] = { |
248 | .name = "CL Laguna", | 240 | .name = "CL Laguna", |
249 | .maxclock = { | 241 | .maxclock = { |
250 | /* guess */ | 242 | /* taken from X11 code */ |
251 | 135100, 135100, 135100, 135100, 135100, | 243 | 170000, 170000, 170000, 170000, 135100, |
244 | }, | ||
245 | .init_sr07 = false, | ||
246 | .init_sr1f = false, | ||
247 | .scrn_start_bit19 = true, | ||
248 | }, | ||
249 | [BT_LAGUNAB] = { | ||
250 | .name = "CL Laguna AGP", | ||
251 | .maxclock = { | ||
252 | /* taken from X11 code */ | ||
253 | 170000, 250000, 170000, 170000, 135100, | ||
252 | }, | 254 | }, |
253 | .init_sr07 = false, | 255 | .init_sr07 = false, |
254 | .init_sr1f = false, | 256 | .init_sr1f = false, |
@@ -262,8 +264,8 @@ static const struct cirrusfb_board_info_rec { | |||
262 | 264 | ||
263 | static struct pci_device_id cirrusfb_pci_table[] = { | 265 | static struct pci_device_id cirrusfb_pci_table[] = { |
264 | CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE), | 266 | CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE), |
265 | CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE), | 267 | CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_SD64), |
266 | CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE), | 268 | CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_SD64), |
267 | CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */ | 269 | CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */ |
268 | CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE), | 270 | CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE), |
269 | CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE), | 271 | CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE), |
@@ -271,7 +273,7 @@ static struct pci_device_id cirrusfb_pci_table[] = { | |||
271 | CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */ | 273 | CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */ |
272 | CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */ | 274 | CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */ |
273 | CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */ | 275 | CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */ |
274 | CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA), /* CL Laguna 3DA*/ | 276 | CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNAB), /* CL Laguna 3DA*/ |
275 | { 0, } | 277 | { 0, } |
276 | }; | 278 | }; |
277 | MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table); | 279 | MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table); |
@@ -326,10 +328,6 @@ static const struct { | |||
326 | }; | 328 | }; |
327 | #endif /* CONFIG_ZORRO */ | 329 | #endif /* CONFIG_ZORRO */ |
328 | 330 | ||
329 | struct cirrusfb_regs { | ||
330 | int multiplexing; | ||
331 | }; | ||
332 | |||
333 | #ifdef CIRRUSFB_DEBUG | 331 | #ifdef CIRRUSFB_DEBUG |
334 | enum cirrusfb_dbg_reg_class { | 332 | enum cirrusfb_dbg_reg_class { |
335 | CRT, | 333 | CRT, |
@@ -340,10 +338,12 @@ enum cirrusfb_dbg_reg_class { | |||
340 | /* info about board */ | 338 | /* info about board */ |
341 | struct cirrusfb_info { | 339 | struct cirrusfb_info { |
342 | u8 __iomem *regbase; | 340 | u8 __iomem *regbase; |
341 | u8 __iomem *laguna_mmio; | ||
343 | enum cirrus_board btype; | 342 | enum cirrus_board btype; |
344 | unsigned char SFR; /* Shadow of special function register */ | 343 | unsigned char SFR; /* Shadow of special function register */ |
345 | 344 | ||
346 | struct cirrusfb_regs currentmode; | 345 | int multiplexing; |
346 | int doubleVCLK; | ||
347 | int blank_mode; | 347 | int blank_mode; |
348 | u32 pseudo_palette[16]; | 348 | u32 pseudo_palette[16]; |
349 | 349 | ||
@@ -357,43 +357,8 @@ static char *mode_option __devinitdata = "640x480@60"; | |||
357 | /**** BEGIN PROTOTYPES ******************************************************/ | 357 | /**** BEGIN PROTOTYPES ******************************************************/ |
358 | 358 | ||
359 | /*--- Interface used by the world ------------------------------------------*/ | 359 | /*--- Interface used by the world ------------------------------------------*/ |
360 | static int cirrusfb_init(void); | ||
361 | #ifndef MODULE | ||
362 | static int cirrusfb_setup(char *options); | ||
363 | #endif | ||
364 | |||
365 | static int cirrusfb_open(struct fb_info *info, int user); | ||
366 | static int cirrusfb_release(struct fb_info *info, int user); | ||
367 | static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
368 | unsigned blue, unsigned transp, | ||
369 | struct fb_info *info); | ||
370 | static int cirrusfb_check_var(struct fb_var_screeninfo *var, | ||
371 | struct fb_info *info); | ||
372 | static int cirrusfb_set_par(struct fb_info *info); | ||
373 | static int cirrusfb_pan_display(struct fb_var_screeninfo *var, | 360 | static int cirrusfb_pan_display(struct fb_var_screeninfo *var, |
374 | struct fb_info *info); | 361 | struct fb_info *info); |
375 | static int cirrusfb_blank(int blank_mode, struct fb_info *info); | ||
376 | static void cirrusfb_fillrect(struct fb_info *info, | ||
377 | const struct fb_fillrect *region); | ||
378 | static void cirrusfb_copyarea(struct fb_info *info, | ||
379 | const struct fb_copyarea *area); | ||
380 | static void cirrusfb_imageblit(struct fb_info *info, | ||
381 | const struct fb_image *image); | ||
382 | |||
383 | /* function table of the above functions */ | ||
384 | static struct fb_ops cirrusfb_ops = { | ||
385 | .owner = THIS_MODULE, | ||
386 | .fb_open = cirrusfb_open, | ||
387 | .fb_release = cirrusfb_release, | ||
388 | .fb_setcolreg = cirrusfb_setcolreg, | ||
389 | .fb_check_var = cirrusfb_check_var, | ||
390 | .fb_set_par = cirrusfb_set_par, | ||
391 | .fb_pan_display = cirrusfb_pan_display, | ||
392 | .fb_blank = cirrusfb_blank, | ||
393 | .fb_fillrect = cirrusfb_fillrect, | ||
394 | .fb_copyarea = cirrusfb_copyarea, | ||
395 | .fb_imageblit = cirrusfb_imageblit, | ||
396 | }; | ||
397 | 362 | ||
398 | /*--- Internal routines ----------------------------------------------------*/ | 363 | /*--- Internal routines ----------------------------------------------------*/ |
399 | static void init_vgachip(struct fb_info *info); | 364 | static void init_vgachip(struct fb_info *info); |
@@ -421,22 +386,27 @@ static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, | |||
421 | static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, | 386 | static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, |
422 | u_short x, u_short y, | 387 | u_short x, u_short y, |
423 | u_short width, u_short height, | 388 | u_short width, u_short height, |
424 | u_char color, u_short line_length); | 389 | u32 fg_color, u32 bg_color, |
390 | u_short line_length, u_char blitmode); | ||
425 | 391 | ||
426 | static void bestclock(long freq, int *nom, int *den, int *div); | 392 | static void bestclock(long freq, int *nom, int *den, int *div); |
427 | 393 | ||
428 | #ifdef CIRRUSFB_DEBUG | 394 | #ifdef CIRRUSFB_DEBUG |
429 | static void cirrusfb_dump(void); | 395 | static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase); |
430 | static void cirrusfb_dbg_reg_dump(caddr_t regbase); | 396 | static void cirrusfb_dbg_print_regs(struct fb_info *info, |
431 | static void cirrusfb_dbg_print_regs(caddr_t regbase, | 397 | caddr_t regbase, |
432 | enum cirrusfb_dbg_reg_class reg_class, ...); | 398 | enum cirrusfb_dbg_reg_class reg_class, ...); |
433 | static void cirrusfb_dbg_print_byte(const char *name, unsigned char val); | ||
434 | #endif /* CIRRUSFB_DEBUG */ | 399 | #endif /* CIRRUSFB_DEBUG */ |
435 | 400 | ||
436 | /*** END PROTOTYPES ********************************************************/ | 401 | /*** END PROTOTYPES ********************************************************/ |
437 | /*****************************************************************************/ | 402 | /*****************************************************************************/ |
438 | /*** BEGIN Interface Used by the World ***************************************/ | 403 | /*** BEGIN Interface Used by the World ***************************************/ |
439 | 404 | ||
405 | static inline int is_laguna(const struct cirrusfb_info *cinfo) | ||
406 | { | ||
407 | return cinfo->btype == BT_LAGUNA || cinfo->btype == BT_LAGUNAB; | ||
408 | } | ||
409 | |||
440 | static int opencount; | 410 | static int opencount; |
441 | 411 | ||
442 | /*--- Open /dev/fbx ---------------------------------------------------------*/ | 412 | /*--- Open /dev/fbx ---------------------------------------------------------*/ |
@@ -460,85 +430,94 @@ static int cirrusfb_release(struct fb_info *info, int user) | |||
460 | /**** BEGIN Hardware specific Routines **************************************/ | 430 | /**** BEGIN Hardware specific Routines **************************************/ |
461 | 431 | ||
462 | /* Check if the MCLK is not a better clock source */ | 432 | /* Check if the MCLK is not a better clock source */ |
463 | static int cirrusfb_check_mclk(struct cirrusfb_info *cinfo, long freq) | 433 | static int cirrusfb_check_mclk(struct fb_info *info, long freq) |
464 | { | 434 | { |
435 | struct cirrusfb_info *cinfo = info->par; | ||
465 | long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f; | 436 | long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f; |
466 | 437 | ||
467 | /* Read MCLK value */ | 438 | /* Read MCLK value */ |
468 | mclk = (14318 * mclk) >> 3; | 439 | mclk = (14318 * mclk) >> 3; |
469 | DPRINTK("Read MCLK of %ld kHz\n", mclk); | 440 | dev_dbg(info->device, "Read MCLK of %ld kHz\n", mclk); |
470 | 441 | ||
471 | /* Determine if we should use MCLK instead of VCLK, and if so, what we | 442 | /* Determine if we should use MCLK instead of VCLK, and if so, what we |
472 | * should divide it by to get VCLK | 443 | * should divide it by to get VCLK |
473 | */ | 444 | */ |
474 | 445 | ||
475 | if (abs(freq - mclk) < 250) { | 446 | if (abs(freq - mclk) < 250) { |
476 | DPRINTK("Using VCLK = MCLK\n"); | 447 | dev_dbg(info->device, "Using VCLK = MCLK\n"); |
477 | return 1; | 448 | return 1; |
478 | } else if (abs(freq - (mclk / 2)) < 250) { | 449 | } else if (abs(freq - (mclk / 2)) < 250) { |
479 | DPRINTK("Using VCLK = MCLK/2\n"); | 450 | dev_dbg(info->device, "Using VCLK = MCLK/2\n"); |
480 | return 2; | 451 | return 2; |
481 | } | 452 | } |
482 | 453 | ||
483 | return 0; | 454 | return 0; |
484 | } | 455 | } |
485 | 456 | ||
486 | static int cirrusfb_check_var(struct fb_var_screeninfo *var, | 457 | static int cirrusfb_check_pixclock(const struct fb_var_screeninfo *var, |
487 | struct fb_info *info) | 458 | struct fb_info *info) |
488 | { | 459 | { |
489 | int yres; | 460 | long freq; |
490 | /* memory size in pixels */ | 461 | long maxclock; |
491 | unsigned pixels = info->screen_size * 8 / var->bits_per_pixel; | 462 | struct cirrusfb_info *cinfo = info->par; |
463 | unsigned maxclockidx = var->bits_per_pixel >> 3; | ||
492 | 464 | ||
493 | switch (var->bits_per_pixel) { | 465 | /* convert from ps to kHz */ |
494 | case 1: | 466 | freq = PICOS2KHZ(var->pixclock); |
495 | pixels /= 4; | ||
496 | break; /* 8 pixel per byte, only 1/4th of mem usable */ | ||
497 | case 8: | ||
498 | case 16: | ||
499 | case 32: | ||
500 | break; /* 1 pixel == 1 byte */ | ||
501 | default: | ||
502 | printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..." | ||
503 | "color depth not supported.\n", | ||
504 | var->xres, var->yres, var->bits_per_pixel); | ||
505 | DPRINTK("EXIT - EINVAL error\n"); | ||
506 | return -EINVAL; | ||
507 | } | ||
508 | 467 | ||
509 | if (var->xres_virtual < var->xres) | 468 | dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq); |
510 | var->xres_virtual = var->xres; | ||
511 | /* use highest possible virtual resolution */ | ||
512 | if (var->yres_virtual == -1) { | ||
513 | var->yres_virtual = pixels / var->xres_virtual; | ||
514 | 469 | ||
515 | printk(KERN_INFO "cirrusfb: virtual resolution set to " | 470 | maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx]; |
516 | "maximum of %dx%d\n", var->xres_virtual, | 471 | cinfo->multiplexing = 0; |
517 | var->yres_virtual); | ||
518 | } | ||
519 | if (var->yres_virtual < var->yres) | ||
520 | var->yres_virtual = var->yres; | ||
521 | 472 | ||
522 | if (var->xres_virtual * var->yres_virtual > pixels) { | 473 | /* If the frequency is greater than we can support, we might be able |
523 | printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected... " | 474 | * to use multiplexing for the video mode */ |
524 | "virtual resolution too high to fit into video memory!\n", | 475 | if (freq > maxclock) { |
525 | var->xres_virtual, var->yres_virtual, | 476 | dev_err(info->device, |
526 | var->bits_per_pixel); | 477 | "Frequency greater than maxclock (%ld kHz)\n", |
527 | DPRINTK("EXIT - EINVAL error\n"); | 478 | maxclock); |
528 | return -EINVAL; | 479 | return -EINVAL; |
529 | } | 480 | } |
481 | /* | ||
482 | * Additional constraint: 8bpp uses DAC clock doubling to allow maximum | ||
483 | * pixel clock | ||
484 | */ | ||
485 | if (var->bits_per_pixel == 8) { | ||
486 | switch (cinfo->btype) { | ||
487 | case BT_ALPINE: | ||
488 | case BT_SD64: | ||
489 | case BT_PICASSO4: | ||
490 | if (freq > 85500) | ||
491 | cinfo->multiplexing = 1; | ||
492 | break; | ||
493 | case BT_GD5480: | ||
494 | if (freq > 135100) | ||
495 | cinfo->multiplexing = 1; | ||
496 | break; | ||
530 | 497 | ||
498 | default: | ||
499 | break; | ||
500 | } | ||
501 | } | ||
531 | 502 | ||
532 | if (var->xoffset < 0) | 503 | /* If we have a 1MB 5434, we need to put ourselves in a mode where |
533 | var->xoffset = 0; | 504 | * the VCLK is double the pixel clock. */ |
534 | if (var->yoffset < 0) | 505 | cinfo->doubleVCLK = 0; |
535 | var->yoffset = 0; | 506 | if (cinfo->btype == BT_SD64 && info->fix.smem_len <= MB_ && |
507 | var->bits_per_pixel == 16) { | ||
508 | cinfo->doubleVCLK = 1; | ||
509 | } | ||
536 | 510 | ||
537 | /* truncate xoffset and yoffset to maximum if too high */ | 511 | return 0; |
538 | if (var->xoffset > var->xres_virtual - var->xres) | 512 | } |
539 | var->xoffset = var->xres_virtual - var->xres - 1; | 513 | |
540 | if (var->yoffset > var->yres_virtual - var->yres) | 514 | static int cirrusfb_check_var(struct fb_var_screeninfo *var, |
541 | var->yoffset = var->yres_virtual - var->yres - 1; | 515 | struct fb_info *info) |
516 | { | ||
517 | int yres; | ||
518 | /* memory size in pixels */ | ||
519 | unsigned pixels = info->screen_size * 8 / var->bits_per_pixel; | ||
520 | struct cirrusfb_info *cinfo = info->par; | ||
542 | 521 | ||
543 | switch (var->bits_per_pixel) { | 522 | switch (var->bits_per_pixel) { |
544 | case 1: | 523 | case 1: |
@@ -550,7 +529,7 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, | |||
550 | 529 | ||
551 | case 8: | 530 | case 8: |
552 | var->red.offset = 0; | 531 | var->red.offset = 0; |
553 | var->red.length = 6; | 532 | var->red.length = 8; |
554 | var->green = var->red; | 533 | var->green = var->red; |
555 | var->blue = var->red; | 534 | var->blue = var->red; |
556 | break; | 535 | break; |
@@ -561,20 +540,20 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, | |||
561 | var->green.offset = -3; | 540 | var->green.offset = -3; |
562 | var->blue.offset = 8; | 541 | var->blue.offset = 8; |
563 | } else { | 542 | } else { |
564 | var->red.offset = 10; | 543 | var->red.offset = 11; |
565 | var->green.offset = 5; | 544 | var->green.offset = 5; |
566 | var->blue.offset = 0; | 545 | var->blue.offset = 0; |
567 | } | 546 | } |
568 | var->red.length = 5; | 547 | var->red.length = 5; |
569 | var->green.length = 5; | 548 | var->green.length = 6; |
570 | var->blue.length = 5; | 549 | var->blue.length = 5; |
571 | break; | 550 | break; |
572 | 551 | ||
573 | case 32: | 552 | case 24: |
574 | if (isPReP) { | 553 | if (isPReP) { |
575 | var->red.offset = 8; | 554 | var->red.offset = 0; |
576 | var->green.offset = 16; | 555 | var->green.offset = 8; |
577 | var->blue.offset = 24; | 556 | var->blue.offset = 16; |
578 | } else { | 557 | } else { |
579 | var->red.offset = 16; | 558 | var->red.offset = 16; |
580 | var->green.offset = 8; | 559 | var->green.offset = 8; |
@@ -586,12 +565,45 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, | |||
586 | break; | 565 | break; |
587 | 566 | ||
588 | default: | 567 | default: |
589 | DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel); | 568 | dev_dbg(info->device, |
569 | "Unsupported bpp size: %d\n", var->bits_per_pixel); | ||
590 | assert(false); | 570 | assert(false); |
591 | /* should never occur */ | 571 | /* should never occur */ |
592 | break; | 572 | break; |
593 | } | 573 | } |
594 | 574 | ||
575 | if (var->xres_virtual < var->xres) | ||
576 | var->xres_virtual = var->xres; | ||
577 | /* use highest possible virtual resolution */ | ||
578 | if (var->yres_virtual == -1) { | ||
579 | var->yres_virtual = pixels / var->xres_virtual; | ||
580 | |||
581 | dev_info(info->device, | ||
582 | "virtual resolution set to maximum of %dx%d\n", | ||
583 | var->xres_virtual, var->yres_virtual); | ||
584 | } | ||
585 | if (var->yres_virtual < var->yres) | ||
586 | var->yres_virtual = var->yres; | ||
587 | |||
588 | if (var->xres_virtual * var->yres_virtual > pixels) { | ||
589 | dev_err(info->device, "mode %dx%dx%d rejected... " | ||
590 | "virtual resolution too high to fit into video memory!\n", | ||
591 | var->xres_virtual, var->yres_virtual, | ||
592 | var->bits_per_pixel); | ||
593 | return -EINVAL; | ||
594 | } | ||
595 | |||
596 | if (var->xoffset < 0) | ||
597 | var->xoffset = 0; | ||
598 | if (var->yoffset < 0) | ||
599 | var->yoffset = 0; | ||
600 | |||
601 | /* truncate xoffset and yoffset to maximum if too high */ | ||
602 | if (var->xoffset > var->xres_virtual - var->xres) | ||
603 | var->xoffset = var->xres_virtual - var->xres - 1; | ||
604 | if (var->yoffset > var->yres_virtual - var->yres) | ||
605 | var->yoffset = var->yres_virtual - var->yres - 1; | ||
606 | |||
595 | var->red.msb_right = | 607 | var->red.msb_right = |
596 | var->green.msb_right = | 608 | var->green.msb_right = |
597 | var->blue.msb_right = | 609 | var->blue.msb_right = |
@@ -606,99 +618,31 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, | |||
606 | yres = (yres + 1) / 2; | 618 | yres = (yres + 1) / 2; |
607 | 619 | ||
608 | if (yres >= 1280) { | 620 | if (yres >= 1280) { |
609 | printk(KERN_ERR "cirrusfb: ERROR: VerticalTotal >= 1280; " | 621 | dev_err(info->device, "ERROR: VerticalTotal >= 1280; " |
610 | "special treatment required! (TODO)\n"); | 622 | "special treatment required! (TODO)\n"); |
611 | DPRINTK("EXIT - EINVAL error\n"); | ||
612 | return -EINVAL; | 623 | return -EINVAL; |
613 | } | 624 | } |
614 | 625 | ||
615 | return 0; | 626 | if (cirrusfb_check_pixclock(var, info)) |
616 | } | 627 | return -EINVAL; |
617 | |||
618 | static int cirrusfb_decode_var(const struct fb_var_screeninfo *var, | ||
619 | struct cirrusfb_regs *regs, | ||
620 | struct fb_info *info) | ||
621 | { | ||
622 | long freq; | ||
623 | long maxclock; | ||
624 | int maxclockidx = var->bits_per_pixel >> 3; | ||
625 | struct cirrusfb_info *cinfo = info->par; | ||
626 | |||
627 | switch (var->bits_per_pixel) { | ||
628 | case 1: | ||
629 | info->fix.line_length = var->xres_virtual / 8; | ||
630 | info->fix.visual = FB_VISUAL_MONO10; | ||
631 | break; | ||
632 | |||
633 | case 8: | ||
634 | info->fix.line_length = var->xres_virtual; | ||
635 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
636 | break; | ||
637 | |||
638 | case 16: | ||
639 | case 32: | ||
640 | info->fix.line_length = var->xres_virtual * maxclockidx; | ||
641 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
642 | break; | ||
643 | |||
644 | default: | ||
645 | DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel); | ||
646 | assert(false); | ||
647 | /* should never occur */ | ||
648 | break; | ||
649 | } | ||
650 | |||
651 | info->fix.type = FB_TYPE_PACKED_PIXELS; | ||
652 | |||
653 | /* convert from ps to kHz */ | ||
654 | freq = PICOS2KHZ(var->pixclock); | ||
655 | |||
656 | DPRINTK("desired pixclock: %ld kHz\n", freq); | ||
657 | |||
658 | maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx]; | ||
659 | regs->multiplexing = 0; | ||
660 | 628 | ||
661 | /* If the frequency is greater than we can support, we might be able | 629 | if (!is_laguna(cinfo)) |
662 | * to use multiplexing for the video mode */ | 630 | var->accel_flags = FB_ACCELF_TEXT; |
663 | if (freq > maxclock) { | ||
664 | switch (cinfo->btype) { | ||
665 | case BT_ALPINE: | ||
666 | case BT_GD5480: | ||
667 | regs->multiplexing = 1; | ||
668 | break; | ||
669 | 631 | ||
670 | default: | ||
671 | printk(KERN_ERR "cirrusfb: Frequency greater " | ||
672 | "than maxclock (%ld kHz)\n", maxclock); | ||
673 | DPRINTK("EXIT - return -EINVAL\n"); | ||
674 | return -EINVAL; | ||
675 | } | ||
676 | } | ||
677 | #if 0 | ||
678 | /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where | ||
679 | * the VCLK is double the pixel clock. */ | ||
680 | switch (var->bits_per_pixel) { | ||
681 | case 16: | ||
682 | case 32: | ||
683 | if (var->xres <= 800) | ||
684 | /* Xbh has this type of clock for 32-bit */ | ||
685 | freq /= 2; | ||
686 | break; | ||
687 | } | ||
688 | #endif | ||
689 | return 0; | 632 | return 0; |
690 | } | 633 | } |
691 | 634 | ||
692 | static void cirrusfb_set_mclk_as_source(const struct cirrusfb_info *cinfo, | 635 | static void cirrusfb_set_mclk_as_source(const struct fb_info *info, int div) |
693 | int div) | ||
694 | { | 636 | { |
637 | struct cirrusfb_info *cinfo = info->par; | ||
695 | unsigned char old1f, old1e; | 638 | unsigned char old1f, old1e; |
639 | |||
696 | assert(cinfo != NULL); | 640 | assert(cinfo != NULL); |
697 | old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40; | 641 | old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40; |
698 | 642 | ||
699 | if (div) { | 643 | if (div) { |
700 | DPRINTK("Set %s as pixclock source.\n", | 644 | dev_dbg(info->device, "Set %s as pixclock source.\n", |
701 | (div == 2) ? "MCLK/2" : "MCLK"); | 645 | (div == 2) ? "MCLK/2" : "MCLK"); |
702 | old1f |= 0x40; | 646 | old1f |= 0x40; |
703 | old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1; | 647 | old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1; |
704 | if (div == 2) | 648 | if (div == 2) |
@@ -718,101 +662,119 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
718 | { | 662 | { |
719 | struct cirrusfb_info *cinfo = info->par; | 663 | struct cirrusfb_info *cinfo = info->par; |
720 | struct fb_var_screeninfo *var = &info->var; | 664 | struct fb_var_screeninfo *var = &info->var; |
721 | struct cirrusfb_regs regs; | ||
722 | u8 __iomem *regbase = cinfo->regbase; | 665 | u8 __iomem *regbase = cinfo->regbase; |
723 | unsigned char tmp; | 666 | unsigned char tmp; |
724 | int offset = 0, err; | 667 | int pitch; |
725 | const struct cirrusfb_board_info_rec *bi; | 668 | const struct cirrusfb_board_info_rec *bi; |
726 | int hdispend, hsyncstart, hsyncend, htotal; | 669 | int hdispend, hsyncstart, hsyncend, htotal; |
727 | int yres, vdispend, vsyncstart, vsyncend, vtotal; | 670 | int yres, vdispend, vsyncstart, vsyncend, vtotal; |
728 | long freq; | 671 | long freq; |
729 | int nom, den, div; | 672 | int nom, den, div; |
673 | unsigned int control = 0, format = 0, threshold = 0; | ||
730 | 674 | ||
731 | DPRINTK("ENTER\n"); | 675 | dev_dbg(info->device, "Requested mode: %dx%dx%d\n", |
732 | DPRINTK("Requested mode: %dx%dx%d\n", | ||
733 | var->xres, var->yres, var->bits_per_pixel); | 676 | var->xres, var->yres, var->bits_per_pixel); |
734 | DPRINTK("pixclock: %d\n", var->pixclock); | ||
735 | 677 | ||
736 | init_vgachip(info); | 678 | switch (var->bits_per_pixel) { |
679 | case 1: | ||
680 | info->fix.line_length = var->xres_virtual / 8; | ||
681 | info->fix.visual = FB_VISUAL_MONO10; | ||
682 | break; | ||
737 | 683 | ||
738 | err = cirrusfb_decode_var(var, ®s, info); | 684 | case 8: |
739 | if (err) { | 685 | info->fix.line_length = var->xres_virtual; |
740 | /* should never happen */ | 686 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; |
741 | DPRINTK("mode change aborted. invalid var.\n"); | 687 | break; |
742 | return -EINVAL; | 688 | |
689 | case 16: | ||
690 | case 24: | ||
691 | info->fix.line_length = var->xres_virtual * | ||
692 | var->bits_per_pixel >> 3; | ||
693 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
694 | break; | ||
743 | } | 695 | } |
696 | info->fix.type = FB_TYPE_PACKED_PIXELS; | ||
697 | |||
698 | init_vgachip(info); | ||
744 | 699 | ||
745 | bi = &cirrusfb_board_info[cinfo->btype]; | 700 | bi = &cirrusfb_board_info[cinfo->btype]; |
746 | 701 | ||
747 | hsyncstart = var->xres + var->right_margin; | 702 | hsyncstart = var->xres + var->right_margin; |
748 | hsyncend = hsyncstart + var->hsync_len; | 703 | hsyncend = hsyncstart + var->hsync_len; |
749 | htotal = (hsyncend + var->left_margin) / 8 - 5; | 704 | htotal = (hsyncend + var->left_margin) / 8; |
750 | hdispend = var->xres / 8 - 1; | 705 | hdispend = var->xres / 8; |
751 | hsyncstart = hsyncstart / 8 + 1; | 706 | hsyncstart = hsyncstart / 8; |
752 | hsyncend = hsyncend / 8 + 1; | 707 | hsyncend = hsyncend / 8; |
753 | 708 | ||
754 | yres = var->yres; | 709 | vdispend = var->yres; |
755 | vsyncstart = yres + var->lower_margin; | 710 | vsyncstart = vdispend + var->lower_margin; |
756 | vsyncend = vsyncstart + var->vsync_len; | 711 | vsyncend = vsyncstart + var->vsync_len; |
757 | vtotal = vsyncend + var->upper_margin; | 712 | vtotal = vsyncend + var->upper_margin; |
758 | vdispend = yres - 1; | ||
759 | 713 | ||
760 | if (var->vmode & FB_VMODE_DOUBLE) { | 714 | if (var->vmode & FB_VMODE_DOUBLE) { |
761 | yres *= 2; | 715 | vdispend *= 2; |
762 | vsyncstart *= 2; | 716 | vsyncstart *= 2; |
763 | vsyncend *= 2; | 717 | vsyncend *= 2; |
764 | vtotal *= 2; | 718 | vtotal *= 2; |
765 | } else if (var->vmode & FB_VMODE_INTERLACED) { | 719 | } else if (var->vmode & FB_VMODE_INTERLACED) { |
766 | yres = (yres + 1) / 2; | 720 | vdispend = (vdispend + 1) / 2; |
767 | vsyncstart = (vsyncstart + 1) / 2; | 721 | vsyncstart = (vsyncstart + 1) / 2; |
768 | vsyncend = (vsyncend + 1) / 2; | 722 | vsyncend = (vsyncend + 1) / 2; |
769 | vtotal = (vtotal + 1) / 2; | 723 | vtotal = (vtotal + 1) / 2; |
770 | } | 724 | } |
771 | 725 | yres = vdispend; | |
772 | vtotal -= 2; | ||
773 | vsyncstart -= 1; | ||
774 | vsyncend -= 1; | ||
775 | |||
776 | if (yres >= 1024) { | 726 | if (yres >= 1024) { |
777 | vtotal /= 2; | 727 | vtotal /= 2; |
778 | vsyncstart /= 2; | 728 | vsyncstart /= 2; |
779 | vsyncend /= 2; | 729 | vsyncend /= 2; |
780 | vdispend /= 2; | 730 | vdispend /= 2; |
781 | } | 731 | } |
782 | if (regs.multiplexing) { | 732 | |
733 | vdispend -= 1; | ||
734 | vsyncstart -= 1; | ||
735 | vsyncend -= 1; | ||
736 | vtotal -= 2; | ||
737 | |||
738 | if (cinfo->multiplexing) { | ||
783 | htotal /= 2; | 739 | htotal /= 2; |
784 | hsyncstart /= 2; | 740 | hsyncstart /= 2; |
785 | hsyncend /= 2; | 741 | hsyncend /= 2; |
786 | hdispend /= 2; | 742 | hdispend /= 2; |
787 | } | 743 | } |
744 | |||
745 | htotal -= 5; | ||
746 | hdispend -= 1; | ||
747 | hsyncstart += 1; | ||
748 | hsyncend += 1; | ||
749 | |||
788 | /* unlock register VGA_CRTC_H_TOTAL..CRT7 */ | 750 | /* unlock register VGA_CRTC_H_TOTAL..CRT7 */ |
789 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */ | 751 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */ |
790 | 752 | ||
791 | /* if debugging is enabled, all parameters get output before writing */ | 753 | /* if debugging is enabled, all parameters get output before writing */ |
792 | DPRINTK("CRT0: %d\n", htotal); | 754 | dev_dbg(info->device, "CRT0: %d\n", htotal); |
793 | vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal); | 755 | vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal); |
794 | 756 | ||
795 | DPRINTK("CRT1: %d\n", hdispend); | 757 | dev_dbg(info->device, "CRT1: %d\n", hdispend); |
796 | vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend); | 758 | vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend); |
797 | 759 | ||
798 | DPRINTK("CRT2: %d\n", var->xres / 8); | 760 | dev_dbg(info->device, "CRT2: %d\n", var->xres / 8); |
799 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8); | 761 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8); |
800 | 762 | ||
801 | /* + 128: Compatible read */ | 763 | /* + 128: Compatible read */ |
802 | DPRINTK("CRT3: 128+%d\n", (htotal + 5) % 32); | 764 | dev_dbg(info->device, "CRT3: 128+%d\n", (htotal + 5) % 32); |
803 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_END, | 765 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_END, |
804 | 128 + ((htotal + 5) % 32)); | 766 | 128 + ((htotal + 5) % 32)); |
805 | 767 | ||
806 | DPRINTK("CRT4: %d\n", hsyncstart); | 768 | dev_dbg(info->device, "CRT4: %d\n", hsyncstart); |
807 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart); | 769 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart); |
808 | 770 | ||
809 | tmp = hsyncend % 32; | 771 | tmp = hsyncend % 32; |
810 | if ((htotal + 5) & 32) | 772 | if ((htotal + 5) & 32) |
811 | tmp += 128; | 773 | tmp += 128; |
812 | DPRINTK("CRT5: %d\n", tmp); | 774 | dev_dbg(info->device, "CRT5: %d\n", tmp); |
813 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp); | 775 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp); |
814 | 776 | ||
815 | DPRINTK("CRT6: %d\n", vtotal & 0xff); | 777 | dev_dbg(info->device, "CRT6: %d\n", vtotal & 0xff); |
816 | vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff); | 778 | vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff); |
817 | 779 | ||
818 | tmp = 16; /* LineCompare bit #9 */ | 780 | tmp = 16; /* LineCompare bit #9 */ |
@@ -830,7 +792,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
830 | tmp |= 64; | 792 | tmp |= 64; |
831 | if (vsyncstart & 512) | 793 | if (vsyncstart & 512) |
832 | tmp |= 128; | 794 | tmp |= 128; |
833 | DPRINTK("CRT7: %d\n", tmp); | 795 | dev_dbg(info->device, "CRT7: %d\n", tmp); |
834 | vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp); | 796 | vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp); |
835 | 797 | ||
836 | tmp = 0x40; /* LineCompare bit #8 */ | 798 | tmp = 0x40; /* LineCompare bit #8 */ |
@@ -838,25 +800,25 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
838 | tmp |= 0x20; | 800 | tmp |= 0x20; |
839 | if (var->vmode & FB_VMODE_DOUBLE) | 801 | if (var->vmode & FB_VMODE_DOUBLE) |
840 | tmp |= 0x80; | 802 | tmp |= 0x80; |
841 | DPRINTK("CRT9: %d\n", tmp); | 803 | dev_dbg(info->device, "CRT9: %d\n", tmp); |
842 | vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp); | 804 | vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp); |
843 | 805 | ||
844 | DPRINTK("CRT10: %d\n", vsyncstart & 0xff); | 806 | dev_dbg(info->device, "CRT10: %d\n", vsyncstart & 0xff); |
845 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff); | 807 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff); |
846 | 808 | ||
847 | DPRINTK("CRT11: 64+32+%d\n", vsyncend % 16); | 809 | dev_dbg(info->device, "CRT11: 64+32+%d\n", vsyncend % 16); |
848 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32); | 810 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32); |
849 | 811 | ||
850 | DPRINTK("CRT12: %d\n", vdispend & 0xff); | 812 | dev_dbg(info->device, "CRT12: %d\n", vdispend & 0xff); |
851 | vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff); | 813 | vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff); |
852 | 814 | ||
853 | DPRINTK("CRT15: %d\n", (vdispend + 1) & 0xff); | 815 | dev_dbg(info->device, "CRT15: %d\n", (vdispend + 1) & 0xff); |
854 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff); | 816 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff); |
855 | 817 | ||
856 | DPRINTK("CRT16: %d\n", vtotal & 0xff); | 818 | dev_dbg(info->device, "CRT16: %d\n", vtotal & 0xff); |
857 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff); | 819 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff); |
858 | 820 | ||
859 | DPRINTK("CRT18: 0xff\n"); | 821 | dev_dbg(info->device, "CRT18: 0xff\n"); |
860 | vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff); | 822 | vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff); |
861 | 823 | ||
862 | tmp = 0; | 824 | tmp = 0; |
@@ -871,41 +833,75 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
871 | if (vtotal & 512) | 833 | if (vtotal & 512) |
872 | tmp |= 128; | 834 | tmp |= 128; |
873 | 835 | ||
874 | DPRINTK("CRT1a: %d\n", tmp); | 836 | dev_dbg(info->device, "CRT1a: %d\n", tmp); |
875 | vga_wcrt(regbase, CL_CRT1A, tmp); | 837 | vga_wcrt(regbase, CL_CRT1A, tmp); |
876 | 838 | ||
877 | freq = PICOS2KHZ(var->pixclock); | 839 | freq = PICOS2KHZ(var->pixclock); |
840 | if (var->bits_per_pixel == 24) | ||
841 | if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64) | ||
842 | freq *= 3; | ||
843 | if (cinfo->multiplexing) | ||
844 | freq /= 2; | ||
845 | if (cinfo->doubleVCLK) | ||
846 | freq *= 2; | ||
847 | |||
878 | bestclock(freq, &nom, &den, &div); | 848 | bestclock(freq, &nom, &den, &div); |
879 | 849 | ||
850 | dev_dbg(info->device, "VCLK freq: %ld kHz nom: %d den: %d div: %d\n", | ||
851 | freq, nom, den, div); | ||
852 | |||
880 | /* set VCLK0 */ | 853 | /* set VCLK0 */ |
881 | /* hardware RefClock: 14.31818 MHz */ | 854 | /* hardware RefClock: 14.31818 MHz */ |
882 | /* formula: VClk = (OSC * N) / (D * (1+P)) */ | 855 | /* formula: VClk = (OSC * N) / (D * (1+P)) */ |
883 | /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ | 856 | /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ |
884 | 857 | ||
885 | if (cinfo->btype == BT_ALPINE) { | 858 | if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_PICASSO4 || |
859 | cinfo->btype == BT_SD64) { | ||
886 | /* if freq is close to mclk or mclk/2 select mclk | 860 | /* if freq is close to mclk or mclk/2 select mclk |
887 | * as clock source | 861 | * as clock source |
888 | */ | 862 | */ |
889 | int divMCLK = cirrusfb_check_mclk(cinfo, freq); | 863 | int divMCLK = cirrusfb_check_mclk(info, freq); |
890 | if (divMCLK) { | 864 | if (divMCLK) |
891 | nom = 0; | 865 | nom = 0; |
892 | cirrusfb_set_mclk_as_source(cinfo, divMCLK); | 866 | cirrusfb_set_mclk_as_source(info, divMCLK); |
867 | } | ||
868 | if (is_laguna(cinfo)) { | ||
869 | long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc); | ||
870 | unsigned char tile = fb_readb(cinfo->laguna_mmio + 0x407); | ||
871 | unsigned short tile_control; | ||
872 | |||
873 | if (cinfo->btype == BT_LAGUNAB) { | ||
874 | tile_control = fb_readw(cinfo->laguna_mmio + 0x2c4); | ||
875 | tile_control &= ~0x80; | ||
876 | fb_writew(tile_control, cinfo->laguna_mmio + 0x2c4); | ||
893 | } | 877 | } |
878 | |||
879 | fb_writel(pcifc | 0x10000000l, cinfo->laguna_mmio + 0x3fc); | ||
880 | fb_writeb(tile & 0x3f, cinfo->laguna_mmio + 0x407); | ||
881 | control = fb_readw(cinfo->laguna_mmio + 0x402); | ||
882 | threshold = fb_readw(cinfo->laguna_mmio + 0xea); | ||
883 | control &= ~0x6800; | ||
884 | format = 0; | ||
885 | threshold &= 0xffc0 & 0x3fbf; | ||
894 | } | 886 | } |
895 | if (nom) { | 887 | if (nom) { |
896 | vga_wseq(regbase, CL_SEQRB, nom); | ||
897 | tmp = den << 1; | 888 | tmp = den << 1; |
898 | if (div != 0) | 889 | if (div != 0) |
899 | tmp |= 1; | 890 | tmp |= 1; |
900 | |||
901 | /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ | 891 | /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ |
902 | if ((cinfo->btype == BT_SD64) || | 892 | if ((cinfo->btype == BT_SD64) || |
903 | (cinfo->btype == BT_ALPINE) || | 893 | (cinfo->btype == BT_ALPINE) || |
904 | (cinfo->btype == BT_GD5480)) | 894 | (cinfo->btype == BT_GD5480)) |
905 | tmp |= 0x80; | 895 | tmp |= 0x80; |
906 | 896 | ||
907 | DPRINTK("CL_SEQR1B: %ld\n", (long) tmp); | 897 | /* Laguna chipset has reversed clock registers */ |
908 | vga_wseq(regbase, CL_SEQR1B, tmp); | 898 | if (is_laguna(cinfo)) { |
899 | vga_wseq(regbase, CL_SEQRE, tmp); | ||
900 | vga_wseq(regbase, CL_SEQR1E, nom); | ||
901 | } else { | ||
902 | vga_wseq(regbase, CL_SEQRE, nom); | ||
903 | vga_wseq(regbase, CL_SEQR1E, tmp); | ||
904 | } | ||
909 | } | 905 | } |
910 | 906 | ||
911 | if (yres >= 1024) | 907 | if (yres >= 1024) |
@@ -916,9 +912,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
916 | * address wrap, no compat. */ | 912 | * address wrap, no compat. */ |
917 | vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3); | 913 | vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3); |
918 | 914 | ||
919 | /* HAEH? vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); | ||
920 | * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */ | ||
921 | |||
922 | /* don't know if it would hurt to also program this if no interlaced */ | 915 | /* don't know if it would hurt to also program this if no interlaced */ |
923 | /* mode is used, but I feel better this way.. :-) */ | 916 | /* mode is used, but I feel better this way.. :-) */ |
924 | if (var->vmode & FB_VMODE_INTERLACED) | 917 | if (var->vmode & FB_VMODE_INTERLACED) |
@@ -926,19 +919,15 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
926 | else | 919 | else |
927 | vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */ | 920 | vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */ |
928 | 921 | ||
929 | vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0); | 922 | /* adjust horizontal/vertical sync type (low/high), use VCLK3 */ |
930 | |||
931 | /* adjust horizontal/vertical sync type (low/high) */ | ||
932 | /* enable display memory & CRTC I/O address for color mode */ | 923 | /* enable display memory & CRTC I/O address for color mode */ |
933 | tmp = 0x03; | 924 | tmp = 0x03 | 0xc; |
934 | if (var->sync & FB_SYNC_HOR_HIGH_ACT) | 925 | if (var->sync & FB_SYNC_HOR_HIGH_ACT) |
935 | tmp |= 0x40; | 926 | tmp |= 0x40; |
936 | if (var->sync & FB_SYNC_VERT_HIGH_ACT) | 927 | if (var->sync & FB_SYNC_VERT_HIGH_ACT) |
937 | tmp |= 0x80; | 928 | tmp |= 0x80; |
938 | WGen(cinfo, VGA_MIS_W, tmp); | 929 | WGen(cinfo, VGA_MIS_W, tmp); |
939 | 930 | ||
940 | /* Screen A Preset Row-Scan register */ | ||
941 | vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0); | ||
942 | /* text cursor on and start line */ | 931 | /* text cursor on and start line */ |
943 | vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0); | 932 | vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0); |
944 | /* text cursor end line */ | 933 | /* text cursor end line */ |
@@ -952,7 +941,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
952 | 941 | ||
953 | /* programming for different color depths */ | 942 | /* programming for different color depths */ |
954 | if (var->bits_per_pixel == 1) { | 943 | if (var->bits_per_pixel == 1) { |
955 | DPRINTK("cirrusfb: preparing for 1 bit deep display\n"); | 944 | dev_dbg(info->device, "preparing for 1 bit deep display\n"); |
956 | vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */ | 945 | vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */ |
957 | 946 | ||
958 | /* SR07 */ | 947 | /* SR07 */ |
@@ -964,68 +953,53 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
964 | case BT_PICASSO4: | 953 | case BT_PICASSO4: |
965 | case BT_ALPINE: | 954 | case BT_ALPINE: |
966 | case BT_GD5480: | 955 | case BT_GD5480: |
967 | DPRINTK(" (for GD54xx)\n"); | ||
968 | vga_wseq(regbase, CL_SEQR7, | 956 | vga_wseq(regbase, CL_SEQR7, |
969 | regs.multiplexing ? | 957 | cinfo->multiplexing ? |
970 | bi->sr07_1bpp_mux : bi->sr07_1bpp); | 958 | bi->sr07_1bpp_mux : bi->sr07_1bpp); |
971 | break; | 959 | break; |
972 | 960 | ||
973 | case BT_LAGUNA: | 961 | case BT_LAGUNA: |
974 | DPRINTK(" (for GD546x)\n"); | 962 | case BT_LAGUNAB: |
975 | vga_wseq(regbase, CL_SEQR7, | 963 | vga_wseq(regbase, CL_SEQR7, |
976 | vga_rseq(regbase, CL_SEQR7) & ~0x01); | 964 | vga_rseq(regbase, CL_SEQR7) & ~0x01); |
977 | break; | 965 | break; |
978 | 966 | ||
979 | default: | 967 | default: |
980 | printk(KERN_WARNING "cirrusfb: unknown Board\n"); | 968 | dev_warn(info->device, "unknown Board\n"); |
981 | break; | 969 | break; |
982 | } | 970 | } |
983 | 971 | ||
984 | /* Extended Sequencer Mode */ | 972 | /* Extended Sequencer Mode */ |
985 | switch (cinfo->btype) { | 973 | switch (cinfo->btype) { |
986 | case BT_SD64: | ||
987 | /* setting the SEQRF on SD64 is not necessary | ||
988 | * (only during init) | ||
989 | */ | ||
990 | DPRINTK("(for SD64)\n"); | ||
991 | /* MCLK select */ | ||
992 | vga_wseq(regbase, CL_SEQR1F, 0x1a); | ||
993 | break; | ||
994 | 974 | ||
995 | case BT_PICCOLO: | 975 | case BT_PICCOLO: |
996 | case BT_SPECTRUM: | 976 | case BT_SPECTRUM: |
997 | DPRINTK("(for Piccolo/Spectrum)\n"); | ||
998 | /* ### ueberall 0x22? */ | ||
999 | /* ##vorher 1c MCLK select */ | ||
1000 | vga_wseq(regbase, CL_SEQR1F, 0x22); | ||
1001 | /* evtl d0 bei 1 bit? avoid FIFO underruns..? */ | 977 | /* evtl d0 bei 1 bit? avoid FIFO underruns..? */ |
1002 | vga_wseq(regbase, CL_SEQRF, 0xb0); | 978 | vga_wseq(regbase, CL_SEQRF, 0xb0); |
1003 | break; | 979 | break; |
1004 | 980 | ||
1005 | case BT_PICASSO: | 981 | case BT_PICASSO: |
1006 | DPRINTK("(for Picasso)\n"); | ||
1007 | /* ##vorher 22 MCLK select */ | ||
1008 | vga_wseq(regbase, CL_SEQR1F, 0x22); | ||
1009 | /* ## vorher d0 avoid FIFO underruns..? */ | 982 | /* ## vorher d0 avoid FIFO underruns..? */ |
1010 | vga_wseq(regbase, CL_SEQRF, 0xd0); | 983 | vga_wseq(regbase, CL_SEQRF, 0xd0); |
1011 | break; | 984 | break; |
1012 | 985 | ||
986 | case BT_SD64: | ||
1013 | case BT_PICASSO4: | 987 | case BT_PICASSO4: |
1014 | case BT_ALPINE: | 988 | case BT_ALPINE: |
1015 | case BT_GD5480: | 989 | case BT_GD5480: |
1016 | case BT_LAGUNA: | 990 | case BT_LAGUNA: |
1017 | DPRINTK(" (for GD54xx)\n"); | 991 | case BT_LAGUNAB: |
1018 | /* do nothing */ | 992 | /* do nothing */ |
1019 | break; | 993 | break; |
1020 | 994 | ||
1021 | default: | 995 | default: |
1022 | printk(KERN_WARNING "cirrusfb: unknown Board\n"); | 996 | dev_warn(info->device, "unknown Board\n"); |
1023 | break; | 997 | break; |
1024 | } | 998 | } |
1025 | 999 | ||
1026 | /* pixel mask: pass-through for first plane */ | 1000 | /* pixel mask: pass-through for first plane */ |
1027 | WGen(cinfo, VGA_PEL_MSK, 0x01); | 1001 | WGen(cinfo, VGA_PEL_MSK, 0x01); |
1028 | if (regs.multiplexing) | 1002 | if (cinfo->multiplexing) |
1029 | /* hidden dac reg: 1280x1024 */ | 1003 | /* hidden dac reg: 1280x1024 */ |
1030 | WHDR(cinfo, 0x4a); | 1004 | WHDR(cinfo, 0x4a); |
1031 | else | 1005 | else |
@@ -1035,7 +1009,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1035 | vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06); | 1009 | vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06); |
1036 | /* plane mask: only write to first plane */ | 1010 | /* plane mask: only write to first plane */ |
1037 | vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01); | 1011 | vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01); |
1038 | offset = var->xres_virtual / 16; | ||
1039 | } | 1012 | } |
1040 | 1013 | ||
1041 | /****************************************************** | 1014 | /****************************************************** |
@@ -1045,7 +1018,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1045 | */ | 1018 | */ |
1046 | 1019 | ||
1047 | else if (var->bits_per_pixel == 8) { | 1020 | else if (var->bits_per_pixel == 8) { |
1048 | DPRINTK("cirrusfb: preparing for 8 bit deep display\n"); | 1021 | dev_dbg(info->device, "preparing for 8 bit deep display\n"); |
1049 | switch (cinfo->btype) { | 1022 | switch (cinfo->btype) { |
1050 | case BT_SD64: | 1023 | case BT_SD64: |
1051 | case BT_PICCOLO: | 1024 | case BT_PICCOLO: |
@@ -1054,34 +1027,27 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1054 | case BT_PICASSO4: | 1027 | case BT_PICASSO4: |
1055 | case BT_ALPINE: | 1028 | case BT_ALPINE: |
1056 | case BT_GD5480: | 1029 | case BT_GD5480: |
1057 | DPRINTK(" (for GD54xx)\n"); | ||
1058 | vga_wseq(regbase, CL_SEQR7, | 1030 | vga_wseq(regbase, CL_SEQR7, |
1059 | regs.multiplexing ? | 1031 | cinfo->multiplexing ? |
1060 | bi->sr07_8bpp_mux : bi->sr07_8bpp); | 1032 | bi->sr07_8bpp_mux : bi->sr07_8bpp); |
1061 | break; | 1033 | break; |
1062 | 1034 | ||
1063 | case BT_LAGUNA: | 1035 | case BT_LAGUNA: |
1064 | DPRINTK(" (for GD546x)\n"); | 1036 | case BT_LAGUNAB: |
1065 | vga_wseq(regbase, CL_SEQR7, | 1037 | vga_wseq(regbase, CL_SEQR7, |
1066 | vga_rseq(regbase, CL_SEQR7) | 0x01); | 1038 | vga_rseq(regbase, CL_SEQR7) | 0x01); |
1039 | threshold |= 0x10; | ||
1067 | break; | 1040 | break; |
1068 | 1041 | ||
1069 | default: | 1042 | default: |
1070 | printk(KERN_WARNING "cirrusfb: unknown Board\n"); | 1043 | dev_warn(info->device, "unknown Board\n"); |
1071 | break; | 1044 | break; |
1072 | } | 1045 | } |
1073 | 1046 | ||
1074 | switch (cinfo->btype) { | 1047 | switch (cinfo->btype) { |
1075 | case BT_SD64: | ||
1076 | /* MCLK select */ | ||
1077 | vga_wseq(regbase, CL_SEQR1F, 0x1d); | ||
1078 | break; | ||
1079 | |||
1080 | case BT_PICCOLO: | 1048 | case BT_PICCOLO: |
1081 | case BT_PICASSO: | 1049 | case BT_PICASSO: |
1082 | case BT_SPECTRUM: | 1050 | case BT_SPECTRUM: |
1083 | /* ### vorher 1c MCLK select */ | ||
1084 | vga_wseq(regbase, CL_SEQR1F, 0x22); | ||
1085 | /* Fast Page-Mode writes */ | 1051 | /* Fast Page-Mode writes */ |
1086 | vga_wseq(regbase, CL_SEQRF, 0xb0); | 1052 | vga_wseq(regbase, CL_SEQRF, 0xb0); |
1087 | break; | 1053 | break; |
@@ -1091,40 +1057,27 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1091 | /* ### INCOMPLETE!! */ | 1057 | /* ### INCOMPLETE!! */ |
1092 | vga_wseq(regbase, CL_SEQRF, 0xb8); | 1058 | vga_wseq(regbase, CL_SEQRF, 0xb8); |
1093 | #endif | 1059 | #endif |
1094 | /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */ | ||
1095 | break; | ||
1096 | |||
1097 | case BT_ALPINE: | 1060 | case BT_ALPINE: |
1098 | DPRINTK(" (for GD543x)\n"); | 1061 | case BT_SD64: |
1099 | /* We already set SRF and SR1F */ | ||
1100 | break; | ||
1101 | |||
1102 | case BT_GD5480: | 1062 | case BT_GD5480: |
1103 | case BT_LAGUNA: | 1063 | case BT_LAGUNA: |
1104 | DPRINTK(" (for GD54xx)\n"); | 1064 | case BT_LAGUNAB: |
1105 | /* do nothing */ | 1065 | /* do nothing */ |
1106 | break; | 1066 | break; |
1107 | 1067 | ||
1108 | default: | 1068 | default: |
1109 | printk(KERN_WARNING "cirrusfb: unknown Board\n"); | 1069 | dev_warn(info->device, "unknown board\n"); |
1110 | break; | 1070 | break; |
1111 | } | 1071 | } |
1112 | 1072 | ||
1113 | /* mode register: 256 color mode */ | 1073 | /* mode register: 256 color mode */ |
1114 | vga_wgfx(regbase, VGA_GFX_MODE, 64); | 1074 | vga_wgfx(regbase, VGA_GFX_MODE, 64); |
1115 | /* pixel mask: pass-through all planes */ | 1075 | if (cinfo->multiplexing) |
1116 | WGen(cinfo, VGA_PEL_MSK, 0xff); | ||
1117 | if (regs.multiplexing) | ||
1118 | /* hidden dac reg: 1280x1024 */ | 1076 | /* hidden dac reg: 1280x1024 */ |
1119 | WHDR(cinfo, 0x4a); | 1077 | WHDR(cinfo, 0x4a); |
1120 | else | 1078 | else |
1121 | /* hidden dac: nothing */ | 1079 | /* hidden dac: nothing */ |
1122 | WHDR(cinfo, 0); | 1080 | WHDR(cinfo, 0); |
1123 | /* memory mode: chain4, ext. memory */ | ||
1124 | vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a); | ||
1125 | /* plane mask: enable writing to all 4 planes */ | ||
1126 | vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff); | ||
1127 | offset = var->xres_virtual / 8; | ||
1128 | } | 1081 | } |
1129 | 1082 | ||
1130 | /****************************************************** | 1083 | /****************************************************** |
@@ -1134,147 +1087,110 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1134 | */ | 1087 | */ |
1135 | 1088 | ||
1136 | else if (var->bits_per_pixel == 16) { | 1089 | else if (var->bits_per_pixel == 16) { |
1137 | DPRINTK("cirrusfb: preparing for 16 bit deep display\n"); | 1090 | dev_dbg(info->device, "preparing for 16 bit deep display\n"); |
1138 | switch (cinfo->btype) { | 1091 | switch (cinfo->btype) { |
1139 | case BT_SD64: | ||
1140 | /* Extended Sequencer Mode: 256c col. mode */ | ||
1141 | vga_wseq(regbase, CL_SEQR7, 0xf7); | ||
1142 | /* MCLK select */ | ||
1143 | vga_wseq(regbase, CL_SEQR1F, 0x1e); | ||
1144 | break; | ||
1145 | |||
1146 | case BT_PICCOLO: | 1092 | case BT_PICCOLO: |
1147 | case BT_SPECTRUM: | 1093 | case BT_SPECTRUM: |
1148 | vga_wseq(regbase, CL_SEQR7, 0x87); | 1094 | vga_wseq(regbase, CL_SEQR7, 0x87); |
1149 | /* Fast Page-Mode writes */ | 1095 | /* Fast Page-Mode writes */ |
1150 | vga_wseq(regbase, CL_SEQRF, 0xb0); | 1096 | vga_wseq(regbase, CL_SEQRF, 0xb0); |
1151 | /* MCLK select */ | ||
1152 | vga_wseq(regbase, CL_SEQR1F, 0x22); | ||
1153 | break; | 1097 | break; |
1154 | 1098 | ||
1155 | case BT_PICASSO: | 1099 | case BT_PICASSO: |
1156 | vga_wseq(regbase, CL_SEQR7, 0x27); | 1100 | vga_wseq(regbase, CL_SEQR7, 0x27); |
1157 | /* Fast Page-Mode writes */ | 1101 | /* Fast Page-Mode writes */ |
1158 | vga_wseq(regbase, CL_SEQRF, 0xb0); | 1102 | vga_wseq(regbase, CL_SEQRF, 0xb0); |
1159 | /* MCLK select */ | ||
1160 | vga_wseq(regbase, CL_SEQR1F, 0x22); | ||
1161 | break; | 1103 | break; |
1162 | 1104 | ||
1105 | case BT_SD64: | ||
1163 | case BT_PICASSO4: | 1106 | case BT_PICASSO4: |
1164 | vga_wseq(regbase, CL_SEQR7, 0x27); | ||
1165 | /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */ | ||
1166 | break; | ||
1167 | |||
1168 | case BT_ALPINE: | 1107 | case BT_ALPINE: |
1169 | DPRINTK(" (for GD543x)\n"); | 1108 | /* Extended Sequencer Mode: 256c col. mode */ |
1170 | vga_wseq(regbase, CL_SEQR7, 0xa7); | 1109 | vga_wseq(regbase, CL_SEQR7, |
1110 | cinfo->doubleVCLK ? 0xa3 : 0xa7); | ||
1171 | break; | 1111 | break; |
1172 | 1112 | ||
1173 | case BT_GD5480: | 1113 | case BT_GD5480: |
1174 | DPRINTK(" (for GD5480)\n"); | ||
1175 | vga_wseq(regbase, CL_SEQR7, 0x17); | 1114 | vga_wseq(regbase, CL_SEQR7, 0x17); |
1176 | /* We already set SRF and SR1F */ | 1115 | /* We already set SRF and SR1F */ |
1177 | break; | 1116 | break; |
1178 | 1117 | ||
1179 | case BT_LAGUNA: | 1118 | case BT_LAGUNA: |
1180 | DPRINTK(" (for GD546x)\n"); | 1119 | case BT_LAGUNAB: |
1181 | vga_wseq(regbase, CL_SEQR7, | 1120 | vga_wseq(regbase, CL_SEQR7, |
1182 | vga_rseq(regbase, CL_SEQR7) & ~0x01); | 1121 | vga_rseq(regbase, CL_SEQR7) & ~0x01); |
1122 | control |= 0x2000; | ||
1123 | format |= 0x1400; | ||
1124 | threshold |= 0x10; | ||
1183 | break; | 1125 | break; |
1184 | 1126 | ||
1185 | default: | 1127 | default: |
1186 | printk(KERN_WARNING "CIRRUSFB: unknown Board\n"); | 1128 | dev_warn(info->device, "unknown Board\n"); |
1187 | break; | 1129 | break; |
1188 | } | 1130 | } |
1189 | 1131 | ||
1190 | /* mode register: 256 color mode */ | 1132 | /* mode register: 256 color mode */ |
1191 | vga_wgfx(regbase, VGA_GFX_MODE, 64); | 1133 | vga_wgfx(regbase, VGA_GFX_MODE, 64); |
1192 | /* pixel mask: pass-through all planes */ | ||
1193 | WGen(cinfo, VGA_PEL_MSK, 0xff); | ||
1194 | #ifdef CONFIG_PCI | 1134 | #ifdef CONFIG_PCI |
1195 | WHDR(cinfo, 0xc0); /* Copy Xbh */ | 1135 | WHDR(cinfo, cinfo->doubleVCLK ? 0xe1 : 0xc1); |
1196 | #elif defined(CONFIG_ZORRO) | 1136 | #elif defined(CONFIG_ZORRO) |
1197 | /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */ | 1137 | /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */ |
1198 | WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */ | 1138 | WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */ |
1199 | #endif | 1139 | #endif |
1200 | /* memory mode: chain4, ext. memory */ | ||
1201 | vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a); | ||
1202 | /* plane mask: enable writing to all 4 planes */ | ||
1203 | vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff); | ||
1204 | offset = var->xres_virtual / 4; | ||
1205 | } | 1140 | } |
1206 | 1141 | ||
1207 | /****************************************************** | 1142 | /****************************************************** |
1208 | * | 1143 | * |
1209 | * 32 bpp | 1144 | * 24 bpp |
1210 | * | 1145 | * |
1211 | */ | 1146 | */ |
1212 | 1147 | ||
1213 | else if (var->bits_per_pixel == 32) { | 1148 | else if (var->bits_per_pixel == 24) { |
1214 | DPRINTK("cirrusfb: preparing for 32 bit deep display\n"); | 1149 | dev_dbg(info->device, "preparing for 24 bit deep display\n"); |
1215 | switch (cinfo->btype) { | 1150 | switch (cinfo->btype) { |
1216 | case BT_SD64: | ||
1217 | /* Extended Sequencer Mode: 256c col. mode */ | ||
1218 | vga_wseq(regbase, CL_SEQR7, 0xf9); | ||
1219 | /* MCLK select */ | ||
1220 | vga_wseq(regbase, CL_SEQR1F, 0x1e); | ||
1221 | break; | ||
1222 | |||
1223 | case BT_PICCOLO: | 1151 | case BT_PICCOLO: |
1224 | case BT_SPECTRUM: | 1152 | case BT_SPECTRUM: |
1225 | vga_wseq(regbase, CL_SEQR7, 0x85); | 1153 | vga_wseq(regbase, CL_SEQR7, 0x85); |
1226 | /* Fast Page-Mode writes */ | 1154 | /* Fast Page-Mode writes */ |
1227 | vga_wseq(regbase, CL_SEQRF, 0xb0); | 1155 | vga_wseq(regbase, CL_SEQRF, 0xb0); |
1228 | /* MCLK select */ | ||
1229 | vga_wseq(regbase, CL_SEQR1F, 0x22); | ||
1230 | break; | 1156 | break; |
1231 | 1157 | ||
1232 | case BT_PICASSO: | 1158 | case BT_PICASSO: |
1233 | vga_wseq(regbase, CL_SEQR7, 0x25); | 1159 | vga_wseq(regbase, CL_SEQR7, 0x25); |
1234 | /* Fast Page-Mode writes */ | 1160 | /* Fast Page-Mode writes */ |
1235 | vga_wseq(regbase, CL_SEQRF, 0xb0); | 1161 | vga_wseq(regbase, CL_SEQRF, 0xb0); |
1236 | /* MCLK select */ | ||
1237 | vga_wseq(regbase, CL_SEQR1F, 0x22); | ||
1238 | break; | 1162 | break; |
1239 | 1163 | ||
1164 | case BT_SD64: | ||
1240 | case BT_PICASSO4: | 1165 | case BT_PICASSO4: |
1241 | vga_wseq(regbase, CL_SEQR7, 0x25); | ||
1242 | /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */ | ||
1243 | break; | ||
1244 | |||
1245 | case BT_ALPINE: | 1166 | case BT_ALPINE: |
1246 | DPRINTK(" (for GD543x)\n"); | 1167 | /* Extended Sequencer Mode: 256c col. mode */ |
1247 | vga_wseq(regbase, CL_SEQR7, 0xa9); | 1168 | vga_wseq(regbase, CL_SEQR7, 0xa5); |
1248 | break; | 1169 | break; |
1249 | 1170 | ||
1250 | case BT_GD5480: | 1171 | case BT_GD5480: |
1251 | DPRINTK(" (for GD5480)\n"); | 1172 | vga_wseq(regbase, CL_SEQR7, 0x15); |
1252 | vga_wseq(regbase, CL_SEQR7, 0x19); | ||
1253 | /* We already set SRF and SR1F */ | 1173 | /* We already set SRF and SR1F */ |
1254 | break; | 1174 | break; |
1255 | 1175 | ||
1256 | case BT_LAGUNA: | 1176 | case BT_LAGUNA: |
1257 | DPRINTK(" (for GD546x)\n"); | 1177 | case BT_LAGUNAB: |
1258 | vga_wseq(regbase, CL_SEQR7, | 1178 | vga_wseq(regbase, CL_SEQR7, |
1259 | vga_rseq(regbase, CL_SEQR7) & ~0x01); | 1179 | vga_rseq(regbase, CL_SEQR7) & ~0x01); |
1180 | control |= 0x4000; | ||
1181 | format |= 0x2400; | ||
1182 | threshold |= 0x20; | ||
1260 | break; | 1183 | break; |
1261 | 1184 | ||
1262 | default: | 1185 | default: |
1263 | printk(KERN_WARNING "cirrusfb: unknown Board\n"); | 1186 | dev_warn(info->device, "unknown Board\n"); |
1264 | break; | 1187 | break; |
1265 | } | 1188 | } |
1266 | 1189 | ||
1267 | /* mode register: 256 color mode */ | 1190 | /* mode register: 256 color mode */ |
1268 | vga_wgfx(regbase, VGA_GFX_MODE, 64); | 1191 | vga_wgfx(regbase, VGA_GFX_MODE, 64); |
1269 | /* pixel mask: pass-through all planes */ | ||
1270 | WGen(cinfo, VGA_PEL_MSK, 0xff); | ||
1271 | /* hidden dac reg: 8-8-8 mode (24 or 32) */ | 1192 | /* hidden dac reg: 8-8-8 mode (24 or 32) */ |
1272 | WHDR(cinfo, 0xc5); | 1193 | WHDR(cinfo, 0xc5); |
1273 | /* memory mode: chain4, ext. memory */ | ||
1274 | vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a); | ||
1275 | /* plane mask: enable writing to all 4 planes */ | ||
1276 | vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff); | ||
1277 | offset = var->xres_virtual / 4; | ||
1278 | } | 1194 | } |
1279 | 1195 | ||
1280 | /****************************************************** | 1196 | /****************************************************** |
@@ -1284,67 +1200,55 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1284 | */ | 1200 | */ |
1285 | 1201 | ||
1286 | else | 1202 | else |
1287 | printk(KERN_ERR "cirrusfb: What's this?? " | 1203 | dev_err(info->device, |
1288 | " requested color depth == %d.\n", | 1204 | "What's this? requested color depth == %d.\n", |
1289 | var->bits_per_pixel); | 1205 | var->bits_per_pixel); |
1290 | 1206 | ||
1291 | vga_wcrt(regbase, VGA_CRTC_OFFSET, offset & 0xff); | 1207 | pitch = info->fix.line_length >> 3; |
1208 | vga_wcrt(regbase, VGA_CRTC_OFFSET, pitch & 0xff); | ||
1292 | tmp = 0x22; | 1209 | tmp = 0x22; |
1293 | if (offset & 0x100) | 1210 | if (pitch & 0x100) |
1294 | tmp |= 0x10; /* offset overflow bit */ | 1211 | tmp |= 0x10; /* offset overflow bit */ |
1295 | 1212 | ||
1296 | /* screen start addr #16-18, fastpagemode cycles */ | 1213 | /* screen start addr #16-18, fastpagemode cycles */ |
1297 | vga_wcrt(regbase, CL_CRT1B, tmp); | 1214 | vga_wcrt(regbase, CL_CRT1B, tmp); |
1298 | 1215 | ||
1299 | if (cinfo->btype == BT_SD64 || | 1216 | /* screen start address bit 19 */ |
1300 | cinfo->btype == BT_PICASSO4 || | 1217 | if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) |
1301 | cinfo->btype == BT_ALPINE || | 1218 | vga_wcrt(regbase, CL_CRT1D, (pitch >> 9) & 1); |
1302 | cinfo->btype == BT_GD5480) | 1219 | |
1303 | /* screen start address bit 19 */ | 1220 | if (is_laguna(cinfo)) { |
1304 | vga_wcrt(regbase, CL_CRT1D, 0x00); | 1221 | tmp = 0; |
1305 | 1222 | if ((htotal + 5) & 256) | |
1306 | /* text cursor location high */ | 1223 | tmp |= 128; |
1307 | vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0); | 1224 | if (hdispend & 256) |
1308 | /* text cursor location low */ | 1225 | tmp |= 64; |
1309 | vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0); | 1226 | if (hsyncstart & 256) |
1310 | /* underline row scanline = at very bottom */ | 1227 | tmp |= 48; |
1311 | vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0); | 1228 | if (vtotal & 1024) |
1312 | 1229 | tmp |= 8; | |
1313 | /* controller mode */ | 1230 | if (vdispend & 1024) |
1314 | vga_wattr(regbase, VGA_ATC_MODE, 1); | 1231 | tmp |= 4; |
1315 | /* overscan (border) color */ | 1232 | if (vsyncstart & 1024) |
1316 | vga_wattr(regbase, VGA_ATC_OVERSCAN, 0); | 1233 | tmp |= 3; |
1317 | /* color plane enable */ | 1234 | |
1318 | vga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 15); | 1235 | vga_wcrt(regbase, CL_CRT1E, tmp); |
1236 | dev_dbg(info->device, "CRT1e: %d\n", tmp); | ||
1237 | } | ||
1238 | |||
1319 | /* pixel panning */ | 1239 | /* pixel panning */ |
1320 | vga_wattr(regbase, CL_AR33, 0); | 1240 | vga_wattr(regbase, CL_AR33, 0); |
1321 | /* color select */ | ||
1322 | vga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0); | ||
1323 | 1241 | ||
1324 | /* [ EGS: SetOffset(); ] */ | 1242 | /* [ EGS: SetOffset(); ] */ |
1325 | /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */ | 1243 | /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */ |
1326 | AttrOn(cinfo); | 1244 | AttrOn(cinfo); |
1327 | 1245 | ||
1328 | /* set/reset register */ | 1246 | if (is_laguna(cinfo)) { |
1329 | vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0); | 1247 | /* no tiles */ |
1330 | /* set/reset enable */ | 1248 | fb_writew(control | 0x1000, cinfo->laguna_mmio + 0x402); |
1331 | vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0); | 1249 | fb_writew(format, cinfo->laguna_mmio + 0xc0); |
1332 | /* color compare */ | 1250 | fb_writew(threshold, cinfo->laguna_mmio + 0xea); |
1333 | vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0); | 1251 | } |
1334 | /* data rotate */ | ||
1335 | vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0); | ||
1336 | /* read map select */ | ||
1337 | vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0); | ||
1338 | /* miscellaneous register */ | ||
1339 | vga_wgfx(regbase, VGA_GFX_MISC, 1); | ||
1340 | /* color don't care */ | ||
1341 | vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 15); | ||
1342 | /* bit mask */ | ||
1343 | vga_wgfx(regbase, VGA_GFX_BIT_MASK, 255); | ||
1344 | |||
1345 | /* graphics cursor attributes: nothing special */ | ||
1346 | vga_wseq(regbase, CL_SEQR12, 0x0); | ||
1347 | |||
1348 | /* finally, turn on everything - turn off "FullBandwidth" bit */ | 1252 | /* finally, turn on everything - turn off "FullBandwidth" bit */ |
1349 | /* also, set "DotClock%2" bit where requested */ | 1253 | /* also, set "DotClock%2" bit where requested */ |
1350 | tmp = 0x01; | 1254 | tmp = 0x01; |
@@ -1355,18 +1259,12 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1355 | */ | 1259 | */ |
1356 | 1260 | ||
1357 | vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp); | 1261 | vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp); |
1358 | DPRINTK("CL_SEQR1: %d\n", tmp); | 1262 | dev_dbg(info->device, "CL_SEQR1: %d\n", tmp); |
1359 | |||
1360 | cinfo->currentmode = regs; | ||
1361 | |||
1362 | /* pan to requested offset */ | ||
1363 | cirrusfb_pan_display(var, info); | ||
1364 | 1263 | ||
1365 | #ifdef CIRRUSFB_DEBUG | 1264 | #ifdef CIRRUSFB_DEBUG |
1366 | cirrusfb_dump(); | 1265 | cirrusfb_dbg_reg_dump(info, NULL); |
1367 | #endif | 1266 | #endif |
1368 | 1267 | ||
1369 | DPRINTK("EXIT\n"); | ||
1370 | return 0; | 1268 | return 0; |
1371 | } | 1269 | } |
1372 | 1270 | ||
@@ -1418,27 +1316,19 @@ static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
1418 | static int cirrusfb_pan_display(struct fb_var_screeninfo *var, | 1316 | static int cirrusfb_pan_display(struct fb_var_screeninfo *var, |
1419 | struct fb_info *info) | 1317 | struct fb_info *info) |
1420 | { | 1318 | { |
1421 | int xoffset = 0; | 1319 | int xoffset; |
1422 | int yoffset = 0; | ||
1423 | unsigned long base; | 1320 | unsigned long base; |
1424 | unsigned char tmp = 0, tmp2 = 0, xpix; | 1321 | unsigned char tmp, xpix; |
1425 | struct cirrusfb_info *cinfo = info->par; | 1322 | struct cirrusfb_info *cinfo = info->par; |
1426 | 1323 | ||
1427 | DPRINTK("ENTER\n"); | ||
1428 | DPRINTK("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset); | ||
1429 | |||
1430 | /* no range checks for xoffset and yoffset, */ | 1324 | /* no range checks for xoffset and yoffset, */ |
1431 | /* as fb_pan_display has already done this */ | 1325 | /* as fb_pan_display has already done this */ |
1432 | if (var->vmode & FB_VMODE_YWRAP) | 1326 | if (var->vmode & FB_VMODE_YWRAP) |
1433 | return -EINVAL; | 1327 | return -EINVAL; |
1434 | 1328 | ||
1435 | info->var.xoffset = var->xoffset; | ||
1436 | info->var.yoffset = var->yoffset; | ||
1437 | |||
1438 | xoffset = var->xoffset * info->var.bits_per_pixel / 8; | 1329 | xoffset = var->xoffset * info->var.bits_per_pixel / 8; |
1439 | yoffset = var->yoffset; | ||
1440 | 1330 | ||
1441 | base = yoffset * info->fix.line_length + xoffset; | 1331 | base = var->yoffset * info->fix.line_length + xoffset; |
1442 | 1332 | ||
1443 | if (info->var.bits_per_pixel == 1) { | 1333 | if (info->var.bits_per_pixel == 1) { |
1444 | /* base is already correct */ | 1334 | /* base is already correct */ |
@@ -1448,14 +1338,15 @@ static int cirrusfb_pan_display(struct fb_var_screeninfo *var, | |||
1448 | xpix = (unsigned char) ((xoffset % 4) * 2); | 1338 | xpix = (unsigned char) ((xoffset % 4) * 2); |
1449 | } | 1339 | } |
1450 | 1340 | ||
1451 | cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */ | 1341 | if (!is_laguna(cinfo)) |
1342 | cirrusfb_WaitBLT(cinfo->regbase); | ||
1452 | 1343 | ||
1453 | /* lower 8 + 8 bits of screen start address */ | 1344 | /* lower 8 + 8 bits of screen start address */ |
1454 | vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, | 1345 | vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, base & 0xff); |
1455 | (unsigned char) (base & 0xff)); | 1346 | vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, (base >> 8) & 0xff); |
1456 | vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, | ||
1457 | (unsigned char) (base >> 8)); | ||
1458 | 1347 | ||
1348 | /* 0xf2 is %11110010, exclude tmp bits */ | ||
1349 | tmp = vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2; | ||
1459 | /* construct bits 16, 17 and 18 of screen start address */ | 1350 | /* construct bits 16, 17 and 18 of screen start address */ |
1460 | if (base & 0x10000) | 1351 | if (base & 0x10000) |
1461 | tmp |= 0x01; | 1352 | tmp |= 0x01; |
@@ -1464,13 +1355,17 @@ static int cirrusfb_pan_display(struct fb_var_screeninfo *var, | |||
1464 | if (base & 0x40000) | 1355 | if (base & 0x40000) |
1465 | tmp |= 0x08; | 1356 | tmp |= 0x08; |
1466 | 1357 | ||
1467 | /* 0xf2 is %11110010, exclude tmp bits */ | 1358 | vga_wcrt(cinfo->regbase, CL_CRT1B, tmp); |
1468 | tmp2 = (vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2) | tmp; | ||
1469 | vga_wcrt(cinfo->regbase, CL_CRT1B, tmp2); | ||
1470 | 1359 | ||
1471 | /* construct bit 19 of screen start address */ | 1360 | /* construct bit 19 of screen start address */ |
1472 | if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) | 1361 | if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) { |
1473 | vga_wcrt(cinfo->regbase, CL_CRT1D, (base >> 12) & 0x80); | 1362 | tmp = vga_rcrt(cinfo->regbase, CL_CRT1D); |
1363 | if (is_laguna(cinfo)) | ||
1364 | tmp = (tmp & ~0x18) | ((base >> 16) & 0x18); | ||
1365 | else | ||
1366 | tmp = (tmp & ~0x80) | ((base >> 12) & 0x80); | ||
1367 | vga_wcrt(cinfo->regbase, CL_CRT1D, tmp); | ||
1368 | } | ||
1474 | 1369 | ||
1475 | /* write pixel panning value to AR33; this does not quite work in 8bpp | 1370 | /* write pixel panning value to AR33; this does not quite work in 8bpp |
1476 | * | 1371 | * |
@@ -1479,9 +1374,6 @@ static int cirrusfb_pan_display(struct fb_var_screeninfo *var, | |||
1479 | if (info->var.bits_per_pixel == 1) | 1374 | if (info->var.bits_per_pixel == 1) |
1480 | vga_wattr(cinfo->regbase, CL_AR33, xpix); | 1375 | vga_wattr(cinfo->regbase, CL_AR33, xpix); |
1481 | 1376 | ||
1482 | cirrusfb_WaitBLT(cinfo->regbase); | ||
1483 | |||
1484 | DPRINTK("EXIT\n"); | ||
1485 | return 0; | 1377 | return 0; |
1486 | } | 1378 | } |
1487 | 1379 | ||
@@ -1502,57 +1394,54 @@ static int cirrusfb_blank(int blank_mode, struct fb_info *info) | |||
1502 | struct cirrusfb_info *cinfo = info->par; | 1394 | struct cirrusfb_info *cinfo = info->par; |
1503 | int current_mode = cinfo->blank_mode; | 1395 | int current_mode = cinfo->blank_mode; |
1504 | 1396 | ||
1505 | DPRINTK("ENTER, blank mode = %d\n", blank_mode); | 1397 | dev_dbg(info->device, "ENTER, blank mode = %d\n", blank_mode); |
1506 | 1398 | ||
1507 | if (info->state != FBINFO_STATE_RUNNING || | 1399 | if (info->state != FBINFO_STATE_RUNNING || |
1508 | current_mode == blank_mode) { | 1400 | current_mode == blank_mode) { |
1509 | DPRINTK("EXIT, returning 0\n"); | 1401 | dev_dbg(info->device, "EXIT, returning 0\n"); |
1510 | return 0; | 1402 | return 0; |
1511 | } | 1403 | } |
1512 | 1404 | ||
1513 | /* Undo current */ | 1405 | /* Undo current */ |
1514 | if (current_mode == FB_BLANK_NORMAL || | 1406 | if (current_mode == FB_BLANK_NORMAL || |
1515 | current_mode == FB_BLANK_UNBLANK) { | 1407 | current_mode == FB_BLANK_UNBLANK) |
1516 | /* unblank the screen */ | ||
1517 | val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE); | ||
1518 | /* clear "FullBandwidth" bit */ | 1408 | /* clear "FullBandwidth" bit */ |
1519 | vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf); | 1409 | val = 0; |
1520 | /* and undo VESA suspend trickery */ | 1410 | else |
1521 | vga_wgfx(cinfo->regbase, CL_GRE, 0x00); | ||
1522 | } | ||
1523 | |||
1524 | /* set new */ | ||
1525 | if (blank_mode > FB_BLANK_NORMAL) { | ||
1526 | /* blank the screen */ | ||
1527 | val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE); | ||
1528 | /* set "FullBandwidth" bit */ | 1411 | /* set "FullBandwidth" bit */ |
1529 | vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20); | 1412 | val = 0x20; |
1530 | } | 1413 | |
1414 | val |= vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE) & 0xdf; | ||
1415 | vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val); | ||
1531 | 1416 | ||
1532 | switch (blank_mode) { | 1417 | switch (blank_mode) { |
1533 | case FB_BLANK_UNBLANK: | 1418 | case FB_BLANK_UNBLANK: |
1534 | case FB_BLANK_NORMAL: | 1419 | case FB_BLANK_NORMAL: |
1420 | val = 0x00; | ||
1535 | break; | 1421 | break; |
1536 | case FB_BLANK_VSYNC_SUSPEND: | 1422 | case FB_BLANK_VSYNC_SUSPEND: |
1537 | vga_wgfx(cinfo->regbase, CL_GRE, 0x04); | 1423 | val = 0x04; |
1538 | break; | 1424 | break; |
1539 | case FB_BLANK_HSYNC_SUSPEND: | 1425 | case FB_BLANK_HSYNC_SUSPEND: |
1540 | vga_wgfx(cinfo->regbase, CL_GRE, 0x02); | 1426 | val = 0x02; |
1541 | break; | 1427 | break; |
1542 | case FB_BLANK_POWERDOWN: | 1428 | case FB_BLANK_POWERDOWN: |
1543 | vga_wgfx(cinfo->regbase, CL_GRE, 0x06); | 1429 | val = 0x06; |
1544 | break; | 1430 | break; |
1545 | default: | 1431 | default: |
1546 | DPRINTK("EXIT, returning 1\n"); | 1432 | dev_dbg(info->device, "EXIT, returning 1\n"); |
1547 | return 1; | 1433 | return 1; |
1548 | } | 1434 | } |
1549 | 1435 | ||
1436 | vga_wgfx(cinfo->regbase, CL_GRE, val); | ||
1437 | |||
1550 | cinfo->blank_mode = blank_mode; | 1438 | cinfo->blank_mode = blank_mode; |
1551 | DPRINTK("EXIT, returning 0\n"); | 1439 | dev_dbg(info->device, "EXIT, returning 0\n"); |
1552 | 1440 | ||
1553 | /* Let fbcon do a soft blank for us */ | 1441 | /* Let fbcon do a soft blank for us */ |
1554 | return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0; | 1442 | return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0; |
1555 | } | 1443 | } |
1444 | |||
1556 | /**** END Hardware specific Routines **************************************/ | 1445 | /**** END Hardware specific Routines **************************************/ |
1557 | /****************************************************************************/ | 1446 | /****************************************************************************/ |
1558 | /**** BEGIN Internal Routines ***********************************************/ | 1447 | /**** BEGIN Internal Routines ***********************************************/ |
@@ -1562,8 +1451,6 @@ static void init_vgachip(struct fb_info *info) | |||
1562 | struct cirrusfb_info *cinfo = info->par; | 1451 | struct cirrusfb_info *cinfo = info->par; |
1563 | const struct cirrusfb_board_info_rec *bi; | 1452 | const struct cirrusfb_board_info_rec *bi; |
1564 | 1453 | ||
1565 | DPRINTK("ENTER\n"); | ||
1566 | |||
1567 | assert(cinfo != NULL); | 1454 | assert(cinfo != NULL); |
1568 | 1455 | ||
1569 | bi = &cirrusfb_board_info[cinfo->btype]; | 1456 | bi = &cirrusfb_board_info[cinfo->btype]; |
@@ -1591,25 +1478,23 @@ static void init_vgachip(struct fb_info *info) | |||
1591 | /* disable flickerfixer */ | 1478 | /* disable flickerfixer */ |
1592 | vga_wcrt(cinfo->regbase, CL_CRT51, 0x00); | 1479 | vga_wcrt(cinfo->regbase, CL_CRT51, 0x00); |
1593 | mdelay(100); | 1480 | mdelay(100); |
1594 | /* from Klaus' NetBSD driver: */ | ||
1595 | vga_wgfx(cinfo->regbase, CL_GR2F, 0x00); | ||
1596 | /* put blitter into 542x compat */ | ||
1597 | vga_wgfx(cinfo->regbase, CL_GR33, 0x00); | ||
1598 | /* mode */ | 1481 | /* mode */ |
1599 | vga_wgfx(cinfo->regbase, CL_GR31, 0x00); | 1482 | vga_wgfx(cinfo->regbase, CL_GR31, 0x00); |
1600 | break; | 1483 | case BT_GD5480: /* fall through */ |
1601 | |||
1602 | case BT_GD5480: | ||
1603 | /* from Klaus' NetBSD driver: */ | 1484 | /* from Klaus' NetBSD driver: */ |
1604 | vga_wgfx(cinfo->regbase, CL_GR2F, 0x00); | 1485 | vga_wgfx(cinfo->regbase, CL_GR2F, 0x00); |
1486 | case BT_ALPINE: /* fall through */ | ||
1487 | /* put blitter into 542x compat */ | ||
1488 | vga_wgfx(cinfo->regbase, CL_GR33, 0x00); | ||
1605 | break; | 1489 | break; |
1606 | 1490 | ||
1607 | case BT_ALPINE: | 1491 | case BT_LAGUNA: |
1492 | case BT_LAGUNAB: | ||
1608 | /* Nothing to do to reset the board. */ | 1493 | /* Nothing to do to reset the board. */ |
1609 | break; | 1494 | break; |
1610 | 1495 | ||
1611 | default: | 1496 | default: |
1612 | printk(KERN_ERR "cirrusfb: Warning: Unknown board type\n"); | 1497 | dev_err(info->device, "Warning: Unknown board type\n"); |
1613 | break; | 1498 | break; |
1614 | } | 1499 | } |
1615 | 1500 | ||
@@ -1629,31 +1514,28 @@ static void init_vgachip(struct fb_info *info) | |||
1629 | WGen(cinfo, CL_VSSM2, 0x01); | 1514 | WGen(cinfo, CL_VSSM2, 0x01); |
1630 | 1515 | ||
1631 | /* reset sequencer logic */ | 1516 | /* reset sequencer logic */ |
1632 | vga_wseq(cinfo->regbase, CL_SEQR0, 0x03); | 1517 | vga_wseq(cinfo->regbase, VGA_SEQ_RESET, 0x03); |
1633 | 1518 | ||
1634 | /* FullBandwidth (video off) and 8/9 dot clock */ | 1519 | /* FullBandwidth (video off) and 8/9 dot clock */ |
1635 | vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21); | 1520 | vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21); |
1636 | /* polarity (-/-), disable access to display memory, | ||
1637 | * VGA_CRTC_START_HI base address: color | ||
1638 | */ | ||
1639 | WGen(cinfo, VGA_MIS_W, 0xc1); | ||
1640 | 1521 | ||
1641 | /* "magic cookie" - doesn't make any sense to me.. */ | 1522 | /* "magic cookie" - doesn't make any sense to me.. */ |
1642 | /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */ | 1523 | /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */ |
1643 | /* unlock all extension registers */ | 1524 | /* unlock all extension registers */ |
1644 | vga_wseq(cinfo->regbase, CL_SEQR6, 0x12); | 1525 | vga_wseq(cinfo->regbase, CL_SEQR6, 0x12); |
1645 | 1526 | ||
1646 | /* reset blitter */ | ||
1647 | vga_wgfx(cinfo->regbase, CL_GR31, 0x04); | ||
1648 | |||
1649 | switch (cinfo->btype) { | 1527 | switch (cinfo->btype) { |
1650 | case BT_GD5480: | 1528 | case BT_GD5480: |
1651 | vga_wseq(cinfo->regbase, CL_SEQRF, 0x98); | 1529 | vga_wseq(cinfo->regbase, CL_SEQRF, 0x98); |
1652 | break; | 1530 | break; |
1653 | case BT_ALPINE: | 1531 | case BT_ALPINE: |
1532 | case BT_LAGUNA: | ||
1533 | case BT_LAGUNAB: | ||
1654 | break; | 1534 | break; |
1655 | case BT_SD64: | 1535 | case BT_SD64: |
1536 | #ifdef CONFIG_ZORRO | ||
1656 | vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8); | 1537 | vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8); |
1538 | #endif | ||
1657 | break; | 1539 | break; |
1658 | default: | 1540 | default: |
1659 | vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f); | 1541 | vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f); |
@@ -1665,8 +1547,8 @@ static void init_vgachip(struct fb_info *info) | |||
1665 | vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff); | 1547 | vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff); |
1666 | /* character map select: doesn't even matter in gx mode */ | 1548 | /* character map select: doesn't even matter in gx mode */ |
1667 | vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); | 1549 | vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); |
1668 | /* memory mode: chain-4, no odd/even, ext. memory */ | 1550 | /* memory mode: chain4, ext. memory */ |
1669 | vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e); | 1551 | vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0a); |
1670 | 1552 | ||
1671 | /* controller-internal base address of video memory */ | 1553 | /* controller-internal base address of video memory */ |
1672 | if (bi->init_sr07) | 1554 | if (bi->init_sr07) |
@@ -1692,20 +1574,12 @@ static void init_vgachip(struct fb_info *info) | |||
1692 | vga_wseq(cinfo->regbase, CL_SEQR18, 0x02); | 1574 | vga_wseq(cinfo->regbase, CL_SEQR18, 0x02); |
1693 | } | 1575 | } |
1694 | 1576 | ||
1695 | /* MCLK select etc. */ | ||
1696 | if (bi->init_sr1f) | ||
1697 | vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f); | ||
1698 | |||
1699 | /* Screen A preset row scan: none */ | 1577 | /* Screen A preset row scan: none */ |
1700 | vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00); | 1578 | vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00); |
1701 | /* Text cursor start: disable text cursor */ | 1579 | /* Text cursor start: disable text cursor */ |
1702 | vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); | 1580 | vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); |
1703 | /* Text cursor end: - */ | 1581 | /* Text cursor end: - */ |
1704 | vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00); | 1582 | vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00); |
1705 | /* Screen start address high: 0 */ | ||
1706 | vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, 0x00); | ||
1707 | /* Screen start address low: 0 */ | ||
1708 | vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 0x00); | ||
1709 | /* text cursor location high: 0 */ | 1583 | /* text cursor location high: 0 */ |
1710 | vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00); | 1584 | vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00); |
1711 | /* text cursor location low: 0 */ | 1585 | /* text cursor location low: 0 */ |
@@ -1713,10 +1587,6 @@ static void init_vgachip(struct fb_info *info) | |||
1713 | 1587 | ||
1714 | /* Underline Row scanline: - */ | 1588 | /* Underline Row scanline: - */ |
1715 | vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00); | 1589 | vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00); |
1716 | /* mode control: timing enable, byte mode, no compat modes */ | ||
1717 | vga_wcrt(cinfo->regbase, VGA_CRTC_MODE, 0xc3); | ||
1718 | /* Line Compare: not needed */ | ||
1719 | vga_wcrt(cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00); | ||
1720 | /* ### add 0x40 for text modes with > 30 MHz pixclock */ | 1590 | /* ### add 0x40 for text modes with > 30 MHz pixclock */ |
1721 | /* ext. display controls: ext.adr. wrap */ | 1591 | /* ext. display controls: ext.adr. wrap */ |
1722 | vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02); | 1592 | vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02); |
@@ -1739,7 +1609,9 @@ static void init_vgachip(struct fb_info *info) | |||
1739 | vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f); | 1609 | vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f); |
1740 | /* Bit Mask: no mask at all */ | 1610 | /* Bit Mask: no mask at all */ |
1741 | vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff); | 1611 | vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff); |
1742 | if (cinfo->btype == BT_ALPINE) | 1612 | |
1613 | if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64 || | ||
1614 | is_laguna(cinfo)) | ||
1743 | /* (5434 can't have bit 3 set for bitblt) */ | 1615 | /* (5434 can't have bit 3 set for bitblt) */ |
1744 | vga_wgfx(cinfo->regbase, CL_GRB, 0x20); | 1616 | vga_wgfx(cinfo->regbase, CL_GRB, 0x20); |
1745 | else | 1617 | else |
@@ -1779,18 +1651,11 @@ static void init_vgachip(struct fb_info *info) | |||
1779 | vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00); | 1651 | vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00); |
1780 | /* Color Plane enable: Enable all 4 planes */ | 1652 | /* Color Plane enable: Enable all 4 planes */ |
1781 | vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f); | 1653 | vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f); |
1782 | /* ### vga_wattr(cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */ | ||
1783 | /* Color Select: - */ | 1654 | /* Color Select: - */ |
1784 | vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00); | 1655 | vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00); |
1785 | 1656 | ||
1786 | WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */ | 1657 | WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */ |
1787 | 1658 | ||
1788 | if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480) | ||
1789 | /* polarity (-/-), enable display mem, | ||
1790 | * VGA_CRTC_START_HI i/o base = color | ||
1791 | */ | ||
1792 | WGen(cinfo, VGA_MIS_W, 0xc3); | ||
1793 | |||
1794 | /* BLT Start/status: Blitter reset */ | 1659 | /* BLT Start/status: Blitter reset */ |
1795 | vga_wgfx(cinfo->regbase, CL_GR31, 0x04); | 1660 | vga_wgfx(cinfo->regbase, CL_GR31, 0x04); |
1796 | /* - " - : "end-of-reset" */ | 1661 | /* - " - : "end-of-reset" */ |
@@ -1798,8 +1663,6 @@ static void init_vgachip(struct fb_info *info) | |||
1798 | 1663 | ||
1799 | /* misc... */ | 1664 | /* misc... */ |
1800 | WHDR(cinfo, 0); /* Hidden DAC register: - */ | 1665 | WHDR(cinfo, 0); /* Hidden DAC register: - */ |
1801 | |||
1802 | DPRINTK("EXIT\n"); | ||
1803 | return; | 1666 | return; |
1804 | } | 1667 | } |
1805 | 1668 | ||
@@ -1808,8 +1671,6 @@ static void switch_monitor(struct cirrusfb_info *cinfo, int on) | |||
1808 | #ifdef CONFIG_ZORRO /* only works on Zorro boards */ | 1671 | #ifdef CONFIG_ZORRO /* only works on Zorro boards */ |
1809 | static int IsOn = 0; /* XXX not ok for multiple boards */ | 1672 | static int IsOn = 0; /* XXX not ok for multiple boards */ |
1810 | 1673 | ||
1811 | DPRINTK("ENTER\n"); | ||
1812 | |||
1813 | if (cinfo->btype == BT_PICASSO4) | 1674 | if (cinfo->btype == BT_PICASSO4) |
1814 | return; /* nothing to switch */ | 1675 | return; /* nothing to switch */ |
1815 | if (cinfo->btype == BT_ALPINE) | 1676 | if (cinfo->btype == BT_ALPINE) |
@@ -1819,8 +1680,6 @@ static void switch_monitor(struct cirrusfb_info *cinfo, int on) | |||
1819 | if (cinfo->btype == BT_PICASSO) { | 1680 | if (cinfo->btype == BT_PICASSO) { |
1820 | if ((on && !IsOn) || (!on && IsOn)) | 1681 | if ((on && !IsOn) || (!on && IsOn)) |
1821 | WSFR(cinfo, 0xff); | 1682 | WSFR(cinfo, 0xff); |
1822 | |||
1823 | DPRINTK("EXIT\n"); | ||
1824 | return; | 1683 | return; |
1825 | } | 1684 | } |
1826 | if (on) { | 1685 | if (on) { |
@@ -1847,11 +1706,10 @@ static void switch_monitor(struct cirrusfb_info *cinfo, int on) | |||
1847 | case BT_SPECTRUM: | 1706 | case BT_SPECTRUM: |
1848 | WSFR(cinfo, 0x4f); | 1707 | WSFR(cinfo, 0x4f); |
1849 | break; | 1708 | break; |
1850 | default: /* do nothing */ break; | 1709 | default: /* do nothing */ |
1710 | break; | ||
1851 | } | 1711 | } |
1852 | } | 1712 | } |
1853 | |||
1854 | DPRINTK("EXIT\n"); | ||
1855 | #endif /* CONFIG_ZORRO */ | 1713 | #endif /* CONFIG_ZORRO */ |
1856 | } | 1714 | } |
1857 | 1715 | ||
@@ -1859,6 +1717,17 @@ static void switch_monitor(struct cirrusfb_info *cinfo, int on) | |||
1859 | /* Linux 2.6-style accelerated functions */ | 1717 | /* Linux 2.6-style accelerated functions */ |
1860 | /******************************************/ | 1718 | /******************************************/ |
1861 | 1719 | ||
1720 | static int cirrusfb_sync(struct fb_info *info) | ||
1721 | { | ||
1722 | struct cirrusfb_info *cinfo = info->par; | ||
1723 | |||
1724 | if (!is_laguna(cinfo)) { | ||
1725 | while (vga_rgfx(cinfo->regbase, CL_GR31) & 0x03) | ||
1726 | cpu_relax(); | ||
1727 | } | ||
1728 | return 0; | ||
1729 | } | ||
1730 | |||
1862 | static void cirrusfb_fillrect(struct fb_info *info, | 1731 | static void cirrusfb_fillrect(struct fb_info *info, |
1863 | const struct fb_fillrect *region) | 1732 | const struct fb_fillrect *region) |
1864 | { | 1733 | { |
@@ -1894,8 +1763,8 @@ static void cirrusfb_fillrect(struct fb_info *info, | |||
1894 | info->var.bits_per_pixel, | 1763 | info->var.bits_per_pixel, |
1895 | (region->dx * m) / 8, region->dy, | 1764 | (region->dx * m) / 8, region->dy, |
1896 | (region->width * m) / 8, region->height, | 1765 | (region->width * m) / 8, region->height, |
1897 | color, | 1766 | color, color, |
1898 | info->fix.line_length); | 1767 | info->fix.line_length, 0x40); |
1899 | } | 1768 | } |
1900 | 1769 | ||
1901 | static void cirrusfb_copyarea(struct fb_info *info, | 1770 | static void cirrusfb_copyarea(struct fb_info *info, |
@@ -1943,9 +1812,46 @@ static void cirrusfb_imageblit(struct fb_info *info, | |||
1943 | const struct fb_image *image) | 1812 | const struct fb_image *image) |
1944 | { | 1813 | { |
1945 | struct cirrusfb_info *cinfo = info->par; | 1814 | struct cirrusfb_info *cinfo = info->par; |
1815 | unsigned char op = (info->var.bits_per_pixel == 24) ? 0xc : 0x4; | ||
1946 | 1816 | ||
1947 | cirrusfb_WaitBLT(cinfo->regbase); | 1817 | if (info->state != FBINFO_STATE_RUNNING) |
1948 | cfb_imageblit(info, image); | 1818 | return; |
1819 | /* Alpine/SD64 does not work at 24bpp ??? */ | ||
1820 | if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1) | ||
1821 | cfb_imageblit(info, image); | ||
1822 | else if ((cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64) && | ||
1823 | op == 0xc) | ||
1824 | cfb_imageblit(info, image); | ||
1825 | else { | ||
1826 | unsigned size = ((image->width + 7) >> 3) * image->height; | ||
1827 | int m = info->var.bits_per_pixel; | ||
1828 | u32 fg, bg; | ||
1829 | |||
1830 | if (info->var.bits_per_pixel == 8) { | ||
1831 | fg = image->fg_color; | ||
1832 | bg = image->bg_color; | ||
1833 | } else { | ||
1834 | fg = ((u32 *)(info->pseudo_palette))[image->fg_color]; | ||
1835 | bg = ((u32 *)(info->pseudo_palette))[image->bg_color]; | ||
1836 | } | ||
1837 | if (info->var.bits_per_pixel == 24) { | ||
1838 | /* clear background first */ | ||
1839 | cirrusfb_RectFill(cinfo->regbase, | ||
1840 | info->var.bits_per_pixel, | ||
1841 | (image->dx * m) / 8, image->dy, | ||
1842 | (image->width * m) / 8, | ||
1843 | image->height, | ||
1844 | bg, bg, | ||
1845 | info->fix.line_length, 0x40); | ||
1846 | } | ||
1847 | cirrusfb_RectFill(cinfo->regbase, | ||
1848 | info->var.bits_per_pixel, | ||
1849 | (image->dx * m) / 8, image->dy, | ||
1850 | (image->width * m) / 8, image->height, | ||
1851 | fg, bg, | ||
1852 | info->fix.line_length, op); | ||
1853 | memcpy(info->screen_base, image->data, size); | ||
1854 | } | ||
1949 | } | 1855 | } |
1950 | 1856 | ||
1951 | #ifdef CONFIG_PPC_PREP | 1857 | #ifdef CONFIG_PPC_PREP |
@@ -1953,12 +1859,8 @@ static void cirrusfb_imageblit(struct fb_info *info, | |||
1953 | #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000) | 1859 | #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000) |
1954 | static void get_prep_addrs(unsigned long *display, unsigned long *registers) | 1860 | static void get_prep_addrs(unsigned long *display, unsigned long *registers) |
1955 | { | 1861 | { |
1956 | DPRINTK("ENTER\n"); | ||
1957 | |||
1958 | *display = PREP_VIDEO_BASE; | 1862 | *display = PREP_VIDEO_BASE; |
1959 | *registers = (unsigned long) PREP_IO_BASE; | 1863 | *registers = (unsigned long) PREP_IO_BASE; |
1960 | |||
1961 | DPRINTK("EXIT\n"); | ||
1962 | } | 1864 | } |
1963 | 1865 | ||
1964 | #endif /* CONFIG_PPC_PREP */ | 1866 | #endif /* CONFIG_PPC_PREP */ |
@@ -1970,40 +1872,43 @@ static int release_io_ports; | |||
1970 | * based on the DRAM bandwidth bit and DRAM bank switching bit. This | 1872 | * based on the DRAM bandwidth bit and DRAM bank switching bit. This |
1971 | * works with 1MB, 2MB and 4MB configurations (which the Motorola boards | 1873 | * works with 1MB, 2MB and 4MB configurations (which the Motorola boards |
1972 | * seem to have. */ | 1874 | * seem to have. */ |
1973 | static unsigned int __devinit cirrusfb_get_memsize(u8 __iomem *regbase) | 1875 | static unsigned int __devinit cirrusfb_get_memsize(struct fb_info *info, |
1876 | u8 __iomem *regbase) | ||
1974 | { | 1877 | { |
1975 | unsigned long mem; | 1878 | unsigned long mem; |
1976 | unsigned char SRF; | 1879 | struct cirrusfb_info *cinfo = info->par; |
1977 | 1880 | ||
1978 | DPRINTK("ENTER\n"); | 1881 | if (is_laguna(cinfo)) { |
1882 | unsigned char SR14 = vga_rseq(regbase, CL_SEQR14); | ||
1979 | 1883 | ||
1980 | SRF = vga_rseq(regbase, CL_SEQRF); | 1884 | mem = ((SR14 & 7) + 1) << 20; |
1981 | switch ((SRF & 0x18)) { | 1885 | } else { |
1982 | case 0x08: | 1886 | unsigned char SRF = vga_rseq(regbase, CL_SEQRF); |
1983 | mem = 512 * 1024; | 1887 | switch ((SRF & 0x18)) { |
1984 | break; | 1888 | case 0x08: |
1985 | case 0x10: | 1889 | mem = 512 * 1024; |
1986 | mem = 1024 * 1024; | 1890 | break; |
1987 | break; | 1891 | case 0x10: |
1988 | /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory | 1892 | mem = 1024 * 1024; |
1989 | * on the 5430. | 1893 | break; |
1990 | */ | 1894 | /* 64-bit DRAM data bus width; assume 2MB. |
1991 | case 0x18: | 1895 | * Also indicates 2MB memory on the 5430. |
1992 | mem = 2048 * 1024; | 1896 | */ |
1993 | break; | 1897 | case 0x18: |
1994 | default: | 1898 | mem = 2048 * 1024; |
1995 | printk(KERN_WARNING "CLgenfb: Unknown memory size!\n"); | 1899 | break; |
1996 | mem = 1024 * 1024; | 1900 | default: |
1901 | dev_warn(info->device, "Unknown memory size!\n"); | ||
1902 | mem = 1024 * 1024; | ||
1903 | } | ||
1904 | /* If DRAM bank switching is enabled, there must be | ||
1905 | * twice as much memory installed. (4MB on the 5434) | ||
1906 | */ | ||
1907 | if (cinfo->btype != BT_ALPINE && (SRF & 0x80) != 0) | ||
1908 | mem *= 2; | ||
1997 | } | 1909 | } |
1998 | if (SRF & 0x80) | ||
1999 | /* If DRAM bank switching is enabled, there must be twice as much | ||
2000 | * memory installed. (4MB on the 5434) | ||
2001 | */ | ||
2002 | mem *= 2; | ||
2003 | 1910 | ||
2004 | /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */ | 1911 | /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */ |
2005 | |||
2006 | DPRINTK("EXIT\n"); | ||
2007 | return mem; | 1912 | return mem; |
2008 | } | 1913 | } |
2009 | 1914 | ||
@@ -2014,8 +1919,6 @@ static void get_pci_addrs(const struct pci_dev *pdev, | |||
2014 | assert(display != NULL); | 1919 | assert(display != NULL); |
2015 | assert(registers != NULL); | 1920 | assert(registers != NULL); |
2016 | 1921 | ||
2017 | DPRINTK("ENTER\n"); | ||
2018 | |||
2019 | *display = 0; | 1922 | *display = 0; |
2020 | *registers = 0; | 1923 | *registers = 0; |
2021 | 1924 | ||
@@ -2030,14 +1933,15 @@ static void get_pci_addrs(const struct pci_dev *pdev, | |||
2030 | } | 1933 | } |
2031 | 1934 | ||
2032 | assert(*display != 0); | 1935 | assert(*display != 0); |
2033 | |||
2034 | DPRINTK("EXIT\n"); | ||
2035 | } | 1936 | } |
2036 | 1937 | ||
2037 | static void cirrusfb_pci_unmap(struct fb_info *info) | 1938 | static void cirrusfb_pci_unmap(struct fb_info *info) |
2038 | { | 1939 | { |
2039 | struct pci_dev *pdev = to_pci_dev(info->device); | 1940 | struct pci_dev *pdev = to_pci_dev(info->device); |
1941 | struct cirrusfb_info *cinfo = info->par; | ||
2040 | 1942 | ||
1943 | if (cinfo->laguna_mmio == NULL) | ||
1944 | iounmap(cinfo->laguna_mmio); | ||
2041 | iounmap(info->screen_base); | 1945 | iounmap(info->screen_base); |
2042 | #if 0 /* if system didn't claim this region, we would... */ | 1946 | #if 0 /* if system didn't claim this region, we would... */ |
2043 | release_mem_region(0xA0000, 65535); | 1947 | release_mem_region(0xA0000, 65535); |
@@ -2067,6 +1971,22 @@ static void cirrusfb_zorro_unmap(struct fb_info *info) | |||
2067 | } | 1971 | } |
2068 | #endif /* CONFIG_ZORRO */ | 1972 | #endif /* CONFIG_ZORRO */ |
2069 | 1973 | ||
1974 | /* function table of the above functions */ | ||
1975 | static struct fb_ops cirrusfb_ops = { | ||
1976 | .owner = THIS_MODULE, | ||
1977 | .fb_open = cirrusfb_open, | ||
1978 | .fb_release = cirrusfb_release, | ||
1979 | .fb_setcolreg = cirrusfb_setcolreg, | ||
1980 | .fb_check_var = cirrusfb_check_var, | ||
1981 | .fb_set_par = cirrusfb_set_par, | ||
1982 | .fb_pan_display = cirrusfb_pan_display, | ||
1983 | .fb_blank = cirrusfb_blank, | ||
1984 | .fb_fillrect = cirrusfb_fillrect, | ||
1985 | .fb_copyarea = cirrusfb_copyarea, | ||
1986 | .fb_sync = cirrusfb_sync, | ||
1987 | .fb_imageblit = cirrusfb_imageblit, | ||
1988 | }; | ||
1989 | |||
2070 | static int __devinit cirrusfb_set_fbinfo(struct fb_info *info) | 1990 | static int __devinit cirrusfb_set_fbinfo(struct fb_info *info) |
2071 | { | 1991 | { |
2072 | struct cirrusfb_info *cinfo = info->par; | 1992 | struct cirrusfb_info *cinfo = info->par; |
@@ -2077,10 +1997,16 @@ static int __devinit cirrusfb_set_fbinfo(struct fb_info *info) | |||
2077 | | FBINFO_HWACCEL_XPAN | 1997 | | FBINFO_HWACCEL_XPAN |
2078 | | FBINFO_HWACCEL_YPAN | 1998 | | FBINFO_HWACCEL_YPAN |
2079 | | FBINFO_HWACCEL_FILLRECT | 1999 | | FBINFO_HWACCEL_FILLRECT |
2000 | | FBINFO_HWACCEL_IMAGEBLIT | ||
2080 | | FBINFO_HWACCEL_COPYAREA; | 2001 | | FBINFO_HWACCEL_COPYAREA; |
2081 | if (noaccel) | 2002 | if (noaccel || is_laguna(cinfo)) { |
2082 | info->flags |= FBINFO_HWACCEL_DISABLED; | 2003 | info->flags |= FBINFO_HWACCEL_DISABLED; |
2004 | info->fix.accel = FB_ACCEL_NONE; | ||
2005 | } else | ||
2006 | info->fix.accel = FB_ACCEL_CIRRUS_ALPINE; | ||
2007 | |||
2083 | info->fbops = &cirrusfb_ops; | 2008 | info->fbops = &cirrusfb_ops; |
2009 | |||
2084 | if (cinfo->btype == BT_GD5480) { | 2010 | if (cinfo->btype == BT_GD5480) { |
2085 | if (var->bits_per_pixel == 16) | 2011 | if (var->bits_per_pixel == 16) |
2086 | info->screen_base += 1 * MB_; | 2012 | info->screen_base += 1 * MB_; |
@@ -2104,7 +2030,6 @@ static int __devinit cirrusfb_set_fbinfo(struct fb_info *info) | |||
2104 | 2030 | ||
2105 | /* FIXME: map region at 0xB8000 if available, fill in here */ | 2031 | /* FIXME: map region at 0xB8000 if available, fill in here */ |
2106 | info->fix.mmio_len = 0; | 2032 | info->fix.mmio_len = 0; |
2107 | info->fix.accel = FB_ACCEL_NONE; | ||
2108 | 2033 | ||
2109 | fb_alloc_cmap(&info->cmap, 256, 0); | 2034 | fb_alloc_cmap(&info->cmap, 256, 0); |
2110 | 2035 | ||
@@ -2115,70 +2040,56 @@ static int __devinit cirrusfb_register(struct fb_info *info) | |||
2115 | { | 2040 | { |
2116 | struct cirrusfb_info *cinfo = info->par; | 2041 | struct cirrusfb_info *cinfo = info->par; |
2117 | int err; | 2042 | int err; |
2118 | enum cirrus_board btype; | ||
2119 | |||
2120 | DPRINTK("ENTER\n"); | ||
2121 | |||
2122 | printk(KERN_INFO "cirrusfb: Driver for Cirrus Logic based " | ||
2123 | "graphic boards, v" CIRRUSFB_VERSION "\n"); | ||
2124 | |||
2125 | btype = cinfo->btype; | ||
2126 | 2043 | ||
2127 | /* sanity checks */ | 2044 | /* sanity checks */ |
2128 | assert(btype != BT_NONE); | 2045 | assert(cinfo->btype != BT_NONE); |
2129 | 2046 | ||
2130 | /* set all the vital stuff */ | 2047 | /* set all the vital stuff */ |
2131 | cirrusfb_set_fbinfo(info); | 2048 | cirrusfb_set_fbinfo(info); |
2132 | 2049 | ||
2133 | DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base); | 2050 | dev_dbg(info->device, "(RAM start set to: 0x%p)\n", info->screen_base); |
2134 | 2051 | ||
2135 | err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); | 2052 | err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); |
2136 | if (!err) { | 2053 | if (!err) { |
2137 | DPRINTK("wrong initial video mode\n"); | 2054 | dev_dbg(info->device, "wrong initial video mode\n"); |
2138 | err = -EINVAL; | 2055 | err = -EINVAL; |
2139 | goto err_dealloc_cmap; | 2056 | goto err_dealloc_cmap; |
2140 | } | 2057 | } |
2141 | 2058 | ||
2142 | info->var.activate = FB_ACTIVATE_NOW; | 2059 | info->var.activate = FB_ACTIVATE_NOW; |
2143 | 2060 | ||
2144 | err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info); | 2061 | err = cirrusfb_check_var(&info->var, info); |
2145 | if (err < 0) { | 2062 | if (err < 0) { |
2146 | /* should never happen */ | 2063 | /* should never happen */ |
2147 | DPRINTK("choking on default var... umm, no good.\n"); | 2064 | dev_dbg(info->device, |
2065 | "choking on default var... umm, no good.\n"); | ||
2148 | goto err_dealloc_cmap; | 2066 | goto err_dealloc_cmap; |
2149 | } | 2067 | } |
2150 | 2068 | ||
2151 | err = register_framebuffer(info); | 2069 | err = register_framebuffer(info); |
2152 | if (err < 0) { | 2070 | if (err < 0) { |
2153 | printk(KERN_ERR "cirrusfb: could not register " | 2071 | dev_err(info->device, |
2154 | "fb device; err = %d!\n", err); | 2072 | "could not register fb device; err = %d!\n", err); |
2155 | goto err_dealloc_cmap; | 2073 | goto err_dealloc_cmap; |
2156 | } | 2074 | } |
2157 | 2075 | ||
2158 | DPRINTK("EXIT, returning 0\n"); | ||
2159 | return 0; | 2076 | return 0; |
2160 | 2077 | ||
2161 | err_dealloc_cmap: | 2078 | err_dealloc_cmap: |
2162 | fb_dealloc_cmap(&info->cmap); | 2079 | fb_dealloc_cmap(&info->cmap); |
2163 | cinfo->unmap(info); | ||
2164 | framebuffer_release(info); | ||
2165 | return err; | 2080 | return err; |
2166 | } | 2081 | } |
2167 | 2082 | ||
2168 | static void __devexit cirrusfb_cleanup(struct fb_info *info) | 2083 | static void __devexit cirrusfb_cleanup(struct fb_info *info) |
2169 | { | 2084 | { |
2170 | struct cirrusfb_info *cinfo = info->par; | 2085 | struct cirrusfb_info *cinfo = info->par; |
2171 | DPRINTK("ENTER\n"); | ||
2172 | 2086 | ||
2173 | switch_monitor(cinfo, 0); | 2087 | switch_monitor(cinfo, 0); |
2174 | |||
2175 | unregister_framebuffer(info); | 2088 | unregister_framebuffer(info); |
2176 | fb_dealloc_cmap(&info->cmap); | 2089 | fb_dealloc_cmap(&info->cmap); |
2177 | printk("Framebuffer unregistered\n"); | 2090 | dev_dbg(info->device, "Framebuffer unregistered\n"); |
2178 | cinfo->unmap(info); | 2091 | cinfo->unmap(info); |
2179 | framebuffer_release(info); | 2092 | framebuffer_release(info); |
2180 | |||
2181 | DPRINTK("EXIT\n"); | ||
2182 | } | 2093 | } |
2183 | 2094 | ||
2184 | #ifdef CONFIG_PCI | 2095 | #ifdef CONFIG_PCI |
@@ -2187,7 +2098,6 @@ static int __devinit cirrusfb_pci_register(struct pci_dev *pdev, | |||
2187 | { | 2098 | { |
2188 | struct cirrusfb_info *cinfo; | 2099 | struct cirrusfb_info *cinfo; |
2189 | struct fb_info *info; | 2100 | struct fb_info *info; |
2190 | enum cirrus_board btype; | ||
2191 | unsigned long board_addr, board_size; | 2101 | unsigned long board_addr, board_size; |
2192 | int ret; | 2102 | int ret; |
2193 | 2103 | ||
@@ -2201,15 +2111,17 @@ static int __devinit cirrusfb_pci_register(struct pci_dev *pdev, | |||
2201 | if (!info) { | 2111 | if (!info) { |
2202 | printk(KERN_ERR "cirrusfb: could not allocate memory\n"); | 2112 | printk(KERN_ERR "cirrusfb: could not allocate memory\n"); |
2203 | ret = -ENOMEM; | 2113 | ret = -ENOMEM; |
2204 | goto err_disable; | 2114 | goto err_out; |
2205 | } | 2115 | } |
2206 | 2116 | ||
2207 | cinfo = info->par; | 2117 | cinfo = info->par; |
2208 | cinfo->btype = btype = (enum cirrus_board) ent->driver_data; | 2118 | cinfo->btype = (enum cirrus_board) ent->driver_data; |
2209 | 2119 | ||
2210 | DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n", | 2120 | dev_dbg(info->device, |
2211 | pdev->resource[0].start, btype); | 2121 | " Found PCI device, base address 0 is 0x%Lx, btype set to %d\n", |
2212 | DPRINTK(" base address 1 is 0x%x\n", pdev->resource[1].start); | 2122 | (unsigned long long)pdev->resource[0].start, cinfo->btype); |
2123 | dev_dbg(info->device, " base address 1 is 0x%Lx\n", | ||
2124 | (unsigned long long)pdev->resource[1].start); | ||
2213 | 2125 | ||
2214 | if (isPReP) { | 2126 | if (isPReP) { |
2215 | pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000); | 2127 | pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000); |
@@ -2219,30 +2131,30 @@ static int __devinit cirrusfb_pci_register(struct pci_dev *pdev, | |||
2219 | /* PReP dies if we ioremap the IO registers, but it works w/out... */ | 2131 | /* PReP dies if we ioremap the IO registers, but it works w/out... */ |
2220 | cinfo->regbase = (char __iomem *) info->fix.mmio_start; | 2132 | cinfo->regbase = (char __iomem *) info->fix.mmio_start; |
2221 | } else { | 2133 | } else { |
2222 | DPRINTK("Attempt to get PCI info for Cirrus Graphics Card\n"); | 2134 | dev_dbg(info->device, |
2135 | "Attempt to get PCI info for Cirrus Graphics Card\n"); | ||
2223 | get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start); | 2136 | get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start); |
2224 | /* FIXME: this forces VGA. alternatives? */ | 2137 | /* FIXME: this forces VGA. alternatives? */ |
2225 | cinfo->regbase = NULL; | 2138 | cinfo->regbase = NULL; |
2139 | cinfo->laguna_mmio = ioremap(info->fix.mmio_start, 0x1000); | ||
2226 | } | 2140 | } |
2227 | 2141 | ||
2228 | DPRINTK("Board address: 0x%lx, register address: 0x%lx\n", | 2142 | dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n", |
2229 | board_addr, info->fix.mmio_start); | 2143 | board_addr, info->fix.mmio_start); |
2230 | 2144 | ||
2231 | board_size = (btype == BT_GD5480) ? | 2145 | board_size = (cinfo->btype == BT_GD5480) ? |
2232 | 32 * MB_ : cirrusfb_get_memsize(cinfo->regbase); | 2146 | 32 * MB_ : cirrusfb_get_memsize(info, cinfo->regbase); |
2233 | 2147 | ||
2234 | ret = pci_request_regions(pdev, "cirrusfb"); | 2148 | ret = pci_request_regions(pdev, "cirrusfb"); |
2235 | if (ret < 0) { | 2149 | if (ret < 0) { |
2236 | printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, " | 2150 | dev_err(info->device, "cannot reserve region 0x%lx, abort\n", |
2237 | "abort\n", | 2151 | board_addr); |
2238 | board_addr); | ||
2239 | goto err_release_fb; | 2152 | goto err_release_fb; |
2240 | } | 2153 | } |
2241 | #if 0 /* if the system didn't claim this region, we would... */ | 2154 | #if 0 /* if the system didn't claim this region, we would... */ |
2242 | if (!request_mem_region(0xA0000, 65535, "cirrusfb")) { | 2155 | if (!request_mem_region(0xA0000, 65535, "cirrusfb")) { |
2243 | printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n" | 2156 | dev_err(info->device, "cannot reserve region 0x%lx, abort\n", |
2244 | , | 2157 | 0xA0000L); |
2245 | 0xA0000L); | ||
2246 | ret = -EBUSY; | 2158 | ret = -EBUSY; |
2247 | goto err_release_regions; | 2159 | goto err_release_regions; |
2248 | } | 2160 | } |
@@ -2260,16 +2172,17 @@ static int __devinit cirrusfb_pci_register(struct pci_dev *pdev, | |||
2260 | info->screen_size = board_size; | 2172 | info->screen_size = board_size; |
2261 | cinfo->unmap = cirrusfb_pci_unmap; | 2173 | cinfo->unmap = cirrusfb_pci_unmap; |
2262 | 2174 | ||
2263 | printk(KERN_INFO "RAM (%lu kB) at 0x%lx, Cirrus " | 2175 | dev_info(info->device, |
2264 | "Logic chipset on PCI bus\n", | 2176 | "Cirrus Logic chipset on PCI bus, RAM (%lu kB) at 0x%lx\n", |
2265 | info->screen_size >> 10, board_addr); | 2177 | info->screen_size >> 10, board_addr); |
2266 | pci_set_drvdata(pdev, info); | 2178 | pci_set_drvdata(pdev, info); |
2267 | 2179 | ||
2268 | ret = cirrusfb_register(info); | 2180 | ret = cirrusfb_register(info); |
2269 | if (ret) | 2181 | if (!ret) |
2270 | iounmap(info->screen_base); | 2182 | return 0; |
2271 | return ret; | ||
2272 | 2183 | ||
2184 | pci_set_drvdata(pdev, NULL); | ||
2185 | iounmap(info->screen_base); | ||
2273 | err_release_legacy: | 2186 | err_release_legacy: |
2274 | if (release_io_ports) | 2187 | if (release_io_ports) |
2275 | release_region(0x3C0, 32); | 2188 | release_region(0x3C0, 32); |
@@ -2279,8 +2192,9 @@ err_release_regions: | |||
2279 | #endif | 2192 | #endif |
2280 | pci_release_regions(pdev); | 2193 | pci_release_regions(pdev); |
2281 | err_release_fb: | 2194 | err_release_fb: |
2195 | if (cinfo->laguna_mmio != NULL) | ||
2196 | iounmap(cinfo->laguna_mmio); | ||
2282 | framebuffer_release(info); | 2197 | framebuffer_release(info); |
2283 | err_disable: | ||
2284 | err_out: | 2198 | err_out: |
2285 | return ret; | 2199 | return ret; |
2286 | } | 2200 | } |
@@ -2288,11 +2202,8 @@ err_out: | |||
2288 | static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev) | 2202 | static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev) |
2289 | { | 2203 | { |
2290 | struct fb_info *info = pci_get_drvdata(pdev); | 2204 | struct fb_info *info = pci_get_drvdata(pdev); |
2291 | DPRINTK("ENTER\n"); | ||
2292 | 2205 | ||
2293 | cirrusfb_cleanup(info); | 2206 | cirrusfb_cleanup(info); |
2294 | |||
2295 | DPRINTK("EXIT\n"); | ||
2296 | } | 2207 | } |
2297 | 2208 | ||
2298 | static struct pci_driver cirrusfb_pci_driver = { | 2209 | static struct pci_driver cirrusfb_pci_driver = { |
@@ -2324,8 +2235,6 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, | |||
2324 | if (cirrusfb_zorro_table2[btype].id2) | 2235 | if (cirrusfb_zorro_table2[btype].id2) |
2325 | z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL); | 2236 | z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL); |
2326 | size = cirrusfb_zorro_table2[btype].size; | 2237 | size = cirrusfb_zorro_table2[btype].size; |
2327 | printk(KERN_INFO "cirrusfb: %s board detected; ", | ||
2328 | cirrusfb_board_info[btype].name); | ||
2329 | 2238 | ||
2330 | info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); | 2239 | info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); |
2331 | if (!info) { | 2240 | if (!info) { |
@@ -2334,6 +2243,9 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, | |||
2334 | goto err_out; | 2243 | goto err_out; |
2335 | } | 2244 | } |
2336 | 2245 | ||
2246 | dev_info(info->device, "%s board detected\n", | ||
2247 | cirrusfb_board_info[btype].name); | ||
2248 | |||
2337 | cinfo = info->par; | 2249 | cinfo = info->par; |
2338 | cinfo->btype = btype; | 2250 | cinfo->btype = btype; |
2339 | 2251 | ||
@@ -2345,19 +2257,16 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, | |||
2345 | info->screen_size = size; | 2257 | info->screen_size = size; |
2346 | 2258 | ||
2347 | if (!zorro_request_device(z, "cirrusfb")) { | 2259 | if (!zorro_request_device(z, "cirrusfb")) { |
2348 | printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, " | 2260 | dev_err(info->device, "cannot reserve region 0x%lx, abort\n", |
2349 | "abort\n", | 2261 | board_addr); |
2350 | board_addr); | ||
2351 | ret = -EBUSY; | 2262 | ret = -EBUSY; |
2352 | goto err_release_fb; | 2263 | goto err_release_fb; |
2353 | } | 2264 | } |
2354 | 2265 | ||
2355 | printk(" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr); | ||
2356 | |||
2357 | ret = -EIO; | 2266 | ret = -EIO; |
2358 | 2267 | ||
2359 | if (btype == BT_PICASSO4) { | 2268 | if (btype == BT_PICASSO4) { |
2360 | printk(KERN_INFO " REG at $%lx\n", board_addr + 0x600000); | 2269 | dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000); |
2361 | 2270 | ||
2362 | /* To be precise, for the P4 this is not the */ | 2271 | /* To be precise, for the P4 this is not the */ |
2363 | /* begin of the board, but the begin of RAM. */ | 2272 | /* begin of the board, but the begin of RAM. */ |
@@ -2367,7 +2276,7 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, | |||
2367 | if (!cinfo->regbase) | 2276 | if (!cinfo->regbase) |
2368 | goto err_release_region; | 2277 | goto err_release_region; |
2369 | 2278 | ||
2370 | DPRINTK("cirrusfb: Virtual address for board set to: $%p\n", | 2279 | dev_dbg(info->device, "Virtual address for board set to: $%p\n", |
2371 | cinfo->regbase); | 2280 | cinfo->regbase); |
2372 | cinfo->regbase += 0x600000; | 2281 | cinfo->regbase += 0x600000; |
2373 | info->fix.mmio_start = board_addr + 0x600000; | 2282 | info->fix.mmio_start = board_addr + 0x600000; |
@@ -2377,8 +2286,8 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, | |||
2377 | if (!info->screen_base) | 2286 | if (!info->screen_base) |
2378 | goto err_unmap_regbase; | 2287 | goto err_unmap_regbase; |
2379 | } else { | 2288 | } else { |
2380 | printk(KERN_INFO " REG at $%lx\n", | 2289 | dev_info(info->device, " REG at $%lx\n", |
2381 | (unsigned long) z2->resource.start); | 2290 | (unsigned long) z2->resource.start); |
2382 | 2291 | ||
2383 | info->fix.smem_start = board_addr; | 2292 | info->fix.smem_start = board_addr; |
2384 | if (board_addr > 0x01000000) | 2293 | if (board_addr > 0x01000000) |
@@ -2392,27 +2301,32 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, | |||
2392 | cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start); | 2301 | cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start); |
2393 | info->fix.mmio_start = z2->resource.start; | 2302 | info->fix.mmio_start = z2->resource.start; |
2394 | 2303 | ||
2395 | DPRINTK("cirrusfb: Virtual address for board set to: $%p\n", | 2304 | dev_dbg(info->device, "Virtual address for board set to: $%p\n", |
2396 | cinfo->regbase); | 2305 | cinfo->regbase); |
2397 | } | 2306 | } |
2398 | cinfo->unmap = cirrusfb_zorro_unmap; | 2307 | cinfo->unmap = cirrusfb_zorro_unmap; |
2399 | 2308 | ||
2400 | printk(KERN_INFO "Cirrus Logic chipset on Zorro bus\n"); | 2309 | dev_info(info->device, |
2310 | "Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n", | ||
2311 | board_size / MB_, board_addr); | ||
2312 | |||
2401 | zorro_set_drvdata(z, info); | 2313 | zorro_set_drvdata(z, info); |
2402 | 2314 | ||
2315 | /* MCLK select etc. */ | ||
2316 | if (cirrusfb_board_info[btype].init_sr1f) | ||
2317 | vga_wseq(cinfo->regbase, CL_SEQR1F, | ||
2318 | cirrusfb_board_info[btype].sr1f); | ||
2319 | |||
2403 | ret = cirrusfb_register(info); | 2320 | ret = cirrusfb_register(info); |
2404 | if (ret) { | 2321 | if (!ret) |
2405 | if (btype == BT_PICASSO4) { | 2322 | return 0; |
2406 | iounmap(info->screen_base); | 2323 | |
2407 | iounmap(cinfo->regbase - 0x600000); | 2324 | if (btype == BT_PICASSO4 || board_addr > 0x01000000) |
2408 | } else if (board_addr > 0x01000000) | 2325 | iounmap(info->screen_base); |
2409 | iounmap(info->screen_base); | ||
2410 | } | ||
2411 | return ret; | ||
2412 | 2326 | ||
2413 | err_unmap_regbase: | 2327 | err_unmap_regbase: |
2414 | /* Parental advisory: explicit hack */ | 2328 | if (btype == BT_PICASSO4) |
2415 | iounmap(cinfo->regbase - 0x600000); | 2329 | iounmap(cinfo->regbase - 0x600000); |
2416 | err_release_region: | 2330 | err_release_region: |
2417 | release_region(board_addr, board_size); | 2331 | release_region(board_addr, board_size); |
2418 | err_release_fb: | 2332 | err_release_fb: |
@@ -2424,11 +2338,8 @@ err_out: | |||
2424 | void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z) | 2338 | void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z) |
2425 | { | 2339 | { |
2426 | struct fb_info *info = zorro_get_drvdata(z); | 2340 | struct fb_info *info = zorro_get_drvdata(z); |
2427 | DPRINTK("ENTER\n"); | ||
2428 | 2341 | ||
2429 | cirrusfb_cleanup(info); | 2342 | cirrusfb_cleanup(info); |
2430 | |||
2431 | DPRINTK("EXIT\n"); | ||
2432 | } | 2343 | } |
2433 | 2344 | ||
2434 | static struct zorro_driver cirrusfb_zorro_driver = { | 2345 | static struct zorro_driver cirrusfb_zorro_driver = { |
@@ -2439,33 +2350,11 @@ static struct zorro_driver cirrusfb_zorro_driver = { | |||
2439 | }; | 2350 | }; |
2440 | #endif /* CONFIG_ZORRO */ | 2351 | #endif /* CONFIG_ZORRO */ |
2441 | 2352 | ||
2442 | static int __init cirrusfb_init(void) | ||
2443 | { | ||
2444 | int error = 0; | ||
2445 | |||
2446 | #ifndef MODULE | 2353 | #ifndef MODULE |
2447 | char *option = NULL; | 2354 | static int __init cirrusfb_setup(char *options) |
2448 | 2355 | { | |
2449 | if (fb_get_options("cirrusfb", &option)) | ||
2450 | return -ENODEV; | ||
2451 | cirrusfb_setup(option); | ||
2452 | #endif | ||
2453 | |||
2454 | #ifdef CONFIG_ZORRO | ||
2455 | error |= zorro_register_driver(&cirrusfb_zorro_driver); | ||
2456 | #endif | ||
2457 | #ifdef CONFIG_PCI | ||
2458 | error |= pci_register_driver(&cirrusfb_pci_driver); | ||
2459 | #endif | ||
2460 | return error; | ||
2461 | } | ||
2462 | |||
2463 | #ifndef MODULE | ||
2464 | static int __init cirrusfb_setup(char *options) { | ||
2465 | char *this_opt; | 2356 | char *this_opt; |
2466 | 2357 | ||
2467 | DPRINTK("ENTER\n"); | ||
2468 | |||
2469 | if (!options || !*options) | 2358 | if (!options || !*options) |
2470 | return 0; | 2359 | return 0; |
2471 | 2360 | ||
@@ -2473,8 +2362,6 @@ static int __init cirrusfb_setup(char *options) { | |||
2473 | if (!*this_opt) | 2362 | if (!*this_opt) |
2474 | continue; | 2363 | continue; |
2475 | 2364 | ||
2476 | DPRINTK("cirrusfb_setup: option '%s'\n", this_opt); | ||
2477 | |||
2478 | if (!strcmp(this_opt, "noaccel")) | 2365 | if (!strcmp(this_opt, "noaccel")) |
2479 | noaccel = 1; | 2366 | noaccel = 1; |
2480 | else if (!strncmp(this_opt, "mode:", 5)) | 2367 | else if (!strncmp(this_opt, "mode:", 5)) |
@@ -2494,6 +2381,27 @@ MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>"); | |||
2494 | MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips"); | 2381 | MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips"); |
2495 | MODULE_LICENSE("GPL"); | 2382 | MODULE_LICENSE("GPL"); |
2496 | 2383 | ||
2384 | static int __init cirrusfb_init(void) | ||
2385 | { | ||
2386 | int error = 0; | ||
2387 | |||
2388 | #ifndef MODULE | ||
2389 | char *option = NULL; | ||
2390 | |||
2391 | if (fb_get_options("cirrusfb", &option)) | ||
2392 | return -ENODEV; | ||
2393 | cirrusfb_setup(option); | ||
2394 | #endif | ||
2395 | |||
2396 | #ifdef CONFIG_ZORRO | ||
2397 | error |= zorro_register_driver(&cirrusfb_zorro_driver); | ||
2398 | #endif | ||
2399 | #ifdef CONFIG_PCI | ||
2400 | error |= pci_register_driver(&cirrusfb_pci_driver); | ||
2401 | #endif | ||
2402 | return error; | ||
2403 | } | ||
2404 | |||
2497 | static void __exit cirrusfb_exit(void) | 2405 | static void __exit cirrusfb_exit(void) |
2498 | { | 2406 | { |
2499 | #ifdef CONFIG_PCI | 2407 | #ifdef CONFIG_PCI |
@@ -2560,8 +2468,6 @@ static void AttrOn(const struct cirrusfb_info *cinfo) | |||
2560 | { | 2468 | { |
2561 | assert(cinfo != NULL); | 2469 | assert(cinfo != NULL); |
2562 | 2470 | ||
2563 | DPRINTK("ENTER\n"); | ||
2564 | |||
2565 | if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) { | 2471 | if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) { |
2566 | /* if we're just in "write value" mode, write back the */ | 2472 | /* if we're just in "write value" mode, write back the */ |
2567 | /* same value as before to not modify anything */ | 2473 | /* same value as before to not modify anything */ |
@@ -2574,8 +2480,6 @@ static void AttrOn(const struct cirrusfb_info *cinfo) | |||
2574 | 2480 | ||
2575 | /* dummy write on Reg0 to be on "write index" mode next time */ | 2481 | /* dummy write on Reg0 to be on "write index" mode next time */ |
2576 | vga_w(cinfo->regbase, VGA_ATT_IW, 0x00); | 2482 | vga_w(cinfo->regbase, VGA_ATT_IW, 0x00); |
2577 | |||
2578 | DPRINTK("EXIT\n"); | ||
2579 | } | 2483 | } |
2580 | 2484 | ||
2581 | /*** WHDR() - write into the Hidden DAC register ***/ | 2485 | /*** WHDR() - write into the Hidden DAC register ***/ |
@@ -2588,6 +2492,8 @@ static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val) | |||
2588 | { | 2492 | { |
2589 | unsigned char dummy; | 2493 | unsigned char dummy; |
2590 | 2494 | ||
2495 | if (is_laguna(cinfo)) | ||
2496 | return; | ||
2591 | if (cinfo->btype == BT_PICASSO) { | 2497 | if (cinfo->btype == BT_PICASSO) { |
2592 | /* Klaus' hint for correct access to HDR on some boards */ | 2498 | /* Klaus' hint for correct access to HDR on some boards */ |
2593 | /* first write 0 to pixel mask (3c6) */ | 2499 | /* first write 0 to pixel mask (3c6) */ |
@@ -2655,7 +2561,8 @@ static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned ch | |||
2655 | vga_w(cinfo->regbase, VGA_PEL_IW, regnum); | 2561 | vga_w(cinfo->regbase, VGA_PEL_IW, regnum); |
2656 | 2562 | ||
2657 | if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 || | 2563 | if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 || |
2658 | cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) { | 2564 | cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480 || |
2565 | cinfo->btype == BT_SD64 || is_laguna(cinfo)) { | ||
2659 | /* but DAC data register IS, at least for Picasso II */ | 2566 | /* but DAC data register IS, at least for Picasso II */ |
2660 | if (cinfo->btype == BT_PICASSO) | 2567 | if (cinfo->btype == BT_PICASSO) |
2661 | data += 0xfff; | 2568 | data += 0xfff; |
@@ -2702,9 +2609,8 @@ static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned ch | |||
2702 | /* FIXME: use interrupts instead */ | 2609 | /* FIXME: use interrupts instead */ |
2703 | static void cirrusfb_WaitBLT(u8 __iomem *regbase) | 2610 | static void cirrusfb_WaitBLT(u8 __iomem *regbase) |
2704 | { | 2611 | { |
2705 | /* now busy-wait until we're done */ | ||
2706 | while (vga_rgfx(regbase, CL_GR31) & 0x08) | 2612 | while (vga_rgfx(regbase, CL_GR31) & 0x08) |
2707 | /* do nothing */ ; | 2613 | cpu_relax(); |
2708 | } | 2614 | } |
2709 | 2615 | ||
2710 | /******************************************************************* | 2616 | /******************************************************************* |
@@ -2713,60 +2619,12 @@ static void cirrusfb_WaitBLT(u8 __iomem *regbase) | |||
2713 | perform accelerated "scrolling" | 2619 | perform accelerated "scrolling" |
2714 | ********************************************************************/ | 2620 | ********************************************************************/ |
2715 | 2621 | ||
2716 | static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, | 2622 | static void cirrusfb_set_blitter(u8 __iomem *regbase, |
2717 | u_short curx, u_short cury, | 2623 | u_short nwidth, u_short nheight, |
2718 | u_short destx, u_short desty, | 2624 | u_long nsrc, u_long ndest, |
2719 | u_short width, u_short height, | 2625 | u_short bltmode, u_short line_length) |
2720 | u_short line_length) | ||
2721 | { | ||
2722 | u_short nwidth, nheight; | ||
2723 | u_long nsrc, ndest; | ||
2724 | u_char bltmode; | ||
2725 | |||
2726 | DPRINTK("ENTER\n"); | ||
2727 | |||
2728 | nwidth = width - 1; | ||
2729 | nheight = height - 1; | ||
2730 | |||
2731 | bltmode = 0x00; | ||
2732 | /* if source adr < dest addr, do the Blt backwards */ | ||
2733 | if (cury <= desty) { | ||
2734 | if (cury == desty) { | ||
2735 | /* if src and dest are on the same line, check x */ | ||
2736 | if (curx < destx) | ||
2737 | bltmode |= 0x01; | ||
2738 | } else | ||
2739 | bltmode |= 0x01; | ||
2740 | } | ||
2741 | if (!bltmode) { | ||
2742 | /* standard case: forward blitting */ | ||
2743 | nsrc = (cury * line_length) + curx; | ||
2744 | ndest = (desty * line_length) + destx; | ||
2745 | } else { | ||
2746 | /* this means start addresses are at the end, | ||
2747 | * counting backwards | ||
2748 | */ | ||
2749 | nsrc = cury * line_length + curx + | ||
2750 | nheight * line_length + nwidth; | ||
2751 | ndest = desty * line_length + destx + | ||
2752 | nheight * line_length + nwidth; | ||
2753 | } | ||
2754 | |||
2755 | /* | ||
2756 | run-down of registers to be programmed: | ||
2757 | destination pitch | ||
2758 | source pitch | ||
2759 | BLT width/height | ||
2760 | source start | ||
2761 | destination start | ||
2762 | BLT mode | ||
2763 | BLT ROP | ||
2764 | VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color" | ||
2765 | start/stop | ||
2766 | */ | ||
2767 | |||
2768 | cirrusfb_WaitBLT(regbase); | ||
2769 | 2626 | ||
2627 | { | ||
2770 | /* pitch: set to line_length */ | 2628 | /* pitch: set to line_length */ |
2771 | /* dest pitch low */ | 2629 | /* dest pitch low */ |
2772 | vga_wgfx(regbase, CL_GR24, line_length & 0xff); | 2630 | vga_wgfx(regbase, CL_GR24, line_length & 0xff); |
@@ -2813,91 +2671,91 @@ static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, | |||
2813 | 2671 | ||
2814 | /* and finally: GO! */ | 2672 | /* and finally: GO! */ |
2815 | vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */ | 2673 | vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */ |
2816 | |||
2817 | DPRINTK("EXIT\n"); | ||
2818 | } | 2674 | } |
2819 | 2675 | ||
2820 | /******************************************************************* | 2676 | /******************************************************************* |
2821 | cirrusfb_RectFill() | 2677 | cirrusfb_BitBLT() |
2822 | 2678 | ||
2823 | perform accelerated rectangle fill | 2679 | perform accelerated "scrolling" |
2824 | ********************************************************************/ | 2680 | ********************************************************************/ |
2825 | 2681 | ||
2826 | static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, | 2682 | static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, |
2827 | u_short x, u_short y, u_short width, u_short height, | 2683 | u_short curx, u_short cury, |
2828 | u_char color, u_short line_length) | 2684 | u_short destx, u_short desty, |
2685 | u_short width, u_short height, | ||
2686 | u_short line_length) | ||
2829 | { | 2687 | { |
2830 | u_short nwidth, nheight; | 2688 | u_short nwidth = width - 1; |
2831 | u_long ndest; | 2689 | u_short nheight = height - 1; |
2832 | u_char op; | 2690 | u_long nsrc, ndest; |
2833 | 2691 | u_char bltmode; | |
2834 | DPRINTK("ENTER\n"); | ||
2835 | |||
2836 | nwidth = width - 1; | ||
2837 | nheight = height - 1; | ||
2838 | 2692 | ||
2839 | ndest = (y * line_length) + x; | 2693 | bltmode = 0x00; |
2694 | /* if source adr < dest addr, do the Blt backwards */ | ||
2695 | if (cury <= desty) { | ||
2696 | if (cury == desty) { | ||
2697 | /* if src and dest are on the same line, check x */ | ||
2698 | if (curx < destx) | ||
2699 | bltmode |= 0x01; | ||
2700 | } else | ||
2701 | bltmode |= 0x01; | ||
2702 | } | ||
2703 | /* standard case: forward blitting */ | ||
2704 | nsrc = (cury * line_length) + curx; | ||
2705 | ndest = (desty * line_length) + destx; | ||
2706 | if (bltmode) { | ||
2707 | /* this means start addresses are at the end, | ||
2708 | * counting backwards | ||
2709 | */ | ||
2710 | nsrc += nheight * line_length + nwidth; | ||
2711 | ndest += nheight * line_length + nwidth; | ||
2712 | } | ||
2840 | 2713 | ||
2841 | cirrusfb_WaitBLT(regbase); | 2714 | cirrusfb_WaitBLT(regbase); |
2842 | 2715 | ||
2843 | /* pitch: set to line_length */ | 2716 | cirrusfb_set_blitter(regbase, nwidth, nheight, |
2844 | vga_wgfx(regbase, CL_GR24, line_length & 0xff); /* dest pitch low */ | 2717 | nsrc, ndest, bltmode, line_length); |
2845 | vga_wgfx(regbase, CL_GR25, line_length >> 8); /* dest pitch hi */ | 2718 | } |
2846 | vga_wgfx(regbase, CL_GR26, line_length & 0xff); /* source pitch low */ | ||
2847 | vga_wgfx(regbase, CL_GR27, line_length >> 8); /* source pitch hi */ | ||
2848 | 2719 | ||
2849 | /* BLT width: actual number of pixels - 1 */ | 2720 | /******************************************************************* |
2850 | vga_wgfx(regbase, CL_GR20, nwidth & 0xff); /* BLT width low */ | 2721 | cirrusfb_RectFill() |
2851 | vga_wgfx(regbase, CL_GR21, nwidth >> 8); /* BLT width hi */ | ||
2852 | 2722 | ||
2853 | /* BLT height: actual number of lines -1 */ | 2723 | perform accelerated rectangle fill |
2854 | vga_wgfx(regbase, CL_GR22, nheight & 0xff); /* BLT height low */ | 2724 | ********************************************************************/ |
2855 | vga_wgfx(regbase, CL_GR23, nheight >> 8); /* BLT width hi */ | ||
2856 | 2725 | ||
2857 | /* BLT destination */ | 2726 | static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, |
2858 | /* BLT dest low */ | 2727 | u_short x, u_short y, u_short width, u_short height, |
2859 | vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff)); | 2728 | u32 fg_color, u32 bg_color, u_short line_length, |
2860 | /* BLT dest mid */ | 2729 | u_char blitmode) |
2861 | vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8)); | 2730 | { |
2862 | /* BLT dest hi */ | 2731 | u_long ndest = (y * line_length) + x; |
2863 | vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16)); | 2732 | u_char op; |
2864 | 2733 | ||
2865 | /* BLT source: set to 0 (is a dummy here anyway) */ | 2734 | cirrusfb_WaitBLT(regbase); |
2866 | vga_wgfx(regbase, CL_GR2C, 0x00); /* BLT src low */ | ||
2867 | vga_wgfx(regbase, CL_GR2D, 0x00); /* BLT src mid */ | ||
2868 | vga_wgfx(regbase, CL_GR2E, 0x00); /* BLT src hi */ | ||
2869 | 2735 | ||
2870 | /* This is a ColorExpand Blt, using the */ | 2736 | /* This is a ColorExpand Blt, using the */ |
2871 | /* same color for foreground and background */ | 2737 | /* same color for foreground and background */ |
2872 | vga_wgfx(regbase, VGA_GFX_SR_VALUE, color); /* foreground color */ | 2738 | vga_wgfx(regbase, VGA_GFX_SR_VALUE, bg_color); |
2873 | vga_wgfx(regbase, VGA_GFX_SR_ENABLE, color); /* background color */ | 2739 | vga_wgfx(regbase, VGA_GFX_SR_ENABLE, fg_color); |
2874 | 2740 | ||
2875 | op = 0xc0; | 2741 | op = 0x80; |
2876 | if (bits_per_pixel == 16) { | 2742 | if (bits_per_pixel >= 16) { |
2877 | vga_wgfx(regbase, CL_GR10, color); /* foreground color */ | 2743 | vga_wgfx(regbase, CL_GR10, bg_color >> 8); |
2878 | vga_wgfx(regbase, CL_GR11, color); /* background color */ | 2744 | vga_wgfx(regbase, CL_GR11, fg_color >> 8); |
2879 | op = 0x50; | 2745 | op = 0x90; |
2880 | op = 0xd0; | 2746 | } |
2881 | } else if (bits_per_pixel == 32) { | 2747 | if (bits_per_pixel >= 24) { |
2882 | vga_wgfx(regbase, CL_GR10, color); /* foreground color */ | 2748 | vga_wgfx(regbase, CL_GR12, bg_color >> 16); |
2883 | vga_wgfx(regbase, CL_GR11, color); /* background color */ | 2749 | vga_wgfx(regbase, CL_GR13, fg_color >> 16); |
2884 | vga_wgfx(regbase, CL_GR12, color); /* foreground color */ | 2750 | op = 0xa0; |
2885 | vga_wgfx(regbase, CL_GR13, color); /* background color */ | 2751 | } |
2886 | vga_wgfx(regbase, CL_GR14, 0); /* foreground color */ | 2752 | if (bits_per_pixel == 32) { |
2887 | vga_wgfx(regbase, CL_GR15, 0); /* background color */ | 2753 | vga_wgfx(regbase, CL_GR14, bg_color >> 24); |
2888 | op = 0x50; | 2754 | vga_wgfx(regbase, CL_GR15, fg_color >> 24); |
2889 | op = 0xf0; | 2755 | op = 0xb0; |
2890 | } | 2756 | } |
2891 | /* BLT mode: color expand, Enable 8x8 copy (faster?) */ | 2757 | cirrusfb_set_blitter(regbase, width - 1, height - 1, |
2892 | vga_wgfx(regbase, CL_GR30, op); /* BLT mode */ | 2758 | 0, ndest, op | blitmode, line_length); |
2893 | |||
2894 | /* BLT ROP: SrcCopy */ | ||
2895 | vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */ | ||
2896 | |||
2897 | /* and finally: GO! */ | ||
2898 | vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */ | ||
2899 | |||
2900 | DPRINTK("EXIT\n"); | ||
2901 | } | 2759 | } |
2902 | 2760 | ||
2903 | /************************************************************************** | 2761 | /************************************************************************** |
@@ -2917,8 +2775,6 @@ static void bestclock(long freq, int *nom, int *den, int *div) | |||
2917 | *den = 0; | 2775 | *den = 0; |
2918 | *div = 0; | 2776 | *div = 0; |
2919 | 2777 | ||
2920 | DPRINTK("ENTER\n"); | ||
2921 | |||
2922 | if (freq < 8000) | 2778 | if (freq < 8000) |
2923 | freq = 8000; | 2779 | freq = 8000; |
2924 | 2780 | ||
@@ -2960,12 +2816,6 @@ static void bestclock(long freq, int *nom, int *den, int *div) | |||
2960 | } | 2816 | } |
2961 | } | 2817 | } |
2962 | } | 2818 | } |
2963 | |||
2964 | DPRINTK("Best possible values for given frequency:\n"); | ||
2965 | DPRINTK(" freq: %ld kHz nom: %d den: %d div: %d\n", | ||
2966 | freq, *nom, *den, *div); | ||
2967 | |||
2968 | DPRINTK("EXIT\n"); | ||
2969 | } | 2819 | } |
2970 | 2820 | ||
2971 | /* ------------------------------------------------------------------------- | 2821 | /* ------------------------------------------------------------------------- |
@@ -2978,32 +2828,6 @@ static void bestclock(long freq, int *nom, int *den, int *div) | |||
2978 | #ifdef CIRRUSFB_DEBUG | 2828 | #ifdef CIRRUSFB_DEBUG |
2979 | 2829 | ||
2980 | /** | 2830 | /** |
2981 | * cirrusfb_dbg_print_byte | ||
2982 | * @name: name associated with byte value to be displayed | ||
2983 | * @val: byte value to be displayed | ||
2984 | * | ||
2985 | * DESCRIPTION: | ||
2986 | * Display an indented string, along with a hexidecimal byte value, and | ||
2987 | * its decoded bits. Bits 7 through 0 are listed in left-to-right | ||
2988 | * order. | ||
2989 | */ | ||
2990 | |||
2991 | static | ||
2992 | void cirrusfb_dbg_print_byte(const char *name, unsigned char val) | ||
2993 | { | ||
2994 | DPRINTK("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n", | ||
2995 | name, val, | ||
2996 | val & 0x80 ? '1' : '0', | ||
2997 | val & 0x40 ? '1' : '0', | ||
2998 | val & 0x20 ? '1' : '0', | ||
2999 | val & 0x10 ? '1' : '0', | ||
3000 | val & 0x08 ? '1' : '0', | ||
3001 | val & 0x04 ? '1' : '0', | ||
3002 | val & 0x02 ? '1' : '0', | ||
3003 | val & 0x01 ? '1' : '0'); | ||
3004 | } | ||
3005 | |||
3006 | /** | ||
3007 | * cirrusfb_dbg_print_regs | 2831 | * cirrusfb_dbg_print_regs |
3008 | * @base: If using newmmio, the newmmio base address, otherwise %NULL | 2832 | * @base: If using newmmio, the newmmio base address, otherwise %NULL |
3009 | * @reg_class: type of registers to read: %CRT, or %SEQ | 2833 | * @reg_class: type of registers to read: %CRT, or %SEQ |
@@ -3014,9 +2838,9 @@ void cirrusfb_dbg_print_byte(const char *name, unsigned char val) | |||
3014 | * used at the given @base address to query the information. | 2838 | * used at the given @base address to query the information. |
3015 | */ | 2839 | */ |
3016 | 2840 | ||
3017 | static | 2841 | static void cirrusfb_dbg_print_regs(struct fb_info *info, |
3018 | void cirrusfb_dbg_print_regs(caddr_t regbase, | 2842 | caddr_t regbase, |
3019 | enum cirrusfb_dbg_reg_class reg_class, ...) | 2843 | enum cirrusfb_dbg_reg_class reg_class, ...) |
3020 | { | 2844 | { |
3021 | va_list list; | 2845 | va_list list; |
3022 | unsigned char val = 0; | 2846 | unsigned char val = 0; |
@@ -3042,7 +2866,7 @@ void cirrusfb_dbg_print_regs(caddr_t regbase, | |||
3042 | break; | 2866 | break; |
3043 | } | 2867 | } |
3044 | 2868 | ||
3045 | cirrusfb_dbg_print_byte(name, val); | 2869 | dev_dbg(info->device, "%8s = 0x%02X\n", name, val); |
3046 | 2870 | ||
3047 | name = va_arg(list, char *); | 2871 | name = va_arg(list, char *); |
3048 | } | 2872 | } |
@@ -3051,18 +2875,6 @@ void cirrusfb_dbg_print_regs(caddr_t regbase, | |||
3051 | } | 2875 | } |
3052 | 2876 | ||
3053 | /** | 2877 | /** |
3054 | * cirrusfb_dump | ||
3055 | * @cirrusfbinfo: | ||
3056 | * | ||
3057 | * DESCRIPTION: | ||
3058 | */ | ||
3059 | |||
3060 | static void cirrusfb_dump(void) | ||
3061 | { | ||
3062 | cirrusfb_dbg_reg_dump(NULL); | ||
3063 | } | ||
3064 | |||
3065 | /** | ||
3066 | * cirrusfb_dbg_reg_dump | 2878 | * cirrusfb_dbg_reg_dump |
3067 | * @base: If using newmmio, the newmmio base address, otherwise %NULL | 2879 | * @base: If using newmmio, the newmmio base address, otherwise %NULL |
3068 | * | 2880 | * |
@@ -3072,12 +2884,11 @@ static void cirrusfb_dump(void) | |||
3072 | * used at the given @base address to query the information. | 2884 | * used at the given @base address to query the information. |
3073 | */ | 2885 | */ |
3074 | 2886 | ||
3075 | static | 2887 | static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase) |
3076 | void cirrusfb_dbg_reg_dump(caddr_t regbase) | ||
3077 | { | 2888 | { |
3078 | DPRINTK("CIRRUSFB VGA CRTC register dump:\n"); | 2889 | dev_dbg(info->device, "VGA CRTC register dump:\n"); |
3079 | 2890 | ||
3080 | cirrusfb_dbg_print_regs(regbase, CRT, | 2891 | cirrusfb_dbg_print_regs(info, regbase, CRT, |
3081 | "CR00", 0x00, | 2892 | "CR00", 0x00, |
3082 | "CR01", 0x01, | 2893 | "CR01", 0x01, |
3083 | "CR02", 0x02, | 2894 | "CR02", 0x02, |
@@ -3127,11 +2938,11 @@ void cirrusfb_dbg_reg_dump(caddr_t regbase) | |||
3127 | "CR3F", 0x3F, | 2938 | "CR3F", 0x3F, |
3128 | NULL); | 2939 | NULL); |
3129 | 2940 | ||
3130 | DPRINTK("\n"); | 2941 | dev_dbg(info->device, "\n"); |
3131 | 2942 | ||
3132 | DPRINTK("CIRRUSFB VGA SEQ register dump:\n"); | 2943 | dev_dbg(info->device, "VGA SEQ register dump:\n"); |
3133 | 2944 | ||
3134 | cirrusfb_dbg_print_regs(regbase, SEQ, | 2945 | cirrusfb_dbg_print_regs(info, regbase, SEQ, |
3135 | "SR00", 0x00, | 2946 | "SR00", 0x00, |
3136 | "SR01", 0x01, | 2947 | "SR01", 0x01, |
3137 | "SR02", 0x02, | 2948 | "SR02", 0x02, |
@@ -3160,7 +2971,7 @@ void cirrusfb_dbg_reg_dump(caddr_t regbase) | |||
3160 | "SR1F", 0x1F, | 2971 | "SR1F", 0x1F, |
3161 | NULL); | 2972 | NULL); |
3162 | 2973 | ||
3163 | DPRINTK("\n"); | 2974 | dev_dbg(info->device, "\n"); |
3164 | } | 2975 | } |
3165 | 2976 | ||
3166 | #endif /* CIRRUSFB_DEBUG */ | 2977 | #endif /* CIRRUSFB_DEBUG */ |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 1657b9608b0..2cd500a304f 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -2954,8 +2954,11 @@ static int fbcon_fb_unbind(int idx) | |||
2954 | 2954 | ||
2955 | static int fbcon_fb_unregistered(struct fb_info *info) | 2955 | static int fbcon_fb_unregistered(struct fb_info *info) |
2956 | { | 2956 | { |
2957 | int i, idx = info->node; | 2957 | int i, idx; |
2958 | 2958 | ||
2959 | if (!lock_fb_info(info)) | ||
2960 | return -ENODEV; | ||
2961 | idx = info->node; | ||
2959 | for (i = first_fb_vc; i <= last_fb_vc; i++) { | 2962 | for (i = first_fb_vc; i <= last_fb_vc; i++) { |
2960 | if (con2fb_map[i] == idx) | 2963 | if (con2fb_map[i] == idx) |
2961 | con2fb_map[i] = -1; | 2964 | con2fb_map[i] = -1; |
@@ -2979,13 +2982,14 @@ static int fbcon_fb_unregistered(struct fb_info *info) | |||
2979 | } | 2982 | } |
2980 | } | 2983 | } |
2981 | 2984 | ||
2982 | if (!num_registered_fb) | ||
2983 | unregister_con_driver(&fb_con); | ||
2984 | |||
2985 | |||
2986 | if (primary_device == idx) | 2985 | if (primary_device == idx) |
2987 | primary_device = -1; | 2986 | primary_device = -1; |
2988 | 2987 | ||
2988 | unlock_fb_info(info); | ||
2989 | |||
2990 | if (!num_registered_fb) | ||
2991 | unregister_con_driver(&fb_con); | ||
2992 | |||
2989 | return 0; | 2993 | return 0; |
2990 | } | 2994 | } |
2991 | 2995 | ||
@@ -3021,9 +3025,13 @@ static inline void fbcon_select_primary(struct fb_info *info) | |||
3021 | 3025 | ||
3022 | static int fbcon_fb_registered(struct fb_info *info) | 3026 | static int fbcon_fb_registered(struct fb_info *info) |
3023 | { | 3027 | { |
3024 | int ret = 0, i, idx = info->node; | 3028 | int ret = 0, i, idx; |
3025 | 3029 | ||
3030 | if (!lock_fb_info(info)) | ||
3031 | return -ENODEV; | ||
3032 | idx = info->node; | ||
3026 | fbcon_select_primary(info); | 3033 | fbcon_select_primary(info); |
3034 | unlock_fb_info(info); | ||
3027 | 3035 | ||
3028 | if (info_idx == -1) { | 3036 | if (info_idx == -1) { |
3029 | for (i = first_fb_vc; i <= last_fb_vc; i++) { | 3037 | for (i = first_fb_vc; i <= last_fb_vc; i++) { |
@@ -3124,7 +3132,7 @@ static void fbcon_get_requirement(struct fb_info *info, | |||
3124 | } | 3132 | } |
3125 | } | 3133 | } |
3126 | 3134 | ||
3127 | static int fbcon_event_notify(struct notifier_block *self, | 3135 | static int fbcon_event_notify(struct notifier_block *self, |
3128 | unsigned long action, void *data) | 3136 | unsigned long action, void *data) |
3129 | { | 3137 | { |
3130 | struct fb_event *event = data; | 3138 | struct fb_event *event = data; |
@@ -3132,7 +3140,7 @@ static int fbcon_event_notify(struct notifier_block *self, | |||
3132 | struct fb_videomode *mode; | 3140 | struct fb_videomode *mode; |
3133 | struct fb_con2fbmap *con2fb; | 3141 | struct fb_con2fbmap *con2fb; |
3134 | struct fb_blit_caps *caps; | 3142 | struct fb_blit_caps *caps; |
3135 | int ret = 0; | 3143 | int idx, ret = 0; |
3136 | 3144 | ||
3137 | /* | 3145 | /* |
3138 | * ignore all events except driver registration and deregistration | 3146 | * ignore all events except driver registration and deregistration |
@@ -3144,23 +3152,54 @@ static int fbcon_event_notify(struct notifier_block *self, | |||
3144 | 3152 | ||
3145 | switch(action) { | 3153 | switch(action) { |
3146 | case FB_EVENT_SUSPEND: | 3154 | case FB_EVENT_SUSPEND: |
3155 | if (!lock_fb_info(info)) { | ||
3156 | ret = -ENODEV; | ||
3157 | goto done; | ||
3158 | } | ||
3147 | fbcon_suspended(info); | 3159 | fbcon_suspended(info); |
3160 | unlock_fb_info(info); | ||
3148 | break; | 3161 | break; |
3149 | case FB_EVENT_RESUME: | 3162 | case FB_EVENT_RESUME: |
3163 | if (!lock_fb_info(info)) { | ||
3164 | ret = -ENODEV; | ||
3165 | goto done; | ||
3166 | } | ||
3150 | fbcon_resumed(info); | 3167 | fbcon_resumed(info); |
3168 | unlock_fb_info(info); | ||
3151 | break; | 3169 | break; |
3152 | case FB_EVENT_MODE_CHANGE: | 3170 | case FB_EVENT_MODE_CHANGE: |
3171 | if (!lock_fb_info(info)) { | ||
3172 | ret = -ENODEV; | ||
3173 | goto done; | ||
3174 | } | ||
3153 | fbcon_modechanged(info); | 3175 | fbcon_modechanged(info); |
3176 | unlock_fb_info(info); | ||
3154 | break; | 3177 | break; |
3155 | case FB_EVENT_MODE_CHANGE_ALL: | 3178 | case FB_EVENT_MODE_CHANGE_ALL: |
3179 | if (!lock_fb_info(info)) { | ||
3180 | ret = -ENODEV; | ||
3181 | goto done; | ||
3182 | } | ||
3156 | fbcon_set_all_vcs(info); | 3183 | fbcon_set_all_vcs(info); |
3184 | unlock_fb_info(info); | ||
3157 | break; | 3185 | break; |
3158 | case FB_EVENT_MODE_DELETE: | 3186 | case FB_EVENT_MODE_DELETE: |
3159 | mode = event->data; | 3187 | mode = event->data; |
3188 | if (!lock_fb_info(info)) { | ||
3189 | ret = -ENODEV; | ||
3190 | goto done; | ||
3191 | } | ||
3160 | ret = fbcon_mode_deleted(info, mode); | 3192 | ret = fbcon_mode_deleted(info, mode); |
3193 | unlock_fb_info(info); | ||
3161 | break; | 3194 | break; |
3162 | case FB_EVENT_FB_UNBIND: | 3195 | case FB_EVENT_FB_UNBIND: |
3163 | ret = fbcon_fb_unbind(info->node); | 3196 | if (!lock_fb_info(info)) { |
3197 | ret = -ENODEV; | ||
3198 | goto done; | ||
3199 | } | ||
3200 | idx = info->node; | ||
3201 | unlock_fb_info(info); | ||
3202 | ret = fbcon_fb_unbind(idx); | ||
3164 | break; | 3203 | break; |
3165 | case FB_EVENT_FB_REGISTERED: | 3204 | case FB_EVENT_FB_REGISTERED: |
3166 | ret = fbcon_fb_registered(info); | 3205 | ret = fbcon_fb_registered(info); |
@@ -3178,17 +3217,31 @@ static int fbcon_event_notify(struct notifier_block *self, | |||
3178 | con2fb->framebuffer = con2fb_map[con2fb->console - 1]; | 3217 | con2fb->framebuffer = con2fb_map[con2fb->console - 1]; |
3179 | break; | 3218 | break; |
3180 | case FB_EVENT_BLANK: | 3219 | case FB_EVENT_BLANK: |
3220 | if (!lock_fb_info(info)) { | ||
3221 | ret = -ENODEV; | ||
3222 | goto done; | ||
3223 | } | ||
3181 | fbcon_fb_blanked(info, *(int *)event->data); | 3224 | fbcon_fb_blanked(info, *(int *)event->data); |
3225 | unlock_fb_info(info); | ||
3182 | break; | 3226 | break; |
3183 | case FB_EVENT_NEW_MODELIST: | 3227 | case FB_EVENT_NEW_MODELIST: |
3228 | if (!lock_fb_info(info)) { | ||
3229 | ret = -ENODEV; | ||
3230 | goto done; | ||
3231 | } | ||
3184 | fbcon_new_modelist(info); | 3232 | fbcon_new_modelist(info); |
3233 | unlock_fb_info(info); | ||
3185 | break; | 3234 | break; |
3186 | case FB_EVENT_GET_REQ: | 3235 | case FB_EVENT_GET_REQ: |
3187 | caps = event->data; | 3236 | caps = event->data; |
3237 | if (!lock_fb_info(info)) { | ||
3238 | ret = -ENODEV; | ||
3239 | goto done; | ||
3240 | } | ||
3188 | fbcon_get_requirement(info, caps); | 3241 | fbcon_get_requirement(info, caps); |
3242 | unlock_fb_info(info); | ||
3189 | break; | 3243 | break; |
3190 | } | 3244 | } |
3191 | |||
3192 | done: | 3245 | done: |
3193 | return ret; | 3246 | return ret; |
3194 | } | 3247 | } |
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c deleted file mode 100644 index 9704b73135f..00000000000 --- a/drivers/video/cyblafb.c +++ /dev/null | |||
@@ -1,1683 +0,0 @@ | |||
1 | /* | ||
2 | * Frame buffer driver for Trident Cyberblade/i1 graphics core | ||
3 | * | ||
4 | * Copyright 2005 Knut Petersen <Knut_Petersen@t-online.de> | ||
5 | * | ||
6 | * CREDITS: | ||
7 | * tridentfb.c by Jani Monoses | ||
8 | * see files above for further credits | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #define CYBLAFB_DEBUG 0 | ||
13 | #define CYBLAFB_KD_GRAPHICS_QUIRK 1 | ||
14 | |||
15 | #define CYBLAFB_PIXMAPSIZE 8192 | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/fb.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/pci.h> | ||
22 | #include <asm/types.h> | ||
23 | #include <video/cyblafb.h> | ||
24 | |||
25 | #define VERSION "0.62" | ||
26 | |||
27 | struct cyblafb_par { | ||
28 | u32 pseudo_pal[16]; | ||
29 | struct fb_ops ops; | ||
30 | }; | ||
31 | |||
32 | static struct fb_fix_screeninfo cyblafb_fix __devinitdata = { | ||
33 | .id = "CyBla", | ||
34 | .type = FB_TYPE_PACKED_PIXELS, | ||
35 | .xpanstep = 1, | ||
36 | .ypanstep = 1, | ||
37 | .ywrapstep = 1, | ||
38 | .visual = FB_VISUAL_PSEUDOCOLOR, | ||
39 | .accel = FB_ACCEL_NONE, | ||
40 | }; | ||
41 | |||
42 | static char *mode __devinitdata = NULL; | ||
43 | static int bpp __devinitdata = 8; | ||
44 | static int ref __devinitdata = 75; | ||
45 | static int fp __devinitdata; | ||
46 | static int crt __devinitdata; | ||
47 | static int memsize __devinitdata; | ||
48 | |||
49 | static int basestride; | ||
50 | static int vesafb; | ||
51 | static int nativex; | ||
52 | static int center; | ||
53 | static int stretch; | ||
54 | static int pciwb = 1; | ||
55 | static int pcirb = 1; | ||
56 | static int pciwr = 1; | ||
57 | static int pcirr = 1; | ||
58 | static int disabled; | ||
59 | static int verbosity; | ||
60 | static int displaytype; | ||
61 | |||
62 | static void __iomem *io_virt; // iospace virtual memory address | ||
63 | |||
64 | module_param(mode, charp, 0); | ||
65 | module_param(bpp, int, 0); | ||
66 | module_param(ref, int, 0); | ||
67 | module_param(fp, int, 0); | ||
68 | module_param(crt, int, 0); | ||
69 | module_param(nativex, int, 0); | ||
70 | module_param(center, int, 0); | ||
71 | module_param(stretch, int, 0); | ||
72 | module_param(pciwb, int, 0); | ||
73 | module_param(pcirb, int, 0); | ||
74 | module_param(pciwr, int, 0); | ||
75 | module_param(pcirr, int, 0); | ||
76 | module_param(memsize, int, 0); | ||
77 | module_param(verbosity, int, 0); | ||
78 | |||
79 | //========================================= | ||
80 | // | ||
81 | // Well, we have to fix the upper layers. | ||
82 | // Until this has been done, we work around | ||
83 | // the bugs. | ||
84 | // | ||
85 | //========================================= | ||
86 | |||
87 | #if (CYBLAFB_KD_GRAPHICS_QUIRK && CYBLAFB_DEBUG) | ||
88 | if (disabled) { \ | ||
89 | printk("********\n");\ | ||
90 | dump_stack();\ | ||
91 | return val;\ | ||
92 | } | ||
93 | |||
94 | #elif CYBLAFB_KD_GRAPHICS_QUIRK | ||
95 | #define KD_GRAPHICS_RETURN(val)\ | ||
96 | if (disabled) {\ | ||
97 | return val;\ | ||
98 | } | ||
99 | #else | ||
100 | #define KD_GRAPHICS_RETURN(val) | ||
101 | #endif | ||
102 | |||
103 | //========================================= | ||
104 | // | ||
105 | // Port access macros for memory mapped io | ||
106 | // | ||
107 | //========================================= | ||
108 | |||
109 | #define out8(r, v) writeb(v, io_virt + r) | ||
110 | #define out32(r, v) writel(v, io_virt + r) | ||
111 | #define in8(r) readb(io_virt + r) | ||
112 | #define in32(r) readl(io_virt + r) | ||
113 | |||
114 | //====================================== | ||
115 | // | ||
116 | // Hardware access inline functions | ||
117 | // | ||
118 | //====================================== | ||
119 | |||
120 | static inline u8 read3X4(u32 reg) | ||
121 | { | ||
122 | out8(0x3D4, reg); | ||
123 | return in8(0x3D5); | ||
124 | } | ||
125 | |||
126 | static inline u8 read3C4(u32 reg) | ||
127 | { | ||
128 | out8(0x3C4, reg); | ||
129 | return in8(0x3C5); | ||
130 | } | ||
131 | |||
132 | static inline u8 read3CE(u32 reg) | ||
133 | { | ||
134 | out8(0x3CE, reg); | ||
135 | return in8(0x3CF); | ||
136 | } | ||
137 | |||
138 | static inline void write3X4(u32 reg, u8 val) | ||
139 | { | ||
140 | out8(0x3D4, reg); | ||
141 | out8(0x3D5, val); | ||
142 | } | ||
143 | |||
144 | static inline void write3C4(u32 reg, u8 val) | ||
145 | { | ||
146 | out8(0x3C4, reg); | ||
147 | out8(0x3C5, val); | ||
148 | } | ||
149 | |||
150 | static inline void write3CE(u32 reg, u8 val) | ||
151 | { | ||
152 | out8(0x3CE, reg); | ||
153 | out8(0x3CF, val); | ||
154 | } | ||
155 | |||
156 | static inline void write3C0(u32 reg, u8 val) | ||
157 | { | ||
158 | in8(0x3DA); // read to reset index | ||
159 | out8(0x3C0, reg); | ||
160 | out8(0x3C0, val); | ||
161 | } | ||
162 | |||
163 | //================================================= | ||
164 | // | ||
165 | // Enable memory mapped io and unprotect registers | ||
166 | // | ||
167 | //================================================= | ||
168 | |||
169 | static void enable_mmio(void) | ||
170 | { | ||
171 | u8 tmp; | ||
172 | |||
173 | outb(0x0B, 0x3C4); | ||
174 | inb(0x3C5); // Set NEW mode | ||
175 | outb(SR0E, 0x3C4); // write enable a lot of extended ports | ||
176 | outb(0x80, 0x3C5); | ||
177 | |||
178 | outb(SR11, 0x3C4); // write enable those extended ports that | ||
179 | outb(0x87, 0x3C5); // are not affected by SR0E_New | ||
180 | |||
181 | outb(CR1E, 0x3d4); // clear write protect bit for port 0x3c2 | ||
182 | tmp = inb(0x3d5) & 0xBF; | ||
183 | outb(CR1E, 0x3d4); | ||
184 | outb(tmp, 0x3d5); | ||
185 | |||
186 | outb(CR39, 0x3D4); | ||
187 | outb(inb(0x3D5) | 0x01, 0x3D5); // Enable mmio | ||
188 | } | ||
189 | |||
190 | //================================================= | ||
191 | // | ||
192 | // Set pixel clock VCLK1 | ||
193 | // - multipliers set elswhere | ||
194 | // - freq in units of 0.01 MHz | ||
195 | // | ||
196 | // Hardware bug: SR18 >= 250 is broken for the | ||
197 | // cyberblade/i1 | ||
198 | // | ||
199 | //================================================= | ||
200 | |||
201 | static void set_vclk(struct cyblafb_par *par, int freq) | ||
202 | { | ||
203 | u32 m, n, k; | ||
204 | int f, fi, d, di; | ||
205 | u8 lo = 0, hi = 0; | ||
206 | |||
207 | d = 2000; | ||
208 | k = freq >= 10000 ? 0 : freq >= 5000 ? 1 : freq >= 2500 ? 2 : 3; | ||
209 | for (m = 0; m < 64; m++) | ||
210 | for (n = 0; n < 250; n++) { | ||
211 | fi = (int)(((5864727 * (n + 8)) / | ||
212 | ((m + 2) * (1 << k))) >> 12); | ||
213 | if ((di = abs(fi - freq)) < d) { | ||
214 | d = di; | ||
215 | f = fi; | ||
216 | lo = (u8) n; | ||
217 | hi = (u8) ((k << 6) | m); | ||
218 | } | ||
219 | } | ||
220 | write3C4(SR19, hi); | ||
221 | write3C4(SR18, lo); | ||
222 | if (verbosity > 0) | ||
223 | output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n", | ||
224 | freq / 100, freq % 100, (hi & 0xc0) >> 6, hi & 0x3f, lo); | ||
225 | } | ||
226 | |||
227 | //================================================ | ||
228 | // | ||
229 | // Cyberblade specific Graphics Engine (GE) setup | ||
230 | // | ||
231 | //================================================ | ||
232 | |||
233 | static void cyblafb_setup_GE(int pitch, int bpp) | ||
234 | { | ||
235 | KD_GRAPHICS_RETURN(); | ||
236 | |||
237 | switch (bpp) { | ||
238 | case 8: | ||
239 | basestride = ((pitch >> 3) << 20) | (0 << 29); | ||
240 | break; | ||
241 | case 15: | ||
242 | basestride = ((pitch >> 3) << 20) | (5 << 29); | ||
243 | break; | ||
244 | case 16: | ||
245 | basestride = ((pitch >> 3) << 20) | (1 << 29); | ||
246 | break; | ||
247 | case 24: | ||
248 | case 32: | ||
249 | basestride = ((pitch >> 3) << 20) | (2 << 29); | ||
250 | break; | ||
251 | } | ||
252 | |||
253 | write3X4(CR36, 0x90); // reset GE | ||
254 | write3X4(CR36, 0x80); // enable GE | ||
255 | out32(GE24, 1 << 7); // reset all GE pointers by toggling | ||
256 | out32(GE24, 0); // d7 of GE24 | ||
257 | write3X4(CR2D, 0x00); // GE Timinigs, no delays | ||
258 | out32(GE6C, 0); // Pattern and Style, p 129, ok | ||
259 | } | ||
260 | |||
261 | //===================================================================== | ||
262 | // | ||
263 | // Cyberblade specific syncing | ||
264 | // | ||
265 | // A timeout might be caused by disabled mmio. | ||
266 | // Cause: | ||
267 | // - bit CR39 & 1 == 0 upon return, X trident driver bug | ||
268 | // - kdm bug (KD_GRAPHICS not set on first switch) | ||
269 | // - kernel design flaw (it believes in the correctness | ||
270 | // of kdm/X | ||
271 | // First we try to sync ignoring that problem, as most of the | ||
272 | // time that will succeed immediately and the enable_mmio() | ||
273 | // would only degrade performance. | ||
274 | // | ||
275 | //===================================================================== | ||
276 | |||
277 | static int cyblafb_sync(struct fb_info *info) | ||
278 | { | ||
279 | u32 status, i = 100000; | ||
280 | |||
281 | KD_GRAPHICS_RETURN(0); | ||
282 | |||
283 | while (((status = in32(GE20)) & 0xFe800000) && i != 0) | ||
284 | i--; | ||
285 | |||
286 | if (i == 0) { | ||
287 | enable_mmio(); | ||
288 | i = 1000000; | ||
289 | while (((status = in32(GE20)) & 0xFA800000) && i != 0) | ||
290 | i--; | ||
291 | if (i == 0) { | ||
292 | output("GE Timeout, status: %x\n", status); | ||
293 | if (status & 0x80000000) | ||
294 | output("Bresenham Engine : Busy\n"); | ||
295 | if (status & 0x40000000) | ||
296 | output("Setup Engine : Busy\n"); | ||
297 | if (status & 0x20000000) | ||
298 | output("SP / DPE : Busy\n"); | ||
299 | if (status & 0x10000000) | ||
300 | output("Memory Interface : Busy\n"); | ||
301 | if (status & 0x08000000) | ||
302 | output("Com Lst Proc : Busy\n"); | ||
303 | if (status & 0x04000000) | ||
304 | output("Block Write : Busy\n"); | ||
305 | if (status & 0x02000000) | ||
306 | output("Command Buffer : Full\n"); | ||
307 | if (status & 0x01000000) | ||
308 | output("RESERVED : Busy\n"); | ||
309 | if (status & 0x00800000) | ||
310 | output("PCI Write Buffer : Busy\n"); | ||
311 | cyblafb_setup_GE(info->var.xres, | ||
312 | info->var.bits_per_pixel); | ||
313 | } | ||
314 | } | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | //============================== | ||
320 | // | ||
321 | // Cyberblade specific fillrect | ||
322 | // | ||
323 | //============================== | ||
324 | |||
325 | static void cyblafb_fillrect(struct fb_info *info, const struct fb_fillrect *fr) | ||
326 | { | ||
327 | u32 bpp = info->var.bits_per_pixel, col, desty, height; | ||
328 | |||
329 | KD_GRAPHICS_RETURN(); | ||
330 | |||
331 | switch (bpp) { | ||
332 | default: | ||
333 | case 8: | ||
334 | col = fr->color; | ||
335 | col |= col << 8; | ||
336 | col |= col << 16; | ||
337 | break; | ||
338 | case 16: | ||
339 | col = ((u32 *) (info->pseudo_palette))[fr->color]; | ||
340 | col |= col << 16; | ||
341 | break; | ||
342 | case 32: | ||
343 | col = ((u32 *) (info->pseudo_palette))[fr->color]; | ||
344 | break; | ||
345 | } | ||
346 | |||
347 | desty = fr->dy; | ||
348 | height = fr->height; | ||
349 | while (height) { | ||
350 | out32(GEB8, basestride | ((desty * info->var.xres_virtual * | ||
351 | bpp) >> 6)); | ||
352 | out32(GE60, col); | ||
353 | out32(GE48, fr->rop ? 0x66 : ROP_S); | ||
354 | out32(GE44, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2); | ||
355 | out32(GE08, point(fr->dx, 0)); | ||
356 | out32(GE0C, point(fr->dx + fr->width - 1, | ||
357 | height > 4096 ? 4095 : height - 1)); | ||
358 | if (likely(height <= 4096)) | ||
359 | return; | ||
360 | desty += 4096; | ||
361 | height -= 4096; | ||
362 | } | ||
363 | } | ||
364 | |||
365 | //================================================ | ||
366 | // | ||
367 | // Cyberblade specific copyarea | ||
368 | // | ||
369 | // This function silently assumes that it never | ||
370 | // will be called with width or height exceeding | ||
371 | // 4096. | ||
372 | // | ||
373 | //================================================ | ||
374 | |||
375 | static void cyblafb_copyarea(struct fb_info *info, const struct fb_copyarea *ca) | ||
376 | { | ||
377 | u32 s1, s2, d1, d2, direction; | ||
378 | |||
379 | KD_GRAPHICS_RETURN(); | ||
380 | |||
381 | s1 = point(ca->sx, 0); | ||
382 | s2 = point(ca->sx + ca->width - 1, ca->height - 1); | ||
383 | d1 = point(ca->dx, 0); | ||
384 | d2 = point(ca->dx + ca->width - 1, ca->height - 1); | ||
385 | |||
386 | if ((ca->sy > ca->dy) || ((ca->sy == ca->dy) && (ca->sx > ca->dx))) | ||
387 | direction = 0; | ||
388 | else | ||
389 | direction = 2; | ||
390 | |||
391 | out32(GEB8, basestride | ((ca->dy * info->var.xres_virtual * | ||
392 | info->var.bits_per_pixel) >> 6)); | ||
393 | out32(GEC8, basestride | ((ca->sy * info->var.xres_virtual * | ||
394 | info->var.bits_per_pixel) >> 6)); | ||
395 | out32(GE44, 0xa0000000 | 1 << 19 | 1 << 2 | direction); | ||
396 | out32(GE00, direction ? s2 : s1); | ||
397 | out32(GE04, direction ? s1 : s2); | ||
398 | out32(GE08, direction ? d2 : d1); | ||
399 | out32(GE0C, direction ? d1 : d2); | ||
400 | } | ||
401 | |||
402 | //======================================================================= | ||
403 | // | ||
404 | // Cyberblade specific imageblit | ||
405 | // | ||
406 | // Accelerated for the most usual case, blitting 1 - bit deep | ||
407 | // character images. Everything else is passed to the generic imageblit | ||
408 | // unless it is so insane that it is better to printk an alert. | ||
409 | // | ||
410 | // Hardware bug: _Never_ blit across pixel column 2048, that will lock | ||
411 | // the system. We split those blit requests into three blitting | ||
412 | // operations. | ||
413 | // | ||
414 | //======================================================================= | ||
415 | |||
416 | static void cyblafb_imageblit(struct fb_info *info, | ||
417 | const struct fb_image *image) | ||
418 | { | ||
419 | u32 fgcol, bgcol; | ||
420 | u32 *pd = (u32 *) image->data; | ||
421 | u32 bpp = info->var.bits_per_pixel; | ||
422 | |||
423 | KD_GRAPHICS_RETURN(); | ||
424 | |||
425 | // Used only for drawing the penguine (image->depth > 1) | ||
426 | if (image->depth != 1) { | ||
427 | cfb_imageblit(info, image); | ||
428 | return; | ||
429 | } | ||
430 | // That should never happen, but it would be fatal | ||
431 | if (image->width == 0 || image->height == 0) { | ||
432 | output("imageblit: width/height 0 detected\n"); | ||
433 | return; | ||
434 | } | ||
435 | |||
436 | if (info->fix.visual == FB_VISUAL_TRUECOLOR || | ||
437 | info->fix.visual == FB_VISUAL_DIRECTCOLOR) { | ||
438 | fgcol = ((u32 *) (info->pseudo_palette))[image->fg_color]; | ||
439 | bgcol = ((u32 *) (info->pseudo_palette))[image->bg_color]; | ||
440 | } else { | ||
441 | fgcol = image->fg_color; | ||
442 | bgcol = image->bg_color; | ||
443 | } | ||
444 | |||
445 | switch (bpp) { | ||
446 | case 8: | ||
447 | fgcol |= fgcol << 8; | ||
448 | bgcol |= bgcol << 8; | ||
449 | case 16: | ||
450 | fgcol |= fgcol << 16; | ||
451 | bgcol |= bgcol << 16; | ||
452 | default: | ||
453 | break; | ||
454 | } | ||
455 | |||
456 | out32(GEB8, basestride | ((image->dy * info->var.xres_virtual * | ||
457 | bpp) >> 6)); | ||
458 | out32(GE60, fgcol); | ||
459 | out32(GE64, bgcol); | ||
460 | |||
461 | if (!(image->dx < 2048 && (image->dx + image->width - 1) >= 2048)) { | ||
462 | u32 dds = ((image->width + 31) >> 5) * image->height; | ||
463 | out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); | ||
464 | out32(GE08, point(image->dx, 0)); | ||
465 | out32(GE0C, point(image->dx + image->width - 1, | ||
466 | image->height - 1)); | ||
467 | while (dds--) | ||
468 | out32(GE9C, *pd++); | ||
469 | } else { | ||
470 | int i, j; | ||
471 | u32 ddstotal = (image->width + 31) >> 5; | ||
472 | u32 ddsleft = (2048 - image->dx + 31) >> 5; | ||
473 | u32 skipleft = ddstotal - ddsleft; | ||
474 | |||
475 | out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); | ||
476 | out32(GE08, point(image->dx, 0)); | ||
477 | out32(GE0C, point(2048 - 1, image->height - 1)); | ||
478 | for (i = 0; i < image->height; i++) { | ||
479 | for (j = 0; j < ddsleft; j++) | ||
480 | out32(GE9C, *pd++); | ||
481 | pd += skipleft; | ||
482 | } | ||
483 | |||
484 | if (image->dx % 32) { | ||
485 | out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); | ||
486 | out32(GE08, point(2048, 0)); | ||
487 | if (image->width > ddsleft << 5) | ||
488 | out32(GE0C, point(image->dx + (ddsleft << 5) - | ||
489 | 1, image->height - 1)); | ||
490 | else | ||
491 | out32(GE0C, point(image->dx + image->width - 1, | ||
492 | image->height - 1)); | ||
493 | pd = ((u32 *) image->data) + ddstotal - skipleft - 1; | ||
494 | for (i = 0; i < image->height; i++) { | ||
495 | out32(GE9C, swab32(swab32(*pd) << ((32 - | ||
496 | (image->dx & 31)) & 31))); | ||
497 | pd += ddstotal; | ||
498 | } | ||
499 | } | ||
500 | |||
501 | if (skipleft) { | ||
502 | out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); | ||
503 | out32(GE08, point(image->dx + (ddsleft << 5), 0)); | ||
504 | out32(GE0C, point(image->dx + image->width - 1, | ||
505 | image->height - 1)); | ||
506 | pd = (u32 *) image->data; | ||
507 | for (i = 0; i < image->height; i++) { | ||
508 | pd += ddsleft; | ||
509 | for (j = 0; j < skipleft; j++) | ||
510 | out32(GE9C, *pd++); | ||
511 | } | ||
512 | } | ||
513 | } | ||
514 | } | ||
515 | |||
516 | //========================================================== | ||
517 | // | ||
518 | // Check if video mode is acceptable. We change var->??? if | ||
519 | // video mode is slightly off or return error otherwise. | ||
520 | // info->??? must not be changed! | ||
521 | // | ||
522 | //========================================================== | ||
523 | |||
524 | static int cyblafb_check_var(struct fb_var_screeninfo *var, | ||
525 | struct fb_info *info) | ||
526 | { | ||
527 | int bpp = var->bits_per_pixel; | ||
528 | |||
529 | // | ||
530 | // we try to support 8, 16, 24 and 32 bpp modes, | ||
531 | // default to 8 | ||
532 | // | ||
533 | // there is a 24 bpp mode, but for now we change requests to 32 bpp | ||
534 | // (This is what tridentfb does ... will be changed in the future) | ||
535 | // | ||
536 | // | ||
537 | if (bpp % 8 != 0 || bpp < 8 || bpp > 32) | ||
538 | bpp = 8; | ||
539 | if (bpp == 24) | ||
540 | bpp = var->bits_per_pixel = 32; | ||
541 | |||
542 | // | ||
543 | // interlaced modes are broken, fail if one is requested | ||
544 | // | ||
545 | if (var->vmode & FB_VMODE_INTERLACED) | ||
546 | return -EINVAL; | ||
547 | |||
548 | // | ||
549 | // fail if requested resolution is higher than physical | ||
550 | // flatpanel resolution | ||
551 | // | ||
552 | if ((displaytype == DISPLAY_FP) && nativex && var->xres > nativex) | ||
553 | return -EINVAL; | ||
554 | |||
555 | // | ||
556 | // we do not allow vclk to exceed 230 MHz. If the requested | ||
557 | // vclk is too high, we default to 200 MHz | ||
558 | // | ||
559 | if ((bpp == 32 ? 200000000 : 100000000) / var->pixclock > 23000) | ||
560 | var->pixclock = (bpp == 32 ? 200000000 : 100000000) / 20000; | ||
561 | |||
562 | // | ||
563 | // enforce (h|v)sync_len limits | ||
564 | // | ||
565 | var->hsync_len &= ~7; | ||
566 | if(var->hsync_len > 248) | ||
567 | var->hsync_len = 248; | ||
568 | |||
569 | var->vsync_len &= 15; | ||
570 | |||
571 | // | ||
572 | // Enforce horizontal and vertical hardware limits. | ||
573 | // 1600x1200 is mentioned as a maximum, but higher resolutions could | ||
574 | // work with slow refresh, small margins and short sync. | ||
575 | // | ||
576 | var->xres &= ~7; | ||
577 | |||
578 | if (((var->xres + var->left_margin + var->right_margin + | ||
579 | var->hsync_len) > (bpp == 32 ? 2040 : 4088)) || | ||
580 | ((var->yres + var->upper_margin + var->lower_margin + | ||
581 | var->vsync_len) > 2047)) | ||
582 | return -EINVAL; | ||
583 | |||
584 | if ((var->xres > 1600) || (var->yres > 1200)) | ||
585 | output("Mode %dx%d exceeds documented limits.\n", | ||
586 | var->xres, var->yres); | ||
587 | // | ||
588 | // try to be smart about (x|y)res_virtual problems. | ||
589 | // | ||
590 | if (var->xres > var->xres_virtual) | ||
591 | var->xres_virtual = var->xres; | ||
592 | if (var->yres > var->yres_virtual) | ||
593 | var->yres_virtual = var->yres; | ||
594 | |||
595 | if (bpp == 8 || bpp == 16) { | ||
596 | if (var->xres_virtual > 4088) | ||
597 | var->xres_virtual = 4088; | ||
598 | } else { | ||
599 | if (var->xres_virtual > 2040) | ||
600 | var->xres_virtual = 2040; | ||
601 | } | ||
602 | var->xres_virtual &= ~7; | ||
603 | while (var->xres_virtual * var->yres_virtual * bpp / 8 > | ||
604 | info->fix.smem_len) { | ||
605 | if (var->yres_virtual > var->yres) | ||
606 | var->yres_virtual--; | ||
607 | else if (var->xres_virtual > var->xres) | ||
608 | var->xres_virtual -= 8; | ||
609 | else | ||
610 | return -EINVAL; | ||
611 | } | ||
612 | |||
613 | switch (bpp) { | ||
614 | case 8: | ||
615 | var->red.offset = 0; | ||
616 | var->green.offset = 0; | ||
617 | var->blue.offset = 0; | ||
618 | var->red.length = 6; | ||
619 | var->green.length = 6; | ||
620 | var->blue.length = 6; | ||
621 | break; | ||
622 | case 16: | ||
623 | var->red.offset = 11; | ||
624 | var->green.offset = 5; | ||
625 | var->blue.offset = 0; | ||
626 | var->red.length = 5; | ||
627 | var->green.length = 6; | ||
628 | var->blue.length = 5; | ||
629 | break; | ||
630 | case 32: | ||
631 | var->red.offset = 16; | ||
632 | var->green.offset = 8; | ||
633 | var->blue.offset = 0; | ||
634 | var->red.length = 8; | ||
635 | var->green.length = 8; | ||
636 | var->blue.length = 8; | ||
637 | break; | ||
638 | default: | ||
639 | return -EINVAL; | ||
640 | } | ||
641 | |||
642 | return 0; | ||
643 | } | ||
644 | |||
645 | //===================================================================== | ||
646 | // | ||
647 | // Pan the display | ||
648 | // | ||
649 | // The datasheets defines crt start address to be 20 bits wide and | ||
650 | // to be programmed to CR0C, CR0D, CR1E and CR27. Actually there is | ||
651 | // CR2B[5] as an undocumented extension bit. Epia BIOS 2.07 does use | ||
652 | // it, so it is also safe to be used here. BTW: datasheet CR0E on page | ||
653 | // 90 really is CR1E, the real CRE is documented on page 72. | ||
654 | // | ||
655 | // BUT: | ||
656 | // | ||
657 | // As of internal version 0.60 we do not use vga panning any longer. | ||
658 | // Vga panning did not allow us the use of all available video memory | ||
659 | // and thus prevented ywrap scrolling. We do use the "right view" | ||
660 | // register now. | ||
661 | // | ||
662 | // | ||
663 | //===================================================================== | ||
664 | |||
665 | static int cyblafb_pan_display(struct fb_var_screeninfo *var, | ||
666 | struct fb_info *info) | ||
667 | { | ||
668 | KD_GRAPHICS_RETURN(0); | ||
669 | |||
670 | info->var.xoffset = var->xoffset; | ||
671 | info->var.yoffset = var->yoffset; | ||
672 | out32(GE10, 0x80000000 | ((var->xoffset + (var->yoffset * | ||
673 | var->xres_virtual)) * var->bits_per_pixel / 32)); | ||
674 | return 0; | ||
675 | } | ||
676 | |||
677 | //============================================ | ||
678 | // | ||
679 | // This will really help in case of a bug ... | ||
680 | // dump most gaphics core registers. | ||
681 | // | ||
682 | //============================================ | ||
683 | |||
684 | static void regdump(struct cyblafb_par *par) | ||
685 | { | ||
686 | int i; | ||
687 | |||
688 | if (verbosity < 2) | ||
689 | return; | ||
690 | |||
691 | printk("\n"); | ||
692 | for (i = 0; i <= 0xff; i++) { | ||
693 | outb(i, 0x3d4); | ||
694 | printk("CR%02x=%02x ", i, inb(0x3d5)); | ||
695 | if (i % 16 == 15) | ||
696 | printk("\n"); | ||
697 | } | ||
698 | |||
699 | outb(0x30, 0x3ce); | ||
700 | outb(inb(0x3cf) | 0x40, 0x3cf); | ||
701 | for (i = 0; i <= 0x1f; i++) { | ||
702 | if (i == 0 || (i > 2 && i < 8) || i == 0x10 || i == 0x11 | ||
703 | || i == 0x16) { | ||
704 | outb(i, 0x3d4); | ||
705 | printk("CR%02x=%02x ", i, inb(0x3d5)); | ||
706 | } else | ||
707 | printk("------- "); | ||
708 | if (i % 16 == 15) | ||
709 | printk("\n"); | ||
710 | } | ||
711 | outb(0x30, 0x3ce); | ||
712 | outb(inb(0x3cf) & 0xbf, 0x3cf); | ||
713 | |||
714 | printk("\n"); | ||
715 | for (i = 0; i <= 0x7f; i++) { | ||
716 | outb(i, 0x3ce); | ||
717 | printk("GR%02x=%02x ", i, inb(0x3cf)); | ||
718 | if (i % 16 == 15) | ||
719 | printk("\n"); | ||
720 | } | ||
721 | |||
722 | printk("\n"); | ||
723 | for (i = 0; i <= 0xff; i++) { | ||
724 | outb(i, 0x3c4); | ||
725 | printk("SR%02x=%02x ", i, inb(0x3c5)); | ||
726 | if (i % 16 == 15) | ||
727 | printk("\n"); | ||
728 | } | ||
729 | |||
730 | printk("\n"); | ||
731 | for (i = 0; i <= 0x1F; i++) { | ||
732 | inb(0x3da); // next access is index! | ||
733 | outb(i, 0x3c0); | ||
734 | printk("AR%02x=%02x ", i, inb(0x3c1)); | ||
735 | if (i % 16 == 15) | ||
736 | printk("\n"); | ||
737 | } | ||
738 | printk("\n"); | ||
739 | |||
740 | inb(0x3DA); // reset internal flag to 3c0 index | ||
741 | outb(0x20, 0x3C0); // enable attr | ||
742 | |||
743 | return; | ||
744 | } | ||
745 | |||
746 | //======================================================================= | ||
747 | // | ||
748 | // Save State | ||
749 | // | ||
750 | // This function is called while a switch to KD_TEXT is in progress, | ||
751 | // before any of the other functions are called. | ||
752 | // | ||
753 | //======================================================================= | ||
754 | |||
755 | static void cyblafb_save_state(struct fb_info *info) | ||
756 | { | ||
757 | struct cyblafb_par *par = info->par; | ||
758 | if (verbosity > 0) | ||
759 | output("Switching to KD_TEXT\n"); | ||
760 | disabled = 0; | ||
761 | regdump(par); | ||
762 | enable_mmio(); | ||
763 | return; | ||
764 | } | ||
765 | |||
766 | //======================================================================= | ||
767 | // | ||
768 | // Restore State | ||
769 | // | ||
770 | // This function is called while a switch to KD_GRAPHICS is in progress, | ||
771 | // We have to turn on vga style panning registers again because the | ||
772 | // trident driver of X does not know about GE10. | ||
773 | // | ||
774 | //======================================================================= | ||
775 | |||
776 | static void cyblafb_restore_state(struct fb_info *info) | ||
777 | { | ||
778 | if (verbosity > 0) | ||
779 | output("Switching to KD_GRAPHICS\n"); | ||
780 | out32(GE10, 0); | ||
781 | disabled = 1; | ||
782 | return; | ||
783 | } | ||
784 | |||
785 | //====================================== | ||
786 | // | ||
787 | // Set hardware to requested video mode | ||
788 | // | ||
789 | //====================================== | ||
790 | |||
791 | static int cyblafb_set_par(struct fb_info *info) | ||
792 | { | ||
793 | struct cyblafb_par *par = info->par; | ||
794 | u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, | ||
795 | hblankend, preendfetch, vtotal, vdispend, vsyncstart, | ||
796 | vsyncend, vblankstart, vblankend; | ||
797 | struct fb_var_screeninfo *var = &info->var; | ||
798 | int bpp = var->bits_per_pixel; | ||
799 | int i; | ||
800 | |||
801 | KD_GRAPHICS_RETURN(0); | ||
802 | |||
803 | if (verbosity > 0) | ||
804 | output("Switching to new mode: " | ||
805 | "fbset -g %d %d %d %d %d -t %d %d %d %d %d %d %d\n", | ||
806 | var->xres, var->yres, var->xres_virtual, | ||
807 | var->yres_virtual, var->bits_per_pixel, var->pixclock, | ||
808 | var->left_margin, var->right_margin, var->upper_margin, | ||
809 | var->lower_margin, var->hsync_len, var->vsync_len); | ||
810 | |||
811 | htotal = (var->xres + var->left_margin + var->right_margin + | ||
812 | var->hsync_len) / 8 - 5; | ||
813 | hdispend = var->xres / 8 - 1; | ||
814 | hsyncstart = (var->xres + var->right_margin) / 8; | ||
815 | hsyncend = var->hsync_len / 8; | ||
816 | hblankstart = hdispend + 1; | ||
817 | hblankend = htotal + 3; // should be htotal + 5, bios does it this way | ||
818 | preendfetch = ((var->xres >> 3) + 1) * ((bpp + 1) >> 3); | ||
819 | |||
820 | vtotal = var->yres + var->upper_margin + var->lower_margin + | ||
821 | var->vsync_len - 2; | ||
822 | vdispend = var->yres - 1; | ||
823 | vsyncstart = var->yres + var->lower_margin; | ||
824 | vblankstart = var->yres; | ||
825 | vblankend = vtotal; // should be vtotal + 2, but bios does it this way | ||
826 | vsyncend = var->vsync_len; | ||
827 | |||
828 | enable_mmio(); // necessary! ... check X ... | ||
829 | |||
830 | write3X4(CR11, read3X4(CR11) & 0x7F); // unlock cr00 .. cr07 | ||
831 | |||
832 | write3CE(GR30, 8); | ||
833 | |||
834 | if ((displaytype == DISPLAY_FP) && var->xres < nativex) { | ||
835 | |||
836 | // stretch or center ? | ||
837 | |||
838 | out8(0x3C2, 0xEB); | ||
839 | |||
840 | write3CE(GR30, read3CE(GR30) | 0x81); // shadow mode on | ||
841 | |||
842 | if (center) { | ||
843 | write3CE(GR52, (read3CE(GR52) & 0x7C) | 0x80); | ||
844 | write3CE(GR53, (read3CE(GR53) & 0x7C) | 0x80); | ||
845 | } else if (stretch) { | ||
846 | write3CE(GR5D, 0); | ||
847 | write3CE(GR52, (read3CE(GR52) & 0x7C) | 1); | ||
848 | write3CE(GR53, (read3CE(GR53) & 0x7C) | 1); | ||
849 | } | ||
850 | |||
851 | } else { | ||
852 | out8(0x3C2, 0x2B); | ||
853 | write3CE(GR30, 8); | ||
854 | } | ||
855 | |||
856 | // | ||
857 | // Setup CRxx regs | ||
858 | // | ||
859 | |||
860 | write3X4(CR00, htotal & 0xFF); | ||
861 | write3X4(CR01, hdispend & 0xFF); | ||
862 | write3X4(CR02, hblankstart & 0xFF); | ||
863 | write3X4(CR03, hblankend & 0x1F); | ||
864 | write3X4(CR04, hsyncstart & 0xFF); | ||
865 | write3X4(CR05, (hsyncend & 0x1F) | ((hblankend & 0x20) << 2)); | ||
866 | write3X4(CR06, vtotal & 0xFF); | ||
867 | write3X4(CR07, (vtotal & 0x100) >> 8 | | ||
868 | (vdispend & 0x100) >> 7 | | ||
869 | (vsyncstart & 0x100) >> 6 | | ||
870 | (vblankstart & 0x100) >> 5 | | ||
871 | 0x10 | | ||
872 | (vtotal & 0x200) >> 4 | | ||
873 | (vdispend & 0x200) >> 3 | (vsyncstart & 0x200) >> 2); | ||
874 | write3X4(CR08, 0); | ||
875 | write3X4(CR09, (vblankstart & 0x200) >> 4 | 0x40 | // FIX !!! | ||
876 | ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0)); | ||
877 | write3X4(CR0A, 0); // Init to some reasonable default | ||
878 | write3X4(CR0B, 0); // Init to some reasonable default | ||
879 | write3X4(CR0C, 0); // Offset 0 | ||
880 | write3X4(CR0D, 0); // Offset 0 | ||
881 | write3X4(CR0E, 0); // Init to some reasonable default | ||
882 | write3X4(CR0F, 0); // Init to some reasonable default | ||
883 | write3X4(CR10, vsyncstart & 0xFF); | ||
884 | write3X4(CR11, (vsyncend & 0x0F)); | ||
885 | write3X4(CR12, vdispend & 0xFF); | ||
886 | write3X4(CR13, ((info->var.xres_virtual * bpp) / (4 * 16)) & 0xFF); | ||
887 | write3X4(CR14, 0x40); // double word mode | ||
888 | write3X4(CR15, vblankstart & 0xFF); | ||
889 | write3X4(CR16, vblankend & 0xFF); | ||
890 | write3X4(CR17, 0xE3); | ||
891 | write3X4(CR18, 0xFF); | ||
892 | // CR19: needed for interlaced modes ... ignore it for now | ||
893 | write3X4(CR1A, 0x07); // Arbitration Control Counter 1 | ||
894 | write3X4(CR1B, 0x07); // Arbitration Control Counter 2 | ||
895 | write3X4(CR1C, 0x07); // Arbitration Control Counter 3 | ||
896 | write3X4(CR1D, 0x00); // Don't know, doesn't hurt ; -) | ||
897 | write3X4(CR1E, (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80); | ||
898 | // CR1F: do not set, contains BIOS info about memsize | ||
899 | write3X4(CR20, 0x20); // enabe wr buf, disable 16bit planar mode | ||
900 | write3X4(CR21, 0x20); // enable linear memory access | ||
901 | // CR22: RO cpu latch readback | ||
902 | // CR23: ??? | ||
903 | // CR24: RO AR flag state | ||
904 | // CR25: RAMDAC rw timing, pclk buffer tristate control ???? | ||
905 | // CR26: ??? | ||
906 | write3X4(CR27, (vdispend & 0x400) >> 6 | | ||
907 | (vsyncstart & 0x400) >> 5 | | ||
908 | (vblankstart & 0x400) >> 4 | | ||
909 | (vtotal & 0x400) >> 3 | | ||
910 | 0x8); | ||
911 | // CR28: ??? | ||
912 | write3X4(CR29, (read3X4(CR29) & 0xCF) | ((((info->var.xres_virtual * | ||
913 | bpp) / (4 * 16)) & 0x300) >> 4)); | ||
914 | write3X4(CR2A, read3X4(CR2A) | 0x40); | ||
915 | write3X4(CR2B, (htotal & 0x100) >> 8 | | ||
916 | (hdispend & 0x100) >> 7 | | ||
917 | // (0x00 & 0x100) >> 6 | hinterlace para bit 8 ??? | ||
918 | (hsyncstart & 0x100) >> 5 | | ||
919 | (hblankstart & 0x100) >> 4); | ||
920 | // CR2C: ??? | ||
921 | // CR2D: initialized in cyblafb_setup_GE() | ||
922 | write3X4(CR2F, 0x92); // conservative, better signal quality | ||
923 | // CR30: reserved | ||
924 | // CR31: reserved | ||
925 | // CR32: reserved | ||
926 | // CR33: reserved | ||
927 | // CR34: disabled in CR36 | ||
928 | // CR35: disabled in CR36 | ||
929 | // CR36: initialized in cyblafb_setup_GE | ||
930 | // CR37: i2c, ignore for now | ||
931 | write3X4(CR38, (bpp == 8) ? 0x00 : // | ||
932 | (bpp == 16) ? 0x05 : // highcolor | ||
933 | (bpp == 24) ? 0x29 : // packed 24bit truecolor | ||
934 | (bpp == 32) ? 0x09 : 0); // truecolor, 16 bit pixelbus | ||
935 | write3X4(CR39, 0x01 | // MMIO enable | ||
936 | (pcirb ? 0x02 : 0) | // pci read burst enable | ||
937 | (pciwb ? 0x04 : 0)); // pci write burst enable | ||
938 | write3X4(CR55, 0x1F | // pci clocks * 2 for STOP# during 1st data phase | ||
939 | (pcirr ? 0x40 : 0) | // pci read retry enable | ||
940 | (pciwr ? 0x80 : 0)); // pci write retry enable | ||
941 | write3X4(CR56, preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01) | 2 | ||
942 | : 0); | ||
943 | write3X4(CR57, preendfetch >> 8 < 2 ? preendfetch & 0xff : 0); | ||
944 | write3X4(CR58, 0x82); // Bios does this .... don't know more | ||
945 | // | ||
946 | // Setup SRxx regs | ||
947 | // | ||
948 | write3C4(SR00, 3); | ||
949 | write3C4(SR01, 1); //set char clock 8 dots wide | ||
950 | write3C4(SR02, 0x0F); //enable 4 maps needed in chain4 mode | ||
951 | write3C4(SR03, 0); //no character map select | ||
952 | write3C4(SR04, 0x0E); //memory mode: ext mem, even, chain4 | ||
953 | |||
954 | out8(0x3C4, 0x0b); | ||
955 | in8(0x3C5); // Set NEW mode | ||
956 | write3C4(SR0D, 0x00); // test ... check | ||
957 | |||
958 | set_vclk(par, (bpp == 32 ? 200000000 : 100000000) | ||
959 | / info->var.pixclock); //SR18, SR19 | ||
960 | |||
961 | // | ||
962 | // Setup GRxx regs | ||
963 | // | ||
964 | write3CE(GR00, 0x00); // test ... check | ||
965 | write3CE(GR01, 0x00); // test ... check | ||
966 | write3CE(GR02, 0x00); // test ... check | ||
967 | write3CE(GR03, 0x00); // test ... check | ||
968 | write3CE(GR04, 0x00); // test ... check | ||
969 | write3CE(GR05, 0x40); // no CGA compat, allow 256 col | ||
970 | write3CE(GR06, 0x05); // graphics mode | ||
971 | write3CE(GR07, 0x0F); // planes? | ||
972 | write3CE(GR08, 0xFF); // test ... check | ||
973 | write3CE(GR0F, (bpp == 32) ? 0x1A : 0x12); // vclk / 2 if 32bpp, chain4 | ||
974 | write3CE(GR20, 0xC0); // test ... check | ||
975 | write3CE(GR2F, 0xA0); // PCLK = VCLK, no skew, | ||
976 | |||
977 | // | ||
978 | // Setup ARxx regs | ||
979 | // | ||
980 | for (i = 0; i < 0x10; i++) // set AR00 .. AR0f | ||
981 | write3C0(i, i); | ||
982 | write3C0(AR10, 0x41); // graphics mode and support 256 color modes | ||
983 | write3C0(AR12, 0x0F); // planes | ||
984 | write3C0(AR13, 0); // horizontal pel panning | ||
985 | in8(0x3DA); // reset internal flag to 3c0 index | ||
986 | out8(0x3C0, 0x20); // enable attr | ||
987 | |||
988 | // | ||
989 | // Setup hidden RAMDAC command register | ||
990 | // | ||
991 | in8(0x3C8); // these reads are | ||
992 | in8(0x3C6); // necessary to | ||
993 | in8(0x3C6); // unmask the RAMDAC | ||
994 | in8(0x3C6); // command reg, otherwise | ||
995 | in8(0x3C6); // we would write the pixelmask reg! | ||
996 | out8(0x3C6, (bpp == 8) ? 0x00 : // 256 colors | ||
997 | (bpp == 15) ? 0x10 : // | ||
998 | (bpp == 16) ? 0x30 : // hicolor | ||
999 | (bpp == 24) ? 0xD0 : // truecolor | ||
1000 | (bpp == 32) ? 0xD0 : 0); // truecolor | ||
1001 | in8(0x3C8); | ||
1002 | |||
1003 | // | ||
1004 | // GR31 is not mentioned in the datasheet | ||
1005 | // | ||
1006 | if (displaytype == DISPLAY_FP) | ||
1007 | write3CE(GR31, (read3CE(GR31) & 0x8F) | | ||
1008 | ((info->var.yres > 1024) ? 0x50 : | ||
1009 | (info->var.yres > 768) ? 0x30 : | ||
1010 | (info->var.yres > 600) ? 0x20 : | ||
1011 | (info->var.yres > 480) ? 0x10 : 0)); | ||
1012 | |||
1013 | info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR | ||
1014 | : FB_VISUAL_TRUECOLOR; | ||
1015 | info->fix.line_length = info->var.xres_virtual * (bpp >> 3); | ||
1016 | info->cmap.len = (bpp == 8) ? 256 : 16; | ||
1017 | |||
1018 | // | ||
1019 | // init acceleration engine | ||
1020 | // | ||
1021 | cyblafb_setup_GE(info->var.xres_virtual, info->var.bits_per_pixel); | ||
1022 | |||
1023 | // | ||
1024 | // Set/clear flags to allow proper scroll mode selection. | ||
1025 | // | ||
1026 | if (var->xres == var->xres_virtual) | ||
1027 | info->flags &= ~FBINFO_HWACCEL_XPAN; | ||
1028 | else | ||
1029 | info->flags |= FBINFO_HWACCEL_XPAN; | ||
1030 | |||
1031 | if (var->yres == var->yres_virtual) | ||
1032 | info->flags &= ~FBINFO_HWACCEL_YPAN; | ||
1033 | else | ||
1034 | info->flags |= FBINFO_HWACCEL_YPAN; | ||
1035 | |||
1036 | if (info->fix.smem_len != | ||
1037 | var->xres_virtual * var->yres_virtual * bpp / 8) | ||
1038 | info->flags &= ~FBINFO_HWACCEL_YWRAP; | ||
1039 | else | ||
1040 | info->flags |= FBINFO_HWACCEL_YWRAP; | ||
1041 | |||
1042 | regdump(par); | ||
1043 | |||
1044 | return 0; | ||
1045 | } | ||
1046 | |||
1047 | //======================== | ||
1048 | // | ||
1049 | // Set one color register | ||
1050 | // | ||
1051 | //======================== | ||
1052 | |||
1053 | static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
1054 | unsigned blue, unsigned transp, | ||
1055 | struct fb_info *info) | ||
1056 | { | ||
1057 | int bpp = info->var.bits_per_pixel; | ||
1058 | |||
1059 | KD_GRAPHICS_RETURN(0); | ||
1060 | |||
1061 | if (regno >= info->cmap.len) | ||
1062 | return 1; | ||
1063 | |||
1064 | if (bpp == 8) { | ||
1065 | out8(0x3C6, 0xFF); | ||
1066 | out8(0x3C8, regno); | ||
1067 | out8(0x3C9, red >> 10); | ||
1068 | out8(0x3C9, green >> 10); | ||
1069 | out8(0x3C9, blue >> 10); | ||
1070 | |||
1071 | } else if (regno < 16) { | ||
1072 | if (bpp == 16) // RGB 565 | ||
1073 | ((u32 *) info->pseudo_palette)[regno] = | ||
1074 | (red & 0xF800) | | ||
1075 | ((green & 0xFC00) >> 5) | | ||
1076 | ((blue & 0xF800) >> 11); | ||
1077 | else if (bpp == 32) // ARGB 8888 | ||
1078 | ((u32 *) info->pseudo_palette)[regno] = | ||
1079 | ((transp & 0xFF00) << 16) | | ||
1080 | ((red & 0xFF00) << 8) | | ||
1081 | ((green & 0xFF00)) | ((blue & 0xFF00) >> 8); | ||
1082 | } | ||
1083 | |||
1084 | return 0; | ||
1085 | } | ||
1086 | |||
1087 | //========================================================== | ||
1088 | // | ||
1089 | // Try blanking the screen. For flat panels it does nothing | ||
1090 | // | ||
1091 | //========================================================== | ||
1092 | |||
1093 | static int cyblafb_blank(int blank_mode, struct fb_info *info) | ||
1094 | { | ||
1095 | unsigned char PMCont, DPMSCont; | ||
1096 | |||
1097 | KD_GRAPHICS_RETURN(0); | ||
1098 | |||
1099 | if (displaytype == DISPLAY_FP) | ||
1100 | return 0; | ||
1101 | |||
1102 | out8(0x83C8, 0x04); // DPMS Control | ||
1103 | PMCont = in8(0x83C6) & 0xFC; | ||
1104 | |||
1105 | DPMSCont = read3CE(GR23) & 0xFC; | ||
1106 | |||
1107 | switch (blank_mode) { | ||
1108 | case FB_BLANK_UNBLANK: // Screen: On, HSync: On, VSync: On | ||
1109 | case FB_BLANK_NORMAL: // Screen: Off, HSync: On, VSync: On | ||
1110 | PMCont |= 0x03; | ||
1111 | DPMSCont |= 0x00; | ||
1112 | break; | ||
1113 | case FB_BLANK_HSYNC_SUSPEND: // Screen: Off, HSync: Off, VSync: On | ||
1114 | PMCont |= 0x02; | ||
1115 | DPMSCont |= 0x01; | ||
1116 | break; | ||
1117 | case FB_BLANK_VSYNC_SUSPEND: // Screen: Off, HSync: On, VSync: Off | ||
1118 | PMCont |= 0x02; | ||
1119 | DPMSCont |= 0x02; | ||
1120 | break; | ||
1121 | case FB_BLANK_POWERDOWN: // Screen: Off, HSync: Off, VSync: Off | ||
1122 | PMCont |= 0x00; | ||
1123 | DPMSCont |= 0x03; | ||
1124 | break; | ||
1125 | } | ||
1126 | |||
1127 | write3CE(GR23, DPMSCont); | ||
1128 | out8(0x83C8, 4); | ||
1129 | out8(0x83C6, PMCont); | ||
1130 | // | ||
1131 | // let fbcon do a softblank for us | ||
1132 | // | ||
1133 | return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0; | ||
1134 | } | ||
1135 | |||
1136 | static struct fb_ops cyblafb_ops __devinitdata = { | ||
1137 | .owner = THIS_MODULE, | ||
1138 | .fb_setcolreg = cyblafb_setcolreg, | ||
1139 | .fb_pan_display = cyblafb_pan_display, | ||
1140 | .fb_blank = cyblafb_blank, | ||
1141 | .fb_check_var = cyblafb_check_var, | ||
1142 | .fb_set_par = cyblafb_set_par, | ||
1143 | .fb_fillrect = cyblafb_fillrect, | ||
1144 | .fb_copyarea = cyblafb_copyarea, | ||
1145 | .fb_imageblit = cyblafb_imageblit, | ||
1146 | .fb_sync = cyblafb_sync, | ||
1147 | .fb_restore_state = cyblafb_restore_state, | ||
1148 | .fb_save_state = cyblafb_save_state, | ||
1149 | }; | ||
1150 | |||
1151 | //========================================================================== | ||
1152 | // | ||
1153 | // getstartupmode() decides about the inital video mode | ||
1154 | // | ||
1155 | // There is no reason to use modedb, a lot of video modes there would | ||
1156 | // need altered timings to display correctly. So I decided that it is much | ||
1157 | // better to provide a limited optimized set of modes plus the option of | ||
1158 | // using the mode in effect at startup time (might be selected using the | ||
1159 | // vga=??? parameter). After that the user might use fbset to select any | ||
1160 | // mode he likes, check_var will not try to alter geometry parameters as | ||
1161 | // it would be necessary otherwise. | ||
1162 | // | ||
1163 | //========================================================================== | ||
1164 | |||
1165 | static int __devinit getstartupmode(struct fb_info *info) | ||
1166 | { | ||
1167 | u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend, | ||
1168 | vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend, | ||
1169 | cr00, cr01, cr02, cr03, cr04, cr05, cr2b, | ||
1170 | cr06, cr07, cr09, cr10, cr11, cr12, cr15, cr16, cr27, | ||
1171 | cr38, sr0d, sr18, sr19, gr0f, fi, pxclkdiv, vclkdiv, tmp, i; | ||
1172 | |||
1173 | struct modus { | ||
1174 | int xres; int vxres; int yres; int vyres; | ||
1175 | int bpp; int pxclk; | ||
1176 | int left_margin; int right_margin; | ||
1177 | int upper_margin; int lower_margin; | ||
1178 | int hsync_len; int vsync_len; | ||
1179 | } modedb[5] = { | ||
1180 | { | ||
1181 | 0, 2048, 0, 4096, 0, 0, 0, 0, 0, 0, 0, 0}, { | ||
1182 | 640, 2048, 480, 4096, 0, 0, -40, 24, 17, 0, 216, 3}, { | ||
1183 | 800, 2048, 600, 4096, 0, 0, 96, 24, 14, 0, 136, 11}, { | ||
1184 | 1024, 2048, 768, 4096, 0, 0, 144, 24, 29, 0, 120, 3}, { | ||
1185 | 1280, 2048, 1024, 4096, 0, 0, 232, 16, 39, 0, 160, 3} | ||
1186 | }; | ||
1187 | |||
1188 | outb(0x00, 0x3d4); cr00 = inb(0x3d5); | ||
1189 | outb(0x01, 0x3d4); cr01 = inb(0x3d5); | ||
1190 | outb(0x02, 0x3d4); cr02 = inb(0x3d5); | ||
1191 | outb(0x03, 0x3d4); cr03 = inb(0x3d5); | ||
1192 | outb(0x04, 0x3d4); cr04 = inb(0x3d5); | ||
1193 | outb(0x05, 0x3d4); cr05 = inb(0x3d5); | ||
1194 | outb(0x06, 0x3d4); cr06 = inb(0x3d5); | ||
1195 | outb(0x07, 0x3d4); cr07 = inb(0x3d5); | ||
1196 | outb(0x09, 0x3d4); cr09 = inb(0x3d5); | ||
1197 | outb(0x10, 0x3d4); cr10 = inb(0x3d5); | ||
1198 | outb(0x11, 0x3d4); cr11 = inb(0x3d5); | ||
1199 | outb(0x12, 0x3d4); cr12 = inb(0x3d5); | ||
1200 | outb(0x15, 0x3d4); cr15 = inb(0x3d5); | ||
1201 | outb(0x16, 0x3d4); cr16 = inb(0x3d5); | ||
1202 | outb(0x27, 0x3d4); cr27 = inb(0x3d5); | ||
1203 | outb(0x2b, 0x3d4); cr2b = inb(0x3d5); | ||
1204 | outb(0x38, 0x3d4); cr38 = inb(0x3d5); | ||
1205 | |||
1206 | outb(0x0b, 0x3c4); | ||
1207 | inb(0x3c5); | ||
1208 | |||
1209 | outb(0x0d, 0x3c4); sr0d = inb(0x3c5); | ||
1210 | outb(0x18, 0x3c4); sr18 = inb(0x3c5); | ||
1211 | outb(0x19, 0x3c4); sr19 = inb(0x3c5); | ||
1212 | outb(0x0f, 0x3ce); gr0f = inb(0x3cf); | ||
1213 | |||
1214 | htotal = cr00 | (cr2b & 0x01) << 8; | ||
1215 | hdispend = cr01 | (cr2b & 0x02) << 7; | ||
1216 | hblankstart = cr02 | (cr2b & 0x10) << 4; | ||
1217 | hblankend = (cr03 & 0x1f) | (cr05 & 0x80) >> 2; | ||
1218 | hsyncstart = cr04 | (cr2b & 0x08) << 5; | ||
1219 | hsyncend = cr05 & 0x1f; | ||
1220 | |||
1221 | modedb[0].xres = hblankstart * 8; | ||
1222 | modedb[0].hsync_len = hsyncend * 8; | ||
1223 | modedb[0].right_margin = hsyncstart * 8 - modedb[0].xres; | ||
1224 | modedb[0].left_margin = (htotal + 5) * 8 - modedb[0].xres - | ||
1225 | modedb[0].right_margin - modedb[0].hsync_len; | ||
1226 | |||
1227 | vtotal = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4 | ||
1228 | | (cr27 & 0x80) << 3; | ||
1229 | vdispend = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3 | ||
1230 | | (cr27 & 0x10) << 6; | ||
1231 | vsyncstart = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2 | ||
1232 | | (cr27 & 0x20) << 5; | ||
1233 | vsyncend = cr11 & 0x0f; | ||
1234 | vblankstart = cr15 | (cr07 & 0x08) << 5 | (cr09 & 0x20) << 4 | ||
1235 | | (cr27 & 0x40) << 4; | ||
1236 | vblankend = cr16; | ||
1237 | |||
1238 | modedb[0].yres = vdispend + 1; | ||
1239 | modedb[0].vsync_len = vsyncend; | ||
1240 | modedb[0].lower_margin = vsyncstart - modedb[0].yres; | ||
1241 | modedb[0].upper_margin = vtotal - modedb[0].yres - | ||
1242 | modedb[0].lower_margin - modedb[0].vsync_len + 2; | ||
1243 | |||
1244 | tmp = cr38 & 0x3c; | ||
1245 | modedb[0].bpp = tmp == 0 ? 8 : tmp == 4 ? 16 : tmp == 28 ? 24 : | ||
1246 | tmp == 8 ? 32 : 8; | ||
1247 | |||
1248 | fi = ((5864727 * (sr18 + 8)) / | ||
1249 | (((sr19 & 0x3f) + 2) * (1 << ((sr19 & 0xc0) >> 6)))) >> 12; | ||
1250 | pxclkdiv = ((gr0f & 0x08) >> 3 | (gr0f & 0x40) >> 5) + 1; | ||
1251 | tmp = sr0d & 0x06; | ||
1252 | vclkdiv = tmp == 0 ? 2 : tmp == 2 ? 4 : tmp == 4 ? 8 : 3; // * 2 ! | ||
1253 | modedb[0].pxclk = ((100000000 * pxclkdiv * vclkdiv) >> 1) / fi; | ||
1254 | |||
1255 | if (verbosity > 0) | ||
1256 | output("detected startup mode: " | ||
1257 | "fbset -g %d %d %d ??? %d -t %d %d %d %d %d %d %d\n", | ||
1258 | modedb[0].xres, modedb[0].yres, modedb[0].xres, | ||
1259 | modedb[0].bpp, modedb[0].pxclk, modedb[0].left_margin, | ||
1260 | modedb[0].right_margin, modedb[0].upper_margin, | ||
1261 | modedb[0].lower_margin, modedb[0].hsync_len, | ||
1262 | modedb[0].vsync_len); | ||
1263 | |||
1264 | // | ||
1265 | // We use this goto target in case of a failed check_var. No, I really | ||
1266 | // do not want to do it in another way! | ||
1267 | // | ||
1268 | |||
1269 | tryagain: | ||
1270 | |||
1271 | i = (mode == NULL) ? 0 : | ||
1272 | !strncmp(mode, "640x480", 7) ? 1 : | ||
1273 | !strncmp(mode, "800x600", 7) ? 2 : | ||
1274 | !strncmp(mode, "1024x768", 8) ? 3 : | ||
1275 | !strncmp(mode, "1280x1024", 9) ? 4 : 0; | ||
1276 | |||
1277 | ref = (ref < 50) ? 50 : (ref > 85) ? 85 : ref; | ||
1278 | |||
1279 | if (i == 0) { | ||
1280 | info->var.pixclock = modedb[i].pxclk; | ||
1281 | info->var.bits_per_pixel = modedb[i].bpp; | ||
1282 | } else { | ||
1283 | info->var.pixclock = (100000000 / | ||
1284 | ((modedb[i].left_margin + | ||
1285 | modedb[i].xres + | ||
1286 | modedb[i].right_margin + | ||
1287 | modedb[i].hsync_len) * | ||
1288 | (modedb[i].upper_margin + | ||
1289 | modedb[i].yres + | ||
1290 | modedb[i].lower_margin + | ||
1291 | modedb[i].vsync_len) * ref / 10000)); | ||
1292 | info->var.bits_per_pixel = bpp; | ||
1293 | } | ||
1294 | |||
1295 | info->var.left_margin = modedb[i].left_margin; | ||
1296 | info->var.right_margin = modedb[i].right_margin; | ||
1297 | info->var.xres = modedb[i].xres; | ||
1298 | if (!(modedb[i].yres == 1280 && modedb[i].bpp == 32)) | ||
1299 | info->var.xres_virtual = modedb[i].vxres; | ||
1300 | else | ||
1301 | info->var.xres_virtual = modedb[i].xres; | ||
1302 | info->var.xoffset = 0; | ||
1303 | info->var.hsync_len = modedb[i].hsync_len; | ||
1304 | info->var.upper_margin = modedb[i].upper_margin; | ||
1305 | info->var.yres = modedb[i].yres; | ||
1306 | info->var.yres_virtual = modedb[i].vyres; | ||
1307 | info->var.yoffset = 0; | ||
1308 | info->var.lower_margin = modedb[i].lower_margin; | ||
1309 | info->var.vsync_len = modedb[i].vsync_len; | ||
1310 | info->var.sync = 0; | ||
1311 | info->var.vmode = FB_VMODE_NONINTERLACED; | ||
1312 | |||
1313 | if (cyblafb_check_var(&info->var, info)) { | ||
1314 | // 640x480 - 8@75 should really never fail. One case would | ||
1315 | // be fp == 1 and nativex < 640 ... give up then | ||
1316 | if (i == 1 && bpp == 8 && ref == 75) { | ||
1317 | output("Can't find a valid mode :-(\n"); | ||
1318 | return -EINVAL; | ||
1319 | } | ||
1320 | // Our detected mode is unlikely to fail. If it does, | ||
1321 | // try 640x480 - 8@75 ... | ||
1322 | if (i == 0) { | ||
1323 | mode = "640x480"; | ||
1324 | bpp = 8; | ||
1325 | ref = 75; | ||
1326 | output("Detected mode failed check_var! " | ||
1327 | "Trying 640x480 - 8@75\n"); | ||
1328 | goto tryagain; | ||
1329 | } | ||
1330 | // A specified video mode failed for some reason. | ||
1331 | // Try the startup mode first | ||
1332 | output("Specified mode '%s' failed check! " | ||
1333 | "Falling back to startup mode.\n", mode); | ||
1334 | mode = NULL; | ||
1335 | goto tryagain; | ||
1336 | } | ||
1337 | |||
1338 | return 0; | ||
1339 | } | ||
1340 | |||
1341 | //======================================================== | ||
1342 | // | ||
1343 | // Detect activated memory size. Undefined values require | ||
1344 | // memsize parameter. | ||
1345 | // | ||
1346 | //======================================================== | ||
1347 | |||
1348 | static unsigned int __devinit get_memsize(void) | ||
1349 | { | ||
1350 | unsigned char tmp; | ||
1351 | unsigned int k; | ||
1352 | |||
1353 | if (memsize) | ||
1354 | k = memsize * Kb; | ||
1355 | else { | ||
1356 | tmp = read3X4(CR1F) & 0x0F; | ||
1357 | switch (tmp) { | ||
1358 | case 0x03: | ||
1359 | k = 1 * 1024 * 1024; | ||
1360 | break; | ||
1361 | case 0x07: | ||
1362 | k = 2 * 1024 * 1024; | ||
1363 | break; | ||
1364 | case 0x0F: | ||
1365 | k = 4 * 1024 * 1024; | ||
1366 | break; | ||
1367 | case 0x04: | ||
1368 | k = 8 * 1024 * 1024; | ||
1369 | break; | ||
1370 | default: | ||
1371 | k = 1 * 1024 * 1024; | ||
1372 | output("Unknown memory size code %x in CR1F." | ||
1373 | " We default to 1 Mb for now, please" | ||
1374 | " do provide a memsize parameter!\n", tmp); | ||
1375 | } | ||
1376 | } | ||
1377 | |||
1378 | if (verbosity > 0) | ||
1379 | output("framebuffer size = %d Kb\n", k / Kb); | ||
1380 | return k; | ||
1381 | } | ||
1382 | |||
1383 | //========================================================= | ||
1384 | // | ||
1385 | // Detect if a flat panel monitor connected to the special | ||
1386 | // interface is active. Override is possible by fp and crt | ||
1387 | // parameters. | ||
1388 | // | ||
1389 | //========================================================= | ||
1390 | |||
1391 | static unsigned int __devinit get_displaytype(void) | ||
1392 | { | ||
1393 | if (fp) | ||
1394 | return DISPLAY_FP; | ||
1395 | if (crt) | ||
1396 | return DISPLAY_CRT; | ||
1397 | return (read3CE(GR33) & 0x10) ? DISPLAY_FP : DISPLAY_CRT; | ||
1398 | } | ||
1399 | |||
1400 | //===================================== | ||
1401 | // | ||
1402 | // Get native resolution of flat panel | ||
1403 | // | ||
1404 | //===================================== | ||
1405 | |||
1406 | static int __devinit get_nativex(void) | ||
1407 | { | ||
1408 | int x, y, tmp; | ||
1409 | |||
1410 | if (nativex) | ||
1411 | return nativex; | ||
1412 | |||
1413 | tmp = (read3CE(GR52) >> 4) & 3; | ||
1414 | |||
1415 | switch (tmp) { | ||
1416 | case 0: x = 1280; y = 1024; | ||
1417 | break; | ||
1418 | case 2: x = 1024; y = 768; | ||
1419 | break; | ||
1420 | case 3: x = 800; y = 600; | ||
1421 | break; | ||
1422 | case 4: x = 1400; y = 1050; | ||
1423 | break; | ||
1424 | case 1: | ||
1425 | default: | ||
1426 | x = 640; y = 480; | ||
1427 | break; | ||
1428 | } | ||
1429 | |||
1430 | if (verbosity > 0) | ||
1431 | output("%dx%d flat panel found\n", x, y); | ||
1432 | return x; | ||
1433 | } | ||
1434 | |||
1435 | static int __devinit cybla_pci_probe(struct pci_dev *dev, | ||
1436 | const struct pci_device_id *id) | ||
1437 | { | ||
1438 | struct fb_info *info; | ||
1439 | struct cyblafb_par *par; | ||
1440 | |||
1441 | info = framebuffer_alloc(sizeof(struct cyblafb_par), &dev->dev); | ||
1442 | if (!info) | ||
1443 | goto errout_alloc_info; | ||
1444 | |||
1445 | info->pixmap.addr = kzalloc(CYBLAFB_PIXMAPSIZE, GFP_KERNEL); | ||
1446 | if (!info->pixmap.addr) { | ||
1447 | output("allocation of pixmap buffer failed!\n"); | ||
1448 | goto errout_alloc_pixmap; | ||
1449 | } | ||
1450 | info->pixmap.size = CYBLAFB_PIXMAPSIZE - 4; | ||
1451 | info->pixmap.buf_align = 4; | ||
1452 | info->pixmap.access_align = 32; | ||
1453 | info->pixmap.flags = FB_PIXMAP_SYSTEM; | ||
1454 | info->pixmap.scan_align = 4; | ||
1455 | |||
1456 | par = info->par; | ||
1457 | par->ops = cyblafb_ops; | ||
1458 | |||
1459 | info->fix = cyblafb_fix; | ||
1460 | info->fbops = &par->ops; | ||
1461 | info->fix = cyblafb_fix; | ||
1462 | |||
1463 | if (pci_enable_device(dev)) { | ||
1464 | output("could not enable device!\n"); | ||
1465 | goto errout_enable; | ||
1466 | } | ||
1467 | // might already be requested by vga console or vesafb, | ||
1468 | // so we do care about success | ||
1469 | if (!request_region(0x3c0, 0x20, "cyblafb")) { | ||
1470 | output("region 0x3c0/0x20 already reserved\n"); | ||
1471 | vesafb |= 1; | ||
1472 | |||
1473 | } | ||
1474 | // | ||
1475 | // Graphics Engine Registers | ||
1476 | // | ||
1477 | if (!request_region(GEBase, 0x100, "cyblafb")) { | ||
1478 | output("region %#x/0x100 already reserved\n", GEBase); | ||
1479 | vesafb |= 2; | ||
1480 | } | ||
1481 | |||
1482 | regdump(par); | ||
1483 | |||
1484 | enable_mmio(); | ||
1485 | |||
1486 | // setup MMIO region | ||
1487 | info->fix.mmio_start = pci_resource_start(dev, 1); | ||
1488 | info->fix.mmio_len = 0x20000; | ||
1489 | |||
1490 | if (!request_mem_region(info->fix.mmio_start, | ||
1491 | info->fix.mmio_len, "cyblafb")) { | ||
1492 | output("request_mem_region failed for mmio region!\n"); | ||
1493 | goto errout_mmio_reqmem; | ||
1494 | } | ||
1495 | |||
1496 | io_virt = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); | ||
1497 | |||
1498 | if (!io_virt) { | ||
1499 | output("ioremap failed for mmio region\n"); | ||
1500 | goto errout_mmio_remap; | ||
1501 | } | ||
1502 | // setup framebuffer memory ... might already be requested | ||
1503 | // by vesafb. Not to fail in case of an unsuccessful request | ||
1504 | // is useful if both are loaded. | ||
1505 | info->fix.smem_start = pci_resource_start(dev, 0); | ||
1506 | info->fix.smem_len = get_memsize(); | ||
1507 | |||
1508 | if (!request_mem_region(info->fix.smem_start, | ||
1509 | info->fix.smem_len, "cyblafb")) { | ||
1510 | output("region %#lx/%#x already reserved\n", | ||
1511 | info->fix.smem_start, info->fix.smem_len); | ||
1512 | vesafb |= 4; | ||
1513 | } | ||
1514 | |||
1515 | info->screen_base = ioremap_nocache(info->fix.smem_start, | ||
1516 | info->fix.smem_len); | ||
1517 | |||
1518 | if (!info->screen_base) { | ||
1519 | output("ioremap failed for smem region\n"); | ||
1520 | goto errout_smem_remap; | ||
1521 | } | ||
1522 | |||
1523 | displaytype = get_displaytype(); | ||
1524 | |||
1525 | if (displaytype == DISPLAY_FP) | ||
1526 | nativex = get_nativex(); | ||
1527 | |||
1528 | info->flags = FBINFO_DEFAULT | ||
1529 | | FBINFO_HWACCEL_COPYAREA | ||
1530 | | FBINFO_HWACCEL_FILLRECT | ||
1531 | | FBINFO_HWACCEL_IMAGEBLIT | ||
1532 | | FBINFO_READS_FAST | ||
1533 | // | FBINFO_PARTIAL_PAN_OK | ||
1534 | | FBINFO_MISC_ALWAYS_SETPAR; | ||
1535 | |||
1536 | info->pseudo_palette = par->pseudo_pal; | ||
1537 | |||
1538 | if (getstartupmode(info)) | ||
1539 | goto errout_findmode; | ||
1540 | |||
1541 | fb_alloc_cmap(&info->cmap, 256, 0); | ||
1542 | |||
1543 | if (register_framebuffer(info)) { | ||
1544 | output("Could not register CyBla framebuffer\n"); | ||
1545 | goto errout_register; | ||
1546 | } | ||
1547 | |||
1548 | pci_set_drvdata(dev, info); | ||
1549 | |||
1550 | // | ||
1551 | // normal exit and error paths | ||
1552 | // | ||
1553 | |||
1554 | return 0; | ||
1555 | |||
1556 | errout_register: | ||
1557 | errout_findmode: | ||
1558 | iounmap(info->screen_base); | ||
1559 | errout_smem_remap: | ||
1560 | if (!(vesafb & 4)) | ||
1561 | release_mem_region(info->fix.smem_start, info->fix.smem_len); | ||
1562 | iounmap(io_virt); | ||
1563 | errout_mmio_remap: | ||
1564 | release_mem_region(info->fix.mmio_start, info->fix.mmio_len); | ||
1565 | errout_mmio_reqmem: | ||
1566 | if (!(vesafb & 1)) | ||
1567 | release_region(0x3c0, 32); | ||
1568 | errout_enable: | ||
1569 | kfree(info->pixmap.addr); | ||
1570 | errout_alloc_pixmap: | ||
1571 | framebuffer_release(info); | ||
1572 | errout_alloc_info: | ||
1573 | output("CyblaFB version %s aborting init.\n", VERSION); | ||
1574 | return -ENODEV; | ||
1575 | } | ||
1576 | |||
1577 | static void __devexit cybla_pci_remove(struct pci_dev *dev) | ||
1578 | { | ||
1579 | struct fb_info *info = pci_get_drvdata(dev); | ||
1580 | |||
1581 | unregister_framebuffer(info); | ||
1582 | iounmap(io_virt); | ||
1583 | iounmap(info->screen_base); | ||
1584 | if (!(vesafb & 4)) | ||
1585 | release_mem_region(info->fix.smem_start, info->fix.smem_len); | ||
1586 | release_mem_region(info->fix.mmio_start, info->fix.mmio_len); | ||
1587 | fb_dealloc_cmap(&info->cmap); | ||
1588 | if (!(vesafb & 2)) | ||
1589 | release_region(GEBase, 0x100); | ||
1590 | if (!(vesafb & 1)) | ||
1591 | release_region(0x3c0, 32); | ||
1592 | kfree(info->pixmap.addr); | ||
1593 | framebuffer_release(info); | ||
1594 | output("CyblaFB version %s normal exit.\n", VERSION); | ||
1595 | } | ||
1596 | |||
1597 | // | ||
1598 | // List of boards that we are trying to support | ||
1599 | // | ||
1600 | static struct pci_device_id cybla_devices[] = { | ||
1601 | {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
1602 | {0,} | ||
1603 | }; | ||
1604 | |||
1605 | MODULE_DEVICE_TABLE(pci, cybla_devices); | ||
1606 | |||
1607 | static struct pci_driver cyblafb_pci_driver = { | ||
1608 | .name = "cyblafb", | ||
1609 | .id_table = cybla_devices, | ||
1610 | .probe = cybla_pci_probe, | ||
1611 | .remove = __devexit_p(cybla_pci_remove) | ||
1612 | }; | ||
1613 | |||
1614 | //============================================================= | ||
1615 | // | ||
1616 | // kernel command line example: | ||
1617 | // | ||
1618 | // video=cyblafb:1280x1024, bpp=16, ref=50 ... | ||
1619 | // | ||
1620 | // modprobe command line example: | ||
1621 | // | ||
1622 | // modprobe cyblafb mode=1280x1024 bpp=16 ref=50 ... | ||
1623 | // | ||
1624 | //============================================================= | ||
1625 | |||
1626 | static int __devinit cyblafb_init(void) | ||
1627 | { | ||
1628 | #ifndef MODULE | ||
1629 | char *options = NULL; | ||
1630 | char *opt; | ||
1631 | |||
1632 | if (fb_get_options("cyblafb", &options)) | ||
1633 | return -ENODEV; | ||
1634 | |||
1635 | if (options && *options) | ||
1636 | while ((opt = strsep(&options, ",")) != NULL) { | ||
1637 | if (!*opt) | ||
1638 | continue; | ||
1639 | else if (!strncmp(opt, "bpp=", 4)) | ||
1640 | bpp = simple_strtoul(opt + 4, NULL, 0); | ||
1641 | else if (!strncmp(opt, "ref=", 4)) | ||
1642 | ref = simple_strtoul(opt + 4, NULL, 0); | ||
1643 | else if (!strncmp(opt, "fp", 2)) | ||
1644 | displaytype = DISPLAY_FP; | ||
1645 | else if (!strncmp(opt, "crt", 3)) | ||
1646 | displaytype = DISPLAY_CRT; | ||
1647 | else if (!strncmp(opt, "nativex=", 8)) | ||
1648 | nativex = simple_strtoul(opt + 8, NULL, 0); | ||
1649 | else if (!strncmp(opt, "center", 6)) | ||
1650 | center = 1; | ||
1651 | else if (!strncmp(opt, "stretch", 7)) | ||
1652 | stretch = 1; | ||
1653 | else if (!strncmp(opt, "pciwb=", 6)) | ||
1654 | pciwb = simple_strtoul(opt + 6, NULL, 0); | ||
1655 | else if (!strncmp(opt, "pcirb=", 6)) | ||
1656 | pcirb = simple_strtoul(opt + 6, NULL, 0); | ||
1657 | else if (!strncmp(opt, "pciwr=", 6)) | ||
1658 | pciwr = simple_strtoul(opt + 6, NULL, 0); | ||
1659 | else if (!strncmp(opt, "pcirr=", 6)) | ||
1660 | pcirr = simple_strtoul(opt + 6, NULL, 0); | ||
1661 | else if (!strncmp(opt, "memsize=", 8)) | ||
1662 | memsize = simple_strtoul(opt + 8, NULL, 0); | ||
1663 | else if (!strncmp(opt, "verbosity=", 10)) | ||
1664 | verbosity = simple_strtoul(opt + 10, NULL, 0); | ||
1665 | else | ||
1666 | mode = opt; | ||
1667 | } | ||
1668 | #endif | ||
1669 | output("CyblaFB version %s initializing\n", VERSION); | ||
1670 | return pci_register_driver(&cyblafb_pci_driver); | ||
1671 | } | ||
1672 | |||
1673 | static void __exit cyblafb_exit(void) | ||
1674 | { | ||
1675 | pci_unregister_driver(&cyblafb_pci_driver); | ||
1676 | } | ||
1677 | |||
1678 | module_init(cyblafb_init); | ||
1679 | module_exit(cyblafb_exit); | ||
1680 | |||
1681 | MODULE_AUTHOR("Knut Petersen <knut_petersen@t-online.de>"); | ||
1682 | MODULE_DESCRIPTION("Framebuffer driver for Cyberblade/i1 graphics core"); | ||
1683 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index daf9b81878a..0c5b9a9fd56 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c | |||
@@ -129,6 +129,8 @@ static int set_system(const struct dmi_system_id *id) | |||
129 | screen_info.lfb_width = info->width; | 129 | screen_info.lfb_width = info->width; |
130 | if (screen_info.lfb_height == 0) | 130 | if (screen_info.lfb_height == 0) |
131 | screen_info.lfb_height = info->height; | 131 | screen_info.lfb_height = info->height; |
132 | if (screen_info.orig_video_isVGA == 0) | ||
133 | screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; | ||
132 | 134 | ||
133 | return 0; | 135 | return 0; |
134 | } | 136 | } |
@@ -374,9 +376,10 @@ static int __init efifb_init(void) | |||
374 | int ret; | 376 | int ret; |
375 | char *option = NULL; | 377 | char *option = NULL; |
376 | 378 | ||
379 | dmi_check_system(dmi_system_table); | ||
380 | |||
377 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) | 381 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) |
378 | return -ENODEV; | 382 | return -ENODEV; |
379 | dmi_check_system(dmi_system_table); | ||
380 | 383 | ||
381 | if (fb_get_options("efifb", &option)) | 384 | if (fb_get_options("efifb", &option)) |
382 | return -ENODEV; | 385 | return -ENODEV; |
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 082026546ae..0a7a6679ee6 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
@@ -85,8 +85,9 @@ EXPORT_SYMBOL_GPL(fb_deferred_io_fsync); | |||
85 | 85 | ||
86 | /* vm_ops->page_mkwrite handler */ | 86 | /* vm_ops->page_mkwrite handler */ |
87 | static int fb_deferred_io_mkwrite(struct vm_area_struct *vma, | 87 | static int fb_deferred_io_mkwrite(struct vm_area_struct *vma, |
88 | struct page *page) | 88 | struct vm_fault *vmf) |
89 | { | 89 | { |
90 | struct page *page = vmf->page; | ||
90 | struct fb_info *info = vma->vm_private_data; | 91 | struct fb_info *info = vma->vm_private_data; |
91 | struct fb_deferred_io *fbdefio = info->fbdefio; | 92 | struct fb_deferred_io *fbdefio = info->fbdefio; |
92 | struct page *cur; | 93 | struct page *cur; |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index cfd9dce1ce0..2ac32e6b595 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -46,6 +46,17 @@ | |||
46 | struct fb_info *registered_fb[FB_MAX] __read_mostly; | 46 | struct fb_info *registered_fb[FB_MAX] __read_mostly; |
47 | int num_registered_fb __read_mostly; | 47 | int num_registered_fb __read_mostly; |
48 | 48 | ||
49 | int lock_fb_info(struct fb_info *info) | ||
50 | { | ||
51 | mutex_lock(&info->lock); | ||
52 | if (!info->fbops) { | ||
53 | mutex_unlock(&info->lock); | ||
54 | return 0; | ||
55 | } | ||
56 | return 1; | ||
57 | } | ||
58 | EXPORT_SYMBOL(lock_fb_info); | ||
59 | |||
49 | /* | 60 | /* |
50 | * Helpers | 61 | * Helpers |
51 | */ | 62 | */ |
@@ -1086,13 +1097,8 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
1086 | return -EINVAL; | 1097 | return -EINVAL; |
1087 | con2fb.framebuffer = -1; | 1098 | con2fb.framebuffer = -1; |
1088 | event.data = &con2fb; | 1099 | event.data = &con2fb; |
1089 | |||
1090 | if (!lock_fb_info(info)) | ||
1091 | return -ENODEV; | ||
1092 | event.info = info; | 1100 | event.info = info; |
1093 | fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); | 1101 | fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); |
1094 | unlock_fb_info(info); | ||
1095 | |||
1096 | ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; | 1102 | ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; |
1097 | break; | 1103 | break; |
1098 | case FBIOPUT_CON2FBMAP: | 1104 | case FBIOPUT_CON2FBMAP: |
@@ -1109,12 +1115,8 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
1109 | break; | 1115 | break; |
1110 | } | 1116 | } |
1111 | event.data = &con2fb; | 1117 | event.data = &con2fb; |
1112 | if (!lock_fb_info(info)) | ||
1113 | return -ENODEV; | ||
1114 | event.info = info; | 1118 | event.info = info; |
1115 | ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, | 1119 | ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); |
1116 | &event); | ||
1117 | unlock_fb_info(info); | ||
1118 | break; | 1120 | break; |
1119 | case FBIOBLANK: | 1121 | case FBIOBLANK: |
1120 | if (!lock_fb_info(info)) | 1122 | if (!lock_fb_info(info)) |
diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h index f132aab8c5d..c03f7f55c76 100644 --- a/drivers/video/nvidia/nv_type.h +++ b/drivers/video/nvidia/nv_type.h | |||
@@ -5,7 +5,6 @@ | |||
5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
6 | #include <linux/i2c.h> | 6 | #include <linux/i2c.h> |
7 | #include <linux/i2c-algo-bit.h> | 7 | #include <linux/i2c-algo-bit.h> |
8 | #include <linux/mutex.h> | ||
9 | #include <video/vga.h> | 8 | #include <video/vga.h> |
10 | 9 | ||
11 | #define NV_ARCH_04 0x04 | 10 | #define NV_ARCH_04 0x04 |
@@ -99,7 +98,6 @@ struct nvidia_par { | |||
99 | RIVA_HW_STATE initial_state; | 98 | RIVA_HW_STATE initial_state; |
100 | RIVA_HW_STATE *CurrentState; | 99 | RIVA_HW_STATE *CurrentState; |
101 | struct vgastate vgastate; | 100 | struct vgastate vgastate; |
102 | struct mutex open_lock; | ||
103 | u32 pseudo_palette[16]; | 101 | u32 pseudo_palette[16]; |
104 | struct pci_dev *pci_dev; | 102 | struct pci_dev *pci_dev; |
105 | u32 Architecture; | 103 | u32 Architecture; |
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 9dbb5a5a267..efe10ff86d6 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
@@ -1004,15 +1004,12 @@ static int nvidiafb_open(struct fb_info *info, int user) | |||
1004 | { | 1004 | { |
1005 | struct nvidia_par *par = info->par; | 1005 | struct nvidia_par *par = info->par; |
1006 | 1006 | ||
1007 | mutex_lock(&par->open_lock); | ||
1008 | |||
1009 | if (!par->open_count) { | 1007 | if (!par->open_count) { |
1010 | save_vga_x86(par); | 1008 | save_vga_x86(par); |
1011 | nvidia_save_vga(par, &par->initial_state); | 1009 | nvidia_save_vga(par, &par->initial_state); |
1012 | } | 1010 | } |
1013 | 1011 | ||
1014 | par->open_count++; | 1012 | par->open_count++; |
1015 | mutex_unlock(&par->open_lock); | ||
1016 | return 0; | 1013 | return 0; |
1017 | } | 1014 | } |
1018 | 1015 | ||
@@ -1021,8 +1018,6 @@ static int nvidiafb_release(struct fb_info *info, int user) | |||
1021 | struct nvidia_par *par = info->par; | 1018 | struct nvidia_par *par = info->par; |
1022 | int err = 0; | 1019 | int err = 0; |
1023 | 1020 | ||
1024 | mutex_lock(&par->open_lock); | ||
1025 | |||
1026 | if (!par->open_count) { | 1021 | if (!par->open_count) { |
1027 | err = -EINVAL; | 1022 | err = -EINVAL; |
1028 | goto done; | 1023 | goto done; |
@@ -1035,7 +1030,6 @@ static int nvidiafb_release(struct fb_info *info, int user) | |||
1035 | 1030 | ||
1036 | par->open_count--; | 1031 | par->open_count--; |
1037 | done: | 1032 | done: |
1038 | mutex_unlock(&par->open_lock); | ||
1039 | return err; | 1033 | return err; |
1040 | } | 1034 | } |
1041 | 1035 | ||
@@ -1300,7 +1294,6 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, | |||
1300 | 1294 | ||
1301 | par = info->par; | 1295 | par = info->par; |
1302 | par->pci_dev = pd; | 1296 | par->pci_dev = pd; |
1303 | mutex_init(&par->open_lock); | ||
1304 | info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL); | 1297 | info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL); |
1305 | 1298 | ||
1306 | if (info->pixmap.addr == NULL) | 1299 | if (info->pixmap.addr == NULL) |
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c index f24df0b54e1..8aa6e47202b 100644 --- a/drivers/video/omap/hwa742.c +++ b/drivers/video/omap/hwa742.c | |||
@@ -742,7 +742,7 @@ static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div) | |||
742 | if (calc_reg_timing(sysclk, div) == 0) | 742 | if (calc_reg_timing(sysclk, div) == 0) |
743 | break; | 743 | break; |
744 | } | 744 | } |
745 | if (div > max_clk_div) | 745 | if (div >= max_clk_div) |
746 | goto err; | 746 | goto err; |
747 | 747 | ||
748 | *extif_mem_div = div; | 748 | *extif_mem_div = div; |
@@ -752,7 +752,7 @@ static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div) | |||
752 | break; | 752 | break; |
753 | } | 753 | } |
754 | 754 | ||
755 | if (div > max_clk_div) | 755 | if (div >= max_clk_div) |
756 | goto err; | 756 | goto err; |
757 | 757 | ||
758 | return 0; | 758 | return 0; |
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index 1a49519dafa..060d72fe57c 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c | |||
@@ -338,7 +338,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi) | |||
338 | 338 | ||
339 | omapfb_rqueue_lock(fbdev); | 339 | omapfb_rqueue_lock(fbdev); |
340 | switch (blank) { | 340 | switch (blank) { |
341 | case VESA_NO_BLANKING: | 341 | case FB_BLANK_UNBLANK: |
342 | if (fbdev->state == OMAPFB_SUSPENDED) { | 342 | if (fbdev->state == OMAPFB_SUSPENDED) { |
343 | if (fbdev->ctrl->resume) | 343 | if (fbdev->ctrl->resume) |
344 | fbdev->ctrl->resume(); | 344 | fbdev->ctrl->resume(); |
@@ -349,7 +349,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi) | |||
349 | do_update = 1; | 349 | do_update = 1; |
350 | } | 350 | } |
351 | break; | 351 | break; |
352 | case VESA_POWERDOWN: | 352 | case FB_BLANK_POWERDOWN: |
353 | if (fbdev->state == OMAPFB_ACTIVE) { | 353 | if (fbdev->state == OMAPFB_ACTIVE) { |
354 | fbdev->panel->disable(fbdev->panel); | 354 | fbdev->panel->disable(fbdev->panel); |
355 | if (fbdev->ctrl->suspend) | 355 | if (fbdev->ctrl->suspend) |
@@ -1818,7 +1818,7 @@ static int omapfb_suspend(struct platform_device *pdev, pm_message_t mesg) | |||
1818 | { | 1818 | { |
1819 | struct omapfb_device *fbdev = platform_get_drvdata(pdev); | 1819 | struct omapfb_device *fbdev = platform_get_drvdata(pdev); |
1820 | 1820 | ||
1821 | omapfb_blank(VESA_POWERDOWN, fbdev->fb_info[0]); | 1821 | omapfb_blank(FB_BLANK_POWERDOWN, fbdev->fb_info[0]); |
1822 | 1822 | ||
1823 | return 0; | 1823 | return 0; |
1824 | } | 1824 | } |
@@ -1828,7 +1828,7 @@ static int omapfb_resume(struct platform_device *pdev) | |||
1828 | { | 1828 | { |
1829 | struct omapfb_device *fbdev = platform_get_drvdata(pdev); | 1829 | struct omapfb_device *fbdev = platform_get_drvdata(pdev); |
1830 | 1830 | ||
1831 | omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info[0]); | 1831 | omapfb_blank(FB_BLANK_UNBLANK, fbdev->fb_info[0]); |
1832 | return 0; | 1832 | return 0; |
1833 | } | 1833 | } |
1834 | 1834 | ||
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index a7b01d2724b..0726aecf3b7 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c | |||
@@ -50,9 +50,22 @@ | |||
50 | #define dbg(fmt, args...) do { } while (0) | 50 | #define dbg(fmt, args...) do { } while (0) |
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | static const int __devinitconst s1d13xxxfb_revisions[] = { | 53 | /* |
54 | S1D13506_CHIP_REV, /* Rev.4 on HP Jornada 7xx S1D13506 */ | 54 | * List of card production ids |
55 | S1D13806_CHIP_REV, /* Rev.7 on .. */ | 55 | */ |
56 | static const int s1d13xxxfb_prod_ids[] = { | ||
57 | S1D13505_PROD_ID, | ||
58 | S1D13506_PROD_ID, | ||
59 | S1D13806_PROD_ID, | ||
60 | }; | ||
61 | |||
62 | /* | ||
63 | * List of card strings | ||
64 | */ | ||
65 | static const char *s1d13xxxfb_prod_names[] = { | ||
66 | "S1D13505", | ||
67 | "S1D13506", | ||
68 | "S1D13806", | ||
56 | }; | 69 | }; |
57 | 70 | ||
58 | /* | 71 | /* |
@@ -377,7 +390,6 @@ s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |||
377 | return 0; | 390 | return 0; |
378 | } | 391 | } |
379 | 392 | ||
380 | |||
381 | /* framebuffer information structures */ | 393 | /* framebuffer information structures */ |
382 | 394 | ||
383 | static struct fb_ops s1d13xxxfb_fbops = { | 395 | static struct fb_ops s1d13xxxfb_fbops = { |
@@ -544,7 +556,7 @@ s1d13xxxfb_probe(struct platform_device *pdev) | |||
544 | struct s1d13xxxfb_pdata *pdata = NULL; | 556 | struct s1d13xxxfb_pdata *pdata = NULL; |
545 | int ret = 0; | 557 | int ret = 0; |
546 | int i; | 558 | int i; |
547 | u8 revision; | 559 | u8 revision, prod_id; |
548 | 560 | ||
549 | dbg("probe called: device is %p\n", pdev); | 561 | dbg("probe called: device is %p\n", pdev); |
550 | 562 | ||
@@ -613,19 +625,31 @@ s1d13xxxfb_probe(struct platform_device *pdev) | |||
613 | goto bail; | 625 | goto bail; |
614 | } | 626 | } |
615 | 627 | ||
616 | revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2; | 628 | /* production id is top 6 bits */ |
617 | 629 | prod_id = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2; | |
630 | /* revision id is lower 2 bits */ | ||
631 | revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) & 0x3; | ||
618 | ret = -ENODEV; | 632 | ret = -ENODEV; |
619 | 633 | ||
620 | for (i = 0; i < ARRAY_SIZE(s1d13xxxfb_revisions); i++) { | 634 | for (i = 0; i < ARRAY_SIZE(s1d13xxxfb_prod_ids); i++) { |
621 | if (revision == s1d13xxxfb_revisions[i]) | 635 | if (prod_id == s1d13xxxfb_prod_ids[i]) { |
636 | /* looks like we got it in our list */ | ||
637 | default_par->prod_id = prod_id; | ||
638 | default_par->revision = revision; | ||
622 | ret = 0; | 639 | ret = 0; |
640 | break; | ||
641 | } | ||
623 | } | 642 | } |
624 | 643 | ||
625 | if (!ret) | 644 | if (!ret) { |
645 | printk(KERN_INFO PFX "chip production id %i = %s\n", | ||
646 | prod_id, s1d13xxxfb_prod_names[i]); | ||
626 | printk(KERN_INFO PFX "chip revision %i\n", revision); | 647 | printk(KERN_INFO PFX "chip revision %i\n", revision); |
627 | else { | 648 | } else { |
628 | printk(KERN_INFO PFX "unknown chip revision %i\n", revision); | 649 | printk(KERN_INFO PFX |
650 | "unknown chip production id %i, revision %i\n", | ||
651 | prod_id, revision); | ||
652 | printk(KERN_INFO PFX "please contant maintainer\n"); | ||
629 | goto bail; | 653 | goto bail; |
630 | } | 654 | } |
631 | 655 | ||
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c new file mode 100644 index 00000000000..5e9c6302433 --- /dev/null +++ b/drivers/video/s3c-fb.c | |||
@@ -0,0 +1,1036 @@ | |||
1 | /* linux/drivers/video/s3c-fb.c | ||
2 | * | ||
3 | * Copyright 2008 Openmoko Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * http://armlinux.simtec.co.uk/ | ||
7 | * | ||
8 | * Samsung SoC Framebuffer driver | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/gfp.h> | ||
21 | #include <linux/clk.h> | ||
22 | #include <linux/fb.h> | ||
23 | #include <linux/io.h> | ||
24 | |||
25 | #include <mach/map.h> | ||
26 | #include <mach/regs-fb.h> | ||
27 | #include <plat/fb.h> | ||
28 | |||
29 | /* This driver will export a number of framebuffer interfaces depending | ||
30 | * on the configuration passed in via the platform data. Each fb instance | ||
31 | * maps to a hardware window. Currently there is no support for runtime | ||
32 | * setting of the alpha-blending functions that each window has, so only | ||
33 | * window 0 is actually useful. | ||
34 | * | ||
35 | * Window 0 is treated specially, it is used for the basis of the LCD | ||
36 | * output timings and as the control for the output power-down state. | ||
37 | */ | ||
38 | |||
39 | /* note, some of the functions that get called are derived from including | ||
40 | * <mach/regs-fb.h> as they are specific to the architecture that the code | ||
41 | * is being built for. | ||
42 | */ | ||
43 | |||
44 | #ifdef CONFIG_FB_S3C_DEBUG_REGWRITE | ||
45 | #undef writel | ||
46 | #define writel(v, r) do { \ | ||
47 | printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \ | ||
48 | __raw_writel(v, r); } while(0) | ||
49 | #endif /* FB_S3C_DEBUG_REGWRITE */ | ||
50 | |||
51 | struct s3c_fb; | ||
52 | |||
53 | /** | ||
54 | * struct s3c_fb_win - per window private data for each framebuffer. | ||
55 | * @windata: The platform data supplied for the window configuration. | ||
56 | * @parent: The hardware that this window is part of. | ||
57 | * @fbinfo: Pointer pack to the framebuffer info for this window. | ||
58 | * @palette_buffer: Buffer/cache to hold palette entries. | ||
59 | * @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/ | ||
60 | * @index: The window number of this window. | ||
61 | * @palette: The bitfields for changing r/g/b into a hardware palette entry. | ||
62 | */ | ||
63 | struct s3c_fb_win { | ||
64 | struct s3c_fb_pd_win *windata; | ||
65 | struct s3c_fb *parent; | ||
66 | struct fb_info *fbinfo; | ||
67 | struct s3c_fb_palette palette; | ||
68 | |||
69 | u32 *palette_buffer; | ||
70 | u32 pseudo_palette[16]; | ||
71 | unsigned int index; | ||
72 | }; | ||
73 | |||
74 | /** | ||
75 | * struct s3c_fb - overall hardware state of the hardware | ||
76 | * @dev: The device that we bound to, for printing, etc. | ||
77 | * @regs_res: The resource we claimed for the IO registers. | ||
78 | * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. | ||
79 | * @regs: The mapped hardware registers. | ||
80 | * @enabled: A bitmask of enabled hardware windows. | ||
81 | * @pdata: The platform configuration data passed with the device. | ||
82 | * @windows: The hardware windows that have been claimed. | ||
83 | */ | ||
84 | struct s3c_fb { | ||
85 | struct device *dev; | ||
86 | struct resource *regs_res; | ||
87 | struct clk *bus_clk; | ||
88 | void __iomem *regs; | ||
89 | |||
90 | unsigned char enabled; | ||
91 | |||
92 | struct s3c_fb_platdata *pdata; | ||
93 | struct s3c_fb_win *windows[S3C_FB_MAX_WIN]; | ||
94 | }; | ||
95 | |||
96 | /** | ||
97 | * s3c_fb_win_has_palette() - determine if a mode has a palette | ||
98 | * @win: The window number being queried. | ||
99 | * @bpp: The number of bits per pixel to test. | ||
100 | * | ||
101 | * Work out if the given window supports palletised data at the specified bpp. | ||
102 | */ | ||
103 | static int s3c_fb_win_has_palette(unsigned int win, unsigned int bpp) | ||
104 | { | ||
105 | return s3c_fb_win_pal_size(win) <= (1 << bpp); | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * s3c_fb_check_var() - framebuffer layer request to verify a given mode. | ||
110 | * @var: The screen information to verify. | ||
111 | * @info: The framebuffer device. | ||
112 | * | ||
113 | * Framebuffer layer call to verify the given information and allow us to | ||
114 | * update various information depending on the hardware capabilities. | ||
115 | */ | ||
116 | static int s3c_fb_check_var(struct fb_var_screeninfo *var, | ||
117 | struct fb_info *info) | ||
118 | { | ||
119 | struct s3c_fb_win *win = info->par; | ||
120 | struct s3c_fb_pd_win *windata = win->windata; | ||
121 | struct s3c_fb *sfb = win->parent; | ||
122 | |||
123 | dev_dbg(sfb->dev, "checking parameters\n"); | ||
124 | |||
125 | var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres); | ||
126 | var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres); | ||
127 | |||
128 | if (!s3c_fb_validate_win_bpp(win->index, var->bits_per_pixel)) { | ||
129 | dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n", | ||
130 | win->index, var->bits_per_pixel); | ||
131 | return -EINVAL; | ||
132 | } | ||
133 | |||
134 | /* always ensure these are zero, for drop through cases below */ | ||
135 | var->transp.offset = 0; | ||
136 | var->transp.length = 0; | ||
137 | |||
138 | switch (var->bits_per_pixel) { | ||
139 | case 1: | ||
140 | case 2: | ||
141 | case 4: | ||
142 | case 8: | ||
143 | if (!s3c_fb_win_has_palette(win->index, var->bits_per_pixel)) { | ||
144 | /* non palletised, A:1,R:2,G:3,B:2 mode */ | ||
145 | var->red.offset = 4; | ||
146 | var->green.offset = 2; | ||
147 | var->blue.offset = 0; | ||
148 | var->red.length = 5; | ||
149 | var->green.length = 3; | ||
150 | var->blue.length = 2; | ||
151 | var->transp.offset = 7; | ||
152 | var->transp.length = 1; | ||
153 | } else { | ||
154 | var->red.offset = 0; | ||
155 | var->red.length = var->bits_per_pixel; | ||
156 | var->green = var->red; | ||
157 | var->blue = var->red; | ||
158 | } | ||
159 | break; | ||
160 | |||
161 | case 19: | ||
162 | /* 666 with one bit alpha/transparency */ | ||
163 | var->transp.offset = 18; | ||
164 | var->transp.length = 1; | ||
165 | case 18: | ||
166 | var->bits_per_pixel = 32; | ||
167 | |||
168 | /* 666 format */ | ||
169 | var->red.offset = 12; | ||
170 | var->green.offset = 6; | ||
171 | var->blue.offset = 0; | ||
172 | var->red.length = 6; | ||
173 | var->green.length = 6; | ||
174 | var->blue.length = 6; | ||
175 | break; | ||
176 | |||
177 | case 16: | ||
178 | /* 16 bpp, 565 format */ | ||
179 | var->red.offset = 11; | ||
180 | var->green.offset = 5; | ||
181 | var->blue.offset = 0; | ||
182 | var->red.length = 5; | ||
183 | var->green.length = 6; | ||
184 | var->blue.length = 5; | ||
185 | break; | ||
186 | |||
187 | case 28: | ||
188 | case 25: | ||
189 | var->transp.length = var->bits_per_pixel - 24; | ||
190 | var->transp.offset = 24; | ||
191 | /* drop through */ | ||
192 | case 24: | ||
193 | /* our 24bpp is unpacked, so 32bpp */ | ||
194 | var->bits_per_pixel = 32; | ||
195 | case 32: | ||
196 | var->red.offset = 16; | ||
197 | var->red.length = 8; | ||
198 | var->green.offset = 8; | ||
199 | var->green.length = 8; | ||
200 | var->blue.offset = 0; | ||
201 | var->blue.length = 8; | ||
202 | break; | ||
203 | |||
204 | default: | ||
205 | dev_err(sfb->dev, "invalid bpp\n"); | ||
206 | } | ||
207 | |||
208 | dev_dbg(sfb->dev, "%s: verified parameters\n", __func__); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | /** | ||
213 | * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. | ||
214 | * @sfb: The hardware state. | ||
215 | * @pixclock: The pixel clock wanted, in picoseconds. | ||
216 | * | ||
217 | * Given the specified pixel clock, work out the necessary divider to get | ||
218 | * close to the output frequency. | ||
219 | */ | ||
220 | static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) | ||
221 | { | ||
222 | unsigned long clk = clk_get_rate(sfb->bus_clk); | ||
223 | unsigned long long tmp; | ||
224 | unsigned int result; | ||
225 | |||
226 | tmp = (unsigned long long)clk; | ||
227 | tmp *= pixclk; | ||
228 | |||
229 | do_div(tmp, 1000000000UL); | ||
230 | result = (unsigned int)tmp / 1000; | ||
231 | |||
232 | dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", | ||
233 | pixclk, clk, result, clk / result); | ||
234 | |||
235 | return result; | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * s3c_fb_align_word() - align pixel count to word boundary | ||
240 | * @bpp: The number of bits per pixel | ||
241 | * @pix: The value to be aligned. | ||
242 | * | ||
243 | * Align the given pixel count so that it will start on an 32bit word | ||
244 | * boundary. | ||
245 | */ | ||
246 | static int s3c_fb_align_word(unsigned int bpp, unsigned int pix) | ||
247 | { | ||
248 | int pix_per_word; | ||
249 | |||
250 | if (bpp > 16) | ||
251 | return pix; | ||
252 | |||
253 | pix_per_word = (8 * 32) / bpp; | ||
254 | return ALIGN(pix, pix_per_word); | ||
255 | } | ||
256 | |||
257 | /** | ||
258 | * s3c_fb_set_par() - framebuffer request to set new framebuffer state. | ||
259 | * @info: The framebuffer to change. | ||
260 | * | ||
261 | * Framebuffer layer request to set a new mode for the specified framebuffer | ||
262 | */ | ||
263 | static int s3c_fb_set_par(struct fb_info *info) | ||
264 | { | ||
265 | struct fb_var_screeninfo *var = &info->var; | ||
266 | struct s3c_fb_win *win = info->par; | ||
267 | struct s3c_fb *sfb = win->parent; | ||
268 | void __iomem *regs = sfb->regs; | ||
269 | int win_no = win->index; | ||
270 | u32 data; | ||
271 | u32 pagewidth; | ||
272 | int clkdiv; | ||
273 | |||
274 | dev_dbg(sfb->dev, "setting framebuffer parameters\n"); | ||
275 | |||
276 | switch (var->bits_per_pixel) { | ||
277 | case 32: | ||
278 | case 24: | ||
279 | case 16: | ||
280 | case 12: | ||
281 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
282 | break; | ||
283 | case 8: | ||
284 | if (s3c_fb_win_has_palette(win_no, 8)) | ||
285 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
286 | else | ||
287 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
288 | break; | ||
289 | case 1: | ||
290 | info->fix.visual = FB_VISUAL_MONO01; | ||
291 | break; | ||
292 | default: | ||
293 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
294 | break; | ||
295 | } | ||
296 | |||
297 | info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8; | ||
298 | |||
299 | /* disable the window whilst we update it */ | ||
300 | writel(0, regs + WINCON(win_no)); | ||
301 | |||
302 | /* use window 0 as the basis for the lcd output timings */ | ||
303 | |||
304 | if (win_no == 0) { | ||
305 | clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); | ||
306 | |||
307 | data = sfb->pdata->vidcon0; | ||
308 | data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); | ||
309 | |||
310 | if (clkdiv > 1) | ||
311 | data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR; | ||
312 | else | ||
313 | data &= ~VIDCON0_CLKDIR; /* 1:1 clock */ | ||
314 | |||
315 | /* write the timing data to the panel */ | ||
316 | |||
317 | data |= VIDCON0_ENVID | VIDCON0_ENVID_F; | ||
318 | writel(data, regs + VIDCON0); | ||
319 | |||
320 | data = VIDTCON0_VBPD(var->upper_margin - 1) | | ||
321 | VIDTCON0_VFPD(var->lower_margin - 1) | | ||
322 | VIDTCON0_VSPW(var->vsync_len - 1); | ||
323 | |||
324 | writel(data, regs + VIDTCON0); | ||
325 | |||
326 | data = VIDTCON1_HBPD(var->left_margin - 1) | | ||
327 | VIDTCON1_HFPD(var->right_margin - 1) | | ||
328 | VIDTCON1_HSPW(var->hsync_len - 1); | ||
329 | |||
330 | writel(data, regs + VIDTCON1); | ||
331 | |||
332 | data = VIDTCON2_LINEVAL(var->yres - 1) | | ||
333 | VIDTCON2_HOZVAL(var->xres - 1); | ||
334 | writel(data, regs + VIDTCON2); | ||
335 | } | ||
336 | |||
337 | /* write the buffer address */ | ||
338 | |||
339 | writel(info->fix.smem_start, regs + VIDW_BUF_START(win_no)); | ||
340 | |||
341 | data = info->fix.smem_start + info->fix.line_length * var->yres; | ||
342 | writel(data, regs + VIDW_BUF_END(win_no)); | ||
343 | |||
344 | pagewidth = (var->xres * var->bits_per_pixel) >> 3; | ||
345 | data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) | | ||
346 | VIDW_BUF_SIZE_PAGEWIDTH(pagewidth); | ||
347 | writel(data, regs + VIDW_BUF_SIZE(win_no)); | ||
348 | |||
349 | /* write 'OSD' registers to control position of framebuffer */ | ||
350 | |||
351 | data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0); | ||
352 | writel(data, regs + VIDOSD_A(win_no)); | ||
353 | |||
354 | data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel, | ||
355 | var->xres - 1)) | | ||
356 | VIDOSDxB_BOTRIGHT_Y(var->yres - 1); | ||
357 | |||
358 | writel(data, regs + VIDOSD_B(win_no)); | ||
359 | |||
360 | data = var->xres * var->yres; | ||
361 | if (s3c_fb_has_osd_d(win_no)) { | ||
362 | writel(data, regs + VIDOSD_D(win_no)); | ||
363 | writel(0, regs + VIDOSD_C(win_no)); | ||
364 | } else | ||
365 | writel(data, regs + VIDOSD_C(win_no)); | ||
366 | |||
367 | data = WINCONx_ENWIN; | ||
368 | |||
369 | /* note, since we have to round up the bits-per-pixel, we end up | ||
370 | * relying on the bitfield information for r/g/b/a to work out | ||
371 | * exactly which mode of operation is intended. */ | ||
372 | |||
373 | switch (var->bits_per_pixel) { | ||
374 | case 1: | ||
375 | data |= WINCON0_BPPMODE_1BPP; | ||
376 | data |= WINCONx_BITSWP; | ||
377 | data |= WINCONx_BURSTLEN_4WORD; | ||
378 | break; | ||
379 | case 2: | ||
380 | data |= WINCON0_BPPMODE_2BPP; | ||
381 | data |= WINCONx_BITSWP; | ||
382 | data |= WINCONx_BURSTLEN_8WORD; | ||
383 | break; | ||
384 | case 4: | ||
385 | data |= WINCON0_BPPMODE_4BPP; | ||
386 | data |= WINCONx_BITSWP; | ||
387 | data |= WINCONx_BURSTLEN_8WORD; | ||
388 | break; | ||
389 | case 8: | ||
390 | if (var->transp.length != 0) | ||
391 | data |= WINCON1_BPPMODE_8BPP_1232; | ||
392 | else | ||
393 | data |= WINCON0_BPPMODE_8BPP_PALETTE; | ||
394 | data |= WINCONx_BURSTLEN_8WORD; | ||
395 | data |= WINCONx_BYTSWP; | ||
396 | break; | ||
397 | case 16: | ||
398 | if (var->transp.length != 0) | ||
399 | data |= WINCON1_BPPMODE_16BPP_A1555; | ||
400 | else | ||
401 | data |= WINCON0_BPPMODE_16BPP_565; | ||
402 | data |= WINCONx_HAWSWP; | ||
403 | data |= WINCONx_BURSTLEN_16WORD; | ||
404 | break; | ||
405 | case 24: | ||
406 | case 32: | ||
407 | if (var->red.length == 6) { | ||
408 | if (var->transp.length != 0) | ||
409 | data |= WINCON1_BPPMODE_19BPP_A1666; | ||
410 | else | ||
411 | data |= WINCON1_BPPMODE_18BPP_666; | ||
412 | } else if (var->transp.length != 0) | ||
413 | data |= WINCON1_BPPMODE_25BPP_A1888; | ||
414 | else | ||
415 | data |= WINCON0_BPPMODE_24BPP_888; | ||
416 | |||
417 | data |= WINCONx_BURSTLEN_16WORD; | ||
418 | break; | ||
419 | } | ||
420 | |||
421 | writel(data, regs + WINCON(win_no)); | ||
422 | writel(0x0, regs + WINxMAP(win_no)); | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | /** | ||
428 | * s3c_fb_update_palette() - set or schedule a palette update. | ||
429 | * @sfb: The hardware information. | ||
430 | * @win: The window being updated. | ||
431 | * @reg: The palette index being changed. | ||
432 | * @value: The computed palette value. | ||
433 | * | ||
434 | * Change the value of a palette register, either by directly writing to | ||
435 | * the palette (this requires the palette RAM to be disconnected from the | ||
436 | * hardware whilst this is in progress) or schedule the update for later. | ||
437 | * | ||
438 | * At the moment, since we have no VSYNC interrupt support, we simply set | ||
439 | * the palette entry directly. | ||
440 | */ | ||
441 | static void s3c_fb_update_palette(struct s3c_fb *sfb, | ||
442 | struct s3c_fb_win *win, | ||
443 | unsigned int reg, | ||
444 | u32 value) | ||
445 | { | ||
446 | void __iomem *palreg; | ||
447 | u32 palcon; | ||
448 | |||
449 | palreg = sfb->regs + s3c_fb_pal_reg(win->index, reg); | ||
450 | |||
451 | dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n", | ||
452 | __func__, win->index, reg, palreg, value); | ||
453 | |||
454 | win->palette_buffer[reg] = value; | ||
455 | |||
456 | palcon = readl(sfb->regs + WPALCON); | ||
457 | writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON); | ||
458 | |||
459 | if (s3c_fb_pal_is16(win->index)) | ||
460 | writew(value, palreg); | ||
461 | else | ||
462 | writel(value, palreg); | ||
463 | |||
464 | writel(palcon, sfb->regs + WPALCON); | ||
465 | } | ||
466 | |||
467 | static inline unsigned int chan_to_field(unsigned int chan, | ||
468 | struct fb_bitfield *bf) | ||
469 | { | ||
470 | chan &= 0xffff; | ||
471 | chan >>= 16 - bf->length; | ||
472 | return chan << bf->offset; | ||
473 | } | ||
474 | |||
475 | /** | ||
476 | * s3c_fb_setcolreg() - framebuffer layer request to change palette. | ||
477 | * @regno: The palette index to change. | ||
478 | * @red: The red field for the palette data. | ||
479 | * @green: The green field for the palette data. | ||
480 | * @blue: The blue field for the palette data. | ||
481 | * @trans: The transparency (alpha) field for the palette data. | ||
482 | * @info: The framebuffer being changed. | ||
483 | */ | ||
484 | static int s3c_fb_setcolreg(unsigned regno, | ||
485 | unsigned red, unsigned green, unsigned blue, | ||
486 | unsigned transp, struct fb_info *info) | ||
487 | { | ||
488 | struct s3c_fb_win *win = info->par; | ||
489 | struct s3c_fb *sfb = win->parent; | ||
490 | unsigned int val; | ||
491 | |||
492 | dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n", | ||
493 | __func__, win->index, regno, red, green, blue); | ||
494 | |||
495 | switch (info->fix.visual) { | ||
496 | case FB_VISUAL_TRUECOLOR: | ||
497 | /* true-colour, use pseudo-palette */ | ||
498 | |||
499 | if (regno < 16) { | ||
500 | u32 *pal = info->pseudo_palette; | ||
501 | |||
502 | val = chan_to_field(red, &info->var.red); | ||
503 | val |= chan_to_field(green, &info->var.green); | ||
504 | val |= chan_to_field(blue, &info->var.blue); | ||
505 | |||
506 | pal[regno] = val; | ||
507 | } | ||
508 | break; | ||
509 | |||
510 | case FB_VISUAL_PSEUDOCOLOR: | ||
511 | if (regno < s3c_fb_win_pal_size(win->index)) { | ||
512 | val = chan_to_field(red, &win->palette.r); | ||
513 | val |= chan_to_field(green, &win->palette.g); | ||
514 | val |= chan_to_field(blue, &win->palette.b); | ||
515 | |||
516 | s3c_fb_update_palette(sfb, win, regno, val); | ||
517 | } | ||
518 | |||
519 | break; | ||
520 | |||
521 | default: | ||
522 | return 1; /* unknown type */ | ||
523 | } | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | /** | ||
529 | * s3c_fb_enable() - Set the state of the main LCD output | ||
530 | * @sfb: The main framebuffer state. | ||
531 | * @enable: The state to set. | ||
532 | */ | ||
533 | static void s3c_fb_enable(struct s3c_fb *sfb, int enable) | ||
534 | { | ||
535 | u32 vidcon0 = readl(sfb->regs + VIDCON0); | ||
536 | |||
537 | if (enable) | ||
538 | vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F; | ||
539 | else { | ||
540 | /* see the note in the framebuffer datasheet about | ||
541 | * why you cannot take both of these bits down at the | ||
542 | * same time. */ | ||
543 | |||
544 | if (!(vidcon0 & VIDCON0_ENVID)) | ||
545 | return; | ||
546 | |||
547 | vidcon0 |= VIDCON0_ENVID; | ||
548 | vidcon0 &= ~VIDCON0_ENVID_F; | ||
549 | } | ||
550 | |||
551 | writel(vidcon0, sfb->regs + VIDCON0); | ||
552 | } | ||
553 | |||
554 | /** | ||
555 | * s3c_fb_blank() - blank or unblank the given window | ||
556 | * @blank_mode: The blank state from FB_BLANK_* | ||
557 | * @info: The framebuffer to blank. | ||
558 | * | ||
559 | * Framebuffer layer request to change the power state. | ||
560 | */ | ||
561 | static int s3c_fb_blank(int blank_mode, struct fb_info *info) | ||
562 | { | ||
563 | struct s3c_fb_win *win = info->par; | ||
564 | struct s3c_fb *sfb = win->parent; | ||
565 | unsigned int index = win->index; | ||
566 | u32 wincon; | ||
567 | |||
568 | dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); | ||
569 | |||
570 | wincon = readl(sfb->regs + WINCON(index)); | ||
571 | |||
572 | switch (blank_mode) { | ||
573 | case FB_BLANK_POWERDOWN: | ||
574 | wincon &= ~WINCONx_ENWIN; | ||
575 | sfb->enabled &= ~(1 << index); | ||
576 | /* fall through to FB_BLANK_NORMAL */ | ||
577 | |||
578 | case FB_BLANK_NORMAL: | ||
579 | /* disable the DMA and display 0x0 (black) */ | ||
580 | writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0), | ||
581 | sfb->regs + WINxMAP(index)); | ||
582 | break; | ||
583 | |||
584 | case FB_BLANK_UNBLANK: | ||
585 | writel(0x0, sfb->regs + WINxMAP(index)); | ||
586 | wincon |= WINCONx_ENWIN; | ||
587 | sfb->enabled |= (1 << index); | ||
588 | break; | ||
589 | |||
590 | case FB_BLANK_VSYNC_SUSPEND: | ||
591 | case FB_BLANK_HSYNC_SUSPEND: | ||
592 | default: | ||
593 | return 1; | ||
594 | } | ||
595 | |||
596 | writel(wincon, sfb->regs + WINCON(index)); | ||
597 | |||
598 | /* Check the enabled state to see if we need to be running the | ||
599 | * main LCD interface, as if there are no active windows then | ||
600 | * it is highly likely that we also do not need to output | ||
601 | * anything. | ||
602 | */ | ||
603 | |||
604 | /* We could do something like the following code, but the current | ||
605 | * system of using framebuffer events means that we cannot make | ||
606 | * the distinction between just window 0 being inactive and all | ||
607 | * the windows being down. | ||
608 | * | ||
609 | * s3c_fb_enable(sfb, sfb->enabled ? 1 : 0); | ||
610 | */ | ||
611 | |||
612 | /* we're stuck with this until we can do something about overriding | ||
613 | * the power control using the blanking event for a single fb. | ||
614 | */ | ||
615 | if (index == 0) | ||
616 | s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0); | ||
617 | |||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | static struct fb_ops s3c_fb_ops = { | ||
622 | .owner = THIS_MODULE, | ||
623 | .fb_check_var = s3c_fb_check_var, | ||
624 | .fb_set_par = s3c_fb_set_par, | ||
625 | .fb_blank = s3c_fb_blank, | ||
626 | .fb_setcolreg = s3c_fb_setcolreg, | ||
627 | .fb_fillrect = cfb_fillrect, | ||
628 | .fb_copyarea = cfb_copyarea, | ||
629 | .fb_imageblit = cfb_imageblit, | ||
630 | }; | ||
631 | |||
632 | /** | ||
633 | * s3c_fb_alloc_memory() - allocate display memory for framebuffer window | ||
634 | * @sfb: The base resources for the hardware. | ||
635 | * @win: The window to initialise memory for. | ||
636 | * | ||
637 | * Allocate memory for the given framebuffer. | ||
638 | */ | ||
639 | static int __devinit s3c_fb_alloc_memory(struct s3c_fb *sfb, | ||
640 | struct s3c_fb_win *win) | ||
641 | { | ||
642 | struct s3c_fb_pd_win *windata = win->windata; | ||
643 | unsigned int real_size, virt_size, size; | ||
644 | struct fb_info *fbi = win->fbinfo; | ||
645 | dma_addr_t map_dma; | ||
646 | |||
647 | dev_dbg(sfb->dev, "allocating memory for display\n"); | ||
648 | |||
649 | real_size = windata->win_mode.xres * windata->win_mode.yres; | ||
650 | virt_size = windata->virtual_x * windata->virtual_y; | ||
651 | |||
652 | dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n", | ||
653 | real_size, windata->win_mode.xres, windata->win_mode.yres, | ||
654 | virt_size, windata->virtual_x, windata->virtual_y); | ||
655 | |||
656 | size = (real_size > virt_size) ? real_size : virt_size; | ||
657 | size *= (windata->max_bpp > 16) ? 32 : windata->max_bpp; | ||
658 | size /= 8; | ||
659 | |||
660 | fbi->fix.smem_len = size; | ||
661 | size = PAGE_ALIGN(size); | ||
662 | |||
663 | dev_dbg(sfb->dev, "want %u bytes for window\n", size); | ||
664 | |||
665 | fbi->screen_base = dma_alloc_writecombine(sfb->dev, size, | ||
666 | &map_dma, GFP_KERNEL); | ||
667 | if (!fbi->screen_base) | ||
668 | return -ENOMEM; | ||
669 | |||
670 | dev_dbg(sfb->dev, "mapped %x to %p\n", | ||
671 | (unsigned int)map_dma, fbi->screen_base); | ||
672 | |||
673 | memset(fbi->screen_base, 0x0, size); | ||
674 | fbi->fix.smem_start = map_dma; | ||
675 | |||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | /** | ||
680 | * s3c_fb_free_memory() - free the display memory for the given window | ||
681 | * @sfb: The base resources for the hardware. | ||
682 | * @win: The window to free the display memory for. | ||
683 | * | ||
684 | * Free the display memory allocated by s3c_fb_alloc_memory(). | ||
685 | */ | ||
686 | static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win) | ||
687 | { | ||
688 | struct fb_info *fbi = win->fbinfo; | ||
689 | |||
690 | dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len), | ||
691 | fbi->screen_base, fbi->fix.smem_start); | ||
692 | } | ||
693 | |||
694 | /** | ||
695 | * s3c_fb_release_win() - release resources for a framebuffer window. | ||
696 | * @win: The window to cleanup the resources for. | ||
697 | * | ||
698 | * Release the resources that where claimed for the hardware window, | ||
699 | * such as the framebuffer instance and any memory claimed for it. | ||
700 | */ | ||
701 | static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win) | ||
702 | { | ||
703 | fb_dealloc_cmap(&win->fbinfo->cmap); | ||
704 | unregister_framebuffer(win->fbinfo); | ||
705 | s3c_fb_free_memory(sfb, win); | ||
706 | } | ||
707 | |||
708 | /** | ||
709 | * s3c_fb_probe_win() - register an hardware window | ||
710 | * @sfb: The base resources for the hardware | ||
711 | * @res: Pointer to where to place the resultant window. | ||
712 | * | ||
713 | * Allocate and do the basic initialisation for one of the hardware's graphics | ||
714 | * windows. | ||
715 | */ | ||
716 | static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | ||
717 | struct s3c_fb_win **res) | ||
718 | { | ||
719 | struct fb_var_screeninfo *var; | ||
720 | struct fb_videomode *initmode; | ||
721 | struct s3c_fb_pd_win *windata; | ||
722 | struct s3c_fb_win *win; | ||
723 | struct fb_info *fbinfo; | ||
724 | int palette_size; | ||
725 | int ret; | ||
726 | |||
727 | dev_dbg(sfb->dev, "probing window %d\n", win_no); | ||
728 | |||
729 | palette_size = s3c_fb_win_pal_size(win_no); | ||
730 | |||
731 | fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) + | ||
732 | palette_size * sizeof(u32), sfb->dev); | ||
733 | if (!fbinfo) { | ||
734 | dev_err(sfb->dev, "failed to allocate framebuffer\n"); | ||
735 | return -ENOENT; | ||
736 | } | ||
737 | |||
738 | windata = sfb->pdata->win[win_no]; | ||
739 | initmode = &windata->win_mode; | ||
740 | |||
741 | WARN_ON(windata->max_bpp == 0); | ||
742 | WARN_ON(windata->win_mode.xres == 0); | ||
743 | WARN_ON(windata->win_mode.yres == 0); | ||
744 | |||
745 | win = fbinfo->par; | ||
746 | var = &fbinfo->var; | ||
747 | win->fbinfo = fbinfo; | ||
748 | win->parent = sfb; | ||
749 | win->windata = windata; | ||
750 | win->index = win_no; | ||
751 | win->palette_buffer = (u32 *)(win + 1); | ||
752 | |||
753 | ret = s3c_fb_alloc_memory(sfb, win); | ||
754 | if (ret) { | ||
755 | dev_err(sfb->dev, "failed to allocate display memory\n"); | ||
756 | goto err_framebuffer; | ||
757 | } | ||
758 | |||
759 | /* setup the r/b/g positions for the window's palette */ | ||
760 | s3c_fb_init_palette(win_no, &win->palette); | ||
761 | |||
762 | /* setup the initial video mode from the window */ | ||
763 | fb_videomode_to_var(&fbinfo->var, initmode); | ||
764 | |||
765 | fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; | ||
766 | fbinfo->fix.accel = FB_ACCEL_NONE; | ||
767 | fbinfo->var.activate = FB_ACTIVATE_NOW; | ||
768 | fbinfo->var.vmode = FB_VMODE_NONINTERLACED; | ||
769 | fbinfo->var.bits_per_pixel = windata->default_bpp; | ||
770 | fbinfo->fbops = &s3c_fb_ops; | ||
771 | fbinfo->flags = FBINFO_FLAG_DEFAULT; | ||
772 | fbinfo->pseudo_palette = &win->pseudo_palette; | ||
773 | |||
774 | /* prepare to actually start the framebuffer */ | ||
775 | |||
776 | ret = s3c_fb_check_var(&fbinfo->var, fbinfo); | ||
777 | if (ret < 0) { | ||
778 | dev_err(sfb->dev, "check_var failed on initial video params\n"); | ||
779 | goto err_alloc_mem; | ||
780 | } | ||
781 | |||
782 | /* create initial colour map */ | ||
783 | |||
784 | ret = fb_alloc_cmap(&fbinfo->cmap, s3c_fb_win_pal_size(win_no), 1); | ||
785 | if (ret == 0) | ||
786 | fb_set_cmap(&fbinfo->cmap, fbinfo); | ||
787 | else | ||
788 | dev_err(sfb->dev, "failed to allocate fb cmap\n"); | ||
789 | |||
790 | s3c_fb_set_par(fbinfo); | ||
791 | |||
792 | dev_dbg(sfb->dev, "about to register framebuffer\n"); | ||
793 | |||
794 | /* run the check_var and set_par on our configuration. */ | ||
795 | |||
796 | ret = register_framebuffer(fbinfo); | ||
797 | if (ret < 0) { | ||
798 | dev_err(sfb->dev, "failed to register framebuffer\n"); | ||
799 | goto err_alloc_mem; | ||
800 | } | ||
801 | |||
802 | *res = win; | ||
803 | dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id); | ||
804 | |||
805 | return 0; | ||
806 | |||
807 | err_alloc_mem: | ||
808 | s3c_fb_free_memory(sfb, win); | ||
809 | |||
810 | err_framebuffer: | ||
811 | unregister_framebuffer(fbinfo); | ||
812 | return ret; | ||
813 | } | ||
814 | |||
815 | /** | ||
816 | * s3c_fb_clear_win() - clear hardware window registers. | ||
817 | * @sfb: The base resources for the hardware. | ||
818 | * @win: The window to process. | ||
819 | * | ||
820 | * Reset the specific window registers to a known state. | ||
821 | */ | ||
822 | static void s3c_fb_clear_win(struct s3c_fb *sfb, int win) | ||
823 | { | ||
824 | void __iomem *regs = sfb->regs; | ||
825 | |||
826 | writel(0, regs + WINCON(win)); | ||
827 | writel(0xffffff, regs + WxKEYCONy(win, 0)); | ||
828 | writel(0xffffff, regs + WxKEYCONy(win, 1)); | ||
829 | |||
830 | writel(0, regs + VIDOSD_A(win)); | ||
831 | writel(0, regs + VIDOSD_B(win)); | ||
832 | writel(0, regs + VIDOSD_C(win)); | ||
833 | } | ||
834 | |||
835 | static int __devinit s3c_fb_probe(struct platform_device *pdev) | ||
836 | { | ||
837 | struct device *dev = &pdev->dev; | ||
838 | struct s3c_fb_platdata *pd; | ||
839 | struct s3c_fb *sfb; | ||
840 | struct resource *res; | ||
841 | int win; | ||
842 | int ret = 0; | ||
843 | |||
844 | pd = pdev->dev.platform_data; | ||
845 | if (!pd) { | ||
846 | dev_err(dev, "no platform data specified\n"); | ||
847 | return -EINVAL; | ||
848 | } | ||
849 | |||
850 | sfb = kzalloc(sizeof(struct s3c_fb), GFP_KERNEL); | ||
851 | if (!sfb) { | ||
852 | dev_err(dev, "no memory for framebuffers\n"); | ||
853 | return -ENOMEM; | ||
854 | } | ||
855 | |||
856 | sfb->dev = dev; | ||
857 | sfb->pdata = pd; | ||
858 | |||
859 | sfb->bus_clk = clk_get(dev, "lcd"); | ||
860 | if (IS_ERR(sfb->bus_clk)) { | ||
861 | dev_err(dev, "failed to get bus clock\n"); | ||
862 | goto err_sfb; | ||
863 | } | ||
864 | |||
865 | clk_enable(sfb->bus_clk); | ||
866 | |||
867 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
868 | if (!res) { | ||
869 | dev_err(dev, "failed to find registers\n"); | ||
870 | ret = -ENOENT; | ||
871 | goto err_clk; | ||
872 | } | ||
873 | |||
874 | sfb->regs_res = request_mem_region(res->start, resource_size(res), | ||
875 | dev_name(dev)); | ||
876 | if (!sfb->regs_res) { | ||
877 | dev_err(dev, "failed to claim register region\n"); | ||
878 | ret = -ENOENT; | ||
879 | goto err_clk; | ||
880 | } | ||
881 | |||
882 | sfb->regs = ioremap(res->start, resource_size(res)); | ||
883 | if (!sfb->regs) { | ||
884 | dev_err(dev, "failed to map registers\n"); | ||
885 | ret = -ENXIO; | ||
886 | goto err_req_region; | ||
887 | } | ||
888 | |||
889 | dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs); | ||
890 | |||
891 | /* setup gpio and output polarity controls */ | ||
892 | |||
893 | pd->setup_gpio(); | ||
894 | |||
895 | writel(pd->vidcon1, sfb->regs + VIDCON1); | ||
896 | |||
897 | /* zero all windows before we do anything */ | ||
898 | |||
899 | for (win = 0; win < S3C_FB_MAX_WIN; win++) | ||
900 | s3c_fb_clear_win(sfb, win); | ||
901 | |||
902 | /* we have the register setup, start allocating framebuffers */ | ||
903 | |||
904 | for (win = 0; win < S3C_FB_MAX_WIN; win++) { | ||
905 | if (!pd->win[win]) | ||
906 | continue; | ||
907 | |||
908 | ret = s3c_fb_probe_win(sfb, win, &sfb->windows[win]); | ||
909 | if (ret < 0) { | ||
910 | dev_err(dev, "failed to create window %d\n", win); | ||
911 | for (; win >= 0; win--) | ||
912 | s3c_fb_release_win(sfb, sfb->windows[win]); | ||
913 | goto err_ioremap; | ||
914 | } | ||
915 | } | ||
916 | |||
917 | platform_set_drvdata(pdev, sfb); | ||
918 | |||
919 | return 0; | ||
920 | |||
921 | err_ioremap: | ||
922 | iounmap(sfb->regs); | ||
923 | |||
924 | err_req_region: | ||
925 | release_resource(sfb->regs_res); | ||
926 | kfree(sfb->regs_res); | ||
927 | |||
928 | err_clk: | ||
929 | clk_disable(sfb->bus_clk); | ||
930 | clk_put(sfb->bus_clk); | ||
931 | |||
932 | err_sfb: | ||
933 | kfree(sfb); | ||
934 | return ret; | ||
935 | } | ||
936 | |||
937 | /** | ||
938 | * s3c_fb_remove() - Cleanup on module finalisation | ||
939 | * @pdev: The platform device we are bound to. | ||
940 | * | ||
941 | * Shutdown and then release all the resources that the driver allocated | ||
942 | * on initialisation. | ||
943 | */ | ||
944 | static int __devexit s3c_fb_remove(struct platform_device *pdev) | ||
945 | { | ||
946 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | ||
947 | int win; | ||
948 | |||
949 | for (win = 0; win <= S3C_FB_MAX_WIN; win++) | ||
950 | s3c_fb_release_win(sfb, sfb->windows[win]); | ||
951 | |||
952 | iounmap(sfb->regs); | ||
953 | |||
954 | clk_disable(sfb->bus_clk); | ||
955 | clk_put(sfb->bus_clk); | ||
956 | |||
957 | release_resource(sfb->regs_res); | ||
958 | kfree(sfb->regs_res); | ||
959 | |||
960 | kfree(sfb); | ||
961 | |||
962 | return 0; | ||
963 | } | ||
964 | |||
965 | #ifdef CONFIG_PM | ||
966 | static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state) | ||
967 | { | ||
968 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | ||
969 | struct s3c_fb_win *win; | ||
970 | int win_no; | ||
971 | |||
972 | for (win_no = S3C_FB_MAX_WIN; win_no >= 0; win_no--) { | ||
973 | win = sfb->windows[win_no]; | ||
974 | if (!win) | ||
975 | continue; | ||
976 | |||
977 | /* use the blank function to push into power-down */ | ||
978 | s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); | ||
979 | } | ||
980 | |||
981 | clk_disable(sfb->bus_clk); | ||
982 | return 0; | ||
983 | } | ||
984 | |||
985 | static int s3c_fb_resume(struct platform_device *pdev) | ||
986 | { | ||
987 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | ||
988 | struct s3c_fb_win *win; | ||
989 | int win_no; | ||
990 | |||
991 | clk_enable(sfb->bus_clk); | ||
992 | |||
993 | for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { | ||
994 | win = sfb->windows[win_no]; | ||
995 | if (!win) | ||
996 | continue; | ||
997 | |||
998 | dev_dbg(&pdev->dev, "resuming window %d\n", win_no); | ||
999 | s3c_fb_set_par(win->fbinfo); | ||
1000 | } | ||
1001 | |||
1002 | return 0; | ||
1003 | } | ||
1004 | #else | ||
1005 | #define s3c_fb_suspend NULL | ||
1006 | #define s3c_fb_resume NULL | ||
1007 | #endif | ||
1008 | |||
1009 | static struct platform_driver s3c_fb_driver = { | ||
1010 | .probe = s3c_fb_probe, | ||
1011 | .remove = s3c_fb_remove, | ||
1012 | .suspend = s3c_fb_suspend, | ||
1013 | .resume = s3c_fb_resume, | ||
1014 | .driver = { | ||
1015 | .name = "s3c-fb", | ||
1016 | .owner = THIS_MODULE, | ||
1017 | }, | ||
1018 | }; | ||
1019 | |||
1020 | static int __init s3c_fb_init(void) | ||
1021 | { | ||
1022 | return platform_driver_register(&s3c_fb_driver); | ||
1023 | } | ||
1024 | |||
1025 | static void __exit s3c_fb_cleanup(void) | ||
1026 | { | ||
1027 | platform_driver_unregister(&s3c_fb_driver); | ||
1028 | } | ||
1029 | |||
1030 | module_init(s3c_fb_init); | ||
1031 | module_exit(s3c_fb_cleanup); | ||
1032 | |||
1033 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | ||
1034 | MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver"); | ||
1035 | MODULE_LICENSE("GPL"); | ||
1036 | MODULE_ALIAS("platform:s3c-fb"); | ||
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index f5252c2552f..bba53714a7b 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c | |||
@@ -837,6 +837,8 @@ static int sgivwfb_remove(struct platform_device *dev) | |||
837 | iounmap(par->regs); | 837 | iounmap(par->regs); |
838 | iounmap(info->screen_base); | 838 | iounmap(info->screen_base); |
839 | release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE); | 839 | release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE); |
840 | fb_dealloc_cmap(&info->cmap); | ||
841 | framebuffer_release(info); | ||
840 | } | 842 | } |
841 | return 0; | 843 | return 0; |
842 | } | 844 | } |
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index df5336561d1..a439159204a 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c | |||
@@ -795,8 +795,9 @@ static int __devinit xxxfb_probe(struct pci_dev *dev, | |||
795 | if (!retval || retval == 4) | 795 | if (!retval || retval == 4) |
796 | return -EINVAL; | 796 | return -EINVAL; |
797 | 797 | ||
798 | /* This has to been done !!! */ | 798 | /* This has to be done! */ |
799 | fb_alloc_cmap(&info->cmap, cmap_len, 0); | 799 | if (fb_alloc_cmap(&info->cmap, cmap_len, 0)) |
800 | return -ENOMEM; | ||
800 | 801 | ||
801 | /* | 802 | /* |
802 | * The following is done in the case of having hardware with a static | 803 | * The following is done in the case of having hardware with a static |
@@ -820,8 +821,10 @@ static int __devinit xxxfb_probe(struct pci_dev *dev, | |||
820 | */ | 821 | */ |
821 | /* xxxfb_set_par(info); */ | 822 | /* xxxfb_set_par(info); */ |
822 | 823 | ||
823 | if (register_framebuffer(info) < 0) | 824 | if (register_framebuffer(info) < 0) { |
825 | fb_dealloc_cmap(&info->cmap); | ||
824 | return -EINVAL; | 826 | return -EINVAL; |
827 | } | ||
825 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, | 828 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, |
826 | info->fix.id); | 829 | info->fix.id); |
827 | pci_set_drvdata(dev, info); /* or platform_set_drvdata(pdev, info) */ | 830 | pci_set_drvdata(dev, info); /* or platform_set_drvdata(pdev, info) */ |
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index dcd98793d56..eb5d73a0670 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
@@ -1525,7 +1525,10 @@ static int sm501fb_init_fb(struct fb_info *fb, | |||
1525 | } | 1525 | } |
1526 | 1526 | ||
1527 | /* initialise and set the palette */ | 1527 | /* initialise and set the palette */ |
1528 | fb_alloc_cmap(&fb->cmap, NR_PALETTE, 0); | 1528 | if (fb_alloc_cmap(&fb->cmap, NR_PALETTE, 0)) { |
1529 | dev_err(info->dev, "failed to allocate cmap memory\n"); | ||
1530 | return -ENOMEM; | ||
1531 | } | ||
1529 | fb_set_cmap(&fb->cmap, fb); | 1532 | fb_set_cmap(&fb->cmap, fb); |
1530 | 1533 | ||
1531 | ret = (fb->fbops->fb_check_var)(&fb->var, fb); | 1534 | ret = (fb->fbops->fb_check_var)(&fb->var, fb); |
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 5b11a00f49b..609d0a521ca 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c | |||
@@ -1421,13 +1421,16 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, | |||
1421 | goto fail; | 1421 | goto fail; |
1422 | } | 1422 | } |
1423 | 1423 | ||
1424 | fb_alloc_cmap(&info->cmap, 256, 0); | 1424 | if (fb_alloc_cmap(&info->cmap, 256, 0)) { |
1425 | printk(KERN_ERR "sstfb: can't alloc cmap memory.\n"); | ||
1426 | goto fail; | ||
1427 | } | ||
1425 | 1428 | ||
1426 | /* register fb */ | 1429 | /* register fb */ |
1427 | info->device = &pdev->dev; | 1430 | info->device = &pdev->dev; |
1428 | if (register_framebuffer(info) < 0) { | 1431 | if (register_framebuffer(info) < 0) { |
1429 | printk(KERN_ERR "sstfb: can't register framebuffer.\n"); | 1432 | printk(KERN_ERR "sstfb: can't register framebuffer.\n"); |
1430 | goto fail; | 1433 | goto fail_register; |
1431 | } | 1434 | } |
1432 | 1435 | ||
1433 | sstfb_clear_screen(info); | 1436 | sstfb_clear_screen(info); |
@@ -1441,8 +1444,9 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, | |||
1441 | 1444 | ||
1442 | return 0; | 1445 | return 0; |
1443 | 1446 | ||
1444 | fail: | 1447 | fail_register: |
1445 | fb_dealloc_cmap(&info->cmap); | 1448 | fb_dealloc_cmap(&info->cmap); |
1449 | fail: | ||
1446 | iounmap(info->screen_base); | 1450 | iounmap(info->screen_base); |
1447 | fail_fb_remap: | 1451 | fail_fb_remap: |
1448 | iounmap(par->mmio_vbase); | 1452 | iounmap(par->mmio_vbase); |
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 16648140241..eabaad765ae 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c | |||
@@ -1262,24 +1262,25 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) | |||
1262 | info->flags = FBINFO_DEFAULT; | 1262 | info->flags = FBINFO_DEFAULT; |
1263 | info->pseudo_palette = &fb->pseudo_palette; | 1263 | info->pseudo_palette = &fb->pseudo_palette; |
1264 | 1264 | ||
1265 | /* This has to been done !!! */ | 1265 | /* This has to be done !!! */ |
1266 | fb_alloc_cmap(&info->cmap, NR_PALETTE, 0); | 1266 | if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0)) |
1267 | goto out_err1; | ||
1267 | stifb_init_display(fb); | 1268 | stifb_init_display(fb); |
1268 | 1269 | ||
1269 | if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb fb")) { | 1270 | if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb fb")) { |
1270 | printk(KERN_ERR "stifb: cannot reserve fb region 0x%04lx-0x%04lx\n", | 1271 | printk(KERN_ERR "stifb: cannot reserve fb region 0x%04lx-0x%04lx\n", |
1271 | fix->smem_start, fix->smem_start+fix->smem_len); | 1272 | fix->smem_start, fix->smem_start+fix->smem_len); |
1272 | goto out_err1; | 1273 | goto out_err2; |
1273 | } | 1274 | } |
1274 | 1275 | ||
1275 | if (!request_mem_region(fix->mmio_start, fix->mmio_len, "stifb mmio")) { | 1276 | if (!request_mem_region(fix->mmio_start, fix->mmio_len, "stifb mmio")) { |
1276 | printk(KERN_ERR "stifb: cannot reserve sti mmio region 0x%04lx-0x%04lx\n", | 1277 | printk(KERN_ERR "stifb: cannot reserve sti mmio region 0x%04lx-0x%04lx\n", |
1277 | fix->mmio_start, fix->mmio_start+fix->mmio_len); | 1278 | fix->mmio_start, fix->mmio_start+fix->mmio_len); |
1278 | goto out_err2; | 1279 | goto out_err3; |
1279 | } | 1280 | } |
1280 | 1281 | ||
1281 | if (register_framebuffer(&fb->info) < 0) | 1282 | if (register_framebuffer(&fb->info) < 0) |
1282 | goto out_err3; | 1283 | goto out_err4; |
1283 | 1284 | ||
1284 | sti->info = info; /* save for unregister_framebuffer() */ | 1285 | sti->info = info; /* save for unregister_framebuffer() */ |
1285 | 1286 | ||
@@ -1297,13 +1298,14 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) | |||
1297 | return 0; | 1298 | return 0; |
1298 | 1299 | ||
1299 | 1300 | ||
1300 | out_err3: | 1301 | out_err4: |
1301 | release_mem_region(fix->mmio_start, fix->mmio_len); | 1302 | release_mem_region(fix->mmio_start, fix->mmio_len); |
1302 | out_err2: | 1303 | out_err3: |
1303 | release_mem_region(fix->smem_start, fix->smem_len); | 1304 | release_mem_region(fix->smem_start, fix->smem_len); |
1305 | out_err2: | ||
1306 | fb_dealloc_cmap(&info->cmap); | ||
1304 | out_err1: | 1307 | out_err1: |
1305 | iounmap(info->screen_base); | 1308 | iounmap(info->screen_base); |
1306 | fb_dealloc_cmap(&info->cmap); | ||
1307 | out_err0: | 1309 | out_err0: |
1308 | kfree(fb); | 1310 | kfree(fb); |
1309 | return -ENXIO; | 1311 | return -ENXIO; |
diff --git a/drivers/video/sunxvr500.c b/drivers/video/sunxvr500.c index c2ba51b7ea1..18b950706ca 100644 --- a/drivers/video/sunxvr500.c +++ b/drivers/video/sunxvr500.c | |||
@@ -349,11 +349,14 @@ static int __devinit e3d_pci_register(struct pci_dev *pdev, | |||
349 | if (err < 0) { | 349 | if (err < 0) { |
350 | printk(KERN_ERR "e3d: Could not register framebuffer %s\n", | 350 | printk(KERN_ERR "e3d: Could not register framebuffer %s\n", |
351 | pci_name(pdev)); | 351 | pci_name(pdev)); |
352 | goto err_unmap_fb; | 352 | goto err_free_cmap; |
353 | } | 353 | } |
354 | 354 | ||
355 | return 0; | 355 | return 0; |
356 | 356 | ||
357 | err_free_cmap: | ||
358 | fb_dealloc_cmap(&info->cmap); | ||
359 | |||
357 | err_unmap_fb: | 360 | err_unmap_fb: |
358 | iounmap(ep->fb_base); | 361 | iounmap(ep->fb_base); |
359 | 362 | ||
@@ -389,6 +392,7 @@ static void __devexit e3d_pci_unregister(struct pci_dev *pdev) | |||
389 | pci_release_region(pdev, 0); | 392 | pci_release_region(pdev, 0); |
390 | pci_release_region(pdev, 1); | 393 | pci_release_region(pdev, 1); |
391 | 394 | ||
395 | fb_dealloc_cmap(&info->cmap); | ||
392 | framebuffer_release(info); | 396 | framebuffer_release(info); |
393 | 397 | ||
394 | pci_disable_device(pdev); | 398 | pci_disable_device(pdev); |
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 14bd3f3680b..ee64771fbe3 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c | |||
@@ -1393,6 +1393,7 @@ static void __devexit tdfxfb_remove(struct pci_dev *pdev) | |||
1393 | release_mem_region(pci_resource_start(pdev, 0), | 1393 | release_mem_region(pci_resource_start(pdev, 0), |
1394 | pci_resource_len(pdev, 0)); | 1394 | pci_resource_len(pdev, 0)); |
1395 | pci_set_drvdata(pdev, NULL); | 1395 | pci_set_drvdata(pdev, NULL); |
1396 | fb_dealloc_cmap(&info->cmap); | ||
1396 | framebuffer_release(info); | 1397 | framebuffer_release(info); |
1397 | } | 1398 | } |
1398 | 1399 | ||
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 680642c089c..a86046ff60a 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c | |||
@@ -1663,7 +1663,7 @@ tgafb_register(struct device *dev) | |||
1663 | if (register_framebuffer(info) < 0) { | 1663 | if (register_framebuffer(info) < 0) { |
1664 | printk(KERN_ERR "tgafb: Could not register framebuffer\n"); | 1664 | printk(KERN_ERR "tgafb: Could not register framebuffer\n"); |
1665 | ret = -EINVAL; | 1665 | ret = -EINVAL; |
1666 | goto err1; | 1666 | goto err2; |
1667 | } | 1667 | } |
1668 | 1668 | ||
1669 | if (tga_bus_pci) { | 1669 | if (tga_bus_pci) { |
@@ -1682,6 +1682,8 @@ tgafb_register(struct device *dev) | |||
1682 | 1682 | ||
1683 | return 0; | 1683 | return 0; |
1684 | 1684 | ||
1685 | err2: | ||
1686 | fb_dealloc_cmap(&info->cmap); | ||
1685 | err1: | 1687 | err1: |
1686 | if (mem_base) | 1688 | if (mem_base) |
1687 | iounmap(mem_base); | 1689 | iounmap(mem_base); |
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index 479b2e79ad6..03a9c35e9f5 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Frame buffer driver for Trident TGUI, Blade and Image series | 2 | * Frame buffer driver for Trident TGUI, Blade and Image series |
3 | * | 3 | * |
4 | * Copyright 2001, 2002 - Jani Monoses <jani@iv.ro> | 4 | * Copyright 2001, 2002 - Jani Monoses <jani@iv.ro> |
5 | * | 5 | * Copyright 2009 Krzysztof Helt <krzysztof.h1@wp.pl> |
6 | * | 6 | * |
7 | * CREDITS:(in order of appearance) | 7 | * CREDITS:(in order of appearance) |
8 | * skeletonfb.c by Geert Uytterhoeven and other fb code in drivers/video | 8 | * skeletonfb.c by Geert Uytterhoeven and other fb code in drivers/video |
@@ -490,7 +490,6 @@ static void tgui_copy_rect(struct tridentfb_par *par, | |||
490 | /* | 490 | /* |
491 | * Accel functions called by the upper layers | 491 | * Accel functions called by the upper layers |
492 | */ | 492 | */ |
493 | #ifdef CONFIG_FB_TRIDENT_ACCEL | ||
494 | static void tridentfb_fillrect(struct fb_info *info, | 493 | static void tridentfb_fillrect(struct fb_info *info, |
495 | const struct fb_fillrect *fr) | 494 | const struct fb_fillrect *fr) |
496 | { | 495 | { |
@@ -565,11 +564,6 @@ static int tridentfb_sync(struct fb_info *info) | |||
565 | par->wait_engine(par); | 564 | par->wait_engine(par); |
566 | return 0; | 565 | return 0; |
567 | } | 566 | } |
568 | #else | ||
569 | #define tridentfb_fillrect cfb_fillrect | ||
570 | #define tridentfb_copyarea cfb_copyarea | ||
571 | #define tridentfb_imageblit cfb_imageblit | ||
572 | #endif /* CONFIG_FB_TRIDENT_ACCEL */ | ||
573 | 567 | ||
574 | /* | 568 | /* |
575 | * Hardware access functions | 569 | * Hardware access functions |
@@ -1333,9 +1327,7 @@ static struct fb_ops tridentfb_ops = { | |||
1333 | .fb_fillrect = tridentfb_fillrect, | 1327 | .fb_fillrect = tridentfb_fillrect, |
1334 | .fb_copyarea = tridentfb_copyarea, | 1328 | .fb_copyarea = tridentfb_copyarea, |
1335 | .fb_imageblit = tridentfb_imageblit, | 1329 | .fb_imageblit = tridentfb_imageblit, |
1336 | #ifdef CONFIG_FB_TRIDENT_ACCEL | ||
1337 | .fb_sync = tridentfb_sync, | 1330 | .fb_sync = tridentfb_sync, |
1338 | #endif | ||
1339 | }; | 1331 | }; |
1340 | 1332 | ||
1341 | static int __devinit trident_pci_probe(struct pci_dev *dev, | 1333 | static int __devinit trident_pci_probe(struct pci_dev *dev, |
@@ -1359,10 +1351,6 @@ static int __devinit trident_pci_probe(struct pci_dev *dev, | |||
1359 | 1351 | ||
1360 | chip_id = id->device; | 1352 | chip_id = id->device; |
1361 | 1353 | ||
1362 | #ifndef CONFIG_FB_TRIDENT_ACCEL | ||
1363 | noaccel = 1; | ||
1364 | #endif | ||
1365 | |||
1366 | /* If PCI id is 0x9660 then further detect chip type */ | 1354 | /* If PCI id is 0x9660 then further detect chip type */ |
1367 | 1355 | ||
1368 | if (chip_id == TGUI9660) { | 1356 | if (chip_id == TGUI9660) { |
@@ -1490,6 +1478,9 @@ static int __devinit trident_pci_probe(struct pci_dev *dev, | |||
1490 | } else | 1478 | } else |
1491 | info->flags |= FBINFO_HWACCEL_DISABLED; | 1479 | info->flags |= FBINFO_HWACCEL_DISABLED; |
1492 | 1480 | ||
1481 | if (is_blade(chip_id) && chip_id != BLADE3D) | ||
1482 | info->flags |= FBINFO_READS_FAST; | ||
1483 | |||
1493 | info->pixmap.addr = kmalloc(4096, GFP_KERNEL); | 1484 | info->pixmap.addr = kmalloc(4096, GFP_KERNEL); |
1494 | if (!info->pixmap.addr) { | 1485 | if (!info->pixmap.addr) { |
1495 | err = -ENOMEM; | 1486 | err = -ENOMEM; |
@@ -1563,6 +1554,7 @@ static void __devexit trident_pci_remove(struct pci_dev *dev) | |||
1563 | release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); | 1554 | release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); |
1564 | pci_set_drvdata(dev, NULL); | 1555 | pci_set_drvdata(dev, NULL); |
1565 | kfree(info->pixmap.addr); | 1556 | kfree(info->pixmap.addr); |
1557 | fb_dealloc_cmap(&info->cmap); | ||
1566 | framebuffer_release(info); | 1558 | framebuffer_release(info); |
1567 | } | 1559 | } |
1568 | 1560 | ||
@@ -1663,4 +1655,5 @@ module_exit(tridentfb_exit); | |||
1663 | MODULE_AUTHOR("Jani Monoses <jani@iv.ro>"); | 1655 | MODULE_AUTHOR("Jani Monoses <jani@iv.ro>"); |
1664 | MODULE_DESCRIPTION("Framebuffer driver for Trident cards"); | 1656 | MODULE_DESCRIPTION("Framebuffer driver for Trident cards"); |
1665 | MODULE_LICENSE("GPL"); | 1657 | MODULE_LICENSE("GPL"); |
1658 | MODULE_ALIAS("cyblafb"); | ||
1666 | 1659 | ||
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index 74ae7589900..0b370aebdbf 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c | |||
@@ -189,7 +189,7 @@ static int uvesafb_exec(struct uvesafb_ktask *task) | |||
189 | uvfb_tasks[seq] = task; | 189 | uvfb_tasks[seq] = task; |
190 | mutex_unlock(&uvfb_lock); | 190 | mutex_unlock(&uvfb_lock); |
191 | 191 | ||
192 | err = cn_netlink_send(m, 0, gfp_any()); | 192 | err = cn_netlink_send(m, 0, GFP_KERNEL); |
193 | if (err == -ESRCH) { | 193 | if (err == -ESRCH) { |
194 | /* | 194 | /* |
195 | * Try to start the userspace helper if sending | 195 | * Try to start the userspace helper if sending |
@@ -850,14 +850,16 @@ static int __devinit uvesafb_vbe_init_mode(struct fb_info *info) | |||
850 | if (vbemode) { | 850 | if (vbemode) { |
851 | for (i = 0; i < par->vbe_modes_cnt; i++) { | 851 | for (i = 0; i < par->vbe_modes_cnt; i++) { |
852 | if (par->vbe_modes[i].mode_id == vbemode) { | 852 | if (par->vbe_modes[i].mode_id == vbemode) { |
853 | modeid = i; | ||
854 | uvesafb_setup_var(&info->var, info, | ||
855 | &par->vbe_modes[modeid]); | ||
853 | fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, | 856 | fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, |
854 | &info->var, info); | 857 | &info->var, info); |
855 | /* | 858 | /* |
856 | * With pixclock set to 0, the default BIOS | 859 | * With pixclock set to 0, the default BIOS |
857 | * timings will be used in set_par(). | 860 | * timings will be used in set_par(). |
858 | */ | 861 | */ |
859 | info->var.pixclock = 0; | 862 | info->var.pixclock = 0; |
860 | modeid = i; | ||
861 | goto gotmode; | 863 | goto gotmode; |
862 | } | 864 | } |
863 | } | 865 | } |
@@ -904,8 +906,11 @@ static int __devinit uvesafb_vbe_init_mode(struct fb_info *info) | |||
904 | fb_videomode_to_var(&info->var, mode); | 906 | fb_videomode_to_var(&info->var, mode); |
905 | } else { | 907 | } else { |
906 | modeid = par->vbe_modes[0].mode_id; | 908 | modeid = par->vbe_modes[0].mode_id; |
909 | uvesafb_setup_var(&info->var, info, | ||
910 | &par->vbe_modes[modeid]); | ||
907 | fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, | 911 | fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, |
908 | &info->var, info); | 912 | &info->var, info); |
913 | |||
909 | goto gotmode; | 914 | goto gotmode; |
910 | } | 915 | } |
911 | } | 916 | } |
@@ -917,9 +922,9 @@ static int __devinit uvesafb_vbe_init_mode(struct fb_info *info) | |||
917 | if (modeid == -1) | 922 | if (modeid == -1) |
918 | return -EINVAL; | 923 | return -EINVAL; |
919 | 924 | ||
920 | gotmode: | ||
921 | uvesafb_setup_var(&info->var, info, &par->vbe_modes[modeid]); | 925 | uvesafb_setup_var(&info->var, info, &par->vbe_modes[modeid]); |
922 | 926 | ||
927 | gotmode: | ||
923 | /* | 928 | /* |
924 | * If we are not VBE3.0+ compliant, we're done -- the BIOS will | 929 | * If we are not VBE3.0+ compliant, we're done -- the BIOS will |
925 | * ignore our timings anyway. | 930 | * ignore our timings anyway. |
@@ -1552,7 +1557,7 @@ static void __devinit uvesafb_init_info(struct fb_info *info, | |||
1552 | } | 1557 | } |
1553 | 1558 | ||
1554 | info->flags = FBINFO_FLAG_DEFAULT | | 1559 | info->flags = FBINFO_FLAG_DEFAULT | |
1555 | (par->ypan) ? FBINFO_HWACCEL_YPAN : 0; | 1560 | (par->ypan ? FBINFO_HWACCEL_YPAN : 0); |
1556 | 1561 | ||
1557 | if (!par->ypan) | 1562 | if (!par->ypan) |
1558 | info->fbops->fb_pan_display = NULL; | 1563 | info->fbops->fb_pan_display = NULL; |
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 7b0cef9ca8f..4bb9a0b1895 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c | |||
@@ -119,7 +119,7 @@ static void set_valkyrie_clock(unsigned char *params); | |||
119 | static int valkyrie_var_to_par(struct fb_var_screeninfo *var, | 119 | static int valkyrie_var_to_par(struct fb_var_screeninfo *var, |
120 | struct fb_par_valkyrie *par, const struct fb_info *fb_info); | 120 | struct fb_par_valkyrie *par, const struct fb_info *fb_info); |
121 | 121 | ||
122 | static void valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p); | 122 | static int valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p); |
123 | static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, struct fb_fix_screeninfo *fix); | 123 | static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, struct fb_fix_screeninfo *fix); |
124 | static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p); | 124 | static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p); |
125 | 125 | ||
@@ -381,18 +381,22 @@ int __init valkyriefb_init(void) | |||
381 | 381 | ||
382 | valkyrie_choose_mode(p); | 382 | valkyrie_choose_mode(p); |
383 | mac_vmode_to_var(default_vmode, default_cmode, &p->info.var); | 383 | mac_vmode_to_var(default_vmode, default_cmode, &p->info.var); |
384 | valkyrie_init_info(&p->info, p); | 384 | err = valkyrie_init_info(&p->info, p); |
385 | if (err < 0) | ||
386 | goto out_free; | ||
385 | valkyrie_init_fix(&p->info.fix, p); | 387 | valkyrie_init_fix(&p->info.fix, p); |
386 | if (valkyriefb_set_par(&p->info)) | 388 | if (valkyriefb_set_par(&p->info)) |
387 | /* "can't happen" */ | 389 | /* "can't happen" */ |
388 | printk(KERN_ERR "valkyriefb: can't set default video mode\n"); | 390 | printk(KERN_ERR "valkyriefb: can't set default video mode\n"); |
389 | 391 | ||
390 | if ((err = register_framebuffer(&p->info)) != 0) | 392 | if ((err = register_framebuffer(&p->info)) != 0) |
391 | goto out_free; | 393 | goto out_cmap_free; |
392 | 394 | ||
393 | printk(KERN_INFO "fb%d: valkyrie frame buffer device\n", p->info.node); | 395 | printk(KERN_INFO "fb%d: valkyrie frame buffer device\n", p->info.node); |
394 | return 0; | 396 | return 0; |
395 | 397 | ||
398 | out_cmap_free: | ||
399 | fb_dealloc_cmap(&p->info.cmap); | ||
396 | out_free: | 400 | out_free: |
397 | if (p->frame_buffer) | 401 | if (p->frame_buffer) |
398 | iounmap(p->frame_buffer); | 402 | iounmap(p->frame_buffer); |
@@ -538,14 +542,15 @@ static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, | |||
538 | /* ywrapstep, xpanstep, ypanstep */ | 542 | /* ywrapstep, xpanstep, ypanstep */ |
539 | } | 543 | } |
540 | 544 | ||
541 | static void __init valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p) | 545 | static int __init valkyrie_init_info(struct fb_info *info, |
546 | struct fb_info_valkyrie *p) | ||
542 | { | 547 | { |
543 | info->fbops = &valkyriefb_ops; | 548 | info->fbops = &valkyriefb_ops; |
544 | info->screen_base = p->frame_buffer + 0x1000; | 549 | info->screen_base = p->frame_buffer + 0x1000; |
545 | info->flags = FBINFO_DEFAULT; | 550 | info->flags = FBINFO_DEFAULT; |
546 | info->pseudo_palette = p->pseudo_palette; | 551 | info->pseudo_palette = p->pseudo_palette; |
547 | fb_alloc_cmap(&info->cmap, 256, 0); | ||
548 | info->par = &p->par; | 552 | info->par = &p->par; |
553 | return fb_alloc_cmap(&info->cmap, 256, 0); | ||
549 | } | 554 | } |
550 | 555 | ||
551 | 556 | ||
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index e16322d157d..d6856f43d24 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c | |||
@@ -438,7 +438,7 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
438 | info->var = vesafb_defined; | 438 | info->var = vesafb_defined; |
439 | info->fix = vesafb_fix; | 439 | info->fix = vesafb_fix; |
440 | info->flags = FBINFO_FLAG_DEFAULT | | 440 | info->flags = FBINFO_FLAG_DEFAULT | |
441 | (ypan) ? FBINFO_HWACCEL_YPAN : 0; | 441 | (ypan ? FBINFO_HWACCEL_YPAN : 0); |
442 | 442 | ||
443 | if (!ypan) | 443 | if (!ypan) |
444 | info->fbops->fb_pan_display = NULL; | 444 | info->fbops->fb_pan_display = NULL; |
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 93fe08d6c78..cc919ae4657 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c | |||
@@ -543,6 +543,7 @@ static int vfb_remove(struct platform_device *dev) | |||
543 | if (info) { | 543 | if (info) { |
544 | unregister_framebuffer(info); | 544 | unregister_framebuffer(info); |
545 | rvfree(videomemory, videomemorysize); | 545 | rvfree(videomemory, videomemorysize); |
546 | fb_dealloc_cmap(&info->cmap); | ||
546 | framebuffer_release(info); | 547 | framebuffer_release(info); |
547 | } | 548 | } |
548 | return 0; | 549 | return 0; |
diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index 632523ff1fb..45c54bfe99b 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c | |||
@@ -267,13 +267,17 @@ int viafb_wait_engine_idle(void) | |||
267 | int loop = 0; | 267 | int loop = 0; |
268 | 268 | ||
269 | while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) & | 269 | while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) & |
270 | VIA_VR_QUEUE_BUSY) && (loop++ < MAXLOOP)) | 270 | VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) { |
271 | loop++; | ||
271 | cpu_relax(); | 272 | cpu_relax(); |
273 | } | ||
272 | 274 | ||
273 | while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) & | 275 | while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) & |
274 | (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && | 276 | (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && |
275 | (loop++ < MAXLOOP)) | 277 | (loop < MAXLOOP)) { |
278 | loop++; | ||
276 | cpu_relax(); | 279 | cpu_relax(); |
280 | } | ||
277 | 281 | ||
278 | return loop >= MAXLOOP; | 282 | return loop >= MAXLOOP; |
279 | } | 283 | } |
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index a76803108d0..b7ff33c6310 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h | |||
@@ -186,6 +186,8 @@ int autofs4_expire_wait(struct dentry *dentry); | |||
186 | int autofs4_expire_run(struct super_block *, struct vfsmount *, | 186 | int autofs4_expire_run(struct super_block *, struct vfsmount *, |
187 | struct autofs_sb_info *, | 187 | struct autofs_sb_info *, |
188 | struct autofs_packet_expire __user *); | 188 | struct autofs_packet_expire __user *); |
189 | int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt, | ||
190 | struct autofs_sb_info *sbi, int when); | ||
189 | int autofs4_expire_multi(struct super_block *, struct vfsmount *, | 191 | int autofs4_expire_multi(struct super_block *, struct vfsmount *, |
190 | struct autofs_sb_info *, int __user *); | 192 | struct autofs_sb_info *, int __user *); |
191 | struct dentry *autofs4_expire_direct(struct super_block *sb, | 193 | struct dentry *autofs4_expire_direct(struct super_block *sb, |
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index 025e105bffe..9e5ae8a4f5c 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c | |||
@@ -525,40 +525,13 @@ static int autofs_dev_ioctl_expire(struct file *fp, | |||
525 | struct autofs_sb_info *sbi, | 525 | struct autofs_sb_info *sbi, |
526 | struct autofs_dev_ioctl *param) | 526 | struct autofs_dev_ioctl *param) |
527 | { | 527 | { |
528 | struct dentry *dentry; | ||
529 | struct vfsmount *mnt; | 528 | struct vfsmount *mnt; |
530 | int err = -EAGAIN; | ||
531 | int how; | 529 | int how; |
532 | 530 | ||
533 | how = param->expire.how; | 531 | how = param->expire.how; |
534 | mnt = fp->f_path.mnt; | 532 | mnt = fp->f_path.mnt; |
535 | 533 | ||
536 | if (autofs_type_trigger(sbi->type)) | 534 | return autofs4_do_expire_multi(sbi->sb, mnt, sbi, how); |
537 | dentry = autofs4_expire_direct(sbi->sb, mnt, sbi, how); | ||
538 | else | ||
539 | dentry = autofs4_expire_indirect(sbi->sb, mnt, sbi, how); | ||
540 | |||
541 | if (dentry) { | ||
542 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | ||
543 | |||
544 | /* | ||
545 | * This is synchronous because it makes the daemon a | ||
546 | * little easier | ||
547 | */ | ||
548 | err = autofs4_wait(sbi, dentry, NFY_EXPIRE); | ||
549 | |||
550 | spin_lock(&sbi->fs_lock); | ||
551 | if (ino->flags & AUTOFS_INF_MOUNTPOINT) { | ||
552 | ino->flags &= ~AUTOFS_INF_MOUNTPOINT; | ||
553 | sbi->sb->s_root->d_mounted++; | ||
554 | } | ||
555 | ino->flags &= ~AUTOFS_INF_EXPIRING; | ||
556 | complete_all(&ino->expire_complete); | ||
557 | spin_unlock(&sbi->fs_lock); | ||
558 | dput(dentry); | ||
559 | } | ||
560 | |||
561 | return err; | ||
562 | } | 535 | } |
563 | 536 | ||
564 | /* Check if autofs mount point is in use */ | 537 | /* Check if autofs mount point is in use */ |
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index e3bd50776f9..75f7ddacf7d 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -478,22 +478,16 @@ int autofs4_expire_run(struct super_block *sb, | |||
478 | return ret; | 478 | return ret; |
479 | } | 479 | } |
480 | 480 | ||
481 | /* Call repeatedly until it returns -EAGAIN, meaning there's nothing | 481 | int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt, |
482 | more to be done */ | 482 | struct autofs_sb_info *sbi, int when) |
483 | int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt, | ||
484 | struct autofs_sb_info *sbi, int __user *arg) | ||
485 | { | 483 | { |
486 | struct dentry *dentry; | 484 | struct dentry *dentry; |
487 | int ret = -EAGAIN; | 485 | int ret = -EAGAIN; |
488 | int do_now = 0; | ||
489 | |||
490 | if (arg && get_user(do_now, arg)) | ||
491 | return -EFAULT; | ||
492 | 486 | ||
493 | if (autofs_type_trigger(sbi->type)) | 487 | if (autofs_type_trigger(sbi->type)) |
494 | dentry = autofs4_expire_direct(sb, mnt, sbi, do_now); | 488 | dentry = autofs4_expire_direct(sb, mnt, sbi, when); |
495 | else | 489 | else |
496 | dentry = autofs4_expire_indirect(sb, mnt, sbi, do_now); | 490 | dentry = autofs4_expire_indirect(sb, mnt, sbi, when); |
497 | 491 | ||
498 | if (dentry) { | 492 | if (dentry) { |
499 | struct autofs_info *ino = autofs4_dentry_ino(dentry); | 493 | struct autofs_info *ino = autofs4_dentry_ino(dentry); |
@@ -516,3 +510,16 @@ int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt, | |||
516 | return ret; | 510 | return ret; |
517 | } | 511 | } |
518 | 512 | ||
513 | /* Call repeatedly until it returns -EAGAIN, meaning there's nothing | ||
514 | more to be done */ | ||
515 | int autofs4_expire_multi(struct super_block *sb, struct vfsmount *mnt, | ||
516 | struct autofs_sb_info *sbi, int __user *arg) | ||
517 | { | ||
518 | int do_now = 0; | ||
519 | |||
520 | if (arg && get_user(do_now, arg)) | ||
521 | return -EFAULT; | ||
522 | |||
523 | return autofs4_do_expire_multi(sb, mnt, sbi, do_now); | ||
524 | } | ||
525 | |||
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 74b1469a950..e383bf0334f 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -485,22 +485,6 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
485 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", | 485 | DPRINTK("pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d", |
486 | current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); | 486 | current->pid, task_pgrp_nr(current), sbi->catatonic, oz_mode); |
487 | 487 | ||
488 | expiring = autofs4_lookup_expiring(sbi, dentry->d_parent, &dentry->d_name); | ||
489 | if (expiring) { | ||
490 | /* | ||
491 | * If we are racing with expire the request might not | ||
492 | * be quite complete but the directory has been removed | ||
493 | * so it must have been successful, so just wait for it. | ||
494 | */ | ||
495 | ino = autofs4_dentry_ino(expiring); | ||
496 | autofs4_expire_wait(expiring); | ||
497 | spin_lock(&sbi->lookup_lock); | ||
498 | if (!list_empty(&ino->expiring)) | ||
499 | list_del_init(&ino->expiring); | ||
500 | spin_unlock(&sbi->lookup_lock); | ||
501 | dput(expiring); | ||
502 | } | ||
503 | |||
504 | unhashed = autofs4_lookup_active(sbi, dentry->d_parent, &dentry->d_name); | 488 | unhashed = autofs4_lookup_active(sbi, dentry->d_parent, &dentry->d_name); |
505 | if (unhashed) | 489 | if (unhashed) |
506 | dentry = unhashed; | 490 | dentry = unhashed; |
@@ -538,14 +522,31 @@ static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, s | |||
538 | } | 522 | } |
539 | 523 | ||
540 | if (!oz_mode) { | 524 | if (!oz_mode) { |
525 | mutex_unlock(&dir->i_mutex); | ||
526 | expiring = autofs4_lookup_expiring(sbi, | ||
527 | dentry->d_parent, | ||
528 | &dentry->d_name); | ||
529 | if (expiring) { | ||
530 | /* | ||
531 | * If we are racing with expire the request might not | ||
532 | * be quite complete but the directory has been removed | ||
533 | * so it must have been successful, so just wait for it. | ||
534 | */ | ||
535 | ino = autofs4_dentry_ino(expiring); | ||
536 | autofs4_expire_wait(expiring); | ||
537 | spin_lock(&sbi->lookup_lock); | ||
538 | if (!list_empty(&ino->expiring)) | ||
539 | list_del_init(&ino->expiring); | ||
540 | spin_unlock(&sbi->lookup_lock); | ||
541 | dput(expiring); | ||
542 | } | ||
543 | |||
541 | spin_lock(&dentry->d_lock); | 544 | spin_lock(&dentry->d_lock); |
542 | dentry->d_flags |= DCACHE_AUTOFS_PENDING; | 545 | dentry->d_flags |= DCACHE_AUTOFS_PENDING; |
543 | spin_unlock(&dentry->d_lock); | 546 | spin_unlock(&dentry->d_lock); |
544 | if (dentry->d_op && dentry->d_op->d_revalidate) { | 547 | if (dentry->d_op && dentry->d_op->d_revalidate) |
545 | mutex_unlock(&dir->i_mutex); | ||
546 | (dentry->d_op->d_revalidate)(dentry, nd); | 548 | (dentry->d_op->d_revalidate)(dentry, nd); |
547 | mutex_lock(&dir->i_mutex); | 549 | mutex_lock(&dir->i_mutex); |
548 | } | ||
549 | } | 550 | } |
550 | 551 | ||
551 | /* | 552 | /* |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 5e1d4e30e9d..7dd1b6d0bf3 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -2060,7 +2060,7 @@ int btrfs_merge_bio_hook(struct page *page, unsigned long offset, | |||
2060 | unsigned long btrfs_force_ra(struct address_space *mapping, | 2060 | unsigned long btrfs_force_ra(struct address_space *mapping, |
2061 | struct file_ra_state *ra, struct file *file, | 2061 | struct file_ra_state *ra, struct file *file, |
2062 | pgoff_t offset, pgoff_t last_index); | 2062 | pgoff_t offset, pgoff_t last_index); |
2063 | int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page); | 2063 | int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); |
2064 | int btrfs_readpage(struct file *file, struct page *page); | 2064 | int btrfs_readpage(struct file *file, struct page *page); |
2065 | void btrfs_delete_inode(struct inode *inode); | 2065 | void btrfs_delete_inode(struct inode *inode); |
2066 | void btrfs_put_inode(struct inode *inode); | 2066 | void btrfs_put_inode(struct inode *inode); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 7d4f948bc22..17e608c4dc7 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -4292,8 +4292,9 @@ static void btrfs_invalidatepage(struct page *page, unsigned long offset) | |||
4292 | * beyond EOF, then the page is guaranteed safe against truncation until we | 4292 | * beyond EOF, then the page is guaranteed safe against truncation until we |
4293 | * unlock the page. | 4293 | * unlock the page. |
4294 | */ | 4294 | */ |
4295 | int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page) | 4295 | int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
4296 | { | 4296 | { |
4297 | struct page *page = vmf->page; | ||
4297 | struct inode *inode = fdentry(vma->vm_file)->d_inode; | 4298 | struct inode *inode = fdentry(vma->vm_file)->d_inode; |
4298 | struct btrfs_root *root = BTRFS_I(inode)->root; | 4299 | struct btrfs_root *root = BTRFS_I(inode)->root; |
4299 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 4300 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
@@ -4306,10 +4307,15 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
4306 | u64 page_end; | 4307 | u64 page_end; |
4307 | 4308 | ||
4308 | ret = btrfs_check_data_free_space(root, inode, PAGE_CACHE_SIZE); | 4309 | ret = btrfs_check_data_free_space(root, inode, PAGE_CACHE_SIZE); |
4309 | if (ret) | 4310 | if (ret) { |
4311 | if (ret == -ENOMEM) | ||
4312 | ret = VM_FAULT_OOM; | ||
4313 | else /* -ENOSPC, -EIO, etc */ | ||
4314 | ret = VM_FAULT_SIGBUS; | ||
4310 | goto out; | 4315 | goto out; |
4316 | } | ||
4311 | 4317 | ||
4312 | ret = -EINVAL; | 4318 | ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */ |
4313 | again: | 4319 | again: |
4314 | lock_page(page); | 4320 | lock_page(page); |
4315 | size = i_size_read(inode); | 4321 | size = i_size_read(inode); |
diff --git a/fs/buffer.c b/fs/buffer.c index a2fd743d97c..f5f8b15a6e4 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -290,7 +290,7 @@ static void free_more_memory(void) | |||
290 | &zone); | 290 | &zone); |
291 | if (zone) | 291 | if (zone) |
292 | try_to_free_pages(node_zonelist(nid, GFP_NOFS), 0, | 292 | try_to_free_pages(node_zonelist(nid, GFP_NOFS), 0, |
293 | GFP_NOFS); | 293 | GFP_NOFS, NULL); |
294 | } | 294 | } |
295 | } | 295 | } |
296 | 296 | ||
@@ -547,6 +547,39 @@ repeat: | |||
547 | return err; | 547 | return err; |
548 | } | 548 | } |
549 | 549 | ||
550 | void do_thaw_all(unsigned long unused) | ||
551 | { | ||
552 | struct super_block *sb; | ||
553 | char b[BDEVNAME_SIZE]; | ||
554 | |||
555 | spin_lock(&sb_lock); | ||
556 | restart: | ||
557 | list_for_each_entry(sb, &super_blocks, s_list) { | ||
558 | sb->s_count++; | ||
559 | spin_unlock(&sb_lock); | ||
560 | down_read(&sb->s_umount); | ||
561 | while (sb->s_bdev && !thaw_bdev(sb->s_bdev, sb)) | ||
562 | printk(KERN_WARNING "Emergency Thaw on %s\n", | ||
563 | bdevname(sb->s_bdev, b)); | ||
564 | up_read(&sb->s_umount); | ||
565 | spin_lock(&sb_lock); | ||
566 | if (__put_super_and_need_restart(sb)) | ||
567 | goto restart; | ||
568 | } | ||
569 | spin_unlock(&sb_lock); | ||
570 | printk(KERN_WARNING "Emergency Thaw complete\n"); | ||
571 | } | ||
572 | |||
573 | /** | ||
574 | * emergency_thaw_all -- forcibly thaw every frozen filesystem | ||
575 | * | ||
576 | * Used for emergency unfreeze of all filesystems via SysRq | ||
577 | */ | ||
578 | void emergency_thaw_all(void) | ||
579 | { | ||
580 | pdflush_operation(do_thaw_all, 0); | ||
581 | } | ||
582 | |||
550 | /** | 583 | /** |
551 | * sync_mapping_buffers - write out & wait upon a mapping's "associated" buffers | 584 | * sync_mapping_buffers - write out & wait upon a mapping's "associated" buffers |
552 | * @mapping: the mapping which wants those buffers written | 585 | * @mapping: the mapping which wants those buffers written |
@@ -621,14 +654,7 @@ static void __set_page_dirty(struct page *page, | |||
621 | spin_lock_irq(&mapping->tree_lock); | 654 | spin_lock_irq(&mapping->tree_lock); |
622 | if (page->mapping) { /* Race with truncate? */ | 655 | if (page->mapping) { /* Race with truncate? */ |
623 | WARN_ON_ONCE(warn && !PageUptodate(page)); | 656 | WARN_ON_ONCE(warn && !PageUptodate(page)); |
624 | 657 | account_page_dirtied(page, mapping); | |
625 | if (mapping_cap_account_dirty(mapping)) { | ||
626 | __inc_zone_page_state(page, NR_FILE_DIRTY); | ||
627 | __inc_bdi_stat(mapping->backing_dev_info, | ||
628 | BDI_RECLAIMABLE); | ||
629 | task_dirty_inc(current); | ||
630 | task_io_account_write(PAGE_CACHE_SIZE); | ||
631 | } | ||
632 | radix_tree_tag_set(&mapping->page_tree, | 658 | radix_tree_tag_set(&mapping->page_tree, |
633 | page_index(page), PAGECACHE_TAG_DIRTY); | 659 | page_index(page), PAGECACHE_TAG_DIRTY); |
634 | } | 660 | } |
@@ -2320,13 +2346,14 @@ int block_commit_write(struct page *page, unsigned from, unsigned to) | |||
2320 | * unlock the page. | 2346 | * unlock the page. |
2321 | */ | 2347 | */ |
2322 | int | 2348 | int |
2323 | block_page_mkwrite(struct vm_area_struct *vma, struct page *page, | 2349 | block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, |
2324 | get_block_t get_block) | 2350 | get_block_t get_block) |
2325 | { | 2351 | { |
2352 | struct page *page = vmf->page; | ||
2326 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; | 2353 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; |
2327 | unsigned long end; | 2354 | unsigned long end; |
2328 | loff_t size; | 2355 | loff_t size; |
2329 | int ret = -EINVAL; | 2356 | int ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */ |
2330 | 2357 | ||
2331 | lock_page(page); | 2358 | lock_page(page); |
2332 | size = i_size_read(inode); | 2359 | size = i_size_read(inode); |
@@ -2346,6 +2373,13 @@ block_page_mkwrite(struct vm_area_struct *vma, struct page *page, | |||
2346 | if (!ret) | 2373 | if (!ret) |
2347 | ret = block_commit_write(page, 0, end); | 2374 | ret = block_commit_write(page, 0, end); |
2348 | 2375 | ||
2376 | if (unlikely(ret)) { | ||
2377 | if (ret == -ENOMEM) | ||
2378 | ret = VM_FAULT_OOM; | ||
2379 | else /* -ENOSPC, -EIO, etc */ | ||
2380 | ret = VM_FAULT_SIGBUS; | ||
2381 | } | ||
2382 | |||
2349 | out_unlock: | 2383 | out_unlock: |
2350 | unlock_page(page); | 2384 | unlock_page(page); |
2351 | return ret; | 2385 | return ret; |
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index e4a6223c314..af737bb56cb 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c | |||
@@ -740,8 +740,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, | |||
740 | out_release_free_unlock: | 740 | out_release_free_unlock: |
741 | crypto_free_hash(s->hash_desc.tfm); | 741 | crypto_free_hash(s->hash_desc.tfm); |
742 | out_free_unlock: | 742 | out_free_unlock: |
743 | memset(s->block_aligned_filename, 0, s->block_aligned_filename_size); | 743 | kzfree(s->block_aligned_filename); |
744 | kfree(s->block_aligned_filename); | ||
745 | out_unlock: | 744 | out_unlock: |
746 | mutex_unlock(s->tfm_mutex); | 745 | mutex_unlock(s->tfm_mutex); |
747 | out: | 746 | out: |
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index 96ef51489e0..295e7fa5675 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c | |||
@@ -291,8 +291,7 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon) | |||
291 | if (daemon->user_ns) | 291 | if (daemon->user_ns) |
292 | put_user_ns(daemon->user_ns); | 292 | put_user_ns(daemon->user_ns); |
293 | mutex_unlock(&daemon->mux); | 293 | mutex_unlock(&daemon->mux); |
294 | memset(daemon, 0, sizeof(*daemon)); | 294 | kzfree(daemon); |
295 | kfree(daemon); | ||
296 | out: | 295 | out: |
297 | return rc; | 296 | return rc; |
298 | } | 297 | } |
diff --git a/fs/eventfd.c b/fs/eventfd.c index 5de2c2db3aa..2a701d593d3 100644 --- a/fs/eventfd.c +++ b/fs/eventfd.c | |||
@@ -28,6 +28,7 @@ struct eventfd_ctx { | |||
28 | * issue a wakeup. | 28 | * issue a wakeup. |
29 | */ | 29 | */ |
30 | __u64 count; | 30 | __u64 count; |
31 | unsigned int flags; | ||
31 | }; | 32 | }; |
32 | 33 | ||
33 | /* | 34 | /* |
@@ -50,7 +51,7 @@ int eventfd_signal(struct file *file, int n) | |||
50 | n = (int) (ULLONG_MAX - ctx->count); | 51 | n = (int) (ULLONG_MAX - ctx->count); |
51 | ctx->count += n; | 52 | ctx->count += n; |
52 | if (waitqueue_active(&ctx->wqh)) | 53 | if (waitqueue_active(&ctx->wqh)) |
53 | wake_up_locked(&ctx->wqh); | 54 | wake_up_locked_poll(&ctx->wqh, POLLIN); |
54 | spin_unlock_irqrestore(&ctx->wqh.lock, flags); | 55 | spin_unlock_irqrestore(&ctx->wqh.lock, flags); |
55 | 56 | ||
56 | return n; | 57 | return n; |
@@ -87,22 +88,20 @@ static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count, | |||
87 | { | 88 | { |
88 | struct eventfd_ctx *ctx = file->private_data; | 89 | struct eventfd_ctx *ctx = file->private_data; |
89 | ssize_t res; | 90 | ssize_t res; |
90 | __u64 ucnt; | 91 | __u64 ucnt = 0; |
91 | DECLARE_WAITQUEUE(wait, current); | 92 | DECLARE_WAITQUEUE(wait, current); |
92 | 93 | ||
93 | if (count < sizeof(ucnt)) | 94 | if (count < sizeof(ucnt)) |
94 | return -EINVAL; | 95 | return -EINVAL; |
95 | spin_lock_irq(&ctx->wqh.lock); | 96 | spin_lock_irq(&ctx->wqh.lock); |
96 | res = -EAGAIN; | 97 | res = -EAGAIN; |
97 | ucnt = ctx->count; | 98 | if (ctx->count > 0) |
98 | if (ucnt > 0) | ||
99 | res = sizeof(ucnt); | 99 | res = sizeof(ucnt); |
100 | else if (!(file->f_flags & O_NONBLOCK)) { | 100 | else if (!(file->f_flags & O_NONBLOCK)) { |
101 | __add_wait_queue(&ctx->wqh, &wait); | 101 | __add_wait_queue(&ctx->wqh, &wait); |
102 | for (res = 0;;) { | 102 | for (res = 0;;) { |
103 | set_current_state(TASK_INTERRUPTIBLE); | 103 | set_current_state(TASK_INTERRUPTIBLE); |
104 | if (ctx->count > 0) { | 104 | if (ctx->count > 0) { |
105 | ucnt = ctx->count; | ||
106 | res = sizeof(ucnt); | 105 | res = sizeof(ucnt); |
107 | break; | 106 | break; |
108 | } | 107 | } |
@@ -117,10 +116,11 @@ static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count, | |||
117 | __remove_wait_queue(&ctx->wqh, &wait); | 116 | __remove_wait_queue(&ctx->wqh, &wait); |
118 | __set_current_state(TASK_RUNNING); | 117 | __set_current_state(TASK_RUNNING); |
119 | } | 118 | } |
120 | if (res > 0) { | 119 | if (likely(res > 0)) { |
121 | ctx->count = 0; | 120 | ucnt = (ctx->flags & EFD_SEMAPHORE) ? 1 : ctx->count; |
121 | ctx->count -= ucnt; | ||
122 | if (waitqueue_active(&ctx->wqh)) | 122 | if (waitqueue_active(&ctx->wqh)) |
123 | wake_up_locked(&ctx->wqh); | 123 | wake_up_locked_poll(&ctx->wqh, POLLOUT); |
124 | } | 124 | } |
125 | spin_unlock_irq(&ctx->wqh.lock); | 125 | spin_unlock_irq(&ctx->wqh.lock); |
126 | if (res > 0 && put_user(ucnt, (__u64 __user *) buf)) | 126 | if (res > 0 && put_user(ucnt, (__u64 __user *) buf)) |
@@ -166,10 +166,10 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c | |||
166 | __remove_wait_queue(&ctx->wqh, &wait); | 166 | __remove_wait_queue(&ctx->wqh, &wait); |
167 | __set_current_state(TASK_RUNNING); | 167 | __set_current_state(TASK_RUNNING); |
168 | } | 168 | } |
169 | if (res > 0) { | 169 | if (likely(res > 0)) { |
170 | ctx->count += ucnt; | 170 | ctx->count += ucnt; |
171 | if (waitqueue_active(&ctx->wqh)) | 171 | if (waitqueue_active(&ctx->wqh)) |
172 | wake_up_locked(&ctx->wqh); | 172 | wake_up_locked_poll(&ctx->wqh, POLLIN); |
173 | } | 173 | } |
174 | spin_unlock_irq(&ctx->wqh.lock); | 174 | spin_unlock_irq(&ctx->wqh.lock); |
175 | 175 | ||
@@ -207,7 +207,7 @@ SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags) | |||
207 | BUILD_BUG_ON(EFD_CLOEXEC != O_CLOEXEC); | 207 | BUILD_BUG_ON(EFD_CLOEXEC != O_CLOEXEC); |
208 | BUILD_BUG_ON(EFD_NONBLOCK != O_NONBLOCK); | 208 | BUILD_BUG_ON(EFD_NONBLOCK != O_NONBLOCK); |
209 | 209 | ||
210 | if (flags & ~(EFD_CLOEXEC | EFD_NONBLOCK)) | 210 | if (flags & ~EFD_FLAGS_SET) |
211 | return -EINVAL; | 211 | return -EINVAL; |
212 | 212 | ||
213 | ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); | 213 | ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); |
@@ -216,13 +216,14 @@ SYSCALL_DEFINE2(eventfd2, unsigned int, count, int, flags) | |||
216 | 216 | ||
217 | init_waitqueue_head(&ctx->wqh); | 217 | init_waitqueue_head(&ctx->wqh); |
218 | ctx->count = count; | 218 | ctx->count = count; |
219 | ctx->flags = flags; | ||
219 | 220 | ||
220 | /* | 221 | /* |
221 | * When we call this, the initialization must be complete, since | 222 | * When we call this, the initialization must be complete, since |
222 | * anon_inode_getfd() will install the fd. | 223 | * anon_inode_getfd() will install the fd. |
223 | */ | 224 | */ |
224 | fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx, | 225 | fd = anon_inode_getfd("[eventfd]", &eventfd_fops, ctx, |
225 | flags & (O_CLOEXEC | O_NONBLOCK)); | 226 | flags & EFD_SHARED_FCNTL_FLAGS); |
226 | if (fd < 0) | 227 | if (fd < 0) |
227 | kfree(ctx); | 228 | kfree(ctx); |
228 | return fd; | 229 | return fd; |
@@ -232,3 +233,4 @@ SYSCALL_DEFINE1(eventfd, unsigned int, count) | |||
232 | { | 233 | { |
233 | return sys_eventfd2(count, 0); | 234 | return sys_eventfd2(count, 0); |
234 | } | 235 | } |
236 | |||
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index c5c424f23fd..a89f370fadb 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * fs/eventpoll.c (Efficent event polling implementation) | 2 | * fs/eventpoll.c (Efficient event retrieval implementation) |
3 | * Copyright (C) 2001,...,2007 Davide Libenzi | 3 | * Copyright (C) 2001,...,2009 Davide Libenzi |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -71,29 +71,11 @@ | |||
71 | * a better scalability. | 71 | * a better scalability. |
72 | */ | 72 | */ |
73 | 73 | ||
74 | #define DEBUG_EPOLL 0 | ||
75 | |||
76 | #if DEBUG_EPOLL > 0 | ||
77 | #define DPRINTK(x) printk x | ||
78 | #define DNPRINTK(n, x) do { if ((n) <= DEBUG_EPOLL) printk x; } while (0) | ||
79 | #else /* #if DEBUG_EPOLL > 0 */ | ||
80 | #define DPRINTK(x) (void) 0 | ||
81 | #define DNPRINTK(n, x) (void) 0 | ||
82 | #endif /* #if DEBUG_EPOLL > 0 */ | ||
83 | |||
84 | #define DEBUG_EPI 0 | ||
85 | |||
86 | #if DEBUG_EPI != 0 | ||
87 | #define EPI_SLAB_DEBUG (SLAB_DEBUG_FREE | SLAB_RED_ZONE /* | SLAB_POISON */) | ||
88 | #else /* #if DEBUG_EPI != 0 */ | ||
89 | #define EPI_SLAB_DEBUG 0 | ||
90 | #endif /* #if DEBUG_EPI != 0 */ | ||
91 | |||
92 | /* Epoll private bits inside the event mask */ | 74 | /* Epoll private bits inside the event mask */ |
93 | #define EP_PRIVATE_BITS (EPOLLONESHOT | EPOLLET) | 75 | #define EP_PRIVATE_BITS (EPOLLONESHOT | EPOLLET) |
94 | 76 | ||
95 | /* Maximum number of poll wake up nests we are allowing */ | 77 | /* Maximum number of nesting allowed inside epoll sets */ |
96 | #define EP_MAX_POLLWAKE_NESTS 4 | 78 | #define EP_MAX_NESTS 4 |
97 | 79 | ||
98 | /* Maximum msec timeout value storeable in a long int */ | 80 | /* Maximum msec timeout value storeable in a long int */ |
99 | #define EP_MAX_MSTIMEO min(1000ULL * MAX_SCHEDULE_TIMEOUT / HZ, (LONG_MAX - 999ULL) / HZ) | 81 | #define EP_MAX_MSTIMEO min(1000ULL * MAX_SCHEDULE_TIMEOUT / HZ, (LONG_MAX - 999ULL) / HZ) |
@@ -110,24 +92,21 @@ struct epoll_filefd { | |||
110 | }; | 92 | }; |
111 | 93 | ||
112 | /* | 94 | /* |
113 | * Node that is linked into the "wake_task_list" member of the "struct poll_safewake". | 95 | * Structure used to track possible nested calls, for too deep recursions |
114 | * It is used to keep track on all tasks that are currently inside the wake_up() code | 96 | * and loop cycles. |
115 | * to 1) short-circuit the one coming from the same task and same wait queue head | ||
116 | * (loop) 2) allow a maximum number of epoll descriptors inclusion nesting | ||
117 | * 3) let go the ones coming from other tasks. | ||
118 | */ | 97 | */ |
119 | struct wake_task_node { | 98 | struct nested_call_node { |
120 | struct list_head llink; | 99 | struct list_head llink; |
121 | struct task_struct *task; | 100 | void *cookie; |
122 | wait_queue_head_t *wq; | 101 | int cpu; |
123 | }; | 102 | }; |
124 | 103 | ||
125 | /* | 104 | /* |
126 | * This is used to implement the safe poll wake up avoiding to reenter | 105 | * This structure is used as collector for nested calls, to check for |
127 | * the poll callback from inside wake_up(). | 106 | * maximum recursion dept and loop cycles. |
128 | */ | 107 | */ |
129 | struct poll_safewake { | 108 | struct nested_calls { |
130 | struct list_head wake_task_list; | 109 | struct list_head tasks_call_list; |
131 | spinlock_t lock; | 110 | spinlock_t lock; |
132 | }; | 111 | }; |
133 | 112 | ||
@@ -213,7 +192,7 @@ struct eppoll_entry { | |||
213 | struct list_head llink; | 192 | struct list_head llink; |
214 | 193 | ||
215 | /* The "base" pointer is set to the container "struct epitem" */ | 194 | /* The "base" pointer is set to the container "struct epitem" */ |
216 | void *base; | 195 | struct epitem *base; |
217 | 196 | ||
218 | /* | 197 | /* |
219 | * Wait queue item that will be linked to the target file wait | 198 | * Wait queue item that will be linked to the target file wait |
@@ -231,6 +210,12 @@ struct ep_pqueue { | |||
231 | struct epitem *epi; | 210 | struct epitem *epi; |
232 | }; | 211 | }; |
233 | 212 | ||
213 | /* Used by the ep_send_events() function as callback private data */ | ||
214 | struct ep_send_events_data { | ||
215 | int maxevents; | ||
216 | struct epoll_event __user *events; | ||
217 | }; | ||
218 | |||
234 | /* | 219 | /* |
235 | * Configuration options available inside /proc/sys/fs/epoll/ | 220 | * Configuration options available inside /proc/sys/fs/epoll/ |
236 | */ | 221 | */ |
@@ -242,8 +227,11 @@ static int max_user_watches __read_mostly; | |||
242 | */ | 227 | */ |
243 | static DEFINE_MUTEX(epmutex); | 228 | static DEFINE_MUTEX(epmutex); |
244 | 229 | ||
245 | /* Safe wake up implementation */ | 230 | /* Used for safe wake up implementation */ |
246 | static struct poll_safewake psw; | 231 | static struct nested_calls poll_safewake_ncalls; |
232 | |||
233 | /* Used to call file's f_op->poll() under the nested calls boundaries */ | ||
234 | static struct nested_calls poll_readywalk_ncalls; | ||
247 | 235 | ||
248 | /* Slab cache used to allocate "struct epitem" */ | 236 | /* Slab cache used to allocate "struct epitem" */ |
249 | static struct kmem_cache *epi_cache __read_mostly; | 237 | static struct kmem_cache *epi_cache __read_mostly; |
@@ -312,89 +300,230 @@ static inline int ep_op_has_event(int op) | |||
312 | } | 300 | } |
313 | 301 | ||
314 | /* Initialize the poll safe wake up structure */ | 302 | /* Initialize the poll safe wake up structure */ |
315 | static void ep_poll_safewake_init(struct poll_safewake *psw) | 303 | static void ep_nested_calls_init(struct nested_calls *ncalls) |
316 | { | 304 | { |
317 | 305 | INIT_LIST_HEAD(&ncalls->tasks_call_list); | |
318 | INIT_LIST_HEAD(&psw->wake_task_list); | 306 | spin_lock_init(&ncalls->lock); |
319 | spin_lock_init(&psw->lock); | ||
320 | } | 307 | } |
321 | 308 | ||
322 | /* | 309 | /** |
323 | * Perform a safe wake up of the poll wait list. The problem is that | 310 | * ep_call_nested - Perform a bound (possibly) nested call, by checking |
324 | * with the new callback'd wake up system, it is possible that the | 311 | * that the recursion limit is not exceeded, and that |
325 | * poll callback is reentered from inside the call to wake_up() done | 312 | * the same nested call (by the meaning of same cookie) is |
326 | * on the poll wait queue head. The rule is that we cannot reenter the | 313 | * no re-entered. |
327 | * wake up code from the same task more than EP_MAX_POLLWAKE_NESTS times, | 314 | * |
328 | * and we cannot reenter the same wait queue head at all. This will | 315 | * @ncalls: Pointer to the nested_calls structure to be used for this call. |
329 | * enable to have a hierarchy of epoll file descriptor of no more than | 316 | * @max_nests: Maximum number of allowed nesting calls. |
330 | * EP_MAX_POLLWAKE_NESTS deep. We need the irq version of the spin lock | 317 | * @nproc: Nested call core function pointer. |
331 | * because this one gets called by the poll callback, that in turn is called | 318 | * @priv: Opaque data to be passed to the @nproc callback. |
332 | * from inside a wake_up(), that might be called from irq context. | 319 | * @cookie: Cookie to be used to identify this nested call. |
320 | * | ||
321 | * Returns: Returns the code returned by the @nproc callback, or -1 if | ||
322 | * the maximum recursion limit has been exceeded. | ||
333 | */ | 323 | */ |
334 | static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq) | 324 | static int ep_call_nested(struct nested_calls *ncalls, int max_nests, |
325 | int (*nproc)(void *, void *, int), void *priv, | ||
326 | void *cookie) | ||
335 | { | 327 | { |
336 | int wake_nests = 0; | 328 | int error, call_nests = 0; |
337 | unsigned long flags; | 329 | unsigned long flags; |
338 | struct task_struct *this_task = current; | 330 | int this_cpu = get_cpu(); |
339 | struct list_head *lsthead = &psw->wake_task_list; | 331 | struct list_head *lsthead = &ncalls->tasks_call_list; |
340 | struct wake_task_node *tncur; | 332 | struct nested_call_node *tncur; |
341 | struct wake_task_node tnode; | 333 | struct nested_call_node tnode; |
342 | 334 | ||
343 | spin_lock_irqsave(&psw->lock, flags); | 335 | spin_lock_irqsave(&ncalls->lock, flags); |
344 | 336 | ||
345 | /* Try to see if the current task is already inside this wakeup call */ | 337 | /* |
338 | * Try to see if the current task is already inside this wakeup call. | ||
339 | * We use a list here, since the population inside this set is always | ||
340 | * very much limited. | ||
341 | */ | ||
346 | list_for_each_entry(tncur, lsthead, llink) { | 342 | list_for_each_entry(tncur, lsthead, llink) { |
347 | 343 | if (tncur->cpu == this_cpu && | |
348 | if (tncur->wq == wq || | 344 | (tncur->cookie == cookie || ++call_nests > max_nests)) { |
349 | (tncur->task == this_task && ++wake_nests > EP_MAX_POLLWAKE_NESTS)) { | ||
350 | /* | 345 | /* |
351 | * Ops ... loop detected or maximum nest level reached. | 346 | * Ops ... loop detected or maximum nest level reached. |
352 | * We abort this wake by breaking the cycle itself. | 347 | * We abort this wake by breaking the cycle itself. |
353 | */ | 348 | */ |
354 | spin_unlock_irqrestore(&psw->lock, flags); | 349 | error = -1; |
355 | return; | 350 | goto out_unlock; |
356 | } | 351 | } |
357 | } | 352 | } |
358 | 353 | ||
359 | /* Add the current task to the list */ | 354 | /* Add the current task and cookie to the list */ |
360 | tnode.task = this_task; | 355 | tnode.cpu = this_cpu; |
361 | tnode.wq = wq; | 356 | tnode.cookie = cookie; |
362 | list_add(&tnode.llink, lsthead); | 357 | list_add(&tnode.llink, lsthead); |
363 | 358 | ||
364 | spin_unlock_irqrestore(&psw->lock, flags); | 359 | spin_unlock_irqrestore(&ncalls->lock, flags); |
365 | 360 | ||
366 | /* Do really wake up now */ | 361 | /* Call the nested function */ |
367 | wake_up_nested(wq, 1 + wake_nests); | 362 | error = (*nproc)(priv, cookie, call_nests); |
368 | 363 | ||
369 | /* Remove the current task from the list */ | 364 | /* Remove the current task from the list */ |
370 | spin_lock_irqsave(&psw->lock, flags); | 365 | spin_lock_irqsave(&ncalls->lock, flags); |
371 | list_del(&tnode.llink); | 366 | list_del(&tnode.llink); |
372 | spin_unlock_irqrestore(&psw->lock, flags); | 367 | out_unlock: |
368 | spin_unlock_irqrestore(&ncalls->lock, flags); | ||
369 | |||
370 | put_cpu(); | ||
371 | return error; | ||
372 | } | ||
373 | |||
374 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
375 | static inline void ep_wake_up_nested(wait_queue_head_t *wqueue, | ||
376 | unsigned long events, int subclass) | ||
377 | { | ||
378 | unsigned long flags; | ||
379 | |||
380 | spin_lock_irqsave_nested(&wqueue->lock, flags, subclass); | ||
381 | wake_up_locked_poll(wqueue, events); | ||
382 | spin_unlock_irqrestore(&wqueue->lock, flags); | ||
383 | } | ||
384 | #else | ||
385 | static inline void ep_wake_up_nested(wait_queue_head_t *wqueue, | ||
386 | unsigned long events, int subclass) | ||
387 | { | ||
388 | wake_up_poll(wqueue, events); | ||
389 | } | ||
390 | #endif | ||
391 | |||
392 | static int ep_poll_wakeup_proc(void *priv, void *cookie, int call_nests) | ||
393 | { | ||
394 | ep_wake_up_nested((wait_queue_head_t *) cookie, POLLIN, | ||
395 | 1 + call_nests); | ||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | /* | ||
400 | * Perform a safe wake up of the poll wait list. The problem is that | ||
401 | * with the new callback'd wake up system, it is possible that the | ||
402 | * poll callback is reentered from inside the call to wake_up() done | ||
403 | * on the poll wait queue head. The rule is that we cannot reenter the | ||
404 | * wake up code from the same task more than EP_MAX_NESTS times, | ||
405 | * and we cannot reenter the same wait queue head at all. This will | ||
406 | * enable to have a hierarchy of epoll file descriptor of no more than | ||
407 | * EP_MAX_NESTS deep. | ||
408 | */ | ||
409 | static void ep_poll_safewake(wait_queue_head_t *wq) | ||
410 | { | ||
411 | ep_call_nested(&poll_safewake_ncalls, EP_MAX_NESTS, | ||
412 | ep_poll_wakeup_proc, NULL, wq); | ||
373 | } | 413 | } |
374 | 414 | ||
375 | /* | 415 | /* |
376 | * This function unregister poll callbacks from the associated file descriptor. | 416 | * This function unregisters poll callbacks from the associated file |
377 | * Since this must be called without holding "ep->lock" the atomic exchange trick | 417 | * descriptor. Must be called with "mtx" held (or "epmutex" if called from |
378 | * will protect us from multiple unregister. | 418 | * ep_free). |
379 | */ | 419 | */ |
380 | static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi) | 420 | static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi) |
381 | { | 421 | { |
382 | int nwait; | ||
383 | struct list_head *lsthead = &epi->pwqlist; | 422 | struct list_head *lsthead = &epi->pwqlist; |
384 | struct eppoll_entry *pwq; | 423 | struct eppoll_entry *pwq; |
385 | 424 | ||
386 | /* This is called without locks, so we need the atomic exchange */ | 425 | while (!list_empty(lsthead)) { |
387 | nwait = xchg(&epi->nwait, 0); | 426 | pwq = list_first_entry(lsthead, struct eppoll_entry, llink); |
388 | 427 | ||
389 | if (nwait) { | 428 | list_del(&pwq->llink); |
390 | while (!list_empty(lsthead)) { | 429 | remove_wait_queue(pwq->whead, &pwq->wait); |
391 | pwq = list_first_entry(lsthead, struct eppoll_entry, llink); | 430 | kmem_cache_free(pwq_cache, pwq); |
431 | } | ||
432 | } | ||
392 | 433 | ||
393 | list_del_init(&pwq->llink); | 434 | /** |
394 | remove_wait_queue(pwq->whead, &pwq->wait); | 435 | * ep_scan_ready_list - Scans the ready list in a way that makes possible for |
395 | kmem_cache_free(pwq_cache, pwq); | 436 | * the scan code, to call f_op->poll(). Also allows for |
396 | } | 437 | * O(NumReady) performance. |
438 | * | ||
439 | * @ep: Pointer to the epoll private data structure. | ||
440 | * @sproc: Pointer to the scan callback. | ||
441 | * @priv: Private opaque data passed to the @sproc callback. | ||
442 | * | ||
443 | * Returns: The same integer error code returned by the @sproc callback. | ||
444 | */ | ||
445 | static int ep_scan_ready_list(struct eventpoll *ep, | ||
446 | int (*sproc)(struct eventpoll *, | ||
447 | struct list_head *, void *), | ||
448 | void *priv) | ||
449 | { | ||
450 | int error, pwake = 0; | ||
451 | unsigned long flags; | ||
452 | struct epitem *epi, *nepi; | ||
453 | LIST_HEAD(txlist); | ||
454 | |||
455 | /* | ||
456 | * We need to lock this because we could be hit by | ||
457 | * eventpoll_release_file() and epoll_ctl(). | ||
458 | */ | ||
459 | mutex_lock(&ep->mtx); | ||
460 | |||
461 | /* | ||
462 | * Steal the ready list, and re-init the original one to the | ||
463 | * empty list. Also, set ep->ovflist to NULL so that events | ||
464 | * happening while looping w/out locks, are not lost. We cannot | ||
465 | * have the poll callback to queue directly on ep->rdllist, | ||
466 | * because we want the "sproc" callback to be able to do it | ||
467 | * in a lockless way. | ||
468 | */ | ||
469 | spin_lock_irqsave(&ep->lock, flags); | ||
470 | list_splice_init(&ep->rdllist, &txlist); | ||
471 | ep->ovflist = NULL; | ||
472 | spin_unlock_irqrestore(&ep->lock, flags); | ||
473 | |||
474 | /* | ||
475 | * Now call the callback function. | ||
476 | */ | ||
477 | error = (*sproc)(ep, &txlist, priv); | ||
478 | |||
479 | spin_lock_irqsave(&ep->lock, flags); | ||
480 | /* | ||
481 | * During the time we spent inside the "sproc" callback, some | ||
482 | * other events might have been queued by the poll callback. | ||
483 | * We re-insert them inside the main ready-list here. | ||
484 | */ | ||
485 | for (nepi = ep->ovflist; (epi = nepi) != NULL; | ||
486 | nepi = epi->next, epi->next = EP_UNACTIVE_PTR) { | ||
487 | /* | ||
488 | * We need to check if the item is already in the list. | ||
489 | * During the "sproc" callback execution time, items are | ||
490 | * queued into ->ovflist but the "txlist" might already | ||
491 | * contain them, and the list_splice() below takes care of them. | ||
492 | */ | ||
493 | if (!ep_is_linked(&epi->rdllink)) | ||
494 | list_add_tail(&epi->rdllink, &ep->rdllist); | ||
495 | } | ||
496 | /* | ||
497 | * We need to set back ep->ovflist to EP_UNACTIVE_PTR, so that after | ||
498 | * releasing the lock, events will be queued in the normal way inside | ||
499 | * ep->rdllist. | ||
500 | */ | ||
501 | ep->ovflist = EP_UNACTIVE_PTR; | ||
502 | |||
503 | /* | ||
504 | * Quickly re-inject items left on "txlist". | ||
505 | */ | ||
506 | list_splice(&txlist, &ep->rdllist); | ||
507 | |||
508 | if (!list_empty(&ep->rdllist)) { | ||
509 | /* | ||
510 | * Wake up (if active) both the eventpoll wait list and | ||
511 | * the ->poll() wait list (delayed after we release the lock). | ||
512 | */ | ||
513 | if (waitqueue_active(&ep->wq)) | ||
514 | wake_up_locked(&ep->wq); | ||
515 | if (waitqueue_active(&ep->poll_wait)) | ||
516 | pwake++; | ||
397 | } | 517 | } |
518 | spin_unlock_irqrestore(&ep->lock, flags); | ||
519 | |||
520 | mutex_unlock(&ep->mtx); | ||
521 | |||
522 | /* We have to call this outside the lock */ | ||
523 | if (pwake) | ||
524 | ep_poll_safewake(&ep->poll_wait); | ||
525 | |||
526 | return error; | ||
398 | } | 527 | } |
399 | 528 | ||
400 | /* | 529 | /* |
@@ -434,9 +563,6 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi) | |||
434 | 563 | ||
435 | atomic_dec(&ep->user->epoll_watches); | 564 | atomic_dec(&ep->user->epoll_watches); |
436 | 565 | ||
437 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_remove(%p, %p)\n", | ||
438 | current, ep, file)); | ||
439 | |||
440 | return 0; | 566 | return 0; |
441 | } | 567 | } |
442 | 568 | ||
@@ -447,7 +573,7 @@ static void ep_free(struct eventpoll *ep) | |||
447 | 573 | ||
448 | /* We need to release all tasks waiting for these file */ | 574 | /* We need to release all tasks waiting for these file */ |
449 | if (waitqueue_active(&ep->poll_wait)) | 575 | if (waitqueue_active(&ep->poll_wait)) |
450 | ep_poll_safewake(&psw, &ep->poll_wait); | 576 | ep_poll_safewake(&ep->poll_wait); |
451 | 577 | ||
452 | /* | 578 | /* |
453 | * We need to lock this because we could be hit by | 579 | * We need to lock this because we could be hit by |
@@ -492,26 +618,54 @@ static int ep_eventpoll_release(struct inode *inode, struct file *file) | |||
492 | if (ep) | 618 | if (ep) |
493 | ep_free(ep); | 619 | ep_free(ep); |
494 | 620 | ||
495 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: close() ep=%p\n", current, ep)); | ||
496 | return 0; | 621 | return 0; |
497 | } | 622 | } |
498 | 623 | ||
624 | static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head, | ||
625 | void *priv) | ||
626 | { | ||
627 | struct epitem *epi, *tmp; | ||
628 | |||
629 | list_for_each_entry_safe(epi, tmp, head, rdllink) { | ||
630 | if (epi->ffd.file->f_op->poll(epi->ffd.file, NULL) & | ||
631 | epi->event.events) | ||
632 | return POLLIN | POLLRDNORM; | ||
633 | else { | ||
634 | /* | ||
635 | * Item has been dropped into the ready list by the poll | ||
636 | * callback, but it's not actually ready, as far as | ||
637 | * caller requested events goes. We can remove it here. | ||
638 | */ | ||
639 | list_del_init(&epi->rdllink); | ||
640 | } | ||
641 | } | ||
642 | |||
643 | return 0; | ||
644 | } | ||
645 | |||
646 | static int ep_poll_readyevents_proc(void *priv, void *cookie, int call_nests) | ||
647 | { | ||
648 | return ep_scan_ready_list(priv, ep_read_events_proc, NULL); | ||
649 | } | ||
650 | |||
499 | static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait) | 651 | static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait) |
500 | { | 652 | { |
501 | unsigned int pollflags = 0; | 653 | int pollflags; |
502 | unsigned long flags; | ||
503 | struct eventpoll *ep = file->private_data; | 654 | struct eventpoll *ep = file->private_data; |
504 | 655 | ||
505 | /* Insert inside our poll wait queue */ | 656 | /* Insert inside our poll wait queue */ |
506 | poll_wait(file, &ep->poll_wait, wait); | 657 | poll_wait(file, &ep->poll_wait, wait); |
507 | 658 | ||
508 | /* Check our condition */ | 659 | /* |
509 | spin_lock_irqsave(&ep->lock, flags); | 660 | * Proceed to find out if wanted events are really available inside |
510 | if (!list_empty(&ep->rdllist)) | 661 | * the ready list. This need to be done under ep_call_nested() |
511 | pollflags = POLLIN | POLLRDNORM; | 662 | * supervision, since the call to f_op->poll() done on listed files |
512 | spin_unlock_irqrestore(&ep->lock, flags); | 663 | * could re-enter here. |
664 | */ | ||
665 | pollflags = ep_call_nested(&poll_readywalk_ncalls, EP_MAX_NESTS, | ||
666 | ep_poll_readyevents_proc, ep, ep); | ||
513 | 667 | ||
514 | return pollflags; | 668 | return pollflags != -1 ? pollflags : 0; |
515 | } | 669 | } |
516 | 670 | ||
517 | /* File callbacks that implement the eventpoll file behaviour */ | 671 | /* File callbacks that implement the eventpoll file behaviour */ |
@@ -541,7 +695,7 @@ void eventpoll_release_file(struct file *file) | |||
541 | * We don't want to get "file->f_lock" because it is not | 695 | * We don't want to get "file->f_lock" because it is not |
542 | * necessary. It is not necessary because we're in the "struct file" | 696 | * necessary. It is not necessary because we're in the "struct file" |
543 | * cleanup path, and this means that noone is using this file anymore. | 697 | * cleanup path, and this means that noone is using this file anymore. |
544 | * So, for example, epoll_ctl() cannot hit here sicne if we reach this | 698 | * So, for example, epoll_ctl() cannot hit here since if we reach this |
545 | * point, the file counter already went to zero and fget() would fail. | 699 | * point, the file counter already went to zero and fget() would fail. |
546 | * The only hit might come from ep_free() but by holding the mutex | 700 | * The only hit might come from ep_free() but by holding the mutex |
547 | * will correctly serialize the operation. We do need to acquire | 701 | * will correctly serialize the operation. We do need to acquire |
@@ -588,8 +742,6 @@ static int ep_alloc(struct eventpoll **pep) | |||
588 | 742 | ||
589 | *pep = ep; | 743 | *pep = ep; |
590 | 744 | ||
591 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_alloc() ep=%p\n", | ||
592 | current, ep)); | ||
593 | return 0; | 745 | return 0; |
594 | 746 | ||
595 | free_uid: | 747 | free_uid: |
@@ -623,9 +775,6 @@ static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd) | |||
623 | } | 775 | } |
624 | } | 776 | } |
625 | 777 | ||
626 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_find(%p) -> %p\n", | ||
627 | current, file, epir)); | ||
628 | |||
629 | return epir; | 778 | return epir; |
630 | } | 779 | } |
631 | 780 | ||
@@ -641,9 +790,6 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k | |||
641 | struct epitem *epi = ep_item_from_wait(wait); | 790 | struct epitem *epi = ep_item_from_wait(wait); |
642 | struct eventpoll *ep = epi->ep; | 791 | struct eventpoll *ep = epi->ep; |
643 | 792 | ||
644 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: poll_callback(%p) epi=%p ep=%p\n", | ||
645 | current, epi->ffd.file, epi, ep)); | ||
646 | |||
647 | spin_lock_irqsave(&ep->lock, flags); | 793 | spin_lock_irqsave(&ep->lock, flags); |
648 | 794 | ||
649 | /* | 795 | /* |
@@ -656,6 +802,15 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k | |||
656 | goto out_unlock; | 802 | goto out_unlock; |
657 | 803 | ||
658 | /* | 804 | /* |
805 | * Check the events coming with the callback. At this stage, not | ||
806 | * every device reports the events in the "key" parameter of the | ||
807 | * callback. We need to be able to handle both cases here, hence the | ||
808 | * test for "key" != NULL before the event match test. | ||
809 | */ | ||
810 | if (key && !((unsigned long) key & epi->event.events)) | ||
811 | goto out_unlock; | ||
812 | |||
813 | /* | ||
659 | * If we are trasfering events to userspace, we can hold no locks | 814 | * If we are trasfering events to userspace, we can hold no locks |
660 | * (because we're accessing user memory, and because of linux f_op->poll() | 815 | * (because we're accessing user memory, and because of linux f_op->poll() |
661 | * semantics). All the events that happens during that period of time are | 816 | * semantics). All the events that happens during that period of time are |
@@ -670,12 +825,9 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k | |||
670 | } | 825 | } |
671 | 826 | ||
672 | /* If this file is already in the ready list we exit soon */ | 827 | /* If this file is already in the ready list we exit soon */ |
673 | if (ep_is_linked(&epi->rdllink)) | 828 | if (!ep_is_linked(&epi->rdllink)) |
674 | goto is_linked; | 829 | list_add_tail(&epi->rdllink, &ep->rdllist); |
675 | |||
676 | list_add_tail(&epi->rdllink, &ep->rdllist); | ||
677 | 830 | ||
678 | is_linked: | ||
679 | /* | 831 | /* |
680 | * Wake up ( if active ) both the eventpoll wait list and the ->poll() | 832 | * Wake up ( if active ) both the eventpoll wait list and the ->poll() |
681 | * wait list. | 833 | * wait list. |
@@ -690,7 +842,7 @@ out_unlock: | |||
690 | 842 | ||
691 | /* We have to call this outside the lock */ | 843 | /* We have to call this outside the lock */ |
692 | if (pwake) | 844 | if (pwake) |
693 | ep_poll_safewake(&psw, &ep->poll_wait); | 845 | ep_poll_safewake(&ep->poll_wait); |
694 | 846 | ||
695 | return 1; | 847 | return 1; |
696 | } | 848 | } |
@@ -817,10 +969,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, | |||
817 | 969 | ||
818 | /* We have to call this outside the lock */ | 970 | /* We have to call this outside the lock */ |
819 | if (pwake) | 971 | if (pwake) |
820 | ep_poll_safewake(&psw, &ep->poll_wait); | 972 | ep_poll_safewake(&ep->poll_wait); |
821 | |||
822 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_insert(%p, %p, %d)\n", | ||
823 | current, ep, tfile, fd)); | ||
824 | 973 | ||
825 | return 0; | 974 | return 0; |
826 | 975 | ||
@@ -851,15 +1000,14 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even | |||
851 | { | 1000 | { |
852 | int pwake = 0; | 1001 | int pwake = 0; |
853 | unsigned int revents; | 1002 | unsigned int revents; |
854 | unsigned long flags; | ||
855 | 1003 | ||
856 | /* | 1004 | /* |
857 | * Set the new event interest mask before calling f_op->poll(), otherwise | 1005 | * Set the new event interest mask before calling f_op->poll(); |
858 | * a potential race might occur. In fact if we do this operation inside | 1006 | * otherwise we might miss an event that happens between the |
859 | * the lock, an event might happen between the f_op->poll() call and the | 1007 | * f_op->poll() call and the new event set registering. |
860 | * new event set registering. | ||
861 | */ | 1008 | */ |
862 | epi->event.events = event->events; | 1009 | epi->event.events = event->events; |
1010 | epi->event.data = event->data; /* protected by mtx */ | ||
863 | 1011 | ||
864 | /* | 1012 | /* |
865 | * Get current event bits. We can safely use the file* here because | 1013 | * Get current event bits. We can safely use the file* here because |
@@ -867,16 +1015,12 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even | |||
867 | */ | 1015 | */ |
868 | revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL); | 1016 | revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL); |
869 | 1017 | ||
870 | spin_lock_irqsave(&ep->lock, flags); | ||
871 | |||
872 | /* Copy the data member from inside the lock */ | ||
873 | epi->event.data = event->data; | ||
874 | |||
875 | /* | 1018 | /* |
876 | * If the item is "hot" and it is not registered inside the ready | 1019 | * If the item is "hot" and it is not registered inside the ready |
877 | * list, push it inside. | 1020 | * list, push it inside. |
878 | */ | 1021 | */ |
879 | if (revents & event->events) { | 1022 | if (revents & event->events) { |
1023 | spin_lock_irq(&ep->lock); | ||
880 | if (!ep_is_linked(&epi->rdllink)) { | 1024 | if (!ep_is_linked(&epi->rdllink)) { |
881 | list_add_tail(&epi->rdllink, &ep->rdllist); | 1025 | list_add_tail(&epi->rdllink, &ep->rdllist); |
882 | 1026 | ||
@@ -886,142 +1030,84 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even | |||
886 | if (waitqueue_active(&ep->poll_wait)) | 1030 | if (waitqueue_active(&ep->poll_wait)) |
887 | pwake++; | 1031 | pwake++; |
888 | } | 1032 | } |
1033 | spin_unlock_irq(&ep->lock); | ||
889 | } | 1034 | } |
890 | spin_unlock_irqrestore(&ep->lock, flags); | ||
891 | 1035 | ||
892 | /* We have to call this outside the lock */ | 1036 | /* We have to call this outside the lock */ |
893 | if (pwake) | 1037 | if (pwake) |
894 | ep_poll_safewake(&psw, &ep->poll_wait); | 1038 | ep_poll_safewake(&ep->poll_wait); |
895 | 1039 | ||
896 | return 0; | 1040 | return 0; |
897 | } | 1041 | } |
898 | 1042 | ||
899 | static int ep_send_events(struct eventpoll *ep, struct epoll_event __user *events, | 1043 | static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head, |
900 | int maxevents) | 1044 | void *priv) |
901 | { | 1045 | { |
902 | int eventcnt, error = -EFAULT, pwake = 0; | 1046 | struct ep_send_events_data *esed = priv; |
1047 | int eventcnt; | ||
903 | unsigned int revents; | 1048 | unsigned int revents; |
904 | unsigned long flags; | 1049 | struct epitem *epi; |
905 | struct epitem *epi, *nepi; | 1050 | struct epoll_event __user *uevent; |
906 | struct list_head txlist; | ||
907 | |||
908 | INIT_LIST_HEAD(&txlist); | ||
909 | |||
910 | /* | ||
911 | * We need to lock this because we could be hit by | ||
912 | * eventpoll_release_file() and epoll_ctl(EPOLL_CTL_DEL). | ||
913 | */ | ||
914 | mutex_lock(&ep->mtx); | ||
915 | |||
916 | /* | ||
917 | * Steal the ready list, and re-init the original one to the | ||
918 | * empty list. Also, set ep->ovflist to NULL so that events | ||
919 | * happening while looping w/out locks, are not lost. We cannot | ||
920 | * have the poll callback to queue directly on ep->rdllist, | ||
921 | * because we are doing it in the loop below, in a lockless way. | ||
922 | */ | ||
923 | spin_lock_irqsave(&ep->lock, flags); | ||
924 | list_splice(&ep->rdllist, &txlist); | ||
925 | INIT_LIST_HEAD(&ep->rdllist); | ||
926 | ep->ovflist = NULL; | ||
927 | spin_unlock_irqrestore(&ep->lock, flags); | ||
928 | 1051 | ||
929 | /* | 1052 | /* |
930 | * We can loop without lock because this is a task private list. | 1053 | * We can loop without lock because we are passed a task private list. |
931 | * We just splice'd out the ep->rdllist in ep_collect_ready_items(). | 1054 | * Items cannot vanish during the loop because ep_scan_ready_list() is |
932 | * Items cannot vanish during the loop because we are holding "mtx". | 1055 | * holding "mtx" during this call. |
933 | */ | 1056 | */ |
934 | for (eventcnt = 0; !list_empty(&txlist) && eventcnt < maxevents;) { | 1057 | for (eventcnt = 0, uevent = esed->events; |
935 | epi = list_first_entry(&txlist, struct epitem, rdllink); | 1058 | !list_empty(head) && eventcnt < esed->maxevents;) { |
1059 | epi = list_first_entry(head, struct epitem, rdllink); | ||
936 | 1060 | ||
937 | list_del_init(&epi->rdllink); | 1061 | list_del_init(&epi->rdllink); |
938 | 1062 | ||
939 | /* | 1063 | revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL) & |
940 | * Get the ready file event set. We can safely use the file | 1064 | epi->event.events; |
941 | * because we are holding the "mtx" and this will guarantee | ||
942 | * that both the file and the item will not vanish. | ||
943 | */ | ||
944 | revents = epi->ffd.file->f_op->poll(epi->ffd.file, NULL); | ||
945 | revents &= epi->event.events; | ||
946 | 1065 | ||
947 | /* | 1066 | /* |
948 | * Is the event mask intersect the caller-requested one, | 1067 | * If the event mask intersect the caller-requested one, |
949 | * deliver the event to userspace. Again, we are holding | 1068 | * deliver the event to userspace. Again, ep_scan_ready_list() |
950 | * "mtx", so no operations coming from userspace can change | 1069 | * is holding "mtx", so no operations coming from userspace |
951 | * the item. | 1070 | * can change the item. |
952 | */ | 1071 | */ |
953 | if (revents) { | 1072 | if (revents) { |
954 | if (__put_user(revents, | 1073 | if (__put_user(revents, &uevent->events) || |
955 | &events[eventcnt].events) || | 1074 | __put_user(epi->event.data, &uevent->data)) { |
956 | __put_user(epi->event.data, | 1075 | list_add(&epi->rdllink, head); |
957 | &events[eventcnt].data)) | 1076 | return eventcnt ? eventcnt : -EFAULT; |
958 | goto errxit; | 1077 | } |
1078 | eventcnt++; | ||
1079 | uevent++; | ||
959 | if (epi->event.events & EPOLLONESHOT) | 1080 | if (epi->event.events & EPOLLONESHOT) |
960 | epi->event.events &= EP_PRIVATE_BITS; | 1081 | epi->event.events &= EP_PRIVATE_BITS; |
961 | eventcnt++; | 1082 | else if (!(epi->event.events & EPOLLET)) { |
1083 | /* | ||
1084 | * If this file has been added with Level | ||
1085 | * Trigger mode, we need to insert back inside | ||
1086 | * the ready list, so that the next call to | ||
1087 | * epoll_wait() will check again the events | ||
1088 | * availability. At this point, noone can insert | ||
1089 | * into ep->rdllist besides us. The epoll_ctl() | ||
1090 | * callers are locked out by | ||
1091 | * ep_scan_ready_list() holding "mtx" and the | ||
1092 | * poll callback will queue them in ep->ovflist. | ||
1093 | */ | ||
1094 | list_add_tail(&epi->rdllink, &ep->rdllist); | ||
1095 | } | ||
962 | } | 1096 | } |
963 | /* | ||
964 | * At this point, noone can insert into ep->rdllist besides | ||
965 | * us. The epoll_ctl() callers are locked out by us holding | ||
966 | * "mtx" and the poll callback will queue them in ep->ovflist. | ||
967 | */ | ||
968 | if (!(epi->event.events & EPOLLET) && | ||
969 | (revents & epi->event.events)) | ||
970 | list_add_tail(&epi->rdllink, &ep->rdllist); | ||
971 | } | ||
972 | error = 0; | ||
973 | |||
974 | errxit: | ||
975 | |||
976 | spin_lock_irqsave(&ep->lock, flags); | ||
977 | /* | ||
978 | * During the time we spent in the loop above, some other events | ||
979 | * might have been queued by the poll callback. We re-insert them | ||
980 | * inside the main ready-list here. | ||
981 | */ | ||
982 | for (nepi = ep->ovflist; (epi = nepi) != NULL; | ||
983 | nepi = epi->next, epi->next = EP_UNACTIVE_PTR) { | ||
984 | /* | ||
985 | * If the above loop quit with errors, the epoll item might still | ||
986 | * be linked to "txlist", and the list_splice() done below will | ||
987 | * take care of those cases. | ||
988 | */ | ||
989 | if (!ep_is_linked(&epi->rdllink)) | ||
990 | list_add_tail(&epi->rdllink, &ep->rdllist); | ||
991 | } | 1097 | } |
992 | /* | ||
993 | * We need to set back ep->ovflist to EP_UNACTIVE_PTR, so that after | ||
994 | * releasing the lock, events will be queued in the normal way inside | ||
995 | * ep->rdllist. | ||
996 | */ | ||
997 | ep->ovflist = EP_UNACTIVE_PTR; | ||
998 | 1098 | ||
999 | /* | 1099 | return eventcnt; |
1000 | * In case of error in the event-send loop, or in case the number of | 1100 | } |
1001 | * ready events exceeds the userspace limit, we need to splice the | ||
1002 | * "txlist" back inside ep->rdllist. | ||
1003 | */ | ||
1004 | list_splice(&txlist, &ep->rdllist); | ||
1005 | |||
1006 | if (!list_empty(&ep->rdllist)) { | ||
1007 | /* | ||
1008 | * Wake up (if active) both the eventpoll wait list and the ->poll() | ||
1009 | * wait list (delayed after we release the lock). | ||
1010 | */ | ||
1011 | if (waitqueue_active(&ep->wq)) | ||
1012 | wake_up_locked(&ep->wq); | ||
1013 | if (waitqueue_active(&ep->poll_wait)) | ||
1014 | pwake++; | ||
1015 | } | ||
1016 | spin_unlock_irqrestore(&ep->lock, flags); | ||
1017 | 1101 | ||
1018 | mutex_unlock(&ep->mtx); | 1102 | static int ep_send_events(struct eventpoll *ep, |
1103 | struct epoll_event __user *events, int maxevents) | ||
1104 | { | ||
1105 | struct ep_send_events_data esed; | ||
1019 | 1106 | ||
1020 | /* We have to call this outside the lock */ | 1107 | esed.maxevents = maxevents; |
1021 | if (pwake) | 1108 | esed.events = events; |
1022 | ep_poll_safewake(&psw, &ep->poll_wait); | ||
1023 | 1109 | ||
1024 | return eventcnt == 0 ? error: eventcnt; | 1110 | return ep_scan_ready_list(ep, ep_send_events_proc, &esed); |
1025 | } | 1111 | } |
1026 | 1112 | ||
1027 | static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, | 1113 | static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, |
@@ -1033,7 +1119,7 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, | |||
1033 | wait_queue_t wait; | 1119 | wait_queue_t wait; |
1034 | 1120 | ||
1035 | /* | 1121 | /* |
1036 | * Calculate the timeout by checking for the "infinite" value ( -1 ) | 1122 | * Calculate the timeout by checking for the "infinite" value (-1) |
1037 | * and the overflow condition. The passed timeout is in milliseconds, | 1123 | * and the overflow condition. The passed timeout is in milliseconds, |
1038 | * that why (t * HZ) / 1000. | 1124 | * that why (t * HZ) / 1000. |
1039 | */ | 1125 | */ |
@@ -1076,9 +1162,8 @@ retry: | |||
1076 | 1162 | ||
1077 | set_current_state(TASK_RUNNING); | 1163 | set_current_state(TASK_RUNNING); |
1078 | } | 1164 | } |
1079 | |||
1080 | /* Is it worth to try to dig for events ? */ | 1165 | /* Is it worth to try to dig for events ? */ |
1081 | eavail = !list_empty(&ep->rdllist); | 1166 | eavail = !list_empty(&ep->rdllist) || ep->ovflist != EP_UNACTIVE_PTR; |
1082 | 1167 | ||
1083 | spin_unlock_irqrestore(&ep->lock, flags); | 1168 | spin_unlock_irqrestore(&ep->lock, flags); |
1084 | 1169 | ||
@@ -1099,41 +1184,30 @@ retry: | |||
1099 | */ | 1184 | */ |
1100 | SYSCALL_DEFINE1(epoll_create1, int, flags) | 1185 | SYSCALL_DEFINE1(epoll_create1, int, flags) |
1101 | { | 1186 | { |
1102 | int error, fd = -1; | 1187 | int error; |
1103 | struct eventpoll *ep; | 1188 | struct eventpoll *ep = NULL; |
1104 | 1189 | ||
1105 | /* Check the EPOLL_* constant for consistency. */ | 1190 | /* Check the EPOLL_* constant for consistency. */ |
1106 | BUILD_BUG_ON(EPOLL_CLOEXEC != O_CLOEXEC); | 1191 | BUILD_BUG_ON(EPOLL_CLOEXEC != O_CLOEXEC); |
1107 | 1192 | ||
1108 | if (flags & ~EPOLL_CLOEXEC) | 1193 | if (flags & ~EPOLL_CLOEXEC) |
1109 | return -EINVAL; | 1194 | return -EINVAL; |
1110 | |||
1111 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n", | ||
1112 | current, flags)); | ||
1113 | |||
1114 | /* | 1195 | /* |
1115 | * Create the internal data structure ( "struct eventpoll" ). | 1196 | * Create the internal data structure ("struct eventpoll"). |
1116 | */ | 1197 | */ |
1117 | error = ep_alloc(&ep); | 1198 | error = ep_alloc(&ep); |
1118 | if (error < 0) { | 1199 | if (error < 0) |
1119 | fd = error; | 1200 | return error; |
1120 | goto error_return; | ||
1121 | } | ||
1122 | |||
1123 | /* | 1201 | /* |
1124 | * Creates all the items needed to setup an eventpoll file. That is, | 1202 | * Creates all the items needed to setup an eventpoll file. That is, |
1125 | * a file structure and a free file descriptor. | 1203 | * a file structure and a free file descriptor. |
1126 | */ | 1204 | */ |
1127 | fd = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep, | 1205 | error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep, |
1128 | flags & O_CLOEXEC); | 1206 | flags & O_CLOEXEC); |
1129 | if (fd < 0) | 1207 | if (error < 0) |
1130 | ep_free(ep); | 1208 | ep_free(ep); |
1131 | 1209 | ||
1132 | error_return: | 1210 | return error; |
1133 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", | ||
1134 | current, flags, fd)); | ||
1135 | |||
1136 | return fd; | ||
1137 | } | 1211 | } |
1138 | 1212 | ||
1139 | SYSCALL_DEFINE1(epoll_create, int, size) | 1213 | SYSCALL_DEFINE1(epoll_create, int, size) |
@@ -1158,9 +1232,6 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, | |||
1158 | struct epitem *epi; | 1232 | struct epitem *epi; |
1159 | struct epoll_event epds; | 1233 | struct epoll_event epds; |
1160 | 1234 | ||
1161 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p)\n", | ||
1162 | current, epfd, op, fd, event)); | ||
1163 | |||
1164 | error = -EFAULT; | 1235 | error = -EFAULT; |
1165 | if (ep_op_has_event(op) && | 1236 | if (ep_op_has_event(op) && |
1166 | copy_from_user(&epds, event, sizeof(struct epoll_event))) | 1237 | copy_from_user(&epds, event, sizeof(struct epoll_event))) |
@@ -1211,7 +1282,6 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, | |||
1211 | case EPOLL_CTL_ADD: | 1282 | case EPOLL_CTL_ADD: |
1212 | if (!epi) { | 1283 | if (!epi) { |
1213 | epds.events |= POLLERR | POLLHUP; | 1284 | epds.events |= POLLERR | POLLHUP; |
1214 | |||
1215 | error = ep_insert(ep, &epds, tfile, fd); | 1285 | error = ep_insert(ep, &epds, tfile, fd); |
1216 | } else | 1286 | } else |
1217 | error = -EEXIST; | 1287 | error = -EEXIST; |
@@ -1237,8 +1307,6 @@ error_tgt_fput: | |||
1237 | error_fput: | 1307 | error_fput: |
1238 | fput(file); | 1308 | fput(file); |
1239 | error_return: | 1309 | error_return: |
1240 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p) = %d\n", | ||
1241 | current, epfd, op, fd, event, error)); | ||
1242 | 1310 | ||
1243 | return error; | 1311 | return error; |
1244 | } | 1312 | } |
@@ -1254,9 +1322,6 @@ SYSCALL_DEFINE4(epoll_wait, int, epfd, struct epoll_event __user *, events, | |||
1254 | struct file *file; | 1322 | struct file *file; |
1255 | struct eventpoll *ep; | 1323 | struct eventpoll *ep; |
1256 | 1324 | ||
1257 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d)\n", | ||
1258 | current, epfd, events, maxevents, timeout)); | ||
1259 | |||
1260 | /* The maximum number of event must be greater than zero */ | 1325 | /* The maximum number of event must be greater than zero */ |
1261 | if (maxevents <= 0 || maxevents > EP_MAX_EVENTS) | 1326 | if (maxevents <= 0 || maxevents > EP_MAX_EVENTS) |
1262 | return -EINVAL; | 1327 | return -EINVAL; |
@@ -1293,8 +1358,6 @@ SYSCALL_DEFINE4(epoll_wait, int, epfd, struct epoll_event __user *, events, | |||
1293 | error_fput: | 1358 | error_fput: |
1294 | fput(file); | 1359 | fput(file); |
1295 | error_return: | 1360 | error_return: |
1296 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d) = %d\n", | ||
1297 | current, epfd, events, maxevents, timeout, error)); | ||
1298 | 1361 | ||
1299 | return error; | 1362 | return error; |
1300 | } | 1363 | } |
@@ -1359,17 +1422,18 @@ static int __init eventpoll_init(void) | |||
1359 | EP_ITEM_COST; | 1422 | EP_ITEM_COST; |
1360 | 1423 | ||
1361 | /* Initialize the structure used to perform safe poll wait head wake ups */ | 1424 | /* Initialize the structure used to perform safe poll wait head wake ups */ |
1362 | ep_poll_safewake_init(&psw); | 1425 | ep_nested_calls_init(&poll_safewake_ncalls); |
1426 | |||
1427 | /* Initialize the structure used to perform file's f_op->poll() calls */ | ||
1428 | ep_nested_calls_init(&poll_readywalk_ncalls); | ||
1363 | 1429 | ||
1364 | /* Allocates slab cache used to allocate "struct epitem" items */ | 1430 | /* Allocates slab cache used to allocate "struct epitem" items */ |
1365 | epi_cache = kmem_cache_create("eventpoll_epi", sizeof(struct epitem), | 1431 | epi_cache = kmem_cache_create("eventpoll_epi", sizeof(struct epitem), |
1366 | 0, SLAB_HWCACHE_ALIGN|EPI_SLAB_DEBUG|SLAB_PANIC, | 1432 | 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); |
1367 | NULL); | ||
1368 | 1433 | ||
1369 | /* Allocates slab cache used to allocate "struct eppoll_entry" */ | 1434 | /* Allocates slab cache used to allocate "struct eppoll_entry" */ |
1370 | pwq_cache = kmem_cache_create("eventpoll_pwq", | 1435 | pwq_cache = kmem_cache_create("eventpoll_pwq", |
1371 | sizeof(struct eppoll_entry), 0, | 1436 | sizeof(struct eppoll_entry), 0, SLAB_PANIC, NULL); |
1372 | EPI_SLAB_DEBUG|SLAB_PANIC, NULL); | ||
1373 | 1437 | ||
1374 | return 0; | 1438 | return 0; |
1375 | } | 1439 | } |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 6083bb38057..990c9400092 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1098,7 +1098,7 @@ extern int ext4_meta_trans_blocks(struct inode *, int nrblocks, int idxblocks); | |||
1098 | extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); | 1098 | extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); |
1099 | extern int ext4_block_truncate_page(handle_t *handle, | 1099 | extern int ext4_block_truncate_page(handle_t *handle, |
1100 | struct address_space *mapping, loff_t from); | 1100 | struct address_space *mapping, loff_t from); |
1101 | extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page); | 1101 | extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); |
1102 | extern qsize_t ext4_get_reserved_space(struct inode *inode); | 1102 | extern qsize_t ext4_get_reserved_space(struct inode *inode); |
1103 | 1103 | ||
1104 | /* ioctl.c */ | 1104 | /* ioctl.c */ |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 71d3ecd5db7..dd82ff39006 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -5146,8 +5146,9 @@ static int ext4_bh_unmapped(handle_t *handle, struct buffer_head *bh) | |||
5146 | return !buffer_mapped(bh); | 5146 | return !buffer_mapped(bh); |
5147 | } | 5147 | } |
5148 | 5148 | ||
5149 | int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page) | 5149 | int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
5150 | { | 5150 | { |
5151 | struct page *page = vmf->page; | ||
5151 | loff_t size; | 5152 | loff_t size; |
5152 | unsigned long len; | 5153 | unsigned long len; |
5153 | int ret = -EINVAL; | 5154 | int ret = -EINVAL; |
@@ -5199,6 +5200,8 @@ int ext4_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
5199 | goto out_unlock; | 5200 | goto out_unlock; |
5200 | ret = 0; | 5201 | ret = 0; |
5201 | out_unlock: | 5202 | out_unlock: |
5203 | if (ret) | ||
5204 | ret = VM_FAULT_SIGBUS; | ||
5202 | up_read(&inode->i_alloc_sem); | 5205 | up_read(&inode->i_alloc_sem); |
5203 | return ret; | 5206 | return ret; |
5204 | } | 5207 | } |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 821d10f719b..4e340fedf76 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -1234,8 +1234,9 @@ static void fuse_vma_close(struct vm_area_struct *vma) | |||
1234 | * - sync(2) | 1234 | * - sync(2) |
1235 | * - try_to_free_pages() with order > PAGE_ALLOC_COSTLY_ORDER | 1235 | * - try_to_free_pages() with order > PAGE_ALLOC_COSTLY_ORDER |
1236 | */ | 1236 | */ |
1237 | static int fuse_page_mkwrite(struct vm_area_struct *vma, struct page *page) | 1237 | static int fuse_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
1238 | { | 1238 | { |
1239 | struct page *page = vmf->page; | ||
1239 | /* | 1240 | /* |
1240 | * Don't use page->mapping as it may become NULL from a | 1241 | * Don't use page->mapping as it may become NULL from a |
1241 | * concurrent truncate. | 1242 | * concurrent truncate. |
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c index 3b9e8de3500..70b9b854894 100644 --- a/fs/gfs2/ops_file.c +++ b/fs/gfs2/ops_file.c | |||
@@ -337,8 +337,9 @@ static int gfs2_allocate_page_backing(struct page *page) | |||
337 | * blocks allocated on disk to back that page. | 337 | * blocks allocated on disk to back that page. |
338 | */ | 338 | */ |
339 | 339 | ||
340 | static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page) | 340 | static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
341 | { | 341 | { |
342 | struct page *page = vmf->page; | ||
342 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; | 343 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; |
343 | struct gfs2_inode *ip = GFS2_I(inode); | 344 | struct gfs2_inode *ip = GFS2_I(inode); |
344 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 345 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
@@ -412,6 +413,8 @@ out_unlock: | |||
412 | gfs2_glock_dq(&gh); | 413 | gfs2_glock_dq(&gh); |
413 | out: | 414 | out: |
414 | gfs2_holder_uninit(&gh); | 415 | gfs2_holder_uninit(&gh); |
416 | if (ret) | ||
417 | ret = VM_FAULT_SIGBUS; | ||
415 | return ret; | 418 | return ret; |
416 | } | 419 | } |
417 | 420 | ||
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 9b800d97a68..23a3c76711e 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -943,14 +943,13 @@ static struct vfsmount *hugetlbfs_vfsmount; | |||
943 | 943 | ||
944 | static int can_do_hugetlb_shm(void) | 944 | static int can_do_hugetlb_shm(void) |
945 | { | 945 | { |
946 | return likely(capable(CAP_IPC_LOCK) || | 946 | return capable(CAP_IPC_LOCK) || in_group_p(sysctl_hugetlb_shm_group); |
947 | in_group_p(sysctl_hugetlb_shm_group) || | ||
948 | can_do_mlock()); | ||
949 | } | 947 | } |
950 | 948 | ||
951 | struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag) | 949 | struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag) |
952 | { | 950 | { |
953 | int error = -ENOMEM; | 951 | int error = -ENOMEM; |
952 | int unlock_shm = 0; | ||
954 | struct file *file; | 953 | struct file *file; |
955 | struct inode *inode; | 954 | struct inode *inode; |
956 | struct dentry *dentry, *root; | 955 | struct dentry *dentry, *root; |
@@ -960,11 +959,14 @@ struct file *hugetlb_file_setup(const char *name, size_t size, int acctflag) | |||
960 | if (!hugetlbfs_vfsmount) | 959 | if (!hugetlbfs_vfsmount) |
961 | return ERR_PTR(-ENOENT); | 960 | return ERR_PTR(-ENOENT); |
962 | 961 | ||
963 | if (!can_do_hugetlb_shm()) | 962 | if (!can_do_hugetlb_shm()) { |
964 | return ERR_PTR(-EPERM); | 963 | if (user_shm_lock(size, user)) { |
965 | 964 | unlock_shm = 1; | |
966 | if (!user_shm_lock(size, user)) | 965 | WARN_ONCE(1, |
967 | return ERR_PTR(-ENOMEM); | 966 | "Using mlock ulimits for SHM_HUGETLB deprecated\n"); |
967 | } else | ||
968 | return ERR_PTR(-EPERM); | ||
969 | } | ||
968 | 970 | ||
969 | root = hugetlbfs_vfsmount->mnt_root; | 971 | root = hugetlbfs_vfsmount->mnt_root; |
970 | quick_string.name = name; | 972 | quick_string.name = name; |
@@ -1004,7 +1006,8 @@ out_inode: | |||
1004 | out_dentry: | 1006 | out_dentry: |
1005 | dput(dentry); | 1007 | dput(dentry); |
1006 | out_shm_unlock: | 1008 | out_shm_unlock: |
1007 | user_shm_unlock(size, user); | 1009 | if (unlock_shm) |
1010 | user_shm_unlock(size, user); | ||
1008 | return ERR_PTR(error); | 1011 | return ERR_PTR(error); |
1009 | } | 1012 | } |
1010 | 1013 | ||
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 90f292b520d..cec79392e4b 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -451,8 +451,9 @@ const struct address_space_operations nfs_file_aops = { | |||
451 | .launder_page = nfs_launder_page, | 451 | .launder_page = nfs_launder_page, |
452 | }; | 452 | }; |
453 | 453 | ||
454 | static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) | 454 | static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
455 | { | 455 | { |
456 | struct page *page = vmf->page; | ||
456 | struct file *filp = vma->vm_file; | 457 | struct file *filp = vma->vm_file; |
457 | struct dentry *dentry = filp->f_path.dentry; | 458 | struct dentry *dentry = filp->f_path.dentry; |
458 | unsigned pagelen; | 459 | unsigned pagelen; |
@@ -483,6 +484,8 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
483 | ret = pagelen; | 484 | ret = pagelen; |
484 | out_unlock: | 485 | out_unlock: |
485 | unlock_page(page); | 486 | unlock_page(page); |
487 | if (ret) | ||
488 | ret = VM_FAULT_SIGBUS; | ||
486 | return ret; | 489 | return ret; |
487 | } | 490 | } |
488 | 491 | ||
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index 34314b33dbd..5a9e34475e3 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c | |||
@@ -32,8 +32,8 @@ | |||
32 | /** | 32 | /** |
33 | * The little endian Unicode string $I30 as a global constant. | 33 | * The little endian Unicode string $I30 as a global constant. |
34 | */ | 34 | */ |
35 | ntfschar I30[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('I'), | 35 | ntfschar I30[5] = { cpu_to_le16('$'), cpu_to_le16('I'), |
36 | const_cpu_to_le16('3'), const_cpu_to_le16('0'), 0 }; | 36 | cpu_to_le16('3'), cpu_to_le16('0'), 0 }; |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * ntfs_lookup_inode_by_name - find an inode in a directory given its name | 39 | * ntfs_lookup_inode_by_name - find an inode in a directory given its name |
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 86bef156cf0..82c5085559c 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c | |||
@@ -1975,8 +1975,7 @@ int ntfs_read_inode_mount(struct inode *vi) | |||
1975 | goto em_put_err_out; | 1975 | goto em_put_err_out; |
1976 | next_al_entry = (ATTR_LIST_ENTRY*)((u8*)al_entry + | 1976 | next_al_entry = (ATTR_LIST_ENTRY*)((u8*)al_entry + |
1977 | le16_to_cpu(al_entry->length)); | 1977 | le16_to_cpu(al_entry->length)); |
1978 | if (le32_to_cpu(al_entry->type) > | 1978 | if (le32_to_cpu(al_entry->type) > le32_to_cpu(AT_DATA)) |
1979 | const_le32_to_cpu(AT_DATA)) | ||
1980 | goto em_put_err_out; | 1979 | goto em_put_err_out; |
1981 | if (AT_DATA != al_entry->type) | 1980 | if (AT_DATA != al_entry->type) |
1982 | continue; | 1981 | continue; |
diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h index 1e383328ece..50931b1ce4b 100644 --- a/fs/ntfs/layout.h +++ b/fs/ntfs/layout.h | |||
@@ -31,19 +31,8 @@ | |||
31 | 31 | ||
32 | #include "types.h" | 32 | #include "types.h" |
33 | 33 | ||
34 | /* | ||
35 | * Constant endianness conversion defines. | ||
36 | */ | ||
37 | #define const_le16_to_cpu(x) __constant_le16_to_cpu(x) | ||
38 | #define const_le32_to_cpu(x) __constant_le32_to_cpu(x) | ||
39 | #define const_le64_to_cpu(x) __constant_le64_to_cpu(x) | ||
40 | |||
41 | #define const_cpu_to_le16(x) __constant_cpu_to_le16(x) | ||
42 | #define const_cpu_to_le32(x) __constant_cpu_to_le32(x) | ||
43 | #define const_cpu_to_le64(x) __constant_cpu_to_le64(x) | ||
44 | |||
45 | /* The NTFS oem_id "NTFS " */ | 34 | /* The NTFS oem_id "NTFS " */ |
46 | #define magicNTFS const_cpu_to_le64(0x202020205346544eULL) | 35 | #define magicNTFS cpu_to_le64(0x202020205346544eULL) |
47 | 36 | ||
48 | /* | 37 | /* |
49 | * Location of bootsector on partition: | 38 | * Location of bootsector on partition: |
@@ -114,25 +103,25 @@ typedef struct { | |||
114 | */ | 103 | */ |
115 | enum { | 104 | enum { |
116 | /* Found in $MFT/$DATA. */ | 105 | /* Found in $MFT/$DATA. */ |
117 | magic_FILE = const_cpu_to_le32(0x454c4946), /* Mft entry. */ | 106 | magic_FILE = cpu_to_le32(0x454c4946), /* Mft entry. */ |
118 | magic_INDX = const_cpu_to_le32(0x58444e49), /* Index buffer. */ | 107 | magic_INDX = cpu_to_le32(0x58444e49), /* Index buffer. */ |
119 | magic_HOLE = const_cpu_to_le32(0x454c4f48), /* ? (NTFS 3.0+?) */ | 108 | magic_HOLE = cpu_to_le32(0x454c4f48), /* ? (NTFS 3.0+?) */ |
120 | 109 | ||
121 | /* Found in $LogFile/$DATA. */ | 110 | /* Found in $LogFile/$DATA. */ |
122 | magic_RSTR = const_cpu_to_le32(0x52545352), /* Restart page. */ | 111 | magic_RSTR = cpu_to_le32(0x52545352), /* Restart page. */ |
123 | magic_RCRD = const_cpu_to_le32(0x44524352), /* Log record page. */ | 112 | magic_RCRD = cpu_to_le32(0x44524352), /* Log record page. */ |
124 | 113 | ||
125 | /* Found in $LogFile/$DATA. (May be found in $MFT/$DATA, also?) */ | 114 | /* Found in $LogFile/$DATA. (May be found in $MFT/$DATA, also?) */ |
126 | magic_CHKD = const_cpu_to_le32(0x444b4843), /* Modified by chkdsk. */ | 115 | magic_CHKD = cpu_to_le32(0x444b4843), /* Modified by chkdsk. */ |
127 | 116 | ||
128 | /* Found in all ntfs record containing records. */ | 117 | /* Found in all ntfs record containing records. */ |
129 | magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector | 118 | magic_BAAD = cpu_to_le32(0x44414142), /* Failed multi sector |
130 | transfer was detected. */ | 119 | transfer was detected. */ |
131 | /* | 120 | /* |
132 | * Found in $LogFile/$DATA when a page is full of 0xff bytes and is | 121 | * Found in $LogFile/$DATA when a page is full of 0xff bytes and is |
133 | * thus not initialized. Page must be initialized before using it. | 122 | * thus not initialized. Page must be initialized before using it. |
134 | */ | 123 | */ |
135 | magic_empty = const_cpu_to_le32(0xffffffff) /* Record is empty. */ | 124 | magic_empty = cpu_to_le32(0xffffffff) /* Record is empty. */ |
136 | }; | 125 | }; |
137 | 126 | ||
138 | typedef le32 NTFS_RECORD_TYPE; | 127 | typedef le32 NTFS_RECORD_TYPE; |
@@ -258,8 +247,8 @@ typedef enum { | |||
258 | * information about the mft record in which they are present. | 247 | * information about the mft record in which they are present. |
259 | */ | 248 | */ |
260 | enum { | 249 | enum { |
261 | MFT_RECORD_IN_USE = const_cpu_to_le16(0x0001), | 250 | MFT_RECORD_IN_USE = cpu_to_le16(0x0001), |
262 | MFT_RECORD_IS_DIRECTORY = const_cpu_to_le16(0x0002), | 251 | MFT_RECORD_IS_DIRECTORY = cpu_to_le16(0x0002), |
263 | } __attribute__ ((__packed__)); | 252 | } __attribute__ ((__packed__)); |
264 | 253 | ||
265 | typedef le16 MFT_RECORD_FLAGS; | 254 | typedef le16 MFT_RECORD_FLAGS; |
@@ -309,7 +298,7 @@ typedef le16 MFT_RECORD_FLAGS; | |||
309 | * Note: The _LE versions will return a CPU endian formatted value! | 298 | * Note: The _LE versions will return a CPU endian formatted value! |
310 | */ | 299 | */ |
311 | #define MFT_REF_MASK_CPU 0x0000ffffffffffffULL | 300 | #define MFT_REF_MASK_CPU 0x0000ffffffffffffULL |
312 | #define MFT_REF_MASK_LE const_cpu_to_le64(MFT_REF_MASK_CPU) | 301 | #define MFT_REF_MASK_LE cpu_to_le64(MFT_REF_MASK_CPU) |
313 | 302 | ||
314 | typedef u64 MFT_REF; | 303 | typedef u64 MFT_REF; |
315 | typedef le64 leMFT_REF; | 304 | typedef le64 leMFT_REF; |
@@ -477,25 +466,25 @@ typedef struct { | |||
477 | * a revealing choice of symbol I do not know what is... (-; | 466 | * a revealing choice of symbol I do not know what is... (-; |
478 | */ | 467 | */ |
479 | enum { | 468 | enum { |
480 | AT_UNUSED = const_cpu_to_le32( 0), | 469 | AT_UNUSED = cpu_to_le32( 0), |
481 | AT_STANDARD_INFORMATION = const_cpu_to_le32( 0x10), | 470 | AT_STANDARD_INFORMATION = cpu_to_le32( 0x10), |
482 | AT_ATTRIBUTE_LIST = const_cpu_to_le32( 0x20), | 471 | AT_ATTRIBUTE_LIST = cpu_to_le32( 0x20), |
483 | AT_FILE_NAME = const_cpu_to_le32( 0x30), | 472 | AT_FILE_NAME = cpu_to_le32( 0x30), |
484 | AT_OBJECT_ID = const_cpu_to_le32( 0x40), | 473 | AT_OBJECT_ID = cpu_to_le32( 0x40), |
485 | AT_SECURITY_DESCRIPTOR = const_cpu_to_le32( 0x50), | 474 | AT_SECURITY_DESCRIPTOR = cpu_to_le32( 0x50), |
486 | AT_VOLUME_NAME = const_cpu_to_le32( 0x60), | 475 | AT_VOLUME_NAME = cpu_to_le32( 0x60), |
487 | AT_VOLUME_INFORMATION = const_cpu_to_le32( 0x70), | 476 | AT_VOLUME_INFORMATION = cpu_to_le32( 0x70), |
488 | AT_DATA = const_cpu_to_le32( 0x80), | 477 | AT_DATA = cpu_to_le32( 0x80), |
489 | AT_INDEX_ROOT = const_cpu_to_le32( 0x90), | 478 | AT_INDEX_ROOT = cpu_to_le32( 0x90), |
490 | AT_INDEX_ALLOCATION = const_cpu_to_le32( 0xa0), | 479 | AT_INDEX_ALLOCATION = cpu_to_le32( 0xa0), |
491 | AT_BITMAP = const_cpu_to_le32( 0xb0), | 480 | AT_BITMAP = cpu_to_le32( 0xb0), |
492 | AT_REPARSE_POINT = const_cpu_to_le32( 0xc0), | 481 | AT_REPARSE_POINT = cpu_to_le32( 0xc0), |
493 | AT_EA_INFORMATION = const_cpu_to_le32( 0xd0), | 482 | AT_EA_INFORMATION = cpu_to_le32( 0xd0), |
494 | AT_EA = const_cpu_to_le32( 0xe0), | 483 | AT_EA = cpu_to_le32( 0xe0), |
495 | AT_PROPERTY_SET = const_cpu_to_le32( 0xf0), | 484 | AT_PROPERTY_SET = cpu_to_le32( 0xf0), |
496 | AT_LOGGED_UTILITY_STREAM = const_cpu_to_le32( 0x100), | 485 | AT_LOGGED_UTILITY_STREAM = cpu_to_le32( 0x100), |
497 | AT_FIRST_USER_DEFINED_ATTRIBUTE = const_cpu_to_le32( 0x1000), | 486 | AT_FIRST_USER_DEFINED_ATTRIBUTE = cpu_to_le32( 0x1000), |
498 | AT_END = const_cpu_to_le32(0xffffffff) | 487 | AT_END = cpu_to_le32(0xffffffff) |
499 | }; | 488 | }; |
500 | 489 | ||
501 | typedef le32 ATTR_TYPE; | 490 | typedef le32 ATTR_TYPE; |
@@ -539,13 +528,13 @@ typedef le32 ATTR_TYPE; | |||
539 | * equal then the second le32 values would be compared, etc. | 528 | * equal then the second le32 values would be compared, etc. |
540 | */ | 529 | */ |
541 | enum { | 530 | enum { |
542 | COLLATION_BINARY = const_cpu_to_le32(0x00), | 531 | COLLATION_BINARY = cpu_to_le32(0x00), |
543 | COLLATION_FILE_NAME = const_cpu_to_le32(0x01), | 532 | COLLATION_FILE_NAME = cpu_to_le32(0x01), |
544 | COLLATION_UNICODE_STRING = const_cpu_to_le32(0x02), | 533 | COLLATION_UNICODE_STRING = cpu_to_le32(0x02), |
545 | COLLATION_NTOFS_ULONG = const_cpu_to_le32(0x10), | 534 | COLLATION_NTOFS_ULONG = cpu_to_le32(0x10), |
546 | COLLATION_NTOFS_SID = const_cpu_to_le32(0x11), | 535 | COLLATION_NTOFS_SID = cpu_to_le32(0x11), |
547 | COLLATION_NTOFS_SECURITY_HASH = const_cpu_to_le32(0x12), | 536 | COLLATION_NTOFS_SECURITY_HASH = cpu_to_le32(0x12), |
548 | COLLATION_NTOFS_ULONGS = const_cpu_to_le32(0x13), | 537 | COLLATION_NTOFS_ULONGS = cpu_to_le32(0x13), |
549 | }; | 538 | }; |
550 | 539 | ||
551 | typedef le32 COLLATION_RULE; | 540 | typedef le32 COLLATION_RULE; |
@@ -559,25 +548,25 @@ typedef le32 COLLATION_RULE; | |||
559 | * NT4. | 548 | * NT4. |
560 | */ | 549 | */ |
561 | enum { | 550 | enum { |
562 | ATTR_DEF_INDEXABLE = const_cpu_to_le32(0x02), /* Attribute can be | 551 | ATTR_DEF_INDEXABLE = cpu_to_le32(0x02), /* Attribute can be |
563 | indexed. */ | 552 | indexed. */ |
564 | ATTR_DEF_MULTIPLE = const_cpu_to_le32(0x04), /* Attribute type | 553 | ATTR_DEF_MULTIPLE = cpu_to_le32(0x04), /* Attribute type |
565 | can be present multiple times in the | 554 | can be present multiple times in the |
566 | mft records of an inode. */ | 555 | mft records of an inode. */ |
567 | ATTR_DEF_NOT_ZERO = const_cpu_to_le32(0x08), /* Attribute value | 556 | ATTR_DEF_NOT_ZERO = cpu_to_le32(0x08), /* Attribute value |
568 | must contain at least one non-zero | 557 | must contain at least one non-zero |
569 | byte. */ | 558 | byte. */ |
570 | ATTR_DEF_INDEXED_UNIQUE = const_cpu_to_le32(0x10), /* Attribute must be | 559 | ATTR_DEF_INDEXED_UNIQUE = cpu_to_le32(0x10), /* Attribute must be |
571 | indexed and the attribute value must be | 560 | indexed and the attribute value must be |
572 | unique for the attribute type in all of | 561 | unique for the attribute type in all of |
573 | the mft records of an inode. */ | 562 | the mft records of an inode. */ |
574 | ATTR_DEF_NAMED_UNIQUE = const_cpu_to_le32(0x20), /* Attribute must be | 563 | ATTR_DEF_NAMED_UNIQUE = cpu_to_le32(0x20), /* Attribute must be |
575 | named and the name must be unique for | 564 | named and the name must be unique for |
576 | the attribute type in all of the mft | 565 | the attribute type in all of the mft |
577 | records of an inode. */ | 566 | records of an inode. */ |
578 | ATTR_DEF_RESIDENT = const_cpu_to_le32(0x40), /* Attribute must be | 567 | ATTR_DEF_RESIDENT = cpu_to_le32(0x40), /* Attribute must be |
579 | resident. */ | 568 | resident. */ |
580 | ATTR_DEF_ALWAYS_LOG = const_cpu_to_le32(0x80), /* Always log | 569 | ATTR_DEF_ALWAYS_LOG = cpu_to_le32(0x80), /* Always log |
581 | modifications to this attribute, | 570 | modifications to this attribute, |
582 | regardless of whether it is resident or | 571 | regardless of whether it is resident or |
583 | non-resident. Without this, only log | 572 | non-resident. Without this, only log |
@@ -614,12 +603,12 @@ typedef struct { | |||
614 | * Attribute flags (16-bit). | 603 | * Attribute flags (16-bit). |
615 | */ | 604 | */ |
616 | enum { | 605 | enum { |
617 | ATTR_IS_COMPRESSED = const_cpu_to_le16(0x0001), | 606 | ATTR_IS_COMPRESSED = cpu_to_le16(0x0001), |
618 | ATTR_COMPRESSION_MASK = const_cpu_to_le16(0x00ff), /* Compression method | 607 | ATTR_COMPRESSION_MASK = cpu_to_le16(0x00ff), /* Compression method |
619 | mask. Also, first | 608 | mask. Also, first |
620 | illegal value. */ | 609 | illegal value. */ |
621 | ATTR_IS_ENCRYPTED = const_cpu_to_le16(0x4000), | 610 | ATTR_IS_ENCRYPTED = cpu_to_le16(0x4000), |
622 | ATTR_IS_SPARSE = const_cpu_to_le16(0x8000), | 611 | ATTR_IS_SPARSE = cpu_to_le16(0x8000), |
623 | } __attribute__ ((__packed__)); | 612 | } __attribute__ ((__packed__)); |
624 | 613 | ||
625 | typedef le16 ATTR_FLAGS; | 614 | typedef le16 ATTR_FLAGS; |
@@ -811,32 +800,32 @@ typedef ATTR_RECORD ATTR_REC; | |||
811 | * flags appear in all of the above. | 800 | * flags appear in all of the above. |
812 | */ | 801 | */ |
813 | enum { | 802 | enum { |
814 | FILE_ATTR_READONLY = const_cpu_to_le32(0x00000001), | 803 | FILE_ATTR_READONLY = cpu_to_le32(0x00000001), |
815 | FILE_ATTR_HIDDEN = const_cpu_to_le32(0x00000002), | 804 | FILE_ATTR_HIDDEN = cpu_to_le32(0x00000002), |
816 | FILE_ATTR_SYSTEM = const_cpu_to_le32(0x00000004), | 805 | FILE_ATTR_SYSTEM = cpu_to_le32(0x00000004), |
817 | /* Old DOS volid. Unused in NT. = const_cpu_to_le32(0x00000008), */ | 806 | /* Old DOS volid. Unused in NT. = cpu_to_le32(0x00000008), */ |
818 | 807 | ||
819 | FILE_ATTR_DIRECTORY = const_cpu_to_le32(0x00000010), | 808 | FILE_ATTR_DIRECTORY = cpu_to_le32(0x00000010), |
820 | /* Note, FILE_ATTR_DIRECTORY is not considered valid in NT. It is | 809 | /* Note, FILE_ATTR_DIRECTORY is not considered valid in NT. It is |
821 | reserved for the DOS SUBDIRECTORY flag. */ | 810 | reserved for the DOS SUBDIRECTORY flag. */ |
822 | FILE_ATTR_ARCHIVE = const_cpu_to_le32(0x00000020), | 811 | FILE_ATTR_ARCHIVE = cpu_to_le32(0x00000020), |
823 | FILE_ATTR_DEVICE = const_cpu_to_le32(0x00000040), | 812 | FILE_ATTR_DEVICE = cpu_to_le32(0x00000040), |
824 | FILE_ATTR_NORMAL = const_cpu_to_le32(0x00000080), | 813 | FILE_ATTR_NORMAL = cpu_to_le32(0x00000080), |
825 | 814 | ||
826 | FILE_ATTR_TEMPORARY = const_cpu_to_le32(0x00000100), | 815 | FILE_ATTR_TEMPORARY = cpu_to_le32(0x00000100), |
827 | FILE_ATTR_SPARSE_FILE = const_cpu_to_le32(0x00000200), | 816 | FILE_ATTR_SPARSE_FILE = cpu_to_le32(0x00000200), |
828 | FILE_ATTR_REPARSE_POINT = const_cpu_to_le32(0x00000400), | 817 | FILE_ATTR_REPARSE_POINT = cpu_to_le32(0x00000400), |
829 | FILE_ATTR_COMPRESSED = const_cpu_to_le32(0x00000800), | 818 | FILE_ATTR_COMPRESSED = cpu_to_le32(0x00000800), |
830 | 819 | ||
831 | FILE_ATTR_OFFLINE = const_cpu_to_le32(0x00001000), | 820 | FILE_ATTR_OFFLINE = cpu_to_le32(0x00001000), |
832 | FILE_ATTR_NOT_CONTENT_INDEXED = const_cpu_to_le32(0x00002000), | 821 | FILE_ATTR_NOT_CONTENT_INDEXED = cpu_to_le32(0x00002000), |
833 | FILE_ATTR_ENCRYPTED = const_cpu_to_le32(0x00004000), | 822 | FILE_ATTR_ENCRYPTED = cpu_to_le32(0x00004000), |
834 | 823 | ||
835 | FILE_ATTR_VALID_FLAGS = const_cpu_to_le32(0x00007fb7), | 824 | FILE_ATTR_VALID_FLAGS = cpu_to_le32(0x00007fb7), |
836 | /* Note, FILE_ATTR_VALID_FLAGS masks out the old DOS VolId and the | 825 | /* Note, FILE_ATTR_VALID_FLAGS masks out the old DOS VolId and the |
837 | FILE_ATTR_DEVICE and preserves everything else. This mask is used | 826 | FILE_ATTR_DEVICE and preserves everything else. This mask is used |
838 | to obtain all flags that are valid for reading. */ | 827 | to obtain all flags that are valid for reading. */ |
839 | FILE_ATTR_VALID_SET_FLAGS = const_cpu_to_le32(0x000031a7), | 828 | FILE_ATTR_VALID_SET_FLAGS = cpu_to_le32(0x000031a7), |
840 | /* Note, FILE_ATTR_VALID_SET_FLAGS masks out the old DOS VolId, the | 829 | /* Note, FILE_ATTR_VALID_SET_FLAGS masks out the old DOS VolId, the |
841 | F_A_DEVICE, F_A_DIRECTORY, F_A_SPARSE_FILE, F_A_REPARSE_POINT, | 830 | F_A_DEVICE, F_A_DIRECTORY, F_A_SPARSE_FILE, F_A_REPARSE_POINT, |
842 | F_A_COMPRESSED, and F_A_ENCRYPTED and preserves the rest. This mask | 831 | F_A_COMPRESSED, and F_A_ENCRYPTED and preserves the rest. This mask |
@@ -846,11 +835,11 @@ enum { | |||
846 | * FILENAME_ATTR attributes but not in the STANDARD_INFORMATION | 835 | * FILENAME_ATTR attributes but not in the STANDARD_INFORMATION |
847 | * attribute of an mft record. | 836 | * attribute of an mft record. |
848 | */ | 837 | */ |
849 | FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT = const_cpu_to_le32(0x10000000), | 838 | FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT = cpu_to_le32(0x10000000), |
850 | /* Note, this is a copy of the corresponding bit from the mft record, | 839 | /* Note, this is a copy of the corresponding bit from the mft record, |
851 | telling us whether this is a directory or not, i.e. whether it has | 840 | telling us whether this is a directory or not, i.e. whether it has |
852 | an index root attribute or not. */ | 841 | an index root attribute or not. */ |
853 | FILE_ATTR_DUP_VIEW_INDEX_PRESENT = const_cpu_to_le32(0x20000000), | 842 | FILE_ATTR_DUP_VIEW_INDEX_PRESENT = cpu_to_le32(0x20000000), |
854 | /* Note, this is a copy of the corresponding bit from the mft record, | 843 | /* Note, this is a copy of the corresponding bit from the mft record, |
855 | telling us whether this file has a view index present (eg. object id | 844 | telling us whether this file has a view index present (eg. object id |
856 | index, quota index, one of the security indexes or the encrypting | 845 | index, quota index, one of the security indexes or the encrypting |
@@ -1446,42 +1435,42 @@ enum { | |||
1446 | /* Specific rights for files and directories are as follows: */ | 1435 | /* Specific rights for files and directories are as follows: */ |
1447 | 1436 | ||
1448 | /* Right to read data from the file. (FILE) */ | 1437 | /* Right to read data from the file. (FILE) */ |
1449 | FILE_READ_DATA = const_cpu_to_le32(0x00000001), | 1438 | FILE_READ_DATA = cpu_to_le32(0x00000001), |
1450 | /* Right to list contents of a directory. (DIRECTORY) */ | 1439 | /* Right to list contents of a directory. (DIRECTORY) */ |
1451 | FILE_LIST_DIRECTORY = const_cpu_to_le32(0x00000001), | 1440 | FILE_LIST_DIRECTORY = cpu_to_le32(0x00000001), |
1452 | 1441 | ||
1453 | /* Right to write data to the file. (FILE) */ | 1442 | /* Right to write data to the file. (FILE) */ |
1454 | FILE_WRITE_DATA = const_cpu_to_le32(0x00000002), | 1443 | FILE_WRITE_DATA = cpu_to_le32(0x00000002), |
1455 | /* Right to create a file in the directory. (DIRECTORY) */ | 1444 | /* Right to create a file in the directory. (DIRECTORY) */ |
1456 | FILE_ADD_FILE = const_cpu_to_le32(0x00000002), | 1445 | FILE_ADD_FILE = cpu_to_le32(0x00000002), |
1457 | 1446 | ||
1458 | /* Right to append data to the file. (FILE) */ | 1447 | /* Right to append data to the file. (FILE) */ |
1459 | FILE_APPEND_DATA = const_cpu_to_le32(0x00000004), | 1448 | FILE_APPEND_DATA = cpu_to_le32(0x00000004), |
1460 | /* Right to create a subdirectory. (DIRECTORY) */ | 1449 | /* Right to create a subdirectory. (DIRECTORY) */ |
1461 | FILE_ADD_SUBDIRECTORY = const_cpu_to_le32(0x00000004), | 1450 | FILE_ADD_SUBDIRECTORY = cpu_to_le32(0x00000004), |
1462 | 1451 | ||
1463 | /* Right to read extended attributes. (FILE/DIRECTORY) */ | 1452 | /* Right to read extended attributes. (FILE/DIRECTORY) */ |
1464 | FILE_READ_EA = const_cpu_to_le32(0x00000008), | 1453 | FILE_READ_EA = cpu_to_le32(0x00000008), |
1465 | 1454 | ||
1466 | /* Right to write extended attributes. (FILE/DIRECTORY) */ | 1455 | /* Right to write extended attributes. (FILE/DIRECTORY) */ |
1467 | FILE_WRITE_EA = const_cpu_to_le32(0x00000010), | 1456 | FILE_WRITE_EA = cpu_to_le32(0x00000010), |
1468 | 1457 | ||
1469 | /* Right to execute a file. (FILE) */ | 1458 | /* Right to execute a file. (FILE) */ |
1470 | FILE_EXECUTE = const_cpu_to_le32(0x00000020), | 1459 | FILE_EXECUTE = cpu_to_le32(0x00000020), |
1471 | /* Right to traverse the directory. (DIRECTORY) */ | 1460 | /* Right to traverse the directory. (DIRECTORY) */ |
1472 | FILE_TRAVERSE = const_cpu_to_le32(0x00000020), | 1461 | FILE_TRAVERSE = cpu_to_le32(0x00000020), |
1473 | 1462 | ||
1474 | /* | 1463 | /* |
1475 | * Right to delete a directory and all the files it contains (its | 1464 | * Right to delete a directory and all the files it contains (its |
1476 | * children), even if the files are read-only. (DIRECTORY) | 1465 | * children), even if the files are read-only. (DIRECTORY) |
1477 | */ | 1466 | */ |
1478 | FILE_DELETE_CHILD = const_cpu_to_le32(0x00000040), | 1467 | FILE_DELETE_CHILD = cpu_to_le32(0x00000040), |
1479 | 1468 | ||
1480 | /* Right to read file attributes. (FILE/DIRECTORY) */ | 1469 | /* Right to read file attributes. (FILE/DIRECTORY) */ |
1481 | FILE_READ_ATTRIBUTES = const_cpu_to_le32(0x00000080), | 1470 | FILE_READ_ATTRIBUTES = cpu_to_le32(0x00000080), |
1482 | 1471 | ||
1483 | /* Right to change file attributes. (FILE/DIRECTORY) */ | 1472 | /* Right to change file attributes. (FILE/DIRECTORY) */ |
1484 | FILE_WRITE_ATTRIBUTES = const_cpu_to_le32(0x00000100), | 1473 | FILE_WRITE_ATTRIBUTES = cpu_to_le32(0x00000100), |
1485 | 1474 | ||
1486 | /* | 1475 | /* |
1487 | * The standard rights (bits 16 to 23). These are independent of the | 1476 | * The standard rights (bits 16 to 23). These are independent of the |
@@ -1489,27 +1478,27 @@ enum { | |||
1489 | */ | 1478 | */ |
1490 | 1479 | ||
1491 | /* Right to delete the object. */ | 1480 | /* Right to delete the object. */ |
1492 | DELETE = const_cpu_to_le32(0x00010000), | 1481 | DELETE = cpu_to_le32(0x00010000), |
1493 | 1482 | ||
1494 | /* | 1483 | /* |
1495 | * Right to read the information in the object's security descriptor, | 1484 | * Right to read the information in the object's security descriptor, |
1496 | * not including the information in the SACL, i.e. right to read the | 1485 | * not including the information in the SACL, i.e. right to read the |
1497 | * security descriptor and owner. | 1486 | * security descriptor and owner. |
1498 | */ | 1487 | */ |
1499 | READ_CONTROL = const_cpu_to_le32(0x00020000), | 1488 | READ_CONTROL = cpu_to_le32(0x00020000), |
1500 | 1489 | ||
1501 | /* Right to modify the DACL in the object's security descriptor. */ | 1490 | /* Right to modify the DACL in the object's security descriptor. */ |
1502 | WRITE_DAC = const_cpu_to_le32(0x00040000), | 1491 | WRITE_DAC = cpu_to_le32(0x00040000), |
1503 | 1492 | ||
1504 | /* Right to change the owner in the object's security descriptor. */ | 1493 | /* Right to change the owner in the object's security descriptor. */ |
1505 | WRITE_OWNER = const_cpu_to_le32(0x00080000), | 1494 | WRITE_OWNER = cpu_to_le32(0x00080000), |
1506 | 1495 | ||
1507 | /* | 1496 | /* |
1508 | * Right to use the object for synchronization. Enables a process to | 1497 | * Right to use the object for synchronization. Enables a process to |
1509 | * wait until the object is in the signalled state. Some object types | 1498 | * wait until the object is in the signalled state. Some object types |
1510 | * do not support this access right. | 1499 | * do not support this access right. |
1511 | */ | 1500 | */ |
1512 | SYNCHRONIZE = const_cpu_to_le32(0x00100000), | 1501 | SYNCHRONIZE = cpu_to_le32(0x00100000), |
1513 | 1502 | ||
1514 | /* | 1503 | /* |
1515 | * The following STANDARD_RIGHTS_* are combinations of the above for | 1504 | * The following STANDARD_RIGHTS_* are combinations of the above for |
@@ -1517,25 +1506,25 @@ enum { | |||
1517 | */ | 1506 | */ |
1518 | 1507 | ||
1519 | /* These are currently defined to READ_CONTROL. */ | 1508 | /* These are currently defined to READ_CONTROL. */ |
1520 | STANDARD_RIGHTS_READ = const_cpu_to_le32(0x00020000), | 1509 | STANDARD_RIGHTS_READ = cpu_to_le32(0x00020000), |
1521 | STANDARD_RIGHTS_WRITE = const_cpu_to_le32(0x00020000), | 1510 | STANDARD_RIGHTS_WRITE = cpu_to_le32(0x00020000), |
1522 | STANDARD_RIGHTS_EXECUTE = const_cpu_to_le32(0x00020000), | 1511 | STANDARD_RIGHTS_EXECUTE = cpu_to_le32(0x00020000), |
1523 | 1512 | ||
1524 | /* Combines DELETE, READ_CONTROL, WRITE_DAC, and WRITE_OWNER access. */ | 1513 | /* Combines DELETE, READ_CONTROL, WRITE_DAC, and WRITE_OWNER access. */ |
1525 | STANDARD_RIGHTS_REQUIRED = const_cpu_to_le32(0x000f0000), | 1514 | STANDARD_RIGHTS_REQUIRED = cpu_to_le32(0x000f0000), |
1526 | 1515 | ||
1527 | /* | 1516 | /* |
1528 | * Combines DELETE, READ_CONTROL, WRITE_DAC, WRITE_OWNER, and | 1517 | * Combines DELETE, READ_CONTROL, WRITE_DAC, WRITE_OWNER, and |
1529 | * SYNCHRONIZE access. | 1518 | * SYNCHRONIZE access. |
1530 | */ | 1519 | */ |
1531 | STANDARD_RIGHTS_ALL = const_cpu_to_le32(0x001f0000), | 1520 | STANDARD_RIGHTS_ALL = cpu_to_le32(0x001f0000), |
1532 | 1521 | ||
1533 | /* | 1522 | /* |
1534 | * The access system ACL and maximum allowed access types (bits 24 to | 1523 | * The access system ACL and maximum allowed access types (bits 24 to |
1535 | * 25, bits 26 to 27 are reserved). | 1524 | * 25, bits 26 to 27 are reserved). |
1536 | */ | 1525 | */ |
1537 | ACCESS_SYSTEM_SECURITY = const_cpu_to_le32(0x01000000), | 1526 | ACCESS_SYSTEM_SECURITY = cpu_to_le32(0x01000000), |
1538 | MAXIMUM_ALLOWED = const_cpu_to_le32(0x02000000), | 1527 | MAXIMUM_ALLOWED = cpu_to_le32(0x02000000), |
1539 | 1528 | ||
1540 | /* | 1529 | /* |
1541 | * The generic rights (bits 28 to 31). These map onto the standard and | 1530 | * The generic rights (bits 28 to 31). These map onto the standard and |
@@ -1543,10 +1532,10 @@ enum { | |||
1543 | */ | 1532 | */ |
1544 | 1533 | ||
1545 | /* Read, write, and execute access. */ | 1534 | /* Read, write, and execute access. */ |
1546 | GENERIC_ALL = const_cpu_to_le32(0x10000000), | 1535 | GENERIC_ALL = cpu_to_le32(0x10000000), |
1547 | 1536 | ||
1548 | /* Execute access. */ | 1537 | /* Execute access. */ |
1549 | GENERIC_EXECUTE = const_cpu_to_le32(0x20000000), | 1538 | GENERIC_EXECUTE = cpu_to_le32(0x20000000), |
1550 | 1539 | ||
1551 | /* | 1540 | /* |
1552 | * Write access. For files, this maps onto: | 1541 | * Write access. For files, this maps onto: |
@@ -1555,7 +1544,7 @@ enum { | |||
1555 | * For directories, the mapping has the same numerical value. See | 1544 | * For directories, the mapping has the same numerical value. See |
1556 | * above for the descriptions of the rights granted. | 1545 | * above for the descriptions of the rights granted. |
1557 | */ | 1546 | */ |
1558 | GENERIC_WRITE = const_cpu_to_le32(0x40000000), | 1547 | GENERIC_WRITE = cpu_to_le32(0x40000000), |
1559 | 1548 | ||
1560 | /* | 1549 | /* |
1561 | * Read access. For files, this maps onto: | 1550 | * Read access. For files, this maps onto: |
@@ -1564,7 +1553,7 @@ enum { | |||
1564 | * For directories, the mapping has the same numberical value. See | 1553 | * For directories, the mapping has the same numberical value. See |
1565 | * above for the descriptions of the rights granted. | 1554 | * above for the descriptions of the rights granted. |
1566 | */ | 1555 | */ |
1567 | GENERIC_READ = const_cpu_to_le32(0x80000000), | 1556 | GENERIC_READ = cpu_to_le32(0x80000000), |
1568 | }; | 1557 | }; |
1569 | 1558 | ||
1570 | typedef le32 ACCESS_MASK; | 1559 | typedef le32 ACCESS_MASK; |
@@ -1604,8 +1593,8 @@ typedef struct { | |||
1604 | * The object ACE flags (32-bit). | 1593 | * The object ACE flags (32-bit). |
1605 | */ | 1594 | */ |
1606 | enum { | 1595 | enum { |
1607 | ACE_OBJECT_TYPE_PRESENT = const_cpu_to_le32(1), | 1596 | ACE_OBJECT_TYPE_PRESENT = cpu_to_le32(1), |
1608 | ACE_INHERITED_OBJECT_TYPE_PRESENT = const_cpu_to_le32(2), | 1597 | ACE_INHERITED_OBJECT_TYPE_PRESENT = cpu_to_le32(2), |
1609 | }; | 1598 | }; |
1610 | 1599 | ||
1611 | typedef le32 OBJECT_ACE_FLAGS; | 1600 | typedef le32 OBJECT_ACE_FLAGS; |
@@ -1706,23 +1695,23 @@ typedef enum { | |||
1706 | * expressed as offsets from the beginning of the security descriptor. | 1695 | * expressed as offsets from the beginning of the security descriptor. |
1707 | */ | 1696 | */ |
1708 | enum { | 1697 | enum { |
1709 | SE_OWNER_DEFAULTED = const_cpu_to_le16(0x0001), | 1698 | SE_OWNER_DEFAULTED = cpu_to_le16(0x0001), |
1710 | SE_GROUP_DEFAULTED = const_cpu_to_le16(0x0002), | 1699 | SE_GROUP_DEFAULTED = cpu_to_le16(0x0002), |
1711 | SE_DACL_PRESENT = const_cpu_to_le16(0x0004), | 1700 | SE_DACL_PRESENT = cpu_to_le16(0x0004), |
1712 | SE_DACL_DEFAULTED = const_cpu_to_le16(0x0008), | 1701 | SE_DACL_DEFAULTED = cpu_to_le16(0x0008), |
1713 | 1702 | ||
1714 | SE_SACL_PRESENT = const_cpu_to_le16(0x0010), | 1703 | SE_SACL_PRESENT = cpu_to_le16(0x0010), |
1715 | SE_SACL_DEFAULTED = const_cpu_to_le16(0x0020), | 1704 | SE_SACL_DEFAULTED = cpu_to_le16(0x0020), |
1716 | 1705 | ||
1717 | SE_DACL_AUTO_INHERIT_REQ = const_cpu_to_le16(0x0100), | 1706 | SE_DACL_AUTO_INHERIT_REQ = cpu_to_le16(0x0100), |
1718 | SE_SACL_AUTO_INHERIT_REQ = const_cpu_to_le16(0x0200), | 1707 | SE_SACL_AUTO_INHERIT_REQ = cpu_to_le16(0x0200), |
1719 | SE_DACL_AUTO_INHERITED = const_cpu_to_le16(0x0400), | 1708 | SE_DACL_AUTO_INHERITED = cpu_to_le16(0x0400), |
1720 | SE_SACL_AUTO_INHERITED = const_cpu_to_le16(0x0800), | 1709 | SE_SACL_AUTO_INHERITED = cpu_to_le16(0x0800), |
1721 | 1710 | ||
1722 | SE_DACL_PROTECTED = const_cpu_to_le16(0x1000), | 1711 | SE_DACL_PROTECTED = cpu_to_le16(0x1000), |
1723 | SE_SACL_PROTECTED = const_cpu_to_le16(0x2000), | 1712 | SE_SACL_PROTECTED = cpu_to_le16(0x2000), |
1724 | SE_RM_CONTROL_VALID = const_cpu_to_le16(0x4000), | 1713 | SE_RM_CONTROL_VALID = cpu_to_le16(0x4000), |
1725 | SE_SELF_RELATIVE = const_cpu_to_le16(0x8000) | 1714 | SE_SELF_RELATIVE = cpu_to_le16(0x8000) |
1726 | } __attribute__ ((__packed__)); | 1715 | } __attribute__ ((__packed__)); |
1727 | 1716 | ||
1728 | typedef le16 SECURITY_DESCRIPTOR_CONTROL; | 1717 | typedef le16 SECURITY_DESCRIPTOR_CONTROL; |
@@ -1910,21 +1899,21 @@ typedef struct { | |||
1910 | * Possible flags for the volume (16-bit). | 1899 | * Possible flags for the volume (16-bit). |
1911 | */ | 1900 | */ |
1912 | enum { | 1901 | enum { |
1913 | VOLUME_IS_DIRTY = const_cpu_to_le16(0x0001), | 1902 | VOLUME_IS_DIRTY = cpu_to_le16(0x0001), |
1914 | VOLUME_RESIZE_LOG_FILE = const_cpu_to_le16(0x0002), | 1903 | VOLUME_RESIZE_LOG_FILE = cpu_to_le16(0x0002), |
1915 | VOLUME_UPGRADE_ON_MOUNT = const_cpu_to_le16(0x0004), | 1904 | VOLUME_UPGRADE_ON_MOUNT = cpu_to_le16(0x0004), |
1916 | VOLUME_MOUNTED_ON_NT4 = const_cpu_to_le16(0x0008), | 1905 | VOLUME_MOUNTED_ON_NT4 = cpu_to_le16(0x0008), |
1917 | 1906 | ||
1918 | VOLUME_DELETE_USN_UNDERWAY = const_cpu_to_le16(0x0010), | 1907 | VOLUME_DELETE_USN_UNDERWAY = cpu_to_le16(0x0010), |
1919 | VOLUME_REPAIR_OBJECT_ID = const_cpu_to_le16(0x0020), | 1908 | VOLUME_REPAIR_OBJECT_ID = cpu_to_le16(0x0020), |
1920 | 1909 | ||
1921 | VOLUME_CHKDSK_UNDERWAY = const_cpu_to_le16(0x4000), | 1910 | VOLUME_CHKDSK_UNDERWAY = cpu_to_le16(0x4000), |
1922 | VOLUME_MODIFIED_BY_CHKDSK = const_cpu_to_le16(0x8000), | 1911 | VOLUME_MODIFIED_BY_CHKDSK = cpu_to_le16(0x8000), |
1923 | 1912 | ||
1924 | VOLUME_FLAGS_MASK = const_cpu_to_le16(0xc03f), | 1913 | VOLUME_FLAGS_MASK = cpu_to_le16(0xc03f), |
1925 | 1914 | ||
1926 | /* To make our life easier when checking if we must mount read-only. */ | 1915 | /* To make our life easier when checking if we must mount read-only. */ |
1927 | VOLUME_MUST_MOUNT_RO_MASK = const_cpu_to_le16(0xc027), | 1916 | VOLUME_MUST_MOUNT_RO_MASK = cpu_to_le16(0xc027), |
1928 | } __attribute__ ((__packed__)); | 1917 | } __attribute__ ((__packed__)); |
1929 | 1918 | ||
1930 | typedef le16 VOLUME_FLAGS; | 1919 | typedef le16 VOLUME_FLAGS; |
@@ -2109,26 +2098,26 @@ typedef struct { | |||
2109 | * The user quota flags. Names explain meaning. | 2098 | * The user quota flags. Names explain meaning. |
2110 | */ | 2099 | */ |
2111 | enum { | 2100 | enum { |
2112 | QUOTA_FLAG_DEFAULT_LIMITS = const_cpu_to_le32(0x00000001), | 2101 | QUOTA_FLAG_DEFAULT_LIMITS = cpu_to_le32(0x00000001), |
2113 | QUOTA_FLAG_LIMIT_REACHED = const_cpu_to_le32(0x00000002), | 2102 | QUOTA_FLAG_LIMIT_REACHED = cpu_to_le32(0x00000002), |
2114 | QUOTA_FLAG_ID_DELETED = const_cpu_to_le32(0x00000004), | 2103 | QUOTA_FLAG_ID_DELETED = cpu_to_le32(0x00000004), |
2115 | 2104 | ||
2116 | QUOTA_FLAG_USER_MASK = const_cpu_to_le32(0x00000007), | 2105 | QUOTA_FLAG_USER_MASK = cpu_to_le32(0x00000007), |
2117 | /* This is a bit mask for the user quota flags. */ | 2106 | /* This is a bit mask for the user quota flags. */ |
2118 | 2107 | ||
2119 | /* | 2108 | /* |
2120 | * These flags are only present in the quota defaults index entry, i.e. | 2109 | * These flags are only present in the quota defaults index entry, i.e. |
2121 | * in the entry where owner_id = QUOTA_DEFAULTS_ID. | 2110 | * in the entry where owner_id = QUOTA_DEFAULTS_ID. |
2122 | */ | 2111 | */ |
2123 | QUOTA_FLAG_TRACKING_ENABLED = const_cpu_to_le32(0x00000010), | 2112 | QUOTA_FLAG_TRACKING_ENABLED = cpu_to_le32(0x00000010), |
2124 | QUOTA_FLAG_ENFORCEMENT_ENABLED = const_cpu_to_le32(0x00000020), | 2113 | QUOTA_FLAG_ENFORCEMENT_ENABLED = cpu_to_le32(0x00000020), |
2125 | QUOTA_FLAG_TRACKING_REQUESTED = const_cpu_to_le32(0x00000040), | 2114 | QUOTA_FLAG_TRACKING_REQUESTED = cpu_to_le32(0x00000040), |
2126 | QUOTA_FLAG_LOG_THRESHOLD = const_cpu_to_le32(0x00000080), | 2115 | QUOTA_FLAG_LOG_THRESHOLD = cpu_to_le32(0x00000080), |
2127 | 2116 | ||
2128 | QUOTA_FLAG_LOG_LIMIT = const_cpu_to_le32(0x00000100), | 2117 | QUOTA_FLAG_LOG_LIMIT = cpu_to_le32(0x00000100), |
2129 | QUOTA_FLAG_OUT_OF_DATE = const_cpu_to_le32(0x00000200), | 2118 | QUOTA_FLAG_OUT_OF_DATE = cpu_to_le32(0x00000200), |
2130 | QUOTA_FLAG_CORRUPT = const_cpu_to_le32(0x00000400), | 2119 | QUOTA_FLAG_CORRUPT = cpu_to_le32(0x00000400), |
2131 | QUOTA_FLAG_PENDING_DELETES = const_cpu_to_le32(0x00000800), | 2120 | QUOTA_FLAG_PENDING_DELETES = cpu_to_le32(0x00000800), |
2132 | }; | 2121 | }; |
2133 | 2122 | ||
2134 | typedef le32 QUOTA_FLAGS; | 2123 | typedef le32 QUOTA_FLAGS; |
@@ -2172,9 +2161,9 @@ typedef struct { | |||
2172 | * Predefined owner_id values (32-bit). | 2161 | * Predefined owner_id values (32-bit). |
2173 | */ | 2162 | */ |
2174 | enum { | 2163 | enum { |
2175 | QUOTA_INVALID_ID = const_cpu_to_le32(0x00000000), | 2164 | QUOTA_INVALID_ID = cpu_to_le32(0x00000000), |
2176 | QUOTA_DEFAULTS_ID = const_cpu_to_le32(0x00000001), | 2165 | QUOTA_DEFAULTS_ID = cpu_to_le32(0x00000001), |
2177 | QUOTA_FIRST_USER_ID = const_cpu_to_le32(0x00000100), | 2166 | QUOTA_FIRST_USER_ID = cpu_to_le32(0x00000100), |
2178 | }; | 2167 | }; |
2179 | 2168 | ||
2180 | /* | 2169 | /* |
@@ -2189,14 +2178,14 @@ typedef enum { | |||
2189 | * Index entry flags (16-bit). | 2178 | * Index entry flags (16-bit). |
2190 | */ | 2179 | */ |
2191 | enum { | 2180 | enum { |
2192 | INDEX_ENTRY_NODE = const_cpu_to_le16(1), /* This entry contains a | 2181 | INDEX_ENTRY_NODE = cpu_to_le16(1), /* This entry contains a |
2193 | sub-node, i.e. a reference to an index block in form of | 2182 | sub-node, i.e. a reference to an index block in form of |
2194 | a virtual cluster number (see below). */ | 2183 | a virtual cluster number (see below). */ |
2195 | INDEX_ENTRY_END = const_cpu_to_le16(2), /* This signifies the last | 2184 | INDEX_ENTRY_END = cpu_to_le16(2), /* This signifies the last |
2196 | entry in an index block. The index entry does not | 2185 | entry in an index block. The index entry does not |
2197 | represent a file but it can point to a sub-node. */ | 2186 | represent a file but it can point to a sub-node. */ |
2198 | 2187 | ||
2199 | INDEX_ENTRY_SPACE_FILLER = const_cpu_to_le16(0xffff), /* gcc: Force | 2188 | INDEX_ENTRY_SPACE_FILLER = cpu_to_le16(0xffff), /* gcc: Force |
2200 | enum bit width to 16-bit. */ | 2189 | enum bit width to 16-bit. */ |
2201 | } __attribute__ ((__packed__)); | 2190 | } __attribute__ ((__packed__)); |
2202 | 2191 | ||
@@ -2334,26 +2323,26 @@ typedef struct { | |||
2334 | * These are the predefined reparse point tags: | 2323 | * These are the predefined reparse point tags: |
2335 | */ | 2324 | */ |
2336 | enum { | 2325 | enum { |
2337 | IO_REPARSE_TAG_IS_ALIAS = const_cpu_to_le32(0x20000000), | 2326 | IO_REPARSE_TAG_IS_ALIAS = cpu_to_le32(0x20000000), |
2338 | IO_REPARSE_TAG_IS_HIGH_LATENCY = const_cpu_to_le32(0x40000000), | 2327 | IO_REPARSE_TAG_IS_HIGH_LATENCY = cpu_to_le32(0x40000000), |
2339 | IO_REPARSE_TAG_IS_MICROSOFT = const_cpu_to_le32(0x80000000), | 2328 | IO_REPARSE_TAG_IS_MICROSOFT = cpu_to_le32(0x80000000), |
2340 | 2329 | ||
2341 | IO_REPARSE_TAG_RESERVED_ZERO = const_cpu_to_le32(0x00000000), | 2330 | IO_REPARSE_TAG_RESERVED_ZERO = cpu_to_le32(0x00000000), |
2342 | IO_REPARSE_TAG_RESERVED_ONE = const_cpu_to_le32(0x00000001), | 2331 | IO_REPARSE_TAG_RESERVED_ONE = cpu_to_le32(0x00000001), |
2343 | IO_REPARSE_TAG_RESERVED_RANGE = const_cpu_to_le32(0x00000001), | 2332 | IO_REPARSE_TAG_RESERVED_RANGE = cpu_to_le32(0x00000001), |
2344 | 2333 | ||
2345 | IO_REPARSE_TAG_NSS = const_cpu_to_le32(0x68000005), | 2334 | IO_REPARSE_TAG_NSS = cpu_to_le32(0x68000005), |
2346 | IO_REPARSE_TAG_NSS_RECOVER = const_cpu_to_le32(0x68000006), | 2335 | IO_REPARSE_TAG_NSS_RECOVER = cpu_to_le32(0x68000006), |
2347 | IO_REPARSE_TAG_SIS = const_cpu_to_le32(0x68000007), | 2336 | IO_REPARSE_TAG_SIS = cpu_to_le32(0x68000007), |
2348 | IO_REPARSE_TAG_DFS = const_cpu_to_le32(0x68000008), | 2337 | IO_REPARSE_TAG_DFS = cpu_to_le32(0x68000008), |
2349 | 2338 | ||
2350 | IO_REPARSE_TAG_MOUNT_POINT = const_cpu_to_le32(0x88000003), | 2339 | IO_REPARSE_TAG_MOUNT_POINT = cpu_to_le32(0x88000003), |
2351 | 2340 | ||
2352 | IO_REPARSE_TAG_HSM = const_cpu_to_le32(0xa8000004), | 2341 | IO_REPARSE_TAG_HSM = cpu_to_le32(0xa8000004), |
2353 | 2342 | ||
2354 | IO_REPARSE_TAG_SYMBOLIC_LINK = const_cpu_to_le32(0xe8000000), | 2343 | IO_REPARSE_TAG_SYMBOLIC_LINK = cpu_to_le32(0xe8000000), |
2355 | 2344 | ||
2356 | IO_REPARSE_TAG_VALID_VALUES = const_cpu_to_le32(0xe000ffff), | 2345 | IO_REPARSE_TAG_VALID_VALUES = cpu_to_le32(0xe000ffff), |
2357 | }; | 2346 | }; |
2358 | 2347 | ||
2359 | /* | 2348 | /* |
diff --git a/fs/ntfs/logfile.h b/fs/ntfs/logfile.h index 9468e1c45ae..b5a6f08bd35 100644 --- a/fs/ntfs/logfile.h +++ b/fs/ntfs/logfile.h | |||
@@ -104,7 +104,7 @@ typedef struct { | |||
104 | * in this particular client array. Also inside the client records themselves, | 104 | * in this particular client array. Also inside the client records themselves, |
105 | * this means that there are no client records preceding or following this one. | 105 | * this means that there are no client records preceding or following this one. |
106 | */ | 106 | */ |
107 | #define LOGFILE_NO_CLIENT const_cpu_to_le16(0xffff) | 107 | #define LOGFILE_NO_CLIENT cpu_to_le16(0xffff) |
108 | #define LOGFILE_NO_CLIENT_CPU 0xffff | 108 | #define LOGFILE_NO_CLIENT_CPU 0xffff |
109 | 109 | ||
110 | /* | 110 | /* |
@@ -112,8 +112,8 @@ typedef struct { | |||
112 | * information about the log file in which they are present. | 112 | * information about the log file in which they are present. |
113 | */ | 113 | */ |
114 | enum { | 114 | enum { |
115 | RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002), | 115 | RESTART_VOLUME_IS_CLEAN = cpu_to_le16(0x0002), |
116 | RESTART_SPACE_FILLER = const_cpu_to_le16(0xffff), /* gcc: Force enum bit width to 16. */ | 116 | RESTART_SPACE_FILLER = cpu_to_le16(0xffff), /* gcc: Force enum bit width to 16. */ |
117 | } __attribute__ ((__packed__)); | 117 | } __attribute__ ((__packed__)); |
118 | 118 | ||
119 | typedef le16 RESTART_AREA_FLAGS; | 119 | typedef le16 RESTART_AREA_FLAGS; |
diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 17d32ca6bc3..23bf68453d7 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c | |||
@@ -2839,7 +2839,7 @@ int ntfs_extent_mft_record_free(ntfs_inode *ni, MFT_RECORD *m) | |||
2839 | */ | 2839 | */ |
2840 | 2840 | ||
2841 | /* Mark the mft record as not in use. */ | 2841 | /* Mark the mft record as not in use. */ |
2842 | m->flags &= const_cpu_to_le16(~const_le16_to_cpu(MFT_RECORD_IN_USE)); | 2842 | m->flags &= ~MFT_RECORD_IN_USE; |
2843 | 2843 | ||
2844 | /* Increment the sequence number, skipping zero, if it is not zero. */ | 2844 | /* Increment the sequence number, skipping zero, if it is not zero. */ |
2845 | old_seq_no = m->sequence_number; | 2845 | old_seq_no = m->sequence_number; |
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 4a46743b507..f76951dcd4a 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c | |||
@@ -618,7 +618,7 @@ static bool is_boot_sector_ntfs(const struct super_block *sb, | |||
618 | * many BIOSes will refuse to boot from a bootsector if the magic is | 618 | * many BIOSes will refuse to boot from a bootsector if the magic is |
619 | * incorrect, so we emit a warning. | 619 | * incorrect, so we emit a warning. |
620 | */ | 620 | */ |
621 | if (!silent && b->end_of_sector_marker != const_cpu_to_le16(0xaa55)) | 621 | if (!silent && b->end_of_sector_marker != cpu_to_le16(0xaa55)) |
622 | ntfs_warning(sb, "Invalid end of sector marker."); | 622 | ntfs_warning(sb, "Invalid end of sector marker."); |
623 | return true; | 623 | return true; |
624 | not_ntfs: | 624 | not_ntfs: |
@@ -1242,13 +1242,13 @@ static int check_windows_hibernation_status(ntfs_volume *vol) | |||
1242 | u32 *kaddr, *kend; | 1242 | u32 *kaddr, *kend; |
1243 | ntfs_name *name = NULL; | 1243 | ntfs_name *name = NULL; |
1244 | int ret = 1; | 1244 | int ret = 1; |
1245 | static const ntfschar hiberfil[13] = { const_cpu_to_le16('h'), | 1245 | static const ntfschar hiberfil[13] = { cpu_to_le16('h'), |
1246 | const_cpu_to_le16('i'), const_cpu_to_le16('b'), | 1246 | cpu_to_le16('i'), cpu_to_le16('b'), |
1247 | const_cpu_to_le16('e'), const_cpu_to_le16('r'), | 1247 | cpu_to_le16('e'), cpu_to_le16('r'), |
1248 | const_cpu_to_le16('f'), const_cpu_to_le16('i'), | 1248 | cpu_to_le16('f'), cpu_to_le16('i'), |
1249 | const_cpu_to_le16('l'), const_cpu_to_le16('.'), | 1249 | cpu_to_le16('l'), cpu_to_le16('.'), |
1250 | const_cpu_to_le16('s'), const_cpu_to_le16('y'), | 1250 | cpu_to_le16('s'), cpu_to_le16('y'), |
1251 | const_cpu_to_le16('s'), 0 }; | 1251 | cpu_to_le16('s'), 0 }; |
1252 | 1252 | ||
1253 | ntfs_debug("Entering."); | 1253 | ntfs_debug("Entering."); |
1254 | /* | 1254 | /* |
@@ -1296,7 +1296,7 @@ static int check_windows_hibernation_status(ntfs_volume *vol) | |||
1296 | goto iput_out; | 1296 | goto iput_out; |
1297 | } | 1297 | } |
1298 | kaddr = (u32*)page_address(page); | 1298 | kaddr = (u32*)page_address(page); |
1299 | if (*(le32*)kaddr == const_cpu_to_le32(0x72626968)/*'hibr'*/) { | 1299 | if (*(le32*)kaddr == cpu_to_le32(0x72626968)/*'hibr'*/) { |
1300 | ntfs_debug("Magic \"hibr\" found in hiberfil.sys. Windows is " | 1300 | ntfs_debug("Magic \"hibr\" found in hiberfil.sys. Windows is " |
1301 | "hibernated on the volume. This is the " | 1301 | "hibernated on the volume. This is the " |
1302 | "system volume."); | 1302 | "system volume."); |
@@ -1337,12 +1337,12 @@ static bool load_and_init_quota(ntfs_volume *vol) | |||
1337 | MFT_REF mref; | 1337 | MFT_REF mref; |
1338 | struct inode *tmp_ino; | 1338 | struct inode *tmp_ino; |
1339 | ntfs_name *name = NULL; | 1339 | ntfs_name *name = NULL; |
1340 | static const ntfschar Quota[7] = { const_cpu_to_le16('$'), | 1340 | static const ntfschar Quota[7] = { cpu_to_le16('$'), |
1341 | const_cpu_to_le16('Q'), const_cpu_to_le16('u'), | 1341 | cpu_to_le16('Q'), cpu_to_le16('u'), |
1342 | const_cpu_to_le16('o'), const_cpu_to_le16('t'), | 1342 | cpu_to_le16('o'), cpu_to_le16('t'), |
1343 | const_cpu_to_le16('a'), 0 }; | 1343 | cpu_to_le16('a'), 0 }; |
1344 | static ntfschar Q[3] = { const_cpu_to_le16('$'), | 1344 | static ntfschar Q[3] = { cpu_to_le16('$'), |
1345 | const_cpu_to_le16('Q'), 0 }; | 1345 | cpu_to_le16('Q'), 0 }; |
1346 | 1346 | ||
1347 | ntfs_debug("Entering."); | 1347 | ntfs_debug("Entering."); |
1348 | /* | 1348 | /* |
@@ -1416,16 +1416,16 @@ static bool load_and_init_usnjrnl(ntfs_volume *vol) | |||
1416 | struct page *page; | 1416 | struct page *page; |
1417 | ntfs_name *name = NULL; | 1417 | ntfs_name *name = NULL; |
1418 | USN_HEADER *uh; | 1418 | USN_HEADER *uh; |
1419 | static const ntfschar UsnJrnl[9] = { const_cpu_to_le16('$'), | 1419 | static const ntfschar UsnJrnl[9] = { cpu_to_le16('$'), |
1420 | const_cpu_to_le16('U'), const_cpu_to_le16('s'), | 1420 | cpu_to_le16('U'), cpu_to_le16('s'), |
1421 | const_cpu_to_le16('n'), const_cpu_to_le16('J'), | 1421 | cpu_to_le16('n'), cpu_to_le16('J'), |
1422 | const_cpu_to_le16('r'), const_cpu_to_le16('n'), | 1422 | cpu_to_le16('r'), cpu_to_le16('n'), |
1423 | const_cpu_to_le16('l'), 0 }; | 1423 | cpu_to_le16('l'), 0 }; |
1424 | static ntfschar Max[5] = { const_cpu_to_le16('$'), | 1424 | static ntfschar Max[5] = { cpu_to_le16('$'), |
1425 | const_cpu_to_le16('M'), const_cpu_to_le16('a'), | 1425 | cpu_to_le16('M'), cpu_to_le16('a'), |
1426 | const_cpu_to_le16('x'), 0 }; | 1426 | cpu_to_le16('x'), 0 }; |
1427 | static ntfschar J[3] = { const_cpu_to_le16('$'), | 1427 | static ntfschar J[3] = { cpu_to_le16('$'), |
1428 | const_cpu_to_le16('J'), 0 }; | 1428 | cpu_to_le16('J'), 0 }; |
1429 | 1429 | ||
1430 | ntfs_debug("Entering."); | 1430 | ntfs_debug("Entering."); |
1431 | /* | 1431 | /* |
diff --git a/fs/ntfs/usnjrnl.h b/fs/ntfs/usnjrnl.h index 4087fbdac32..00d8e6bd7c3 100644 --- a/fs/ntfs/usnjrnl.h +++ b/fs/ntfs/usnjrnl.h | |||
@@ -116,27 +116,27 @@ typedef struct { | |||
116 | * documentation: http://www.linux-ntfs.org/ | 116 | * documentation: http://www.linux-ntfs.org/ |
117 | */ | 117 | */ |
118 | enum { | 118 | enum { |
119 | USN_REASON_DATA_OVERWRITE = const_cpu_to_le32(0x00000001), | 119 | USN_REASON_DATA_OVERWRITE = cpu_to_le32(0x00000001), |
120 | USN_REASON_DATA_EXTEND = const_cpu_to_le32(0x00000002), | 120 | USN_REASON_DATA_EXTEND = cpu_to_le32(0x00000002), |
121 | USN_REASON_DATA_TRUNCATION = const_cpu_to_le32(0x00000004), | 121 | USN_REASON_DATA_TRUNCATION = cpu_to_le32(0x00000004), |
122 | USN_REASON_NAMED_DATA_OVERWRITE = const_cpu_to_le32(0x00000010), | 122 | USN_REASON_NAMED_DATA_OVERWRITE = cpu_to_le32(0x00000010), |
123 | USN_REASON_NAMED_DATA_EXTEND = const_cpu_to_le32(0x00000020), | 123 | USN_REASON_NAMED_DATA_EXTEND = cpu_to_le32(0x00000020), |
124 | USN_REASON_NAMED_DATA_TRUNCATION= const_cpu_to_le32(0x00000040), | 124 | USN_REASON_NAMED_DATA_TRUNCATION= cpu_to_le32(0x00000040), |
125 | USN_REASON_FILE_CREATE = const_cpu_to_le32(0x00000100), | 125 | USN_REASON_FILE_CREATE = cpu_to_le32(0x00000100), |
126 | USN_REASON_FILE_DELETE = const_cpu_to_le32(0x00000200), | 126 | USN_REASON_FILE_DELETE = cpu_to_le32(0x00000200), |
127 | USN_REASON_EA_CHANGE = const_cpu_to_le32(0x00000400), | 127 | USN_REASON_EA_CHANGE = cpu_to_le32(0x00000400), |
128 | USN_REASON_SECURITY_CHANGE = const_cpu_to_le32(0x00000800), | 128 | USN_REASON_SECURITY_CHANGE = cpu_to_le32(0x00000800), |
129 | USN_REASON_RENAME_OLD_NAME = const_cpu_to_le32(0x00001000), | 129 | USN_REASON_RENAME_OLD_NAME = cpu_to_le32(0x00001000), |
130 | USN_REASON_RENAME_NEW_NAME = const_cpu_to_le32(0x00002000), | 130 | USN_REASON_RENAME_NEW_NAME = cpu_to_le32(0x00002000), |
131 | USN_REASON_INDEXABLE_CHANGE = const_cpu_to_le32(0x00004000), | 131 | USN_REASON_INDEXABLE_CHANGE = cpu_to_le32(0x00004000), |
132 | USN_REASON_BASIC_INFO_CHANGE = const_cpu_to_le32(0x00008000), | 132 | USN_REASON_BASIC_INFO_CHANGE = cpu_to_le32(0x00008000), |
133 | USN_REASON_HARD_LINK_CHANGE = const_cpu_to_le32(0x00010000), | 133 | USN_REASON_HARD_LINK_CHANGE = cpu_to_le32(0x00010000), |
134 | USN_REASON_COMPRESSION_CHANGE = const_cpu_to_le32(0x00020000), | 134 | USN_REASON_COMPRESSION_CHANGE = cpu_to_le32(0x00020000), |
135 | USN_REASON_ENCRYPTION_CHANGE = const_cpu_to_le32(0x00040000), | 135 | USN_REASON_ENCRYPTION_CHANGE = cpu_to_le32(0x00040000), |
136 | USN_REASON_OBJECT_ID_CHANGE = const_cpu_to_le32(0x00080000), | 136 | USN_REASON_OBJECT_ID_CHANGE = cpu_to_le32(0x00080000), |
137 | USN_REASON_REPARSE_POINT_CHANGE = const_cpu_to_le32(0x00100000), | 137 | USN_REASON_REPARSE_POINT_CHANGE = cpu_to_le32(0x00100000), |
138 | USN_REASON_STREAM_CHANGE = const_cpu_to_le32(0x00200000), | 138 | USN_REASON_STREAM_CHANGE = cpu_to_le32(0x00200000), |
139 | USN_REASON_CLOSE = const_cpu_to_le32(0x80000000), | 139 | USN_REASON_CLOSE = cpu_to_le32(0x80000000), |
140 | }; | 140 | }; |
141 | 141 | ||
142 | typedef le32 USN_REASON_FLAGS; | 142 | typedef le32 USN_REASON_FLAGS; |
@@ -148,9 +148,9 @@ typedef le32 USN_REASON_FLAGS; | |||
148 | * http://www.linux-ntfs.org/ | 148 | * http://www.linux-ntfs.org/ |
149 | */ | 149 | */ |
150 | enum { | 150 | enum { |
151 | USN_SOURCE_DATA_MANAGEMENT = const_cpu_to_le32(0x00000001), | 151 | USN_SOURCE_DATA_MANAGEMENT = cpu_to_le32(0x00000001), |
152 | USN_SOURCE_AUXILIARY_DATA = const_cpu_to_le32(0x00000002), | 152 | USN_SOURCE_AUXILIARY_DATA = cpu_to_le32(0x00000002), |
153 | USN_SOURCE_REPLICATION_MANAGEMENT = const_cpu_to_le32(0x00000004), | 153 | USN_SOURCE_REPLICATION_MANAGEMENT = cpu_to_le32(0x00000004), |
154 | }; | 154 | }; |
155 | 155 | ||
156 | typedef le32 USN_SOURCE_INFO_FLAGS; | 156 | typedef le32 USN_SOURCE_INFO_FLAGS; |
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index eea1d24713e..b606496b72e 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c | |||
@@ -154,8 +154,9 @@ out: | |||
154 | return ret; | 154 | return ret; |
155 | } | 155 | } |
156 | 156 | ||
157 | static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct page *page) | 157 | static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
158 | { | 158 | { |
159 | struct page *page = vmf->page; | ||
159 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; | 160 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; |
160 | struct buffer_head *di_bh = NULL; | 161 | struct buffer_head *di_bh = NULL; |
161 | sigset_t blocked, oldset; | 162 | sigset_t blocked, oldset; |
@@ -196,7 +197,8 @@ out: | |||
196 | ret2 = ocfs2_vm_op_unblock_sigs(&oldset); | 197 | ret2 = ocfs2_vm_op_unblock_sigs(&oldset); |
197 | if (ret2 < 0) | 198 | if (ret2 < 0) |
198 | mlog_errno(ret2); | 199 | mlog_errno(ret2); |
199 | 200 | if (ret) | |
201 | ret = VM_FAULT_SIGBUS; | ||
200 | return ret; | 202 | return ret; |
201 | } | 203 | } |
202 | 204 | ||
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c index 4a9e0f65ae6..83adcc86943 100644 --- a/fs/proc/proc_tty.c +++ b/fs/proc/proc_tty.c | |||
@@ -144,16 +144,12 @@ void proc_tty_register_driver(struct tty_driver *driver) | |||
144 | { | 144 | { |
145 | struct proc_dir_entry *ent; | 145 | struct proc_dir_entry *ent; |
146 | 146 | ||
147 | if (!driver->ops->read_proc || !driver->driver_name || | 147 | if (!driver->driver_name || driver->proc_entry || |
148 | driver->proc_entry) | 148 | !driver->ops->proc_fops) |
149 | return; | 149 | return; |
150 | 150 | ||
151 | ent = create_proc_entry(driver->driver_name, 0, proc_tty_driver); | 151 | ent = proc_create_data(driver->driver_name, 0, proc_tty_driver, |
152 | if (!ent) | 152 | driver->ops->proc_fops, driver); |
153 | return; | ||
154 | ent->read_proc = driver->ops->read_proc; | ||
155 | ent->data = driver; | ||
156 | |||
157 | driver->proc_entry = ent; | 153 | driver->proc_entry = ent; |
158 | } | 154 | } |
159 | 155 | ||
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index 995ef1d6686..ebb2c417912 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c | |||
@@ -59,7 +59,6 @@ const struct inode_operations ramfs_file_inode_operations = { | |||
59 | */ | 59 | */ |
60 | int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) | 60 | int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) |
61 | { | 61 | { |
62 | struct pagevec lru_pvec; | ||
63 | unsigned long npages, xpages, loop, limit; | 62 | unsigned long npages, xpages, loop, limit; |
64 | struct page *pages; | 63 | struct page *pages; |
65 | unsigned order; | 64 | unsigned order; |
@@ -102,24 +101,20 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) | |||
102 | memset(data, 0, newsize); | 101 | memset(data, 0, newsize); |
103 | 102 | ||
104 | /* attach all the pages to the inode's address space */ | 103 | /* attach all the pages to the inode's address space */ |
105 | pagevec_init(&lru_pvec, 0); | ||
106 | for (loop = 0; loop < npages; loop++) { | 104 | for (loop = 0; loop < npages; loop++) { |
107 | struct page *page = pages + loop; | 105 | struct page *page = pages + loop; |
108 | 106 | ||
109 | ret = add_to_page_cache(page, inode->i_mapping, loop, GFP_KERNEL); | 107 | ret = add_to_page_cache_lru(page, inode->i_mapping, loop, |
108 | GFP_KERNEL); | ||
110 | if (ret < 0) | 109 | if (ret < 0) |
111 | goto add_error; | 110 | goto add_error; |
112 | 111 | ||
113 | if (!pagevec_add(&lru_pvec, page)) | ||
114 | __pagevec_lru_add_file(&lru_pvec); | ||
115 | |||
116 | /* prevent the page from being discarded on memory pressure */ | 112 | /* prevent the page from being discarded on memory pressure */ |
117 | SetPageDirty(page); | 113 | SetPageDirty(page); |
118 | 114 | ||
119 | unlock_page(page); | 115 | unlock_page(page); |
120 | } | 116 | } |
121 | 117 | ||
122 | pagevec_lru_add_file(&lru_pvec); | ||
123 | return 0; | 118 | return 0; |
124 | 119 | ||
125 | fsize_exceeded: | 120 | fsize_exceeded: |
@@ -128,10 +123,8 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) | |||
128 | return -EFBIG; | 123 | return -EFBIG; |
129 | 124 | ||
130 | add_error: | 125 | add_error: |
131 | pagevec_lru_add_file(&lru_pvec); | 126 | while (loop < npages) |
132 | page_cache_release(pages + loop); | 127 | __free_page(pages + loop++); |
133 | for (loop++; loop < npages; loop++) | ||
134 | __free_page(pages + loop); | ||
135 | return ret; | 128 | return ret; |
136 | } | 129 | } |
137 | 130 | ||
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index b7e6ac706b8..a404fb88e45 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c | |||
@@ -33,12 +33,15 @@ | |||
33 | #include <linux/backing-dev.h> | 33 | #include <linux/backing-dev.h> |
34 | #include <linux/ramfs.h> | 34 | #include <linux/ramfs.h> |
35 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
36 | #include <linux/parser.h> | ||
36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
37 | #include "internal.h" | 38 | #include "internal.h" |
38 | 39 | ||
39 | /* some random number */ | 40 | /* some random number */ |
40 | #define RAMFS_MAGIC 0x858458f6 | 41 | #define RAMFS_MAGIC 0x858458f6 |
41 | 42 | ||
43 | #define RAMFS_DEFAULT_MODE 0755 | ||
44 | |||
42 | static const struct super_operations ramfs_ops; | 45 | static const struct super_operations ramfs_ops; |
43 | static const struct inode_operations ramfs_dir_inode_operations; | 46 | static const struct inode_operations ramfs_dir_inode_operations; |
44 | 47 | ||
@@ -158,12 +161,75 @@ static const struct inode_operations ramfs_dir_inode_operations = { | |||
158 | static const struct super_operations ramfs_ops = { | 161 | static const struct super_operations ramfs_ops = { |
159 | .statfs = simple_statfs, | 162 | .statfs = simple_statfs, |
160 | .drop_inode = generic_delete_inode, | 163 | .drop_inode = generic_delete_inode, |
164 | .show_options = generic_show_options, | ||
165 | }; | ||
166 | |||
167 | struct ramfs_mount_opts { | ||
168 | umode_t mode; | ||
169 | }; | ||
170 | |||
171 | enum { | ||
172 | Opt_mode, | ||
173 | Opt_err | ||
174 | }; | ||
175 | |||
176 | static const match_table_t tokens = { | ||
177 | {Opt_mode, "mode=%o"}, | ||
178 | {Opt_err, NULL} | ||
179 | }; | ||
180 | |||
181 | struct ramfs_fs_info { | ||
182 | struct ramfs_mount_opts mount_opts; | ||
161 | }; | 183 | }; |
162 | 184 | ||
185 | static int ramfs_parse_options(char *data, struct ramfs_mount_opts *opts) | ||
186 | { | ||
187 | substring_t args[MAX_OPT_ARGS]; | ||
188 | int option; | ||
189 | int token; | ||
190 | char *p; | ||
191 | |||
192 | opts->mode = RAMFS_DEFAULT_MODE; | ||
193 | |||
194 | while ((p = strsep(&data, ",")) != NULL) { | ||
195 | if (!*p) | ||
196 | continue; | ||
197 | |||
198 | token = match_token(p, tokens, args); | ||
199 | switch (token) { | ||
200 | case Opt_mode: | ||
201 | if (match_octal(&args[0], &option)) | ||
202 | return -EINVAL; | ||
203 | opts->mode = option & S_IALLUGO; | ||
204 | break; | ||
205 | default: | ||
206 | printk(KERN_ERR "ramfs: bad mount option: %s\n", p); | ||
207 | return -EINVAL; | ||
208 | } | ||
209 | } | ||
210 | |||
211 | return 0; | ||
212 | } | ||
213 | |||
163 | static int ramfs_fill_super(struct super_block * sb, void * data, int silent) | 214 | static int ramfs_fill_super(struct super_block * sb, void * data, int silent) |
164 | { | 215 | { |
165 | struct inode * inode; | 216 | struct ramfs_fs_info *fsi; |
166 | struct dentry * root; | 217 | struct inode *inode = NULL; |
218 | struct dentry *root; | ||
219 | int err; | ||
220 | |||
221 | save_mount_options(sb, data); | ||
222 | |||
223 | fsi = kzalloc(sizeof(struct ramfs_fs_info), GFP_KERNEL); | ||
224 | if (!fsi) { | ||
225 | err = -ENOMEM; | ||
226 | goto fail; | ||
227 | } | ||
228 | sb->s_fs_info = fsi; | ||
229 | |||
230 | err = ramfs_parse_options(data, &fsi->mount_opts); | ||
231 | if (err) | ||
232 | goto fail; | ||
167 | 233 | ||
168 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 234 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
169 | sb->s_blocksize = PAGE_CACHE_SIZE; | 235 | sb->s_blocksize = PAGE_CACHE_SIZE; |
@@ -171,17 +237,23 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent) | |||
171 | sb->s_magic = RAMFS_MAGIC; | 237 | sb->s_magic = RAMFS_MAGIC; |
172 | sb->s_op = &ramfs_ops; | 238 | sb->s_op = &ramfs_ops; |
173 | sb->s_time_gran = 1; | 239 | sb->s_time_gran = 1; |
174 | inode = ramfs_get_inode(sb, S_IFDIR | 0755, 0); | 240 | inode = ramfs_get_inode(sb, S_IFDIR | fsi->mount_opts.mode, 0); |
175 | if (!inode) | 241 | if (!inode) { |
176 | return -ENOMEM; | 242 | err = -ENOMEM; |
243 | goto fail; | ||
244 | } | ||
177 | 245 | ||
178 | root = d_alloc_root(inode); | 246 | root = d_alloc_root(inode); |
179 | if (!root) { | 247 | if (!root) { |
180 | iput(inode); | 248 | err = -ENOMEM; |
181 | return -ENOMEM; | 249 | goto fail; |
182 | } | 250 | } |
183 | sb->s_root = root; | 251 | sb->s_root = root; |
184 | return 0; | 252 | return 0; |
253 | fail: | ||
254 | kfree(fsi); | ||
255 | iput(inode); | ||
256 | return err; | ||
185 | } | 257 | } |
186 | 258 | ||
187 | int ramfs_get_sb(struct file_system_type *fs_type, | 259 | int ramfs_get_sb(struct file_system_type *fs_type, |
@@ -197,10 +269,16 @@ static int rootfs_get_sb(struct file_system_type *fs_type, | |||
197 | mnt); | 269 | mnt); |
198 | } | 270 | } |
199 | 271 | ||
272 | static void ramfs_kill_sb(struct super_block *sb) | ||
273 | { | ||
274 | kfree(sb->s_fs_info); | ||
275 | kill_litter_super(sb); | ||
276 | } | ||
277 | |||
200 | static struct file_system_type ramfs_fs_type = { | 278 | static struct file_system_type ramfs_fs_type = { |
201 | .name = "ramfs", | 279 | .name = "ramfs", |
202 | .get_sb = ramfs_get_sb, | 280 | .get_sb = ramfs_get_sb, |
203 | .kill_sb = kill_litter_super, | 281 | .kill_sb = ramfs_kill_sb, |
204 | }; | 282 | }; |
205 | static struct file_system_type rootfs_fs_type = { | 283 | static struct file_system_type rootfs_fs_type = { |
206 | .name = "rootfs", | 284 | .name = "rootfs", |
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 07703d3ff4a..93e0c0281d4 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c | |||
@@ -234,7 +234,7 @@ static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
234 | return ret; | 234 | return ret; |
235 | } | 235 | } |
236 | 236 | ||
237 | static int bin_page_mkwrite(struct vm_area_struct *vma, struct page *page) | 237 | static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
238 | { | 238 | { |
239 | struct file *file = vma->vm_file; | 239 | struct file *file = vma->vm_file; |
240 | struct bin_buffer *bb = file->private_data; | 240 | struct bin_buffer *bb = file->private_data; |
@@ -242,15 +242,15 @@ static int bin_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
242 | int ret; | 242 | int ret; |
243 | 243 | ||
244 | if (!bb->vm_ops) | 244 | if (!bb->vm_ops) |
245 | return -EINVAL; | 245 | return VM_FAULT_SIGBUS; |
246 | 246 | ||
247 | if (!bb->vm_ops->page_mkwrite) | 247 | if (!bb->vm_ops->page_mkwrite) |
248 | return 0; | 248 | return 0; |
249 | 249 | ||
250 | if (!sysfs_get_active_two(attr_sd)) | 250 | if (!sysfs_get_active_two(attr_sd)) |
251 | return -EINVAL; | 251 | return VM_FAULT_SIGBUS; |
252 | 252 | ||
253 | ret = bb->vm_ops->page_mkwrite(vma, page); | 253 | ret = bb->vm_ops->page_mkwrite(vma, vmf); |
254 | 254 | ||
255 | sysfs_put_active_two(attr_sd); | 255 | sysfs_put_active_two(attr_sd); |
256 | return ret; | 256 | return ret; |
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 93b6de51f26..0ff89fe71e5 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c | |||
@@ -1434,8 +1434,9 @@ static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags) | |||
1434 | * mmap()d file has taken write protection fault and is being made | 1434 | * mmap()d file has taken write protection fault and is being made |
1435 | * writable. UBIFS must ensure page is budgeted for. | 1435 | * writable. UBIFS must ensure page is budgeted for. |
1436 | */ | 1436 | */ |
1437 | static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) | 1437 | static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
1438 | { | 1438 | { |
1439 | struct page *page = vmf->page; | ||
1439 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; | 1440 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; |
1440 | struct ubifs_info *c = inode->i_sb->s_fs_info; | 1441 | struct ubifs_info *c = inode->i_sb->s_fs_info; |
1441 | struct timespec now = ubifs_current_time(inode); | 1442 | struct timespec now = ubifs_current_time(inode); |
@@ -1447,7 +1448,7 @@ static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
1447 | ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY)); | 1448 | ubifs_assert(!(inode->i_sb->s_flags & MS_RDONLY)); |
1448 | 1449 | ||
1449 | if (unlikely(c->ro_media)) | 1450 | if (unlikely(c->ro_media)) |
1450 | return -EROFS; | 1451 | return VM_FAULT_SIGBUS; /* -EROFS */ |
1451 | 1452 | ||
1452 | /* | 1453 | /* |
1453 | * We have not locked @page so far so we may budget for changing the | 1454 | * We have not locked @page so far so we may budget for changing the |
@@ -1480,7 +1481,7 @@ static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
1480 | if (err == -ENOSPC) | 1481 | if (err == -ENOSPC) |
1481 | ubifs_warn("out of space for mmapped file " | 1482 | ubifs_warn("out of space for mmapped file " |
1482 | "(inode number %lu)", inode->i_ino); | 1483 | "(inode number %lu)", inode->i_ino); |
1483 | return err; | 1484 | return VM_FAULT_SIGBUS; |
1484 | } | 1485 | } |
1485 | 1486 | ||
1486 | lock_page(page); | 1487 | lock_page(page); |
@@ -1520,6 +1521,8 @@ static int ubifs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
1520 | out_unlock: | 1521 | out_unlock: |
1521 | unlock_page(page); | 1522 | unlock_page(page); |
1522 | ubifs_release_budget(c, &req); | 1523 | ubifs_release_budget(c, &req); |
1524 | if (err) | ||
1525 | err = VM_FAULT_SIGBUS; | ||
1523 | return err; | 1526 | return err; |
1524 | } | 1527 | } |
1525 | 1528 | ||
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index e14c4e3aea0..f4e25544157 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -234,9 +234,9 @@ xfs_file_mmap( | |||
234 | STATIC int | 234 | STATIC int |
235 | xfs_vm_page_mkwrite( | 235 | xfs_vm_page_mkwrite( |
236 | struct vm_area_struct *vma, | 236 | struct vm_area_struct *vma, |
237 | struct page *page) | 237 | struct vm_fault *vmf) |
238 | { | 238 | { |
239 | return block_page_mkwrite(vma, page, xfs_get_blocks); | 239 | return block_page_mkwrite(vma, vmf, xfs_get_blocks); |
240 | } | 240 | } |
241 | 241 | ||
242 | const struct file_operations xfs_file_operations = { | 242 | const struct file_operations xfs_file_operations = { |
diff --git a/include/asm-frv/highmem.h b/include/asm-frv/highmem.h index 26cefcde5ce..68e4677fb9e 100644 --- a/include/asm-frv/highmem.h +++ b/include/asm-frv/highmem.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #ifdef __KERNEL__ | 18 | #ifdef __KERNEL__ |
19 | 19 | ||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/highmem.h> | ||
21 | #include <asm/mem-layout.h> | 22 | #include <asm/mem-layout.h> |
22 | #include <asm/spr-regs.h> | 23 | #include <asm/spr-regs.h> |
23 | #include <asm/mb-regs.h> | 24 | #include <asm/mb-regs.h> |
@@ -116,6 +117,7 @@ static inline void *kmap_atomic(struct page *page, enum km_type type) | |||
116 | unsigned long paddr; | 117 | unsigned long paddr; |
117 | 118 | ||
118 | pagefault_disable(); | 119 | pagefault_disable(); |
120 | debug_kmap_atomic(type); | ||
119 | paddr = page_to_phys(page); | 121 | paddr = page_to_phys(page); |
120 | 122 | ||
121 | switch (type) { | 123 | switch (type) { |
diff --git a/include/asm-generic/dma-mapping.h b/include/asm-generic/dma-mapping.h deleted file mode 100644 index 189486c3f92..00000000000 --- a/include/asm-generic/dma-mapping.h +++ /dev/null | |||
@@ -1,308 +0,0 @@ | |||
1 | /* Copyright (C) 2002 by James.Bottomley@HansenPartnership.com | ||
2 | * | ||
3 | * Implements the generic device dma API via the existing pci_ one | ||
4 | * for unconverted architectures | ||
5 | */ | ||
6 | |||
7 | #ifndef _ASM_GENERIC_DMA_MAPPING_H | ||
8 | #define _ASM_GENERIC_DMA_MAPPING_H | ||
9 | |||
10 | |||
11 | #ifdef CONFIG_PCI | ||
12 | |||
13 | /* we implement the API below in terms of the existing PCI one, | ||
14 | * so include it */ | ||
15 | #include <linux/pci.h> | ||
16 | /* need struct page definitions */ | ||
17 | #include <linux/mm.h> | ||
18 | |||
19 | static inline int | ||
20 | dma_supported(struct device *dev, u64 mask) | ||
21 | { | ||
22 | BUG_ON(dev->bus != &pci_bus_type); | ||
23 | |||
24 | return pci_dma_supported(to_pci_dev(dev), mask); | ||
25 | } | ||
26 | |||
27 | static inline int | ||
28 | dma_set_mask(struct device *dev, u64 dma_mask) | ||
29 | { | ||
30 | BUG_ON(dev->bus != &pci_bus_type); | ||
31 | |||
32 | return pci_set_dma_mask(to_pci_dev(dev), dma_mask); | ||
33 | } | ||
34 | |||
35 | static inline void * | ||
36 | dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, | ||
37 | gfp_t flag) | ||
38 | { | ||
39 | BUG_ON(dev->bus != &pci_bus_type); | ||
40 | |||
41 | return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle); | ||
42 | } | ||
43 | |||
44 | static inline void | ||
45 | dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, | ||
46 | dma_addr_t dma_handle) | ||
47 | { | ||
48 | BUG_ON(dev->bus != &pci_bus_type); | ||
49 | |||
50 | pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle); | ||
51 | } | ||
52 | |||
53 | static inline dma_addr_t | ||
54 | dma_map_single(struct device *dev, void *cpu_addr, size_t size, | ||
55 | enum dma_data_direction direction) | ||
56 | { | ||
57 | BUG_ON(dev->bus != &pci_bus_type); | ||
58 | |||
59 | return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction); | ||
60 | } | ||
61 | |||
62 | static inline void | ||
63 | dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | ||
64 | enum dma_data_direction direction) | ||
65 | { | ||
66 | BUG_ON(dev->bus != &pci_bus_type); | ||
67 | |||
68 | pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction); | ||
69 | } | ||
70 | |||
71 | static inline dma_addr_t | ||
72 | dma_map_page(struct device *dev, struct page *page, | ||
73 | unsigned long offset, size_t size, | ||
74 | enum dma_data_direction direction) | ||
75 | { | ||
76 | BUG_ON(dev->bus != &pci_bus_type); | ||
77 | |||
78 | return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction); | ||
79 | } | ||
80 | |||
81 | static inline void | ||
82 | dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, | ||
83 | enum dma_data_direction direction) | ||
84 | { | ||
85 | BUG_ON(dev->bus != &pci_bus_type); | ||
86 | |||
87 | pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction); | ||
88 | } | ||
89 | |||
90 | static inline int | ||
91 | dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | ||
92 | enum dma_data_direction direction) | ||
93 | { | ||
94 | BUG_ON(dev->bus != &pci_bus_type); | ||
95 | |||
96 | return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction); | ||
97 | } | ||
98 | |||
99 | static inline void | ||
100 | dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | ||
101 | enum dma_data_direction direction) | ||
102 | { | ||
103 | BUG_ON(dev->bus != &pci_bus_type); | ||
104 | |||
105 | pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction); | ||
106 | } | ||
107 | |||
108 | static inline void | ||
109 | dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, | ||
110 | enum dma_data_direction direction) | ||
111 | { | ||
112 | BUG_ON(dev->bus != &pci_bus_type); | ||
113 | |||
114 | pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle, | ||
115 | size, (int)direction); | ||
116 | } | ||
117 | |||
118 | static inline void | ||
119 | dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, | ||
120 | enum dma_data_direction direction) | ||
121 | { | ||
122 | BUG_ON(dev->bus != &pci_bus_type); | ||
123 | |||
124 | pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle, | ||
125 | size, (int)direction); | ||
126 | } | ||
127 | |||
128 | static inline void | ||
129 | dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, | ||
130 | enum dma_data_direction direction) | ||
131 | { | ||
132 | BUG_ON(dev->bus != &pci_bus_type); | ||
133 | |||
134 | pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction); | ||
135 | } | ||
136 | |||
137 | static inline void | ||
138 | dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, | ||
139 | enum dma_data_direction direction) | ||
140 | { | ||
141 | BUG_ON(dev->bus != &pci_bus_type); | ||
142 | |||
143 | pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction); | ||
144 | } | ||
145 | |||
146 | static inline int | ||
147 | dma_mapping_error(struct device *dev, dma_addr_t dma_addr) | ||
148 | { | ||
149 | return pci_dma_mapping_error(to_pci_dev(dev), dma_addr); | ||
150 | } | ||
151 | |||
152 | |||
153 | #else | ||
154 | |||
155 | static inline int | ||
156 | dma_supported(struct device *dev, u64 mask) | ||
157 | { | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static inline int | ||
162 | dma_set_mask(struct device *dev, u64 dma_mask) | ||
163 | { | ||
164 | BUG(); | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static inline void * | ||
169 | dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, | ||
170 | gfp_t flag) | ||
171 | { | ||
172 | BUG(); | ||
173 | return NULL; | ||
174 | } | ||
175 | |||
176 | static inline void | ||
177 | dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, | ||
178 | dma_addr_t dma_handle) | ||
179 | { | ||
180 | BUG(); | ||
181 | } | ||
182 | |||
183 | static inline dma_addr_t | ||
184 | dma_map_single(struct device *dev, void *cpu_addr, size_t size, | ||
185 | enum dma_data_direction direction) | ||
186 | { | ||
187 | BUG(); | ||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | static inline void | ||
192 | dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, | ||
193 | enum dma_data_direction direction) | ||
194 | { | ||
195 | BUG(); | ||
196 | } | ||
197 | |||
198 | static inline dma_addr_t | ||
199 | dma_map_page(struct device *dev, struct page *page, | ||
200 | unsigned long offset, size_t size, | ||
201 | enum dma_data_direction direction) | ||
202 | { | ||
203 | BUG(); | ||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | static inline void | ||
208 | dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, | ||
209 | enum dma_data_direction direction) | ||
210 | { | ||
211 | BUG(); | ||
212 | } | ||
213 | |||
214 | static inline int | ||
215 | dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, | ||
216 | enum dma_data_direction direction) | ||
217 | { | ||
218 | BUG(); | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static inline void | ||
223 | dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | ||
224 | enum dma_data_direction direction) | ||
225 | { | ||
226 | BUG(); | ||
227 | } | ||
228 | |||
229 | static inline void | ||
230 | dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, | ||
231 | enum dma_data_direction direction) | ||
232 | { | ||
233 | BUG(); | ||
234 | } | ||
235 | |||
236 | static inline void | ||
237 | dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, | ||
238 | enum dma_data_direction direction) | ||
239 | { | ||
240 | BUG(); | ||
241 | } | ||
242 | |||
243 | static inline void | ||
244 | dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, | ||
245 | enum dma_data_direction direction) | ||
246 | { | ||
247 | BUG(); | ||
248 | } | ||
249 | |||
250 | static inline void | ||
251 | dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, | ||
252 | enum dma_data_direction direction) | ||
253 | { | ||
254 | BUG(); | ||
255 | } | ||
256 | |||
257 | static inline int | ||
258 | dma_error(dma_addr_t dma_addr) | ||
259 | { | ||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | #endif | ||
264 | |||
265 | /* Now for the API extensions over the pci_ one */ | ||
266 | |||
267 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) | ||
268 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) | ||
269 | #define dma_is_consistent(d, h) (1) | ||
270 | |||
271 | static inline int | ||
272 | dma_get_cache_alignment(void) | ||
273 | { | ||
274 | /* no easy way to get cache size on all processors, so return | ||
275 | * the maximum possible, to be safe */ | ||
276 | return (1 << INTERNODE_CACHE_SHIFT); | ||
277 | } | ||
278 | |||
279 | static inline void | ||
280 | dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, | ||
281 | unsigned long offset, size_t size, | ||
282 | enum dma_data_direction direction) | ||
283 | { | ||
284 | /* just sync everything, that's all the pci API can do */ | ||
285 | dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction); | ||
286 | } | ||
287 | |||
288 | static inline void | ||
289 | dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, | ||
290 | unsigned long offset, size_t size, | ||
291 | enum dma_data_direction direction) | ||
292 | { | ||
293 | /* just sync everything, that's all the pci API can do */ | ||
294 | dma_sync_single_for_device(dev, dma_handle, offset+size, direction); | ||
295 | } | ||
296 | |||
297 | static inline void | ||
298 | dma_cache_sync(struct device *dev, void *vaddr, size_t size, | ||
299 | enum dma_data_direction direction) | ||
300 | { | ||
301 | /* could define this in terms of the dma_cache ... operations, | ||
302 | * but if you get this on a platform, you should convert the platform | ||
303 | * to using the generic device DMA API */ | ||
304 | BUG(); | ||
305 | } | ||
306 | |||
307 | #endif | ||
308 | |||
diff --git a/include/asm-mn10300/highmem.h b/include/asm-mn10300/highmem.h index 5256854c045..90f2abb04bf 100644 --- a/include/asm-mn10300/highmem.h +++ b/include/asm-mn10300/highmem.h | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/highmem.h> | ||
19 | #include <asm/kmap_types.h> | 20 | #include <asm/kmap_types.h> |
20 | #include <asm/pgtable.h> | 21 | #include <asm/pgtable.h> |
21 | 22 | ||
@@ -77,6 +78,7 @@ static inline unsigned long kmap_atomic(struct page *page, enum km_type type) | |||
77 | if (page < highmem_start_page) | 78 | if (page < highmem_start_page) |
78 | return page_address(page); | 79 | return page_address(page); |
79 | 80 | ||
81 | debug_kmap_atomic(type); | ||
80 | idx = type + KM_TYPE_NR * smp_processor_id(); | 82 | idx = type + KM_TYPE_NR * smp_processor_id(); |
81 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 83 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
82 | #if HIGHMEM_DEBUG | 84 | #if HIGHMEM_DEBUG |
diff --git a/include/linux/auto_dev-ioctl.h b/include/linux/auto_dev-ioctl.h index 91a773993a5..850f39b33e7 100644 --- a/include/linux/auto_dev-ioctl.h +++ b/include/linux/auto_dev-ioctl.h | |||
@@ -10,8 +10,13 @@ | |||
10 | #ifndef _LINUX_AUTO_DEV_IOCTL_H | 10 | #ifndef _LINUX_AUTO_DEV_IOCTL_H |
11 | #define _LINUX_AUTO_DEV_IOCTL_H | 11 | #define _LINUX_AUTO_DEV_IOCTL_H |
12 | 12 | ||
13 | #include <linux/auto_fs.h> | ||
14 | |||
15 | #ifdef __KERNEL__ | ||
13 | #include <linux/string.h> | 16 | #include <linux/string.h> |
14 | #include <linux/types.h> | 17 | #else |
18 | #include <string.h> | ||
19 | #endif /* __KERNEL__ */ | ||
15 | 20 | ||
16 | #define AUTOFS_DEVICE_NAME "autofs" | 21 | #define AUTOFS_DEVICE_NAME "autofs" |
17 | 22 | ||
diff --git a/include/linux/auto_fs.h b/include/linux/auto_fs.h index c21e5972a3e..63265852b7d 100644 --- a/include/linux/auto_fs.h +++ b/include/linux/auto_fs.h | |||
@@ -17,11 +17,13 @@ | |||
17 | #ifdef __KERNEL__ | 17 | #ifdef __KERNEL__ |
18 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
19 | #include <linux/limits.h> | 19 | #include <linux/limits.h> |
20 | #include <linux/types.h> | ||
21 | #include <linux/ioctl.h> | ||
22 | #else | ||
20 | #include <asm/types.h> | 23 | #include <asm/types.h> |
24 | #include <sys/ioctl.h> | ||
21 | #endif /* __KERNEL__ */ | 25 | #endif /* __KERNEL__ */ |
22 | 26 | ||
23 | #include <linux/ioctl.h> | ||
24 | |||
25 | /* This file describes autofs v3 */ | 27 | /* This file describes autofs v3 */ |
26 | #define AUTOFS_PROTO_VERSION 3 | 28 | #define AUTOFS_PROTO_VERSION 3 |
27 | 29 | ||
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index 455d83219fa..bc3ab707369 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h | |||
@@ -146,10 +146,10 @@ extern void *alloc_large_system_hash(const char *tablename, | |||
146 | 146 | ||
147 | #define HASH_EARLY 0x00000001 /* Allocating during early boot? */ | 147 | #define HASH_EARLY 0x00000001 /* Allocating during early boot? */ |
148 | 148 | ||
149 | /* Only NUMA needs hash distribution. | 149 | /* Only NUMA needs hash distribution. 64bit NUMA architectures have |
150 | * IA64 and x86_64 have sufficient vmalloc space. | 150 | * sufficient vmalloc space. |
151 | */ | 151 | */ |
152 | #if defined(CONFIG_NUMA) && (defined(CONFIG_IA64) || defined(CONFIG_X86_64)) | 152 | #if defined(CONFIG_NUMA) && defined(CONFIG_64BIT) |
153 | #define HASHDIST_DEFAULT 1 | 153 | #define HASHDIST_DEFAULT 1 |
154 | #else | 154 | #else |
155 | #define HASHDIST_DEFAULT 0 | 155 | #define HASHDIST_DEFAULT 0 |
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index f19fd9045ea..3d7bcde2e33 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h | |||
@@ -216,7 +216,7 @@ int cont_write_begin(struct file *, struct address_space *, loff_t, | |||
216 | get_block_t *, loff_t *); | 216 | get_block_t *, loff_t *); |
217 | int generic_cont_expand_simple(struct inode *inode, loff_t size); | 217 | int generic_cont_expand_simple(struct inode *inode, loff_t size); |
218 | int block_commit_write(struct page *page, unsigned from, unsigned to); | 218 | int block_commit_write(struct page *page, unsigned from, unsigned to); |
219 | int block_page_mkwrite(struct vm_area_struct *vma, struct page *page, | 219 | int block_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, |
220 | get_block_t get_block); | 220 | get_block_t get_block); |
221 | void block_sync_page(struct page *); | 221 | void block_sync_page(struct page *); |
222 | sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *); | 222 | sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *); |
diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h index a667637b54e..f45a8ae5f82 100644 --- a/include/linux/eventfd.h +++ b/include/linux/eventfd.h | |||
@@ -13,10 +13,20 @@ | |||
13 | /* For O_CLOEXEC and O_NONBLOCK */ | 13 | /* For O_CLOEXEC and O_NONBLOCK */ |
14 | #include <linux/fcntl.h> | 14 | #include <linux/fcntl.h> |
15 | 15 | ||
16 | /* Flags for eventfd2. */ | 16 | /* |
17 | * CAREFUL: Check include/asm-generic/fcntl.h when defining | ||
18 | * new flags, since they might collide with O_* ones. We want | ||
19 | * to re-use O_* flags that couldn't possibly have a meaning | ||
20 | * from eventfd, in order to leave a free define-space for | ||
21 | * shared O_* flags. | ||
22 | */ | ||
23 | #define EFD_SEMAPHORE (1 << 0) | ||
17 | #define EFD_CLOEXEC O_CLOEXEC | 24 | #define EFD_CLOEXEC O_CLOEXEC |
18 | #define EFD_NONBLOCK O_NONBLOCK | 25 | #define EFD_NONBLOCK O_NONBLOCK |
19 | 26 | ||
27 | #define EFD_SHARED_FCNTL_FLAGS (O_CLOEXEC | O_NONBLOCK) | ||
28 | #define EFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS | EFD_SEMAPHORE) | ||
29 | |||
20 | struct file *eventfd_fget(int fd); | 30 | struct file *eventfd_fget(int fd); |
21 | int eventfd_signal(struct file *file, int n); | 31 | int eventfd_signal(struct file *file, int n); |
22 | 32 | ||
diff --git a/include/linux/fb.h b/include/linux/fb.h index 31527e17076..f563c501393 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
@@ -123,6 +123,7 @@ struct dentry; | |||
123 | #define FB_ACCEL_TRIDENT_3DIMAGE 51 /* Trident 3DImage */ | 123 | #define FB_ACCEL_TRIDENT_3DIMAGE 51 /* Trident 3DImage */ |
124 | #define FB_ACCEL_TRIDENT_BLADE3D 52 /* Trident Blade3D */ | 124 | #define FB_ACCEL_TRIDENT_BLADE3D 52 /* Trident Blade3D */ |
125 | #define FB_ACCEL_TRIDENT_BLADEXP 53 /* Trident BladeXP */ | 125 | #define FB_ACCEL_TRIDENT_BLADEXP 53 /* Trident BladeXP */ |
126 | #define FB_ACCEL_CIRRUS_ALPINE 53 /* Cirrus Logic 543x/544x/5480 */ | ||
126 | #define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */ | 127 | #define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */ |
127 | #define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */ | 128 | #define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */ |
128 | #define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */ | 129 | #define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */ |
@@ -960,15 +961,7 @@ extern struct fb_info *registered_fb[FB_MAX]; | |||
960 | extern int num_registered_fb; | 961 | extern int num_registered_fb; |
961 | extern struct class *fb_class; | 962 | extern struct class *fb_class; |
962 | 963 | ||
963 | static inline int lock_fb_info(struct fb_info *info) | 964 | extern int lock_fb_info(struct fb_info *info); |
964 | { | ||
965 | mutex_lock(&info->lock); | ||
966 | if (!info->fbops) { | ||
967 | mutex_unlock(&info->lock); | ||
968 | return 0; | ||
969 | } | ||
970 | return 1; | ||
971 | } | ||
972 | 965 | ||
973 | static inline void unlock_fb_info(struct fb_info *info) | 966 | static inline void unlock_fb_info(struct fb_info *info) |
974 | { | 967 | { |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 87e7bfc5ebd..61211ad823f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1878,6 +1878,7 @@ extern struct block_device *open_by_devnum(dev_t, fmode_t); | |||
1878 | extern void invalidate_bdev(struct block_device *); | 1878 | extern void invalidate_bdev(struct block_device *); |
1879 | extern int sync_blockdev(struct block_device *bdev); | 1879 | extern int sync_blockdev(struct block_device *bdev); |
1880 | extern struct super_block *freeze_bdev(struct block_device *); | 1880 | extern struct super_block *freeze_bdev(struct block_device *); |
1881 | extern void emergency_thaw_all(void); | ||
1881 | extern int thaw_bdev(struct block_device *bdev, struct super_block *sb); | 1882 | extern int thaw_bdev(struct block_device *bdev, struct super_block *sb); |
1882 | extern int fsync_bdev(struct block_device *); | 1883 | extern int fsync_bdev(struct block_device *); |
1883 | extern int fsync_super(struct super_block *); | 1884 | extern int fsync_super(struct super_block *); |
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index d9051d717d2..7ef1caf5026 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h | |||
@@ -95,14 +95,15 @@ struct fsl_usb2_platform_data { | |||
95 | #define FSL_USB2_PORT0_ENABLED 0x00000001 | 95 | #define FSL_USB2_PORT0_ENABLED 0x00000001 |
96 | #define FSL_USB2_PORT1_ENABLED 0x00000002 | 96 | #define FSL_USB2_PORT1_ENABLED 0x00000002 |
97 | 97 | ||
98 | struct spi_device; | ||
99 | |||
98 | struct fsl_spi_platform_data { | 100 | struct fsl_spi_platform_data { |
99 | u32 initial_spmode; /* initial SPMODE value */ | 101 | u32 initial_spmode; /* initial SPMODE value */ |
100 | u16 bus_num; | 102 | s16 bus_num; |
101 | bool qe_mode; | 103 | bool qe_mode; |
102 | /* board specific information */ | 104 | /* board specific information */ |
103 | u16 max_chipselect; | 105 | u16 max_chipselect; |
104 | void (*activate_cs)(u8 cs, u8 polarity); | 106 | void (*cs_control)(struct spi_device *spi, bool on); |
105 | void (*deactivate_cs)(u8 cs, u8 polarity); | ||
106 | u32 sysclk; | 107 | u32 sysclk; |
107 | }; | 108 | }; |
108 | 109 | ||
diff --git a/include/linux/highmem.h b/include/linux/highmem.h index 13875ce9112..7ff5c55f9b5 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h | |||
@@ -187,4 +187,16 @@ static inline void copy_highpage(struct page *to, struct page *from) | |||
187 | kunmap_atomic(vto, KM_USER1); | 187 | kunmap_atomic(vto, KM_USER1); |
188 | } | 188 | } |
189 | 189 | ||
190 | #if defined(CONFIG_DEBUG_HIGHMEM) && defined(CONFIG_TRACE_IRQFLAGS_SUPPORT) | ||
191 | |||
192 | void debug_kmap_atomic(enum km_type type); | ||
193 | |||
194 | #else | ||
195 | |||
196 | static inline void debug_kmap_atomic(enum km_type type) | ||
197 | { | ||
198 | } | ||
199 | |||
200 | #endif | ||
201 | |||
190 | #endif /* _LINUX_HIGHMEM_H */ | 202 | #endif /* _LINUX_HIGHMEM_H */ |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index f81d80f47dc..e720b0da775 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -353,6 +353,8 @@ static inline char *pack_hex_byte(char *buf, u8 byte) | |||
353 | printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__) | 353 | printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__) |
354 | #define pr_info(fmt, ...) \ | 354 | #define pr_info(fmt, ...) \ |
355 | printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) | 355 | printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__) |
356 | #define pr_cont(fmt, ...) \ | ||
357 | printk(KERN_CONT fmt, ##__VA_ARGS__) | ||
356 | 358 | ||
357 | /* If you are writing a driver, please use dev_dbg instead */ | 359 | /* If you are writing a driver, please use dev_dbg instead */ |
358 | #if defined(DEBUG) | 360 | #if defined(DEBUG) |
diff --git a/include/linux/loop.h b/include/linux/loop.h index 6ffd6db5bb0..40725447f5e 100644 --- a/include/linux/loop.h +++ b/include/linux/loop.h | |||
@@ -160,5 +160,6 @@ int loop_unregister_transfer(int number); | |||
160 | #define LOOP_SET_STATUS64 0x4C04 | 160 | #define LOOP_SET_STATUS64 0x4C04 |
161 | #define LOOP_GET_STATUS64 0x4C05 | 161 | #define LOOP_GET_STATUS64 0x4C05 |
162 | #define LOOP_CHANGE_FD 0x4C06 | 162 | #define LOOP_CHANGE_FD 0x4C06 |
163 | #define LOOP_SET_CAPACITY 0x4C07 | ||
163 | 164 | ||
164 | #endif | 165 | #endif |
diff --git a/include/linux/mm.h b/include/linux/mm.h index b1ea37fc7a2..aeabe953ba4 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -135,6 +135,7 @@ extern pgprot_t protection_map[16]; | |||
135 | 135 | ||
136 | #define FAULT_FLAG_WRITE 0x01 /* Fault was a write access */ | 136 | #define FAULT_FLAG_WRITE 0x01 /* Fault was a write access */ |
137 | #define FAULT_FLAG_NONLINEAR 0x02 /* Fault was via a nonlinear mapping */ | 137 | #define FAULT_FLAG_NONLINEAR 0x02 /* Fault was via a nonlinear mapping */ |
138 | #define FAULT_FLAG_MKWRITE 0x04 /* Fault was mkwrite of existing pte */ | ||
138 | 139 | ||
139 | /* | 140 | /* |
140 | * This interface is used by x86 PAT code to identify a pfn mapping that is | 141 | * This interface is used by x86 PAT code to identify a pfn mapping that is |
@@ -187,7 +188,7 @@ struct vm_operations_struct { | |||
187 | 188 | ||
188 | /* notification that a previously read-only page is about to become | 189 | /* notification that a previously read-only page is about to become |
189 | * writable, if an error is returned it will cause a SIGBUS */ | 190 | * writable, if an error is returned it will cause a SIGBUS */ |
190 | int (*page_mkwrite)(struct vm_area_struct *vma, struct page *page); | 191 | int (*page_mkwrite)(struct vm_area_struct *vma, struct vm_fault *vmf); |
191 | 192 | ||
192 | /* called by access_process_vm when get_user_pages() fails, typically | 193 | /* called by access_process_vm when get_user_pages() fails, typically |
193 | * for use by special VMAs that can switch between memory and hardware | 194 | * for use by special VMAs that can switch between memory and hardware |
@@ -834,6 +835,7 @@ int __set_page_dirty_nobuffers(struct page *page); | |||
834 | int __set_page_dirty_no_writeback(struct page *page); | 835 | int __set_page_dirty_no_writeback(struct page *page); |
835 | int redirty_page_for_writepage(struct writeback_control *wbc, | 836 | int redirty_page_for_writepage(struct writeback_control *wbc, |
836 | struct page *page); | 837 | struct page *page); |
838 | void account_page_dirtied(struct page *page, struct address_space *mapping); | ||
837 | int set_page_dirty(struct page *page); | 839 | int set_page_dirty(struct page *page); |
838 | int set_page_dirty_lock(struct page *page); | 840 | int set_page_dirty_lock(struct page *page); |
839 | int clear_page_dirty_for_io(struct page *page); | 841 | int clear_page_dirty_for_io(struct page *page); |
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index d84feb7bdbf..ddadb4defe0 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/rwsem.h> | 11 | #include <linux/rwsem.h> |
12 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
13 | #include <linux/cpumask.h> | 13 | #include <linux/cpumask.h> |
14 | #include <linux/page-debug-flags.h> | ||
14 | #include <asm/page.h> | 15 | #include <asm/page.h> |
15 | #include <asm/mmu.h> | 16 | #include <asm/mmu.h> |
16 | 17 | ||
@@ -174,6 +175,9 @@ struct vm_area_struct { | |||
174 | #ifdef CONFIG_NUMA | 175 | #ifdef CONFIG_NUMA |
175 | struct mempolicy *vm_policy; /* NUMA policy for the VMA */ | 176 | struct mempolicy *vm_policy; /* NUMA policy for the VMA */ |
176 | #endif | 177 | #endif |
178 | #ifdef CONFIG_WANT_PAGE_DEBUG_FLAGS | ||
179 | unsigned long debug_flags; /* Use atomic bitops on this */ | ||
180 | #endif | ||
177 | }; | 181 | }; |
178 | 182 | ||
179 | struct core_thread { | 183 | struct core_thread { |
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 1aca6cebbb7..26ef24076b7 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -806,6 +806,14 @@ extern struct zone *next_zone(struct zone *zone); | |||
806 | zone; \ | 806 | zone; \ |
807 | zone = next_zone(zone)) | 807 | zone = next_zone(zone)) |
808 | 808 | ||
809 | #define for_each_populated_zone(zone) \ | ||
810 | for (zone = (first_online_pgdat())->node_zones; \ | ||
811 | zone; \ | ||
812 | zone = next_zone(zone)) \ | ||
813 | if (!populated_zone(zone)) \ | ||
814 | ; /* do nothing */ \ | ||
815 | else | ||
816 | |||
809 | static inline struct zone *zonelist_zone(struct zoneref *zoneref) | 817 | static inline struct zone *zonelist_zone(struct zoneref *zoneref) |
810 | { | 818 | { |
811 | return zoneref->zone; | 819 | return zoneref->zone; |
diff --git a/include/linux/page-debug-flags.h b/include/linux/page-debug-flags.h new file mode 100644 index 00000000000..b0638fd91e9 --- /dev/null +++ b/include/linux/page-debug-flags.h | |||
@@ -0,0 +1,30 @@ | |||
1 | #ifndef LINUX_PAGE_DEBUG_FLAGS_H | ||
2 | #define LINUX_PAGE_DEBUG_FLAGS_H | ||
3 | |||
4 | /* | ||
5 | * page->debug_flags bits: | ||
6 | * | ||
7 | * PAGE_DEBUG_FLAG_POISON is set for poisoned pages. This is used to | ||
8 | * implement generic debug pagealloc feature. The pages are filled with | ||
9 | * poison patterns and set this flag after free_pages(). The poisoned | ||
10 | * pages are verified whether the patterns are not corrupted and clear | ||
11 | * the flag before alloc_pages(). | ||
12 | */ | ||
13 | |||
14 | enum page_debug_flags { | ||
15 | PAGE_DEBUG_FLAG_POISON, /* Page is poisoned */ | ||
16 | }; | ||
17 | |||
18 | /* | ||
19 | * Ensure that CONFIG_WANT_PAGE_DEBUG_FLAGS reliably | ||
20 | * gets turned off when no debug features are enabling it! | ||
21 | */ | ||
22 | |||
23 | #ifdef CONFIG_WANT_PAGE_DEBUG_FLAGS | ||
24 | #if !defined(CONFIG_PAGE_POISONING) \ | ||
25 | /* && !defined(CONFIG_PAGE_DEBUG_SOMETHING_ELSE) && ... */ | ||
26 | #error WANT_PAGE_DEBUG_FLAGS is turned on with no debug features! | ||
27 | #endif | ||
28 | #endif /* CONFIG_WANT_PAGE_DEBUG_FLAGS */ | ||
29 | |||
30 | #endif /* LINUX_PAGE_DEBUG_FLAGS_H */ | ||
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 219a523ecdb..61df1779b2a 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h | |||
@@ -96,6 +96,8 @@ enum pageflags { | |||
96 | PG_swapbacked, /* Page is backed by RAM/swap */ | 96 | PG_swapbacked, /* Page is backed by RAM/swap */ |
97 | #ifdef CONFIG_UNEVICTABLE_LRU | 97 | #ifdef CONFIG_UNEVICTABLE_LRU |
98 | PG_unevictable, /* Page is "unevictable" */ | 98 | PG_unevictable, /* Page is "unevictable" */ |
99 | #endif | ||
100 | #ifdef CONFIG_HAVE_MLOCKED_PAGE_BIT | ||
99 | PG_mlocked, /* Page is vma mlocked */ | 101 | PG_mlocked, /* Page is vma mlocked */ |
100 | #endif | 102 | #endif |
101 | #ifdef CONFIG_IA64_UNCACHED_ALLOCATOR | 103 | #ifdef CONFIG_IA64_UNCACHED_ALLOCATOR |
@@ -234,20 +236,20 @@ PAGEFLAG_FALSE(SwapCache) | |||
234 | #ifdef CONFIG_UNEVICTABLE_LRU | 236 | #ifdef CONFIG_UNEVICTABLE_LRU |
235 | PAGEFLAG(Unevictable, unevictable) __CLEARPAGEFLAG(Unevictable, unevictable) | 237 | PAGEFLAG(Unevictable, unevictable) __CLEARPAGEFLAG(Unevictable, unevictable) |
236 | TESTCLEARFLAG(Unevictable, unevictable) | 238 | TESTCLEARFLAG(Unevictable, unevictable) |
239 | #else | ||
240 | PAGEFLAG_FALSE(Unevictable) TESTCLEARFLAG_FALSE(Unevictable) | ||
241 | SETPAGEFLAG_NOOP(Unevictable) CLEARPAGEFLAG_NOOP(Unevictable) | ||
242 | __CLEARPAGEFLAG_NOOP(Unevictable) | ||
243 | #endif | ||
237 | 244 | ||
245 | #ifdef CONFIG_HAVE_MLOCKED_PAGE_BIT | ||
238 | #define MLOCK_PAGES 1 | 246 | #define MLOCK_PAGES 1 |
239 | PAGEFLAG(Mlocked, mlocked) __CLEARPAGEFLAG(Mlocked, mlocked) | 247 | PAGEFLAG(Mlocked, mlocked) __CLEARPAGEFLAG(Mlocked, mlocked) |
240 | TESTSCFLAG(Mlocked, mlocked) | 248 | TESTSCFLAG(Mlocked, mlocked) |
241 | |||
242 | #else | 249 | #else |
243 | |||
244 | #define MLOCK_PAGES 0 | 250 | #define MLOCK_PAGES 0 |
245 | PAGEFLAG_FALSE(Mlocked) | 251 | PAGEFLAG_FALSE(Mlocked) |
246 | SETPAGEFLAG_NOOP(Mlocked) TESTCLEARFLAG_FALSE(Mlocked) | 252 | SETPAGEFLAG_NOOP(Mlocked) TESTCLEARFLAG_FALSE(Mlocked) |
247 | |||
248 | PAGEFLAG_FALSE(Unevictable) TESTCLEARFLAG_FALSE(Unevictable) | ||
249 | SETPAGEFLAG_NOOP(Unevictable) CLEARPAGEFLAG_NOOP(Unevictable) | ||
250 | __CLEARPAGEFLAG_NOOP(Unevictable) | ||
251 | #endif | 253 | #endif |
252 | 254 | ||
253 | #ifdef CONFIG_IA64_UNCACHED_ALLOCATOR | 255 | #ifdef CONFIG_IA64_UNCACHED_ALLOCATOR |
@@ -367,9 +369,13 @@ static inline void __ClearPageTail(struct page *page) | |||
367 | 369 | ||
368 | #ifdef CONFIG_UNEVICTABLE_LRU | 370 | #ifdef CONFIG_UNEVICTABLE_LRU |
369 | #define __PG_UNEVICTABLE (1 << PG_unevictable) | 371 | #define __PG_UNEVICTABLE (1 << PG_unevictable) |
370 | #define __PG_MLOCKED (1 << PG_mlocked) | ||
371 | #else | 372 | #else |
372 | #define __PG_UNEVICTABLE 0 | 373 | #define __PG_UNEVICTABLE 0 |
374 | #endif | ||
375 | |||
376 | #ifdef CONFIG_HAVE_MLOCKED_PAGE_BIT | ||
377 | #define __PG_MLOCKED (1 << PG_mlocked) | ||
378 | #else | ||
373 | #define __PG_MLOCKED 0 | 379 | #define __PG_MLOCKED 0 |
374 | #endif | 380 | #endif |
375 | 381 | ||
diff --git a/include/linux/pagevec.h b/include/linux/pagevec.h index 7b2886fa7fd..bab82f4c571 100644 --- a/include/linux/pagevec.h +++ b/include/linux/pagevec.h | |||
@@ -24,7 +24,6 @@ void __pagevec_release(struct pagevec *pvec); | |||
24 | void __pagevec_free(struct pagevec *pvec); | 24 | void __pagevec_free(struct pagevec *pvec); |
25 | void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru); | 25 | void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru); |
26 | void pagevec_strip(struct pagevec *pvec); | 26 | void pagevec_strip(struct pagevec *pvec); |
27 | void pagevec_swap_free(struct pagevec *pvec); | ||
28 | unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping, | 27 | unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping, |
29 | pgoff_t start, unsigned nr_pages); | 28 | pgoff_t start, unsigned nr_pages); |
30 | unsigned pagevec_lookup_tag(struct pagevec *pvec, | 29 | unsigned pagevec_lookup_tag(struct pagevec *pvec, |
diff --git a/include/linux/poison.h b/include/linux/poison.h index 9f31683728f..6729f7dcd60 100644 --- a/include/linux/poison.h +++ b/include/linux/poison.h | |||
@@ -17,6 +17,9 @@ | |||
17 | */ | 17 | */ |
18 | #define TIMER_ENTRY_STATIC ((void *) 0x74737461) | 18 | #define TIMER_ENTRY_STATIC ((void *) 0x74737461) |
19 | 19 | ||
20 | /********** mm/debug-pagealloc.c **********/ | ||
21 | #define PAGE_POISON 0xaa | ||
22 | |||
20 | /********** mm/slab.c **********/ | 23 | /********** mm/slab.c **********/ |
21 | /* | 24 | /* |
22 | * Magic nums for obj red zoning. | 25 | * Magic nums for obj red zoning. |
diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 4046b75563c..60f88a7fb13 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h | |||
@@ -99,6 +99,7 @@ struct rtc_pll_info { | |||
99 | 99 | ||
100 | #ifdef __KERNEL__ | 100 | #ifdef __KERNEL__ |
101 | 101 | ||
102 | #include <linux/types.h> | ||
102 | #include <linux/interrupt.h> | 103 | #include <linux/interrupt.h> |
103 | 104 | ||
104 | extern int rtc_month_days(unsigned int month, unsigned int year); | 105 | extern int rtc_month_days(unsigned int month, unsigned int year); |
@@ -232,6 +233,11 @@ int rtc_register(rtc_task_t *task); | |||
232 | int rtc_unregister(rtc_task_t *task); | 233 | int rtc_unregister(rtc_task_t *task); |
233 | int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg); | 234 | int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg); |
234 | 235 | ||
236 | static inline bool is_leap_year(unsigned int year) | ||
237 | { | ||
238 | return (!(year % 4) && (year % 100)) || !(year % 400); | ||
239 | } | ||
240 | |||
235 | #endif /* __KERNEL__ */ | 241 | #endif /* __KERNEL__ */ |
236 | 242 | ||
237 | #endif /* _LINUX_RTC_H_ */ | 243 | #endif /* _LINUX_RTC_H_ */ |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 29df6374d2d..481fad3a9b4 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -391,8 +391,15 @@ extern void arch_unmap_area_topdown(struct mm_struct *, unsigned long); | |||
391 | (mm)->hiwater_vm = (mm)->total_vm; \ | 391 | (mm)->hiwater_vm = (mm)->total_vm; \ |
392 | } while (0) | 392 | } while (0) |
393 | 393 | ||
394 | #define get_mm_hiwater_rss(mm) max((mm)->hiwater_rss, get_mm_rss(mm)) | 394 | static inline unsigned long get_mm_hiwater_rss(struct mm_struct *mm) |
395 | #define get_mm_hiwater_vm(mm) max((mm)->hiwater_vm, (mm)->total_vm) | 395 | { |
396 | return max(mm->hiwater_rss, get_mm_rss(mm)); | ||
397 | } | ||
398 | |||
399 | static inline unsigned long get_mm_hiwater_vm(struct mm_struct *mm) | ||
400 | { | ||
401 | return max(mm->hiwater_vm, mm->total_vm); | ||
402 | } | ||
396 | 403 | ||
397 | extern void set_dumpable(struct mm_struct *mm, int value); | 404 | extern void set_dumpable(struct mm_struct *mm, int value); |
398 | extern int get_dumpable(struct mm_struct *mm); | 405 | extern int get_dumpable(struct mm_struct *mm); |
diff --git a/include/linux/string.h b/include/linux/string.h index d18fc198aa2..8852739f36d 100644 --- a/include/linux/string.h +++ b/include/linux/string.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/stddef.h> /* for NULL */ | 12 | #include <linux/stddef.h> /* for NULL */ |
13 | 13 | ||
14 | extern char *strndup_user(const char __user *, long); | 14 | extern char *strndup_user(const char __user *, long); |
15 | extern void *memdup_user(const void __user *, size_t); | ||
15 | 16 | ||
16 | /* | 17 | /* |
17 | * Include machine specific inline routines | 18 | * Include machine specific inline routines |
diff --git a/include/linux/suspend.h b/include/linux/suspend.h index c7d9bb1832b..3e3a4364cbf 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h | |||
@@ -1,9 +1,6 @@ | |||
1 | #ifndef _LINUX_SUSPEND_H | 1 | #ifndef _LINUX_SUSPEND_H |
2 | #define _LINUX_SUSPEND_H | 2 | #define _LINUX_SUSPEND_H |
3 | 3 | ||
4 | #if defined(CONFIG_X86) || defined(CONFIG_FRV) || defined(CONFIG_PPC32) || defined(CONFIG_PPC64) | ||
5 | #include <asm/suspend.h> | ||
6 | #endif | ||
7 | #include <linux/swap.h> | 4 | #include <linux/swap.h> |
8 | #include <linux/notifier.h> | 5 | #include <linux/notifier.h> |
9 | #include <linux/init.h> | 6 | #include <linux/init.h> |
diff --git a/include/linux/swap.h b/include/linux/swap.h index d3021557887..62d81435347 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h | |||
@@ -212,7 +212,7 @@ static inline void lru_cache_add_active_file(struct page *page) | |||
212 | 212 | ||
213 | /* linux/mm/vmscan.c */ | 213 | /* linux/mm/vmscan.c */ |
214 | extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order, | 214 | extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order, |
215 | gfp_t gfp_mask); | 215 | gfp_t gfp_mask, nodemask_t *mask); |
216 | extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem, | 216 | extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem, |
217 | gfp_t gfp_mask, bool noswap, | 217 | gfp_t gfp_mask, bool noswap, |
218 | unsigned int swappiness); | 218 | unsigned int swappiness); |
@@ -382,6 +382,11 @@ static inline struct page *swapin_readahead(swp_entry_t swp, gfp_t gfp_mask, | |||
382 | return NULL; | 382 | return NULL; |
383 | } | 383 | } |
384 | 384 | ||
385 | static inline int swap_writepage(struct page *p, struct writeback_control *wbc) | ||
386 | { | ||
387 | return 0; | ||
388 | } | ||
389 | |||
385 | static inline struct page *lookup_swap_cache(swp_entry_t swp) | 390 | static inline struct page *lookup_swap_cache(swp_entry_t swp) |
386 | { | 391 | { |
387 | return NULL; | 392 | return NULL; |
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 08e088334db..8615d661ab6 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h | |||
@@ -252,8 +252,6 @@ struct tty_operations { | |||
252 | void (*set_ldisc)(struct tty_struct *tty); | 252 | void (*set_ldisc)(struct tty_struct *tty); |
253 | void (*wait_until_sent)(struct tty_struct *tty, int timeout); | 253 | void (*wait_until_sent)(struct tty_struct *tty, int timeout); |
254 | void (*send_xchar)(struct tty_struct *tty, char ch); | 254 | void (*send_xchar)(struct tty_struct *tty, char ch); |
255 | int (*read_proc)(char *page, char **start, off_t off, | ||
256 | int count, int *eof, void *data); | ||
257 | int (*tiocmget)(struct tty_struct *tty, struct file *file); | 255 | int (*tiocmget)(struct tty_struct *tty, struct file *file); |
258 | int (*tiocmset)(struct tty_struct *tty, struct file *file, | 256 | int (*tiocmset)(struct tty_struct *tty, struct file *file, |
259 | unsigned int set, unsigned int clear); | 257 | unsigned int set, unsigned int clear); |
@@ -264,6 +262,7 @@ struct tty_operations { | |||
264 | int (*poll_get_char)(struct tty_driver *driver, int line); | 262 | int (*poll_get_char)(struct tty_driver *driver, int line); |
265 | void (*poll_put_char)(struct tty_driver *driver, int line, char ch); | 263 | void (*poll_put_char)(struct tty_driver *driver, int line, char ch); |
266 | #endif | 264 | #endif |
265 | const struct file_operations *proc_fops; | ||
267 | }; | 266 | }; |
268 | 267 | ||
269 | struct tty_driver { | 268 | struct tty_driver { |
diff --git a/include/linux/wait.h b/include/linux/wait.h index a210ede73b5..5d631c17eae 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h | |||
@@ -135,8 +135,11 @@ static inline void __remove_wait_queue(wait_queue_head_t *head, | |||
135 | void __wake_up_common(wait_queue_head_t *q, unsigned int mode, | 135 | void __wake_up_common(wait_queue_head_t *q, unsigned int mode, |
136 | int nr_exclusive, int sync, void *key); | 136 | int nr_exclusive, int sync, void *key); |
137 | void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key); | 137 | void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key); |
138 | extern void __wake_up_locked(wait_queue_head_t *q, unsigned int mode); | 138 | void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key); |
139 | extern void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr); | 139 | void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, int nr, |
140 | void *key); | ||
141 | void __wake_up_locked(wait_queue_head_t *q, unsigned int mode); | ||
142 | void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr); | ||
140 | void __wake_up_bit(wait_queue_head_t *, void *, int); | 143 | void __wake_up_bit(wait_queue_head_t *, void *, int); |
141 | int __wait_on_bit(wait_queue_head_t *, struct wait_bit_queue *, int (*)(void *), unsigned); | 144 | int __wait_on_bit(wait_queue_head_t *, struct wait_bit_queue *, int (*)(void *), unsigned); |
142 | int __wait_on_bit_lock(wait_queue_head_t *, struct wait_bit_queue *, int (*)(void *), unsigned); | 145 | int __wait_on_bit_lock(wait_queue_head_t *, struct wait_bit_queue *, int (*)(void *), unsigned); |
@@ -155,21 +158,17 @@ wait_queue_head_t *bit_waitqueue(void *, int); | |||
155 | #define wake_up_interruptible_all(x) __wake_up(x, TASK_INTERRUPTIBLE, 0, NULL) | 158 | #define wake_up_interruptible_all(x) __wake_up(x, TASK_INTERRUPTIBLE, 0, NULL) |
156 | #define wake_up_interruptible_sync(x) __wake_up_sync((x), TASK_INTERRUPTIBLE, 1) | 159 | #define wake_up_interruptible_sync(x) __wake_up_sync((x), TASK_INTERRUPTIBLE, 1) |
157 | 160 | ||
158 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | ||
159 | /* | 161 | /* |
160 | * macro to avoid include hell | 162 | * Wakeup macros to be used to report events to the targets. |
161 | */ | 163 | */ |
162 | #define wake_up_nested(x, s) \ | 164 | #define wake_up_poll(x, m) \ |
163 | do { \ | 165 | __wake_up(x, TASK_NORMAL, 1, (void *) (m)) |
164 | unsigned long flags; \ | 166 | #define wake_up_locked_poll(x, m) \ |
165 | \ | 167 | __wake_up_locked_key((x), TASK_NORMAL, (void *) (m)) |
166 | spin_lock_irqsave_nested(&(x)->lock, flags, (s)); \ | 168 | #define wake_up_interruptible_poll(x, m) \ |
167 | wake_up_locked(x); \ | 169 | __wake_up(x, TASK_INTERRUPTIBLE, 1, (void *) (m)) |
168 | spin_unlock_irqrestore(&(x)->lock, flags); \ | 170 | #define wake_up_interruptible_sync_poll(x, m) \ |
169 | } while (0) | 171 | __wake_up_sync_key((x), TASK_INTERRUPTIBLE, 1, (void *) (m)) |
170 | #else | ||
171 | #define wake_up_nested(x, s) wake_up(x) | ||
172 | #endif | ||
173 | 172 | ||
174 | #define __wait_event(wq, condition) \ | 173 | #define __wait_event(wq, condition) \ |
175 | do { \ | 174 | do { \ |
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 7300ecdc480..93445477f86 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
@@ -109,8 +109,8 @@ extern int dirty_background_ratio; | |||
109 | extern unsigned long dirty_background_bytes; | 109 | extern unsigned long dirty_background_bytes; |
110 | extern int vm_dirty_ratio; | 110 | extern int vm_dirty_ratio; |
111 | extern unsigned long vm_dirty_bytes; | 111 | extern unsigned long vm_dirty_bytes; |
112 | extern int dirty_writeback_interval; | 112 | extern unsigned int dirty_writeback_interval; |
113 | extern int dirty_expire_interval; | 113 | extern unsigned int dirty_expire_interval; |
114 | extern int vm_highmem_is_dirtyable; | 114 | extern int vm_highmem_is_dirtyable; |
115 | extern int block_dump; | 115 | extern int block_dump; |
116 | extern int laptop_mode; | 116 | extern int laptop_mode; |
diff --git a/include/video/aty128.h b/include/video/aty128.h index 51ac69f05bd..f0851e3bb7c 100644 --- a/include/video/aty128.h +++ b/include/video/aty128.h | |||
@@ -415,7 +415,7 @@ | |||
415 | #define PWR_MGT_SLOWDOWN_MCLK 0x00002000 | 415 | #define PWR_MGT_SLOWDOWN_MCLK 0x00002000 |
416 | 416 | ||
417 | #define PMI_PMSCR_REG 0x60 | 417 | #define PMI_PMSCR_REG 0x60 |
418 | 418 | ||
419 | /* used by ATI bug fix for hardware ROM */ | 419 | /* used by ATI bug fix for hardware ROM */ |
420 | #define RAGE128_MPP_TB_CONFIG 0x01c0 | 420 | #define RAGE128_MPP_TB_CONFIG 0x01c0 |
421 | 421 | ||
diff --git a/include/video/cirrus.h b/include/video/cirrus.h index b2776b6c867..9a5e9ee3078 100644 --- a/include/video/cirrus.h +++ b/include/video/cirrus.h | |||
@@ -32,7 +32,6 @@ | |||
32 | #define CL_VSSM2 0x3c3 /* Motherboard Sleep */ | 32 | #define CL_VSSM2 0x3c3 /* Motherboard Sleep */ |
33 | 33 | ||
34 | /*** VGA Sequencer Registers ***/ | 34 | /*** VGA Sequencer Registers ***/ |
35 | #define CL_SEQR0 0x0 /* Reset */ | ||
36 | /* the following are from the "extension registers" group */ | 35 | /* the following are from the "extension registers" group */ |
37 | #define CL_SEQR6 0x6 /* Unlock ALL Extensions */ | 36 | #define CL_SEQR6 0x6 /* Unlock ALL Extensions */ |
38 | #define CL_SEQR7 0x7 /* Extended Sequencer Mode */ | 37 | #define CL_SEQR7 0x7 /* Extended Sequencer Mode */ |
@@ -71,6 +70,7 @@ | |||
71 | #define CL_CRT1B 0x1b /* Extended Display Controls */ | 70 | #define CL_CRT1B 0x1b /* Extended Display Controls */ |
72 | #define CL_CRT1C 0x1c /* Sync adjust and genlock register */ | 71 | #define CL_CRT1C 0x1c /* Sync adjust and genlock register */ |
73 | #define CL_CRT1D 0x1d /* Overlay Extended Control register */ | 72 | #define CL_CRT1D 0x1d /* Overlay Extended Control register */ |
73 | #define CL_CRT1E 0x1e /* Another overflow register */ | ||
74 | #define CL_CRT25 0x25 /* Part Status Register */ | 74 | #define CL_CRT25 0x25 /* Part Status Register */ |
75 | #define CL_CRT27 0x27 /* ID Register */ | 75 | #define CL_CRT27 0x27 /* ID Register */ |
76 | #define CL_CRT51 0x51 /* P4 disable "flicker fixer" */ | 76 | #define CL_CRT51 0x51 /* P4 disable "flicker fixer" */ |
diff --git a/include/video/newport.h b/include/video/newport.h index 1f5ebeaa818..001b935e71c 100644 --- a/include/video/newport.h +++ b/include/video/newport.h | |||
@@ -453,7 +453,7 @@ static __inline__ int newport_wait(struct newport_regs *regs) | |||
453 | { | 453 | { |
454 | int t = BUSY_TIMEOUT; | 454 | int t = BUSY_TIMEOUT; |
455 | 455 | ||
456 | while (t--) | 456 | while (--t) |
457 | if (!(regs->cset.status & NPORT_STAT_GBUSY)) | 457 | if (!(regs->cset.status & NPORT_STAT_GBUSY)) |
458 | break; | 458 | break; |
459 | return !t; | 459 | return !t; |
@@ -463,7 +463,7 @@ static __inline__ int newport_bfwait(struct newport_regs *regs) | |||
463 | { | 463 | { |
464 | int t = BUSY_TIMEOUT; | 464 | int t = BUSY_TIMEOUT; |
465 | 465 | ||
466 | while (t--) | 466 | while (--t) |
467 | if(!(regs->cset.status & NPORT_STAT_BBUSY)) | 467 | if(!(regs->cset.status & NPORT_STAT_BBUSY)) |
468 | break; | 468 | break; |
469 | return !t; | 469 | return !t; |
diff --git a/include/video/radeon.h b/include/video/radeon.h index e072b16b39a..56b188abfb5 100644 --- a/include/video/radeon.h +++ b/include/video/radeon.h | |||
@@ -5,12 +5,12 @@ | |||
5 | #define RADEON_REGSIZE 0x4000 | 5 | #define RADEON_REGSIZE 0x4000 |
6 | 6 | ||
7 | 7 | ||
8 | #define MM_INDEX 0x0000 | 8 | #define MM_INDEX 0x0000 |
9 | #define MM_DATA 0x0004 | 9 | #define MM_DATA 0x0004 |
10 | #define BUS_CNTL 0x0030 | 10 | #define BUS_CNTL 0x0030 |
11 | #define HI_STAT 0x004C | 11 | #define HI_STAT 0x004C |
12 | #define BUS_CNTL1 0x0034 | 12 | #define BUS_CNTL1 0x0034 |
13 | #define I2C_CNTL_1 0x0094 | 13 | #define I2C_CNTL_1 0x0094 |
14 | #define CNFG_CNTL 0x00E0 | 14 | #define CNFG_CNTL 0x00E0 |
15 | #define CNFG_MEMSIZE 0x00F8 | 15 | #define CNFG_MEMSIZE 0x00F8 |
16 | #define CNFG_APER_0_BASE 0x0100 | 16 | #define CNFG_APER_0_BASE 0x0100 |
@@ -18,8 +18,8 @@ | |||
18 | #define CNFG_APER_SIZE 0x0108 | 18 | #define CNFG_APER_SIZE 0x0108 |
19 | #define CNFG_REG_1_BASE 0x010C | 19 | #define CNFG_REG_1_BASE 0x010C |
20 | #define CNFG_REG_APER_SIZE 0x0110 | 20 | #define CNFG_REG_APER_SIZE 0x0110 |
21 | #define PAD_AGPINPUT_DELAY 0x0164 | 21 | #define PAD_AGPINPUT_DELAY 0x0164 |
22 | #define PAD_CTLR_STRENGTH 0x0168 | 22 | #define PAD_CTLR_STRENGTH 0x0168 |
23 | #define PAD_CTLR_UPDATE 0x016C | 23 | #define PAD_CTLR_UPDATE 0x016C |
24 | #define PAD_CTLR_MISC 0x0aa0 | 24 | #define PAD_CTLR_MISC 0x0aa0 |
25 | #define AGP_CNTL 0x0174 | 25 | #define AGP_CNTL 0x0174 |
@@ -27,171 +27,171 @@ | |||
27 | #define CAP0_TRIG_CNTL 0x0950 | 27 | #define CAP0_TRIG_CNTL 0x0950 |
28 | #define CAP1_TRIG_CNTL 0x09c0 | 28 | #define CAP1_TRIG_CNTL 0x09c0 |
29 | #define VIPH_CONTROL 0x0C40 | 29 | #define VIPH_CONTROL 0x0C40 |
30 | #define VENDOR_ID 0x0F00 | 30 | #define VENDOR_ID 0x0F00 |
31 | #define DEVICE_ID 0x0F02 | 31 | #define DEVICE_ID 0x0F02 |
32 | #define COMMAND 0x0F04 | 32 | #define COMMAND 0x0F04 |
33 | #define STATUS 0x0F06 | 33 | #define STATUS 0x0F06 |
34 | #define REVISION_ID 0x0F08 | 34 | #define REVISION_ID 0x0F08 |
35 | #define REGPROG_INF 0x0F09 | 35 | #define REGPROG_INF 0x0F09 |
36 | #define SUB_CLASS 0x0F0A | 36 | #define SUB_CLASS 0x0F0A |
37 | #define BASE_CODE 0x0F0B | 37 | #define BASE_CODE 0x0F0B |
38 | #define CACHE_LINE 0x0F0C | 38 | #define CACHE_LINE 0x0F0C |
39 | #define LATENCY 0x0F0D | 39 | #define LATENCY 0x0F0D |
40 | #define HEADER 0x0F0E | 40 | #define HEADER 0x0F0E |
41 | #define BIST 0x0F0F | 41 | #define BIST 0x0F0F |
42 | #define REG_MEM_BASE 0x0F10 | 42 | #define REG_MEM_BASE 0x0F10 |
43 | #define REG_IO_BASE 0x0F14 | 43 | #define REG_IO_BASE 0x0F14 |
44 | #define REG_REG_BASE 0x0F18 | 44 | #define REG_REG_BASE 0x0F18 |
45 | #define ADAPTER_ID 0x0F2C | 45 | #define ADAPTER_ID 0x0F2C |
46 | #define BIOS_ROM 0x0F30 | 46 | #define BIOS_ROM 0x0F30 |
47 | #define CAPABILITIES_PTR 0x0F34 | 47 | #define CAPABILITIES_PTR 0x0F34 |
48 | #define INTERRUPT_LINE 0x0F3C | 48 | #define INTERRUPT_LINE 0x0F3C |
49 | #define INTERRUPT_PIN 0x0F3D | 49 | #define INTERRUPT_PIN 0x0F3D |
50 | #define MIN_GRANT 0x0F3E | 50 | #define MIN_GRANT 0x0F3E |
51 | #define MAX_LATENCY 0x0F3F | 51 | #define MAX_LATENCY 0x0F3F |
52 | #define ADAPTER_ID_W 0x0F4C | 52 | #define ADAPTER_ID_W 0x0F4C |
53 | #define PMI_CAP_ID 0x0F50 | 53 | #define PMI_CAP_ID 0x0F50 |
54 | #define PMI_NXT_CAP_PTR 0x0F51 | 54 | #define PMI_NXT_CAP_PTR 0x0F51 |
55 | #define PMI_PMC_REG 0x0F52 | 55 | #define PMI_PMC_REG 0x0F52 |
56 | #define PM_STATUS 0x0F54 | 56 | #define PM_STATUS 0x0F54 |
57 | #define PMI_DATA 0x0F57 | 57 | #define PMI_DATA 0x0F57 |
58 | #define AGP_CAP_ID 0x0F58 | 58 | #define AGP_CAP_ID 0x0F58 |
59 | #define AGP_STATUS 0x0F5C | 59 | #define AGP_STATUS 0x0F5C |
60 | #define AGP_COMMAND 0x0F60 | 60 | #define AGP_COMMAND 0x0F60 |
61 | #define AIC_CTRL 0x01D0 | 61 | #define AIC_CTRL 0x01D0 |
62 | #define AIC_STAT 0x01D4 | 62 | #define AIC_STAT 0x01D4 |
63 | #define AIC_PT_BASE 0x01D8 | 63 | #define AIC_PT_BASE 0x01D8 |
64 | #define AIC_LO_ADDR 0x01DC | 64 | #define AIC_LO_ADDR 0x01DC |
65 | #define AIC_HI_ADDR 0x01E0 | 65 | #define AIC_HI_ADDR 0x01E0 |
66 | #define AIC_TLB_ADDR 0x01E4 | 66 | #define AIC_TLB_ADDR 0x01E4 |
67 | #define AIC_TLB_DATA 0x01E8 | 67 | #define AIC_TLB_DATA 0x01E8 |
68 | #define DAC_CNTL 0x0058 | 68 | #define DAC_CNTL 0x0058 |
69 | #define DAC_CNTL2 0x007c | 69 | #define DAC_CNTL2 0x007c |
70 | #define CRTC_GEN_CNTL 0x0050 | 70 | #define CRTC_GEN_CNTL 0x0050 |
71 | #define MEM_CNTL 0x0140 | 71 | #define MEM_CNTL 0x0140 |
72 | #define MC_CNTL 0x0140 | 72 | #define MC_CNTL 0x0140 |
73 | #define EXT_MEM_CNTL 0x0144 | 73 | #define EXT_MEM_CNTL 0x0144 |
74 | #define MC_TIMING_CNTL 0x0144 | 74 | #define MC_TIMING_CNTL 0x0144 |
75 | #define MC_AGP_LOCATION 0x014C | 75 | #define MC_AGP_LOCATION 0x014C |
76 | #define MEM_IO_CNTL_A0 0x0178 | 76 | #define MEM_IO_CNTL_A0 0x0178 |
77 | #define MEM_REFRESH_CNTL 0x0178 | 77 | #define MEM_REFRESH_CNTL 0x0178 |
78 | #define MEM_INIT_LATENCY_TIMER 0x0154 | 78 | #define MEM_INIT_LATENCY_TIMER 0x0154 |
79 | #define MC_INIT_GFX_LAT_TIMER 0x0154 | 79 | #define MC_INIT_GFX_LAT_TIMER 0x0154 |
80 | #define MEM_SDRAM_MODE_REG 0x0158 | 80 | #define MEM_SDRAM_MODE_REG 0x0158 |
81 | #define AGP_BASE 0x0170 | 81 | #define AGP_BASE 0x0170 |
82 | #define MEM_IO_CNTL_A1 0x017C | 82 | #define MEM_IO_CNTL_A1 0x017C |
83 | #define MC_READ_CNTL_AB 0x017C | 83 | #define MC_READ_CNTL_AB 0x017C |
84 | #define MEM_IO_CNTL_B0 0x0180 | 84 | #define MEM_IO_CNTL_B0 0x0180 |
85 | #define MC_INIT_MISC_LAT_TIMER 0x0180 | 85 | #define MC_INIT_MISC_LAT_TIMER 0x0180 |
86 | #define MEM_IO_CNTL_B1 0x0184 | 86 | #define MEM_IO_CNTL_B1 0x0184 |
87 | #define MC_IOPAD_CNTL 0x0184 | 87 | #define MC_IOPAD_CNTL 0x0184 |
88 | #define MC_DEBUG 0x0188 | 88 | #define MC_DEBUG 0x0188 |
89 | #define MC_STATUS 0x0150 | 89 | #define MC_STATUS 0x0150 |
90 | #define MEM_IO_OE_CNTL 0x018C | 90 | #define MEM_IO_OE_CNTL 0x018C |
91 | #define MC_CHIP_IO_OE_CNTL_AB 0x018C | 91 | #define MC_CHIP_IO_OE_CNTL_AB 0x018C |
92 | #define MC_FB_LOCATION 0x0148 | 92 | #define MC_FB_LOCATION 0x0148 |
93 | #define HOST_PATH_CNTL 0x0130 | 93 | #define HOST_PATH_CNTL 0x0130 |
94 | #define MEM_VGA_WP_SEL 0x0038 | 94 | #define MEM_VGA_WP_SEL 0x0038 |
95 | #define MEM_VGA_RP_SEL 0x003C | 95 | #define MEM_VGA_RP_SEL 0x003C |
96 | #define HDP_DEBUG 0x0138 | 96 | #define HDP_DEBUG 0x0138 |
97 | #define SW_SEMAPHORE 0x013C | 97 | #define SW_SEMAPHORE 0x013C |
98 | #define CRTC2_GEN_CNTL 0x03f8 | 98 | #define CRTC2_GEN_CNTL 0x03f8 |
99 | #define CRTC2_DISPLAY_BASE_ADDR 0x033c | 99 | #define CRTC2_DISPLAY_BASE_ADDR 0x033c |
100 | #define SURFACE_CNTL 0x0B00 | 100 | #define SURFACE_CNTL 0x0B00 |
101 | #define SURFACE0_LOWER_BOUND 0x0B04 | 101 | #define SURFACE0_LOWER_BOUND 0x0B04 |
102 | #define SURFACE1_LOWER_BOUND 0x0B14 | 102 | #define SURFACE1_LOWER_BOUND 0x0B14 |
103 | #define SURFACE2_LOWER_BOUND 0x0B24 | 103 | #define SURFACE2_LOWER_BOUND 0x0B24 |
104 | #define SURFACE3_LOWER_BOUND 0x0B34 | 104 | #define SURFACE3_LOWER_BOUND 0x0B34 |
105 | #define SURFACE4_LOWER_BOUND 0x0B44 | 105 | #define SURFACE4_LOWER_BOUND 0x0B44 |
106 | #define SURFACE5_LOWER_BOUND 0x0B54 | 106 | #define SURFACE5_LOWER_BOUND 0x0B54 |
107 | #define SURFACE6_LOWER_BOUND 0x0B64 | 107 | #define SURFACE6_LOWER_BOUND 0x0B64 |
108 | #define SURFACE7_LOWER_BOUND 0x0B74 | 108 | #define SURFACE7_LOWER_BOUND 0x0B74 |
109 | #define SURFACE0_UPPER_BOUND 0x0B08 | 109 | #define SURFACE0_UPPER_BOUND 0x0B08 |
110 | #define SURFACE1_UPPER_BOUND 0x0B18 | 110 | #define SURFACE1_UPPER_BOUND 0x0B18 |
111 | #define SURFACE2_UPPER_BOUND 0x0B28 | 111 | #define SURFACE2_UPPER_BOUND 0x0B28 |
112 | #define SURFACE3_UPPER_BOUND 0x0B38 | 112 | #define SURFACE3_UPPER_BOUND 0x0B38 |
113 | #define SURFACE4_UPPER_BOUND 0x0B48 | 113 | #define SURFACE4_UPPER_BOUND 0x0B48 |
114 | #define SURFACE5_UPPER_BOUND 0x0B58 | 114 | #define SURFACE5_UPPER_BOUND 0x0B58 |
115 | #define SURFACE6_UPPER_BOUND 0x0B68 | 115 | #define SURFACE6_UPPER_BOUND 0x0B68 |
116 | #define SURFACE7_UPPER_BOUND 0x0B78 | 116 | #define SURFACE7_UPPER_BOUND 0x0B78 |
117 | #define SURFACE0_INFO 0x0B0C | 117 | #define SURFACE0_INFO 0x0B0C |
118 | #define SURFACE1_INFO 0x0B1C | 118 | #define SURFACE1_INFO 0x0B1C |
119 | #define SURFACE2_INFO 0x0B2C | 119 | #define SURFACE2_INFO 0x0B2C |
120 | #define SURFACE3_INFO 0x0B3C | 120 | #define SURFACE3_INFO 0x0B3C |
121 | #define SURFACE4_INFO 0x0B4C | 121 | #define SURFACE4_INFO 0x0B4C |
122 | #define SURFACE5_INFO 0x0B5C | 122 | #define SURFACE5_INFO 0x0B5C |
123 | #define SURFACE6_INFO 0x0B6C | 123 | #define SURFACE6_INFO 0x0B6C |
124 | #define SURFACE7_INFO 0x0B7C | 124 | #define SURFACE7_INFO 0x0B7C |
125 | #define SURFACE_ACCESS_FLAGS 0x0BF8 | 125 | #define SURFACE_ACCESS_FLAGS 0x0BF8 |
126 | #define SURFACE_ACCESS_CLR 0x0BFC | 126 | #define SURFACE_ACCESS_CLR 0x0BFC |
127 | #define GEN_INT_CNTL 0x0040 | 127 | #define GEN_INT_CNTL 0x0040 |
128 | #define GEN_INT_STATUS 0x0044 | 128 | #define GEN_INT_STATUS 0x0044 |
129 | #define CRTC_EXT_CNTL 0x0054 | 129 | #define CRTC_EXT_CNTL 0x0054 |
130 | #define RB3D_CNTL 0x1C3C | 130 | #define RB3D_CNTL 0x1C3C |
131 | #define WAIT_UNTIL 0x1720 | 131 | #define WAIT_UNTIL 0x1720 |
132 | #define ISYNC_CNTL 0x1724 | 132 | #define ISYNC_CNTL 0x1724 |
133 | #define RBBM_GUICNTL 0x172C | 133 | #define RBBM_GUICNTL 0x172C |
134 | #define RBBM_STATUS 0x0E40 | 134 | #define RBBM_STATUS 0x0E40 |
135 | #define RBBM_STATUS_alt_1 0x1740 | 135 | #define RBBM_STATUS_alt_1 0x1740 |
136 | #define RBBM_CNTL 0x00EC | 136 | #define RBBM_CNTL 0x00EC |
137 | #define RBBM_CNTL_alt_1 0x0E44 | 137 | #define RBBM_CNTL_alt_1 0x0E44 |
138 | #define RBBM_SOFT_RESET 0x00F0 | 138 | #define RBBM_SOFT_RESET 0x00F0 |
139 | #define RBBM_SOFT_RESET_alt_1 0x0E48 | 139 | #define RBBM_SOFT_RESET_alt_1 0x0E48 |
140 | #define NQWAIT_UNTIL 0x0E50 | 140 | #define NQWAIT_UNTIL 0x0E50 |
141 | #define RBBM_DEBUG 0x0E6C | 141 | #define RBBM_DEBUG 0x0E6C |
142 | #define RBBM_CMDFIFO_ADDR 0x0E70 | 142 | #define RBBM_CMDFIFO_ADDR 0x0E70 |
143 | #define RBBM_CMDFIFO_DATAL 0x0E74 | 143 | #define RBBM_CMDFIFO_DATAL 0x0E74 |
144 | #define RBBM_CMDFIFO_DATAH 0x0E78 | 144 | #define RBBM_CMDFIFO_DATAH 0x0E78 |
145 | #define RBBM_CMDFIFO_STAT 0x0E7C | 145 | #define RBBM_CMDFIFO_STAT 0x0E7C |
146 | #define CRTC_STATUS 0x005C | 146 | #define CRTC_STATUS 0x005C |
147 | #define GPIO_VGA_DDC 0x0060 | 147 | #define GPIO_VGA_DDC 0x0060 |
148 | #define GPIO_DVI_DDC 0x0064 | 148 | #define GPIO_DVI_DDC 0x0064 |
149 | #define GPIO_MONID 0x0068 | 149 | #define GPIO_MONID 0x0068 |
150 | #define GPIO_CRT2_DDC 0x006c | 150 | #define GPIO_CRT2_DDC 0x006c |
151 | #define PALETTE_INDEX 0x00B0 | 151 | #define PALETTE_INDEX 0x00B0 |
152 | #define PALETTE_DATA 0x00B4 | 152 | #define PALETTE_DATA 0x00B4 |
153 | #define PALETTE_30_DATA 0x00B8 | 153 | #define PALETTE_30_DATA 0x00B8 |
154 | #define CRTC_H_TOTAL_DISP 0x0200 | 154 | #define CRTC_H_TOTAL_DISP 0x0200 |
155 | #define CRTC_H_SYNC_STRT_WID 0x0204 | 155 | #define CRTC_H_SYNC_STRT_WID 0x0204 |
156 | #define CRTC_V_TOTAL_DISP 0x0208 | 156 | #define CRTC_V_TOTAL_DISP 0x0208 |
157 | #define CRTC_V_SYNC_STRT_WID 0x020C | 157 | #define CRTC_V_SYNC_STRT_WID 0x020C |
158 | #define CRTC_VLINE_CRNT_VLINE 0x0210 | 158 | #define CRTC_VLINE_CRNT_VLINE 0x0210 |
159 | #define CRTC_CRNT_FRAME 0x0214 | 159 | #define CRTC_CRNT_FRAME 0x0214 |
160 | #define CRTC_GUI_TRIG_VLINE 0x0218 | 160 | #define CRTC_GUI_TRIG_VLINE 0x0218 |
161 | #define CRTC_DEBUG 0x021C | 161 | #define CRTC_DEBUG 0x021C |
162 | #define CRTC_OFFSET_RIGHT 0x0220 | 162 | #define CRTC_OFFSET_RIGHT 0x0220 |
163 | #define CRTC_OFFSET 0x0224 | 163 | #define CRTC_OFFSET 0x0224 |
164 | #define CRTC_OFFSET_CNTL 0x0228 | 164 | #define CRTC_OFFSET_CNTL 0x0228 |
165 | #define CRTC_PITCH 0x022C | 165 | #define CRTC_PITCH 0x022C |
166 | #define OVR_CLR 0x0230 | 166 | #define OVR_CLR 0x0230 |
167 | #define OVR_WID_LEFT_RIGHT 0x0234 | 167 | #define OVR_WID_LEFT_RIGHT 0x0234 |
168 | #define OVR_WID_TOP_BOTTOM 0x0238 | 168 | #define OVR_WID_TOP_BOTTOM 0x0238 |
169 | #define DISPLAY_BASE_ADDR 0x023C | 169 | #define DISPLAY_BASE_ADDR 0x023C |
170 | #define SNAPSHOT_VH_COUNTS 0x0240 | 170 | #define SNAPSHOT_VH_COUNTS 0x0240 |
171 | #define SNAPSHOT_F_COUNT 0x0244 | 171 | #define SNAPSHOT_F_COUNT 0x0244 |
172 | #define N_VIF_COUNT 0x0248 | 172 | #define N_VIF_COUNT 0x0248 |
173 | #define SNAPSHOT_VIF_COUNT 0x024C | 173 | #define SNAPSHOT_VIF_COUNT 0x024C |
174 | #define FP_CRTC_H_TOTAL_DISP 0x0250 | 174 | #define FP_CRTC_H_TOTAL_DISP 0x0250 |
175 | #define FP_CRTC_V_TOTAL_DISP 0x0254 | 175 | #define FP_CRTC_V_TOTAL_DISP 0x0254 |
176 | #define CRT_CRTC_H_SYNC_STRT_WID 0x0258 | 176 | #define CRT_CRTC_H_SYNC_STRT_WID 0x0258 |
177 | #define CRT_CRTC_V_SYNC_STRT_WID 0x025C | 177 | #define CRT_CRTC_V_SYNC_STRT_WID 0x025C |
178 | #define CUR_OFFSET 0x0260 | 178 | #define CUR_OFFSET 0x0260 |
179 | #define CUR_HORZ_VERT_POSN 0x0264 | 179 | #define CUR_HORZ_VERT_POSN 0x0264 |
180 | #define CUR_HORZ_VERT_OFF 0x0268 | 180 | #define CUR_HORZ_VERT_OFF 0x0268 |
181 | #define CUR_CLR0 0x026C | 181 | #define CUR_CLR0 0x026C |
182 | #define CUR_CLR1 0x0270 | 182 | #define CUR_CLR1 0x0270 |
183 | #define FP_HORZ_VERT_ACTIVE 0x0278 | 183 | #define FP_HORZ_VERT_ACTIVE 0x0278 |
184 | #define CRTC_MORE_CNTL 0x027C | 184 | #define CRTC_MORE_CNTL 0x027C |
185 | #define CRTC_H_CUTOFF_ACTIVE_EN (1<<4) | 185 | #define CRTC_H_CUTOFF_ACTIVE_EN (1<<4) |
186 | #define CRTC_V_CUTOFF_ACTIVE_EN (1<<5) | 186 | #define CRTC_V_CUTOFF_ACTIVE_EN (1<<5) |
187 | #define DAC_EXT_CNTL 0x0280 | 187 | #define DAC_EXT_CNTL 0x0280 |
188 | #define FP_GEN_CNTL 0x0284 | 188 | #define FP_GEN_CNTL 0x0284 |
189 | #define FP_HORZ_STRETCH 0x028C | 189 | #define FP_HORZ_STRETCH 0x028C |
190 | #define FP_VERT_STRETCH 0x0290 | 190 | #define FP_VERT_STRETCH 0x0290 |
191 | #define FP_H_SYNC_STRT_WID 0x02C4 | 191 | #define FP_H_SYNC_STRT_WID 0x02C4 |
192 | #define FP_V_SYNC_STRT_WID 0x02C8 | 192 | #define FP_V_SYNC_STRT_WID 0x02C8 |
193 | #define AUX_WINDOW_HORZ_CNTL 0x02D8 | 193 | #define AUX_WINDOW_HORZ_CNTL 0x02D8 |
194 | #define AUX_WINDOW_VERT_CNTL 0x02DC | 194 | #define AUX_WINDOW_VERT_CNTL 0x02DC |
195 | //#define DDA_CONFIG 0x02e0 | 195 | //#define DDA_CONFIG 0x02e0 |
196 | //#define DDA_ON_OFF 0x02e4 | 196 | //#define DDA_ON_OFF 0x02e4 |
197 | #define DVI_I2C_CNTL_1 0x02e4 | 197 | #define DVI_I2C_CNTL_1 0x02e4 |
@@ -199,192 +199,192 @@ | |||
199 | #define GRPH2_BUFFER_CNTL 0x03F0 | 199 | #define GRPH2_BUFFER_CNTL 0x03F0 |
200 | #define VGA_BUFFER_CNTL 0x02F4 | 200 | #define VGA_BUFFER_CNTL 0x02F4 |
201 | #define OV0_Y_X_START 0x0400 | 201 | #define OV0_Y_X_START 0x0400 |
202 | #define OV0_Y_X_END 0x0404 | 202 | #define OV0_Y_X_END 0x0404 |
203 | #define OV0_PIPELINE_CNTL 0x0408 | 203 | #define OV0_PIPELINE_CNTL 0x0408 |
204 | #define OV0_REG_LOAD_CNTL 0x0410 | 204 | #define OV0_REG_LOAD_CNTL 0x0410 |
205 | #define OV0_SCALE_CNTL 0x0420 | 205 | #define OV0_SCALE_CNTL 0x0420 |
206 | #define OV0_V_INC 0x0424 | 206 | #define OV0_V_INC 0x0424 |
207 | #define OV0_P1_V_ACCUM_INIT 0x0428 | 207 | #define OV0_P1_V_ACCUM_INIT 0x0428 |
208 | #define OV0_P23_V_ACCUM_INIT 0x042C | 208 | #define OV0_P23_V_ACCUM_INIT 0x042C |
209 | #define OV0_P1_BLANK_LINES_AT_TOP 0x0430 | 209 | #define OV0_P1_BLANK_LINES_AT_TOP 0x0430 |
210 | #define OV0_P23_BLANK_LINES_AT_TOP 0x0434 | 210 | #define OV0_P23_BLANK_LINES_AT_TOP 0x0434 |
211 | #define OV0_BASE_ADDR 0x043C | 211 | #define OV0_BASE_ADDR 0x043C |
212 | #define OV0_VID_BUF0_BASE_ADRS 0x0440 | 212 | #define OV0_VID_BUF0_BASE_ADRS 0x0440 |
213 | #define OV0_VID_BUF1_BASE_ADRS 0x0444 | 213 | #define OV0_VID_BUF1_BASE_ADRS 0x0444 |
214 | #define OV0_VID_BUF2_BASE_ADRS 0x0448 | 214 | #define OV0_VID_BUF2_BASE_ADRS 0x0448 |
215 | #define OV0_VID_BUF3_BASE_ADRS 0x044C | 215 | #define OV0_VID_BUF3_BASE_ADRS 0x044C |
216 | #define OV0_VID_BUF4_BASE_ADRS 0x0450 | 216 | #define OV0_VID_BUF4_BASE_ADRS 0x0450 |
217 | #define OV0_VID_BUF5_BASE_ADRS 0x0454 | 217 | #define OV0_VID_BUF5_BASE_ADRS 0x0454 |
218 | #define OV0_VID_BUF_PITCH0_VALUE 0x0460 | 218 | #define OV0_VID_BUF_PITCH0_VALUE 0x0460 |
219 | #define OV0_VID_BUF_PITCH1_VALUE 0x0464 | 219 | #define OV0_VID_BUF_PITCH1_VALUE 0x0464 |
220 | #define OV0_AUTO_FLIP_CNTRL 0x0470 | 220 | #define OV0_AUTO_FLIP_CNTRL 0x0470 |
221 | #define OV0_DEINTERLACE_PATTERN 0x0474 | 221 | #define OV0_DEINTERLACE_PATTERN 0x0474 |
222 | #define OV0_SUBMIT_HISTORY 0x0478 | 222 | #define OV0_SUBMIT_HISTORY 0x0478 |
223 | #define OV0_H_INC 0x0480 | 223 | #define OV0_H_INC 0x0480 |
224 | #define OV0_STEP_BY 0x0484 | 224 | #define OV0_STEP_BY 0x0484 |
225 | #define OV0_P1_H_ACCUM_INIT 0x0488 | 225 | #define OV0_P1_H_ACCUM_INIT 0x0488 |
226 | #define OV0_P23_H_ACCUM_INIT 0x048C | 226 | #define OV0_P23_H_ACCUM_INIT 0x048C |
227 | #define OV0_P1_X_START_END 0x0494 | 227 | #define OV0_P1_X_START_END 0x0494 |
228 | #define OV0_P2_X_START_END 0x0498 | 228 | #define OV0_P2_X_START_END 0x0498 |
229 | #define OV0_P3_X_START_END 0x049C | 229 | #define OV0_P3_X_START_END 0x049C |
230 | #define OV0_FILTER_CNTL 0x04A0 | 230 | #define OV0_FILTER_CNTL 0x04A0 |
231 | #define OV0_FOUR_TAP_COEF_0 0x04B0 | 231 | #define OV0_FOUR_TAP_COEF_0 0x04B0 |
232 | #define OV0_FOUR_TAP_COEF_1 0x04B4 | 232 | #define OV0_FOUR_TAP_COEF_1 0x04B4 |
233 | #define OV0_FOUR_TAP_COEF_2 0x04B8 | 233 | #define OV0_FOUR_TAP_COEF_2 0x04B8 |
234 | #define OV0_FOUR_TAP_COEF_3 0x04BC | 234 | #define OV0_FOUR_TAP_COEF_3 0x04BC |
235 | #define OV0_FOUR_TAP_COEF_4 0x04C0 | 235 | #define OV0_FOUR_TAP_COEF_4 0x04C0 |
236 | #define OV0_FLAG_CNTRL 0x04DC | 236 | #define OV0_FLAG_CNTRL 0x04DC |
237 | #define OV0_SLICE_CNTL 0x04E0 | 237 | #define OV0_SLICE_CNTL 0x04E0 |
238 | #define OV0_VID_KEY_CLR_LOW 0x04E4 | 238 | #define OV0_VID_KEY_CLR_LOW 0x04E4 |
239 | #define OV0_VID_KEY_CLR_HIGH 0x04E8 | 239 | #define OV0_VID_KEY_CLR_HIGH 0x04E8 |
240 | #define OV0_GRPH_KEY_CLR_LOW 0x04EC | 240 | #define OV0_GRPH_KEY_CLR_LOW 0x04EC |
241 | #define OV0_GRPH_KEY_CLR_HIGH 0x04F0 | 241 | #define OV0_GRPH_KEY_CLR_HIGH 0x04F0 |
242 | #define OV0_KEY_CNTL 0x04F4 | 242 | #define OV0_KEY_CNTL 0x04F4 |
243 | #define OV0_TEST 0x04F8 | 243 | #define OV0_TEST 0x04F8 |
244 | #define SUBPIC_CNTL 0x0540 | 244 | #define SUBPIC_CNTL 0x0540 |
245 | #define SUBPIC_DEFCOLCON 0x0544 | 245 | #define SUBPIC_DEFCOLCON 0x0544 |
246 | #define SUBPIC_Y_X_START 0x054C | 246 | #define SUBPIC_Y_X_START 0x054C |
247 | #define SUBPIC_Y_X_END 0x0550 | 247 | #define SUBPIC_Y_X_END 0x0550 |
248 | #define SUBPIC_V_INC 0x0554 | 248 | #define SUBPIC_V_INC 0x0554 |
249 | #define SUBPIC_H_INC 0x0558 | 249 | #define SUBPIC_H_INC 0x0558 |
250 | #define SUBPIC_BUF0_OFFSET 0x055C | 250 | #define SUBPIC_BUF0_OFFSET 0x055C |
251 | #define SUBPIC_BUF1_OFFSET 0x0560 | 251 | #define SUBPIC_BUF1_OFFSET 0x0560 |
252 | #define SUBPIC_LC0_OFFSET 0x0564 | 252 | #define SUBPIC_LC0_OFFSET 0x0564 |
253 | #define SUBPIC_LC1_OFFSET 0x0568 | 253 | #define SUBPIC_LC1_OFFSET 0x0568 |
254 | #define SUBPIC_PITCH 0x056C | 254 | #define SUBPIC_PITCH 0x056C |
255 | #define SUBPIC_BTN_HLI_COLCON 0x0570 | 255 | #define SUBPIC_BTN_HLI_COLCON 0x0570 |
256 | #define SUBPIC_BTN_HLI_Y_X_START 0x0574 | 256 | #define SUBPIC_BTN_HLI_Y_X_START 0x0574 |
257 | #define SUBPIC_BTN_HLI_Y_X_END 0x0578 | 257 | #define SUBPIC_BTN_HLI_Y_X_END 0x0578 |
258 | #define SUBPIC_PALETTE_INDEX 0x057C | 258 | #define SUBPIC_PALETTE_INDEX 0x057C |
259 | #define SUBPIC_PALETTE_DATA 0x0580 | 259 | #define SUBPIC_PALETTE_DATA 0x0580 |
260 | #define SUBPIC_H_ACCUM_INIT 0x0584 | 260 | #define SUBPIC_H_ACCUM_INIT 0x0584 |
261 | #define SUBPIC_V_ACCUM_INIT 0x0588 | 261 | #define SUBPIC_V_ACCUM_INIT 0x0588 |
262 | #define DISP_MISC_CNTL 0x0D00 | 262 | #define DISP_MISC_CNTL 0x0D00 |
263 | #define DAC_MACRO_CNTL 0x0D04 | 263 | #define DAC_MACRO_CNTL 0x0D04 |
264 | #define DISP_PWR_MAN 0x0D08 | 264 | #define DISP_PWR_MAN 0x0D08 |
265 | #define DISP_TEST_DEBUG_CNTL 0x0D10 | 265 | #define DISP_TEST_DEBUG_CNTL 0x0D10 |
266 | #define DISP_HW_DEBUG 0x0D14 | 266 | #define DISP_HW_DEBUG 0x0D14 |
267 | #define DAC_CRC_SIG1 0x0D18 | 267 | #define DAC_CRC_SIG1 0x0D18 |
268 | #define DAC_CRC_SIG2 0x0D1C | 268 | #define DAC_CRC_SIG2 0x0D1C |
269 | #define OV0_LIN_TRANS_A 0x0D20 | 269 | #define OV0_LIN_TRANS_A 0x0D20 |
270 | #define OV0_LIN_TRANS_B 0x0D24 | 270 | #define OV0_LIN_TRANS_B 0x0D24 |
271 | #define OV0_LIN_TRANS_C 0x0D28 | 271 | #define OV0_LIN_TRANS_C 0x0D28 |
272 | #define OV0_LIN_TRANS_D 0x0D2C | 272 | #define OV0_LIN_TRANS_D 0x0D2C |
273 | #define OV0_LIN_TRANS_E 0x0D30 | 273 | #define OV0_LIN_TRANS_E 0x0D30 |
274 | #define OV0_LIN_TRANS_F 0x0D34 | 274 | #define OV0_LIN_TRANS_F 0x0D34 |
275 | #define OV0_GAMMA_0_F 0x0D40 | 275 | #define OV0_GAMMA_0_F 0x0D40 |
276 | #define OV0_GAMMA_10_1F 0x0D44 | 276 | #define OV0_GAMMA_10_1F 0x0D44 |
277 | #define OV0_GAMMA_20_3F 0x0D48 | 277 | #define OV0_GAMMA_20_3F 0x0D48 |
278 | #define OV0_GAMMA_40_7F 0x0D4C | 278 | #define OV0_GAMMA_40_7F 0x0D4C |
279 | #define OV0_GAMMA_380_3BF 0x0D50 | 279 | #define OV0_GAMMA_380_3BF 0x0D50 |
280 | #define OV0_GAMMA_3C0_3FF 0x0D54 | 280 | #define OV0_GAMMA_3C0_3FF 0x0D54 |
281 | #define DISP_MERGE_CNTL 0x0D60 | 281 | #define DISP_MERGE_CNTL 0x0D60 |
282 | #define DISP_OUTPUT_CNTL 0x0D64 | 282 | #define DISP_OUTPUT_CNTL 0x0D64 |
283 | #define DISP_LIN_TRANS_GRPH_A 0x0D80 | 283 | #define DISP_LIN_TRANS_GRPH_A 0x0D80 |
284 | #define DISP_LIN_TRANS_GRPH_B 0x0D84 | 284 | #define DISP_LIN_TRANS_GRPH_B 0x0D84 |
285 | #define DISP_LIN_TRANS_GRPH_C 0x0D88 | 285 | #define DISP_LIN_TRANS_GRPH_C 0x0D88 |
286 | #define DISP_LIN_TRANS_GRPH_D 0x0D8C | 286 | #define DISP_LIN_TRANS_GRPH_D 0x0D8C |
287 | #define DISP_LIN_TRANS_GRPH_E 0x0D90 | 287 | #define DISP_LIN_TRANS_GRPH_E 0x0D90 |
288 | #define DISP_LIN_TRANS_GRPH_F 0x0D94 | 288 | #define DISP_LIN_TRANS_GRPH_F 0x0D94 |
289 | #define DISP_LIN_TRANS_VID_A 0x0D98 | 289 | #define DISP_LIN_TRANS_VID_A 0x0D98 |
290 | #define DISP_LIN_TRANS_VID_B 0x0D9C | 290 | #define DISP_LIN_TRANS_VID_B 0x0D9C |
291 | #define DISP_LIN_TRANS_VID_C 0x0DA0 | 291 | #define DISP_LIN_TRANS_VID_C 0x0DA0 |
292 | #define DISP_LIN_TRANS_VID_D 0x0DA4 | 292 | #define DISP_LIN_TRANS_VID_D 0x0DA4 |
293 | #define DISP_LIN_TRANS_VID_E 0x0DA8 | 293 | #define DISP_LIN_TRANS_VID_E 0x0DA8 |
294 | #define DISP_LIN_TRANS_VID_F 0x0DAC | 294 | #define DISP_LIN_TRANS_VID_F 0x0DAC |
295 | #define RMX_HORZ_FILTER_0TAP_COEF 0x0DB0 | 295 | #define RMX_HORZ_FILTER_0TAP_COEF 0x0DB0 |
296 | #define RMX_HORZ_FILTER_1TAP_COEF 0x0DB4 | 296 | #define RMX_HORZ_FILTER_1TAP_COEF 0x0DB4 |
297 | #define RMX_HORZ_FILTER_2TAP_COEF 0x0DB8 | 297 | #define RMX_HORZ_FILTER_2TAP_COEF 0x0DB8 |
298 | #define RMX_HORZ_PHASE 0x0DBC | 298 | #define RMX_HORZ_PHASE 0x0DBC |
299 | #define DAC_EMBEDDED_SYNC_CNTL 0x0DC0 | 299 | #define DAC_EMBEDDED_SYNC_CNTL 0x0DC0 |
300 | #define DAC_BROAD_PULSE 0x0DC4 | 300 | #define DAC_BROAD_PULSE 0x0DC4 |
301 | #define DAC_SKEW_CLKS 0x0DC8 | 301 | #define DAC_SKEW_CLKS 0x0DC8 |
302 | #define DAC_INCR 0x0DCC | 302 | #define DAC_INCR 0x0DCC |
303 | #define DAC_NEG_SYNC_LEVEL 0x0DD0 | 303 | #define DAC_NEG_SYNC_LEVEL 0x0DD0 |
304 | #define DAC_POS_SYNC_LEVEL 0x0DD4 | 304 | #define DAC_POS_SYNC_LEVEL 0x0DD4 |
305 | #define DAC_BLANK_LEVEL 0x0DD8 | 305 | #define DAC_BLANK_LEVEL 0x0DD8 |
306 | #define CLOCK_CNTL_INDEX 0x0008 | 306 | #define CLOCK_CNTL_INDEX 0x0008 |
307 | #define CLOCK_CNTL_DATA 0x000C | 307 | #define CLOCK_CNTL_DATA 0x000C |
308 | #define CP_RB_CNTL 0x0704 | 308 | #define CP_RB_CNTL 0x0704 |
309 | #define CP_RB_BASE 0x0700 | 309 | #define CP_RB_BASE 0x0700 |
310 | #define CP_RB_RPTR_ADDR 0x070C | 310 | #define CP_RB_RPTR_ADDR 0x070C |
311 | #define CP_RB_RPTR 0x0710 | 311 | #define CP_RB_RPTR 0x0710 |
312 | #define CP_RB_WPTR 0x0714 | 312 | #define CP_RB_WPTR 0x0714 |
313 | #define CP_RB_WPTR_DELAY 0x0718 | 313 | #define CP_RB_WPTR_DELAY 0x0718 |
314 | #define CP_IB_BASE 0x0738 | 314 | #define CP_IB_BASE 0x0738 |
315 | #define CP_IB_BUFSZ 0x073C | 315 | #define CP_IB_BUFSZ 0x073C |
316 | #define SCRATCH_REG0 0x15E0 | 316 | #define SCRATCH_REG0 0x15E0 |
317 | #define GUI_SCRATCH_REG0 0x15E0 | 317 | #define GUI_SCRATCH_REG0 0x15E0 |
318 | #define SCRATCH_REG1 0x15E4 | 318 | #define SCRATCH_REG1 0x15E4 |
319 | #define GUI_SCRATCH_REG1 0x15E4 | 319 | #define GUI_SCRATCH_REG1 0x15E4 |
320 | #define SCRATCH_REG2 0x15E8 | 320 | #define SCRATCH_REG2 0x15E8 |
321 | #define GUI_SCRATCH_REG2 0x15E8 | 321 | #define GUI_SCRATCH_REG2 0x15E8 |
322 | #define SCRATCH_REG3 0x15EC | 322 | #define SCRATCH_REG3 0x15EC |
323 | #define GUI_SCRATCH_REG3 0x15EC | 323 | #define GUI_SCRATCH_REG3 0x15EC |
324 | #define SCRATCH_REG4 0x15F0 | 324 | #define SCRATCH_REG4 0x15F0 |
325 | #define GUI_SCRATCH_REG4 0x15F0 | 325 | #define GUI_SCRATCH_REG4 0x15F0 |
326 | #define SCRATCH_REG5 0x15F4 | 326 | #define SCRATCH_REG5 0x15F4 |
327 | #define GUI_SCRATCH_REG5 0x15F4 | 327 | #define GUI_SCRATCH_REG5 0x15F4 |
328 | #define SCRATCH_UMSK 0x0770 | 328 | #define SCRATCH_UMSK 0x0770 |
329 | #define SCRATCH_ADDR 0x0774 | 329 | #define SCRATCH_ADDR 0x0774 |
330 | #define DP_BRUSH_FRGD_CLR 0x147C | 330 | #define DP_BRUSH_FRGD_CLR 0x147C |
331 | #define DP_BRUSH_BKGD_CLR 0x1478 | 331 | #define DP_BRUSH_BKGD_CLR 0x1478 |
332 | #define DST_LINE_START 0x1600 | 332 | #define DST_LINE_START 0x1600 |
333 | #define DST_LINE_END 0x1604 | 333 | #define DST_LINE_END 0x1604 |
334 | #define SRC_OFFSET 0x15AC | 334 | #define SRC_OFFSET 0x15AC |
335 | #define SRC_PITCH 0x15B0 | 335 | #define SRC_PITCH 0x15B0 |
336 | #define SRC_TILE 0x1704 | 336 | #define SRC_TILE 0x1704 |
337 | #define SRC_PITCH_OFFSET 0x1428 | 337 | #define SRC_PITCH_OFFSET 0x1428 |
338 | #define SRC_X 0x1414 | 338 | #define SRC_X 0x1414 |
339 | #define SRC_Y 0x1418 | 339 | #define SRC_Y 0x1418 |
340 | #define SRC_X_Y 0x1590 | 340 | #define SRC_X_Y 0x1590 |
341 | #define SRC_Y_X 0x1434 | 341 | #define SRC_Y_X 0x1434 |
342 | #define DST_Y_X 0x1438 | 342 | #define DST_Y_X 0x1438 |
343 | #define DST_WIDTH_HEIGHT 0x1598 | 343 | #define DST_WIDTH_HEIGHT 0x1598 |
344 | #define DST_HEIGHT_WIDTH 0x143c | 344 | #define DST_HEIGHT_WIDTH 0x143c |
345 | #define DST_OFFSET 0x1404 | 345 | #define DST_OFFSET 0x1404 |
346 | #define SRC_CLUT_ADDRESS 0x1780 | 346 | #define SRC_CLUT_ADDRESS 0x1780 |
347 | #define SRC_CLUT_DATA 0x1784 | 347 | #define SRC_CLUT_DATA 0x1784 |
348 | #define SRC_CLUT_DATA_RD 0x1788 | 348 | #define SRC_CLUT_DATA_RD 0x1788 |
349 | #define HOST_DATA0 0x17C0 | 349 | #define HOST_DATA0 0x17C0 |
350 | #define HOST_DATA1 0x17C4 | 350 | #define HOST_DATA1 0x17C4 |
351 | #define HOST_DATA2 0x17C8 | 351 | #define HOST_DATA2 0x17C8 |
352 | #define HOST_DATA3 0x17CC | 352 | #define HOST_DATA3 0x17CC |
353 | #define HOST_DATA4 0x17D0 | 353 | #define HOST_DATA4 0x17D0 |
354 | #define HOST_DATA5 0x17D4 | 354 | #define HOST_DATA5 0x17D4 |
355 | #define HOST_DATA6 0x17D8 | 355 | #define HOST_DATA6 0x17D8 |
356 | #define HOST_DATA7 0x17DC | 356 | #define HOST_DATA7 0x17DC |
357 | #define HOST_DATA_LAST 0x17E0 | 357 | #define HOST_DATA_LAST 0x17E0 |
358 | #define DP_SRC_ENDIAN 0x15D4 | 358 | #define DP_SRC_ENDIAN 0x15D4 |
359 | #define DP_SRC_FRGD_CLR 0x15D8 | 359 | #define DP_SRC_FRGD_CLR 0x15D8 |
360 | #define DP_SRC_BKGD_CLR 0x15DC | 360 | #define DP_SRC_BKGD_CLR 0x15DC |
361 | #define SC_LEFT 0x1640 | 361 | #define SC_LEFT 0x1640 |
362 | #define SC_RIGHT 0x1644 | 362 | #define SC_RIGHT 0x1644 |
363 | #define SC_TOP 0x1648 | 363 | #define SC_TOP 0x1648 |
364 | #define SC_BOTTOM 0x164C | 364 | #define SC_BOTTOM 0x164C |
365 | #define SRC_SC_RIGHT 0x1654 | 365 | #define SRC_SC_RIGHT 0x1654 |
366 | #define SRC_SC_BOTTOM 0x165C | 366 | #define SRC_SC_BOTTOM 0x165C |
367 | #define DP_CNTL 0x16C0 | 367 | #define DP_CNTL 0x16C0 |
368 | #define DP_CNTL_XDIR_YDIR_YMAJOR 0x16D0 | 368 | #define DP_CNTL_XDIR_YDIR_YMAJOR 0x16D0 |
369 | #define DP_DATATYPE 0x16C4 | 369 | #define DP_DATATYPE 0x16C4 |
370 | #define DP_MIX 0x16C8 | 370 | #define DP_MIX 0x16C8 |
371 | #define DP_WRITE_MSK 0x16CC | 371 | #define DP_WRITE_MSK 0x16CC |
372 | #define DP_XOP 0x17F8 | 372 | #define DP_XOP 0x17F8 |
373 | #define CLR_CMP_CLR_SRC 0x15C4 | 373 | #define CLR_CMP_CLR_SRC 0x15C4 |
374 | #define CLR_CMP_CLR_DST 0x15C8 | 374 | #define CLR_CMP_CLR_DST 0x15C8 |
375 | #define CLR_CMP_CNTL 0x15C0 | 375 | #define CLR_CMP_CNTL 0x15C0 |
376 | #define CLR_CMP_MSK 0x15CC | 376 | #define CLR_CMP_MSK 0x15CC |
377 | #define DSTCACHE_MODE 0x1710 | 377 | #define DSTCACHE_MODE 0x1710 |
378 | #define DSTCACHE_CTLSTAT 0x1714 | 378 | #define DSTCACHE_CTLSTAT 0x1714 |
379 | #define DEFAULT_PITCH_OFFSET 0x16E0 | 379 | #define DEFAULT_PITCH_OFFSET 0x16E0 |
380 | #define DEFAULT_SC_BOTTOM_RIGHT 0x16E8 | 380 | #define DEFAULT_SC_BOTTOM_RIGHT 0x16E8 |
381 | #define DEFAULT_SC_TOP_LEFT 0x16EC | 381 | #define DEFAULT_SC_TOP_LEFT 0x16EC |
382 | #define SRC_PITCH_OFFSET 0x1428 | 382 | #define SRC_PITCH_OFFSET 0x1428 |
383 | #define DST_PITCH_OFFSET 0x142C | 383 | #define DST_PITCH_OFFSET 0x142C |
384 | #define DP_GUI_MASTER_CNTL 0x146C | 384 | #define DP_GUI_MASTER_CNTL 0x146C |
385 | #define SC_TOP_LEFT 0x16EC | 385 | #define SC_TOP_LEFT 0x16EC |
386 | #define SC_BOTTOM_RIGHT 0x16F0 | 386 | #define SC_BOTTOM_RIGHT 0x16F0 |
387 | #define SRC_SC_BOTTOM_RIGHT 0x16F4 | 387 | #define SRC_SC_BOTTOM_RIGHT 0x16F4 |
388 | #define RB2D_DSTCACHE_MODE 0x3428 | 388 | #define RB2D_DSTCACHE_MODE 0x3428 |
389 | #define RB2D_DSTCACHE_CTLSTAT_broken 0x342C /* do not use */ | 389 | #define RB2D_DSTCACHE_CTLSTAT_broken 0x342C /* do not use */ |
390 | #define LVDS_GEN_CNTL 0x02d0 | 390 | #define LVDS_GEN_CNTL 0x02d0 |
@@ -686,7 +686,7 @@ | |||
686 | #define VERT_FP_LOOP_STRETCH (0x7 << 28) | 686 | #define VERT_FP_LOOP_STRETCH (0x7 << 28) |
687 | #define VERT_STRETCH_RESERVED 0xf1000000 | 687 | #define VERT_STRETCH_RESERVED 0xf1000000 |
688 | 688 | ||
689 | /* DAC_CNTL bit constants */ | 689 | /* DAC_CNTL bit constants */ |
690 | #define DAC_8BIT_EN 0x00000100 | 690 | #define DAC_8BIT_EN 0x00000100 |
691 | #define DAC_4BPP_PIX_ORDER 0x00000200 | 691 | #define DAC_4BPP_PIX_ORDER 0x00000200 |
692 | #define DAC_CRC_EN 0x00080000 | 692 | #define DAC_CRC_EN 0x00080000 |
@@ -700,7 +700,7 @@ | |||
700 | #define DAC_CMP_EN (1 << 3) | 700 | #define DAC_CMP_EN (1 << 3) |
701 | #define DAC_CMP_OUTPUT (1 << 7) | 701 | #define DAC_CMP_OUTPUT (1 << 7) |
702 | 702 | ||
703 | /* DAC_CNTL2 bit constants */ | 703 | /* DAC_CNTL2 bit constants */ |
704 | #define DAC2_EXPAND_MODE (1 << 14) | 704 | #define DAC2_EXPAND_MODE (1 << 14) |
705 | #define DAC2_CMP_EN (1 << 7) | 705 | #define DAC2_CMP_EN (1 << 7) |
706 | #define DAC2_PALETTE_ACCESS_CNTL (1 << 5) | 706 | #define DAC2_PALETTE_ACCESS_CNTL (1 << 5) |
diff --git a/include/video/s1d13xxxfb.h b/include/video/s1d13xxxfb.h index fe41b840794..c3b2a2aa714 100644 --- a/include/video/s1d13xxxfb.h +++ b/include/video/s1d13xxxfb.h | |||
@@ -14,13 +14,16 @@ | |||
14 | #define S1D13XXXFB_H | 14 | #define S1D13XXXFB_H |
15 | 15 | ||
16 | #define S1D_PALETTE_SIZE 256 | 16 | #define S1D_PALETTE_SIZE 256 |
17 | #define S1D13506_CHIP_REV 4 /* expected chip revision number for s1d13506 */ | 17 | #define S1D_FBID "S1D13xxx" |
18 | #define S1D13806_CHIP_REV 7 /* expected chip revision number for s1d13806 */ | 18 | #define S1D_DEVICENAME "s1d13xxxfb" |
19 | #define S1D_FBID "S1D13806" | 19 | |
20 | #define S1D_DEVICENAME "s1d13806fb" | 20 | /* S1DREG_REV_CODE register = prod_id (6 bits) + revision (2 bits) */ |
21 | #define S1D13505_PROD_ID 0x3 /* 000011 */ | ||
22 | #define S1D13506_PROD_ID 0x4 /* 000100 */ | ||
23 | #define S1D13806_PROD_ID 0x7 /* 000111 */ | ||
21 | 24 | ||
22 | /* register definitions (tested on s1d13896) */ | 25 | /* register definitions (tested on s1d13896) */ |
23 | #define S1DREG_REV_CODE 0x0000 /* Revision Code Register */ | 26 | #define S1DREG_REV_CODE 0x0000 /* Prod + Rev Code Register */ |
24 | #define S1DREG_MISC 0x0001 /* Miscellaneous Register */ | 27 | #define S1DREG_MISC 0x0001 /* Miscellaneous Register */ |
25 | #define S1DREG_GPIO_CNF0 0x0004 /* General IO Pins Configuration Register 0 */ | 28 | #define S1DREG_GPIO_CNF0 0x0004 /* General IO Pins Configuration Register 0 */ |
26 | #define S1DREG_GPIO_CNF1 0x0005 /* General IO Pins Configuration Register 1 */ | 29 | #define S1DREG_GPIO_CNF1 0x0005 /* General IO Pins Configuration Register 1 */ |
@@ -141,10 +144,11 @@ struct s1d13xxxfb_regval { | |||
141 | u8 value; | 144 | u8 value; |
142 | }; | 145 | }; |
143 | 146 | ||
144 | |||
145 | struct s1d13xxxfb_par { | 147 | struct s1d13xxxfb_par { |
146 | void __iomem *regs; | 148 | void __iomem *regs; |
147 | unsigned char display; | 149 | unsigned char display; |
150 | unsigned char prod_id; | ||
151 | unsigned char revision; | ||
148 | 152 | ||
149 | unsigned int pseudo_palette[16]; | 153 | unsigned int pseudo_palette[16]; |
150 | #ifdef CONFIG_PM | 154 | #ifdef CONFIG_PM |
diff --git a/init/main.c b/init/main.c index d6b388fbffa..07c8658ffca 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -793,6 +793,7 @@ static void run_init_process(char *init_filename) | |||
793 | * makes it inline to init() and it becomes part of init.text section | 793 | * makes it inline to init() and it becomes part of init.text section |
794 | */ | 794 | */ |
795 | static noinline int init_post(void) | 795 | static noinline int init_post(void) |
796 | __releases(kernel_lock) | ||
796 | { | 797 | { |
797 | /* need to finish all async __init code before freeing the memory */ | 798 | /* need to finish all async __init code before freeing the memory */ |
798 | async_synchronize_full(); | 799 | async_synchronize_full(); |
diff --git a/kernel/power/disk.c b/kernel/power/disk.c index e886d1332a1..f3db382c2b2 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/console.h> | 22 | #include <linux/console.h> |
23 | #include <linux/cpu.h> | 23 | #include <linux/cpu.h> |
24 | #include <linux/freezer.h> | 24 | #include <linux/freezer.h> |
25 | #include <asm/suspend.h> | ||
25 | 26 | ||
26 | #include "power.h" | 27 | #include "power.h" |
27 | 28 | ||
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index f5fc2d7680f..33e2e4a819f 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c | |||
@@ -321,13 +321,10 @@ static int create_mem_extents(struct list_head *list, gfp_t gfp_mask) | |||
321 | 321 | ||
322 | INIT_LIST_HEAD(list); | 322 | INIT_LIST_HEAD(list); |
323 | 323 | ||
324 | for_each_zone(zone) { | 324 | for_each_populated_zone(zone) { |
325 | unsigned long zone_start, zone_end; | 325 | unsigned long zone_start, zone_end; |
326 | struct mem_extent *ext, *cur, *aux; | 326 | struct mem_extent *ext, *cur, *aux; |
327 | 327 | ||
328 | if (!populated_zone(zone)) | ||
329 | continue; | ||
330 | |||
331 | zone_start = zone->zone_start_pfn; | 328 | zone_start = zone->zone_start_pfn; |
332 | zone_end = zone->zone_start_pfn + zone->spanned_pages; | 329 | zone_end = zone->zone_start_pfn + zone->spanned_pages; |
333 | 330 | ||
@@ -804,8 +801,8 @@ static unsigned int count_free_highmem_pages(void) | |||
804 | struct zone *zone; | 801 | struct zone *zone; |
805 | unsigned int cnt = 0; | 802 | unsigned int cnt = 0; |
806 | 803 | ||
807 | for_each_zone(zone) | 804 | for_each_populated_zone(zone) |
808 | if (populated_zone(zone) && is_highmem(zone)) | 805 | if (is_highmem(zone)) |
809 | cnt += zone_page_state(zone, NR_FREE_PAGES); | 806 | cnt += zone_page_state(zone, NR_FREE_PAGES); |
810 | 807 | ||
811 | return cnt; | 808 | return cnt; |
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index a92c9145155..78c35047586 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/highmem.h> | 51 | #include <linux/highmem.h> |
52 | #include <linux/time.h> | 52 | #include <linux/time.h> |
53 | #include <linux/rbtree.h> | 53 | #include <linux/rbtree.h> |
54 | #include <linux/io.h> | ||
54 | 55 | ||
55 | #include "power.h" | 56 | #include "power.h" |
56 | 57 | ||
@@ -229,17 +230,16 @@ int swsusp_shrink_memory(void) | |||
229 | size = count_data_pages() + PAGES_FOR_IO + SPARE_PAGES; | 230 | size = count_data_pages() + PAGES_FOR_IO + SPARE_PAGES; |
230 | tmp = size; | 231 | tmp = size; |
231 | size += highmem_size; | 232 | size += highmem_size; |
232 | for_each_zone (zone) | 233 | for_each_populated_zone(zone) { |
233 | if (populated_zone(zone)) { | 234 | tmp += snapshot_additional_pages(zone); |
234 | tmp += snapshot_additional_pages(zone); | 235 | if (is_highmem(zone)) { |
235 | if (is_highmem(zone)) { | 236 | highmem_size -= |
236 | highmem_size -= | ||
237 | zone_page_state(zone, NR_FREE_PAGES); | 237 | zone_page_state(zone, NR_FREE_PAGES); |
238 | } else { | 238 | } else { |
239 | tmp -= zone_page_state(zone, NR_FREE_PAGES); | 239 | tmp -= zone_page_state(zone, NR_FREE_PAGES); |
240 | tmp += zone->lowmem_reserve[ZONE_NORMAL]; | 240 | tmp += zone->lowmem_reserve[ZONE_NORMAL]; |
241 | } | ||
242 | } | 241 | } |
242 | } | ||
243 | 243 | ||
244 | if (highmem_size < 0) | 244 | if (highmem_size < 0) |
245 | highmem_size = 0; | 245 | highmem_size = 0; |
diff --git a/kernel/sched.c b/kernel/sched.c index 196d48babbe..73513f4e19d 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -5196,11 +5196,17 @@ void __wake_up_locked(wait_queue_head_t *q, unsigned int mode) | |||
5196 | __wake_up_common(q, mode, 1, 0, NULL); | 5196 | __wake_up_common(q, mode, 1, 0, NULL); |
5197 | } | 5197 | } |
5198 | 5198 | ||
5199 | void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key) | ||
5200 | { | ||
5201 | __wake_up_common(q, mode, 1, 0, key); | ||
5202 | } | ||
5203 | |||
5199 | /** | 5204 | /** |
5200 | * __wake_up_sync - wake up threads blocked on a waitqueue. | 5205 | * __wake_up_sync_key - wake up threads blocked on a waitqueue. |
5201 | * @q: the waitqueue | 5206 | * @q: the waitqueue |
5202 | * @mode: which threads | 5207 | * @mode: which threads |
5203 | * @nr_exclusive: how many wake-one or wake-many threads to wake up | 5208 | * @nr_exclusive: how many wake-one or wake-many threads to wake up |
5209 | * @key: opaque value to be passed to wakeup targets | ||
5204 | * | 5210 | * |
5205 | * The sync wakeup differs that the waker knows that it will schedule | 5211 | * The sync wakeup differs that the waker knows that it will schedule |
5206 | * away soon, so while the target thread will be woken up, it will not | 5212 | * away soon, so while the target thread will be woken up, it will not |
@@ -5209,8 +5215,8 @@ void __wake_up_locked(wait_queue_head_t *q, unsigned int mode) | |||
5209 | * | 5215 | * |
5210 | * On UP it can prevent extra preemption. | 5216 | * On UP it can prevent extra preemption. |
5211 | */ | 5217 | */ |
5212 | void | 5218 | void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, |
5213 | __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive) | 5219 | int nr_exclusive, void *key) |
5214 | { | 5220 | { |
5215 | unsigned long flags; | 5221 | unsigned long flags; |
5216 | int sync = 1; | 5222 | int sync = 1; |
@@ -5222,9 +5228,18 @@ __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive) | |||
5222 | sync = 0; | 5228 | sync = 0; |
5223 | 5229 | ||
5224 | spin_lock_irqsave(&q->lock, flags); | 5230 | spin_lock_irqsave(&q->lock, flags); |
5225 | __wake_up_common(q, mode, nr_exclusive, sync, NULL); | 5231 | __wake_up_common(q, mode, nr_exclusive, sync, key); |
5226 | spin_unlock_irqrestore(&q->lock, flags); | 5232 | spin_unlock_irqrestore(&q->lock, flags); |
5227 | } | 5233 | } |
5234 | EXPORT_SYMBOL_GPL(__wake_up_sync_key); | ||
5235 | |||
5236 | /* | ||
5237 | * __wake_up_sync - see __wake_up_sync_key() | ||
5238 | */ | ||
5239 | void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive) | ||
5240 | { | ||
5241 | __wake_up_sync_key(q, mode, nr_exclusive, NULL); | ||
5242 | } | ||
5228 | EXPORT_SYMBOL_GPL(__wake_up_sync); /* For internal use only */ | 5243 | EXPORT_SYMBOL_GPL(__wake_up_sync); /* For internal use only */ |
5229 | 5244 | ||
5230 | /** | 5245 | /** |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index c5ef44ff850..2e490a389dd 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -1010,7 +1010,7 @@ static struct ctl_table vm_table[] = { | |||
1010 | .data = &dirty_expire_interval, | 1010 | .data = &dirty_expire_interval, |
1011 | .maxlen = sizeof(dirty_expire_interval), | 1011 | .maxlen = sizeof(dirty_expire_interval), |
1012 | .mode = 0644, | 1012 | .mode = 0644, |
1013 | .proc_handler = &proc_dointvec_userhz_jiffies, | 1013 | .proc_handler = &proc_dointvec, |
1014 | }, | 1014 | }, |
1015 | { | 1015 | { |
1016 | .ctl_name = VM_NR_PDFLUSH_THREADS, | 1016 | .ctl_name = VM_NR_PDFLUSH_THREADS, |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 58bfe7e8fab..9638d99644a 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -796,6 +796,7 @@ config SYSCTL_SYSCALL_CHECK | |||
796 | to properly maintain and use. This enables checks that help | 796 | to properly maintain and use. This enables checks that help |
797 | you to keep things correct. | 797 | you to keep things correct. |
798 | 798 | ||
799 | source mm/Kconfig.debug | ||
799 | source kernel/trace/Kconfig | 800 | source kernel/trace/Kconfig |
800 | 801 | ||
801 | config PROVIDE_OHCI1394_DMA_INIT | 802 | config PROVIDE_OHCI1394_DMA_INIT |
diff --git a/lib/rbtree.c b/lib/rbtree.c index 9956b99649f..f653659e0bc 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c | |||
@@ -163,17 +163,14 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, | |||
163 | { | 163 | { |
164 | if (!other->rb_right || rb_is_black(other->rb_right)) | 164 | if (!other->rb_right || rb_is_black(other->rb_right)) |
165 | { | 165 | { |
166 | struct rb_node *o_left; | 166 | rb_set_black(other->rb_left); |
167 | if ((o_left = other->rb_left)) | ||
168 | rb_set_black(o_left); | ||
169 | rb_set_red(other); | 167 | rb_set_red(other); |
170 | __rb_rotate_right(other, root); | 168 | __rb_rotate_right(other, root); |
171 | other = parent->rb_right; | 169 | other = parent->rb_right; |
172 | } | 170 | } |
173 | rb_set_color(other, rb_color(parent)); | 171 | rb_set_color(other, rb_color(parent)); |
174 | rb_set_black(parent); | 172 | rb_set_black(parent); |
175 | if (other->rb_right) | 173 | rb_set_black(other->rb_right); |
176 | rb_set_black(other->rb_right); | ||
177 | __rb_rotate_left(parent, root); | 174 | __rb_rotate_left(parent, root); |
178 | node = root->rb_node; | 175 | node = root->rb_node; |
179 | break; | 176 | break; |
@@ -200,17 +197,14 @@ static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, | |||
200 | { | 197 | { |
201 | if (!other->rb_left || rb_is_black(other->rb_left)) | 198 | if (!other->rb_left || rb_is_black(other->rb_left)) |
202 | { | 199 | { |
203 | register struct rb_node *o_right; | 200 | rb_set_black(other->rb_right); |
204 | if ((o_right = other->rb_right)) | ||
205 | rb_set_black(o_right); | ||
206 | rb_set_red(other); | 201 | rb_set_red(other); |
207 | __rb_rotate_left(other, root); | 202 | __rb_rotate_left(other, root); |
208 | other = parent->rb_left; | 203 | other = parent->rb_left; |
209 | } | 204 | } |
210 | rb_set_color(other, rb_color(parent)); | 205 | rb_set_color(other, rb_color(parent)); |
211 | rb_set_black(parent); | 206 | rb_set_black(parent); |
212 | if (other->rb_left) | 207 | rb_set_black(other->rb_left); |
213 | rb_set_black(other->rb_left); | ||
214 | __rb_rotate_right(parent, root); | 208 | __rb_rotate_right(parent, root); |
215 | node = root->rb_node; | 209 | node = root->rb_node; |
216 | break; | 210 | break; |
diff --git a/mm/Kconfig b/mm/Kconfig index a5b77811fdf..b53427ad30a 100644 --- a/mm/Kconfig +++ b/mm/Kconfig | |||
@@ -206,7 +206,6 @@ config VIRT_TO_BUS | |||
206 | config UNEVICTABLE_LRU | 206 | config UNEVICTABLE_LRU |
207 | bool "Add LRU list to track non-evictable pages" | 207 | bool "Add LRU list to track non-evictable pages" |
208 | default y | 208 | default y |
209 | depends on MMU | ||
210 | help | 209 | help |
211 | Keeps unevictable pages off of the active and inactive pageout | 210 | Keeps unevictable pages off of the active and inactive pageout |
212 | lists, so kswapd will not waste CPU time or have its balancing | 211 | lists, so kswapd will not waste CPU time or have its balancing |
@@ -214,5 +213,13 @@ config UNEVICTABLE_LRU | |||
214 | will use one page flag and increase the code size a little, | 213 | will use one page flag and increase the code size a little, |
215 | say Y unless you know what you are doing. | 214 | say Y unless you know what you are doing. |
216 | 215 | ||
216 | config HAVE_MLOCK | ||
217 | bool | ||
218 | default y if MMU=y | ||
219 | |||
220 | config HAVE_MLOCKED_PAGE_BIT | ||
221 | bool | ||
222 | default y if HAVE_MLOCK=y && UNEVICTABLE_LRU=y | ||
223 | |||
217 | config MMU_NOTIFIER | 224 | config MMU_NOTIFIER |
218 | bool | 225 | bool |
diff --git a/mm/Kconfig.debug b/mm/Kconfig.debug new file mode 100644 index 00000000000..c8d62d49a44 --- /dev/null +++ b/mm/Kconfig.debug | |||
@@ -0,0 +1,17 @@ | |||
1 | config WANT_PAGE_DEBUG_FLAGS | ||
2 | bool | ||
3 | |||
4 | config PAGE_POISONING | ||
5 | bool "Debug page memory allocations" | ||
6 | depends on DEBUG_KERNEL && !ARCH_SUPPORTS_DEBUG_PAGEALLOC | ||
7 | depends on !HIBERNATION | ||
8 | select DEBUG_PAGEALLOC | ||
9 | select WANT_PAGE_DEBUG_FLAGS | ||
10 | help | ||
11 | Fill the pages with poison patterns after free_pages() and verify | ||
12 | the patterns before alloc_pages(). This results in a large slowdown, | ||
13 | but helps to find certain types of memory corruptions. | ||
14 | |||
15 | This option cannot enalbe with hibernation. Otherwise, it will get | ||
16 | wrong messages for memory corruption because the free pages are not | ||
17 | saved to the suspend image. | ||
diff --git a/mm/Makefile b/mm/Makefile index 818569b68f4..ec73c68b601 100644 --- a/mm/Makefile +++ b/mm/Makefile | |||
@@ -24,6 +24,7 @@ obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o | |||
24 | obj-$(CONFIG_TMPFS_POSIX_ACL) += shmem_acl.o | 24 | obj-$(CONFIG_TMPFS_POSIX_ACL) += shmem_acl.o |
25 | obj-$(CONFIG_SLOB) += slob.o | 25 | obj-$(CONFIG_SLOB) += slob.o |
26 | obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o | 26 | obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o |
27 | obj-$(CONFIG_PAGE_POISONING) += debug-pagealloc.o | ||
27 | obj-$(CONFIG_SLAB) += slab.o | 28 | obj-$(CONFIG_SLAB) += slab.o |
28 | obj-$(CONFIG_SLUB) += slub.o | 29 | obj-$(CONFIG_SLUB) += slub.o |
29 | obj-$(CONFIG_FAILSLAB) += failslab.o | 30 | obj-$(CONFIG_FAILSLAB) += failslab.o |
diff --git a/mm/debug-pagealloc.c b/mm/debug-pagealloc.c new file mode 100644 index 00000000000..a1e3324de2b --- /dev/null +++ b/mm/debug-pagealloc.c | |||
@@ -0,0 +1,129 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/mm.h> | ||
3 | #include <linux/page-debug-flags.h> | ||
4 | #include <linux/poison.h> | ||
5 | |||
6 | static inline void set_page_poison(struct page *page) | ||
7 | { | ||
8 | __set_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags); | ||
9 | } | ||
10 | |||
11 | static inline void clear_page_poison(struct page *page) | ||
12 | { | ||
13 | __clear_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags); | ||
14 | } | ||
15 | |||
16 | static inline bool page_poison(struct page *page) | ||
17 | { | ||
18 | return test_bit(PAGE_DEBUG_FLAG_POISON, &page->debug_flags); | ||
19 | } | ||
20 | |||
21 | static void poison_highpage(struct page *page) | ||
22 | { | ||
23 | /* | ||
24 | * Page poisoning for highmem pages is not implemented. | ||
25 | * | ||
26 | * This can be called from interrupt contexts. | ||
27 | * So we need to create a new kmap_atomic slot for this | ||
28 | * application and it will need interrupt protection. | ||
29 | */ | ||
30 | } | ||
31 | |||
32 | static void poison_page(struct page *page) | ||
33 | { | ||
34 | void *addr; | ||
35 | |||
36 | if (PageHighMem(page)) { | ||
37 | poison_highpage(page); | ||
38 | return; | ||
39 | } | ||
40 | set_page_poison(page); | ||
41 | addr = page_address(page); | ||
42 | memset(addr, PAGE_POISON, PAGE_SIZE); | ||
43 | } | ||
44 | |||
45 | static void poison_pages(struct page *page, int n) | ||
46 | { | ||
47 | int i; | ||
48 | |||
49 | for (i = 0; i < n; i++) | ||
50 | poison_page(page + i); | ||
51 | } | ||
52 | |||
53 | static bool single_bit_flip(unsigned char a, unsigned char b) | ||
54 | { | ||
55 | unsigned char error = a ^ b; | ||
56 | |||
57 | return error && !(error & (error - 1)); | ||
58 | } | ||
59 | |||
60 | static void check_poison_mem(unsigned char *mem, size_t bytes) | ||
61 | { | ||
62 | unsigned char *start; | ||
63 | unsigned char *end; | ||
64 | |||
65 | for (start = mem; start < mem + bytes; start++) { | ||
66 | if (*start != PAGE_POISON) | ||
67 | break; | ||
68 | } | ||
69 | if (start == mem + bytes) | ||
70 | return; | ||
71 | |||
72 | for (end = mem + bytes - 1; end > start; end--) { | ||
73 | if (*end != PAGE_POISON) | ||
74 | break; | ||
75 | } | ||
76 | |||
77 | if (!printk_ratelimit()) | ||
78 | return; | ||
79 | else if (start == end && single_bit_flip(*start, PAGE_POISON)) | ||
80 | printk(KERN_ERR "pagealloc: single bit error\n"); | ||
81 | else | ||
82 | printk(KERN_ERR "pagealloc: memory corruption\n"); | ||
83 | |||
84 | print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, start, | ||
85 | end - start + 1, 1); | ||
86 | dump_stack(); | ||
87 | } | ||
88 | |||
89 | static void unpoison_highpage(struct page *page) | ||
90 | { | ||
91 | /* | ||
92 | * See comment in poison_highpage(). | ||
93 | * Highmem pages should not be poisoned for now | ||
94 | */ | ||
95 | BUG_ON(page_poison(page)); | ||
96 | } | ||
97 | |||
98 | static void unpoison_page(struct page *page) | ||
99 | { | ||
100 | if (PageHighMem(page)) { | ||
101 | unpoison_highpage(page); | ||
102 | return; | ||
103 | } | ||
104 | if (page_poison(page)) { | ||
105 | void *addr = page_address(page); | ||
106 | |||
107 | check_poison_mem(addr, PAGE_SIZE); | ||
108 | clear_page_poison(page); | ||
109 | } | ||
110 | } | ||
111 | |||
112 | static void unpoison_pages(struct page *page, int n) | ||
113 | { | ||
114 | int i; | ||
115 | |||
116 | for (i = 0; i < n; i++) | ||
117 | unpoison_page(page + i); | ||
118 | } | ||
119 | |||
120 | void kernel_map_pages(struct page *page, int numpages, int enable) | ||
121 | { | ||
122 | if (!debug_pagealloc_enabled) | ||
123 | return; | ||
124 | |||
125 | if (enable) | ||
126 | unpoison_pages(page, numpages); | ||
127 | else | ||
128 | poison_pages(page, numpages); | ||
129 | } | ||
diff --git a/mm/highmem.c b/mm/highmem.c index 910198037bf..68eb1d9b63f 100644 --- a/mm/highmem.c +++ b/mm/highmem.c | |||
@@ -422,3 +422,48 @@ void __init page_address_init(void) | |||
422 | } | 422 | } |
423 | 423 | ||
424 | #endif /* defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) */ | 424 | #endif /* defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) */ |
425 | |||
426 | #if defined(CONFIG_DEBUG_HIGHMEM) && defined(CONFIG_TRACE_IRQFLAGS_SUPPORT) | ||
427 | |||
428 | void debug_kmap_atomic(enum km_type type) | ||
429 | { | ||
430 | static unsigned warn_count = 10; | ||
431 | |||
432 | if (unlikely(warn_count == 0)) | ||
433 | return; | ||
434 | |||
435 | if (unlikely(in_interrupt())) { | ||
436 | if (in_irq()) { | ||
437 | if (type != KM_IRQ0 && type != KM_IRQ1 && | ||
438 | type != KM_BIO_SRC_IRQ && type != KM_BIO_DST_IRQ && | ||
439 | type != KM_BOUNCE_READ) { | ||
440 | WARN_ON(1); | ||
441 | warn_count--; | ||
442 | } | ||
443 | } else if (!irqs_disabled()) { /* softirq */ | ||
444 | if (type != KM_IRQ0 && type != KM_IRQ1 && | ||
445 | type != KM_SOFTIRQ0 && type != KM_SOFTIRQ1 && | ||
446 | type != KM_SKB_SUNRPC_DATA && | ||
447 | type != KM_SKB_DATA_SOFTIRQ && | ||
448 | type != KM_BOUNCE_READ) { | ||
449 | WARN_ON(1); | ||
450 | warn_count--; | ||
451 | } | ||
452 | } | ||
453 | } | ||
454 | |||
455 | if (type == KM_IRQ0 || type == KM_IRQ1 || type == KM_BOUNCE_READ || | ||
456 | type == KM_BIO_SRC_IRQ || type == KM_BIO_DST_IRQ) { | ||
457 | if (!irqs_disabled()) { | ||
458 | WARN_ON(1); | ||
459 | warn_count--; | ||
460 | } | ||
461 | } else if (type == KM_SOFTIRQ0 || type == KM_SOFTIRQ1) { | ||
462 | if (irq_count() == 0 && !irqs_disabled()) { | ||
463 | WARN_ON(1); | ||
464 | warn_count--; | ||
465 | } | ||
466 | } | ||
467 | } | ||
468 | |||
469 | #endif | ||
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 107da3d809a..28c655ba935 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -918,7 +918,7 @@ static void return_unused_surplus_pages(struct hstate *h, | |||
918 | * an instantiated the change should be committed via vma_commit_reservation. | 918 | * an instantiated the change should be committed via vma_commit_reservation. |
919 | * No action is required on failure. | 919 | * No action is required on failure. |
920 | */ | 920 | */ |
921 | static int vma_needs_reservation(struct hstate *h, | 921 | static long vma_needs_reservation(struct hstate *h, |
922 | struct vm_area_struct *vma, unsigned long addr) | 922 | struct vm_area_struct *vma, unsigned long addr) |
923 | { | 923 | { |
924 | struct address_space *mapping = vma->vm_file->f_mapping; | 924 | struct address_space *mapping = vma->vm_file->f_mapping; |
@@ -933,7 +933,7 @@ static int vma_needs_reservation(struct hstate *h, | |||
933 | return 1; | 933 | return 1; |
934 | 934 | ||
935 | } else { | 935 | } else { |
936 | int err; | 936 | long err; |
937 | pgoff_t idx = vma_hugecache_offset(h, vma, addr); | 937 | pgoff_t idx = vma_hugecache_offset(h, vma, addr); |
938 | struct resv_map *reservations = vma_resv_map(vma); | 938 | struct resv_map *reservations = vma_resv_map(vma); |
939 | 939 | ||
@@ -969,7 +969,7 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma, | |||
969 | struct page *page; | 969 | struct page *page; |
970 | struct address_space *mapping = vma->vm_file->f_mapping; | 970 | struct address_space *mapping = vma->vm_file->f_mapping; |
971 | struct inode *inode = mapping->host; | 971 | struct inode *inode = mapping->host; |
972 | unsigned int chg; | 972 | long chg; |
973 | 973 | ||
974 | /* | 974 | /* |
975 | * Processes that did not create the mapping will have no reserves and | 975 | * Processes that did not create the mapping will have no reserves and |
diff --git a/mm/internal.h b/mm/internal.h index 478223b73a2..987bb03fbdd 100644 --- a/mm/internal.h +++ b/mm/internal.h | |||
@@ -63,6 +63,7 @@ static inline unsigned long page_order(struct page *page) | |||
63 | return page_private(page); | 63 | return page_private(page); |
64 | } | 64 | } |
65 | 65 | ||
66 | #ifdef CONFIG_HAVE_MLOCK | ||
66 | extern long mlock_vma_pages_range(struct vm_area_struct *vma, | 67 | extern long mlock_vma_pages_range(struct vm_area_struct *vma, |
67 | unsigned long start, unsigned long end); | 68 | unsigned long start, unsigned long end); |
68 | extern void munlock_vma_pages_range(struct vm_area_struct *vma, | 69 | extern void munlock_vma_pages_range(struct vm_area_struct *vma, |
@@ -71,6 +72,7 @@ static inline void munlock_vma_pages_all(struct vm_area_struct *vma) | |||
71 | { | 72 | { |
72 | munlock_vma_pages_range(vma, vma->vm_start, vma->vm_end); | 73 | munlock_vma_pages_range(vma, vma->vm_start, vma->vm_end); |
73 | } | 74 | } |
75 | #endif | ||
74 | 76 | ||
75 | #ifdef CONFIG_UNEVICTABLE_LRU | 77 | #ifdef CONFIG_UNEVICTABLE_LRU |
76 | /* | 78 | /* |
@@ -90,7 +92,7 @@ static inline void unevictable_migrate_page(struct page *new, struct page *old) | |||
90 | } | 92 | } |
91 | #endif | 93 | #endif |
92 | 94 | ||
93 | #ifdef CONFIG_UNEVICTABLE_LRU | 95 | #ifdef CONFIG_HAVE_MLOCKED_PAGE_BIT |
94 | /* | 96 | /* |
95 | * Called only in fault path via page_evictable() for a new page | 97 | * Called only in fault path via page_evictable() for a new page |
96 | * to determine if it's being mapped into a LOCKED vma. | 98 | * to determine if it's being mapped into a LOCKED vma. |
@@ -165,7 +167,7 @@ static inline void free_page_mlock(struct page *page) | |||
165 | } | 167 | } |
166 | } | 168 | } |
167 | 169 | ||
168 | #else /* CONFIG_UNEVICTABLE_LRU */ | 170 | #else /* CONFIG_HAVE_MLOCKED_PAGE_BIT */ |
169 | static inline int is_mlocked_vma(struct vm_area_struct *v, struct page *p) | 171 | static inline int is_mlocked_vma(struct vm_area_struct *v, struct page *p) |
170 | { | 172 | { |
171 | return 0; | 173 | return 0; |
@@ -175,7 +177,7 @@ static inline void mlock_vma_page(struct page *page) { } | |||
175 | static inline void mlock_migrate_page(struct page *new, struct page *old) { } | 177 | static inline void mlock_migrate_page(struct page *new, struct page *old) { } |
176 | static inline void free_page_mlock(struct page *page) { } | 178 | static inline void free_page_mlock(struct page *page) { } |
177 | 179 | ||
178 | #endif /* CONFIG_UNEVICTABLE_LRU */ | 180 | #endif /* CONFIG_HAVE_MLOCKED_PAGE_BIT */ |
179 | 181 | ||
180 | /* | 182 | /* |
181 | * Return the mem_map entry representing the 'offset' subpage within | 183 | * Return the mem_map entry representing the 'offset' subpage within |
diff --git a/mm/memory.c b/mm/memory.c index 2032ad2fc34..cf6873e91c6 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1151,6 +1151,11 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address, | |||
1151 | if ((flags & FOLL_WRITE) && | 1151 | if ((flags & FOLL_WRITE) && |
1152 | !pte_dirty(pte) && !PageDirty(page)) | 1152 | !pte_dirty(pte) && !PageDirty(page)) |
1153 | set_page_dirty(page); | 1153 | set_page_dirty(page); |
1154 | /* | ||
1155 | * pte_mkyoung() would be more correct here, but atomic care | ||
1156 | * is needed to avoid losing the dirty bit: it is easier to use | ||
1157 | * mark_page_accessed(). | ||
1158 | */ | ||
1154 | mark_page_accessed(page); | 1159 | mark_page_accessed(page); |
1155 | } | 1160 | } |
1156 | unlock: | 1161 | unlock: |
@@ -1940,6 +1945,15 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1940 | * get_user_pages(.write=1, .force=1). | 1945 | * get_user_pages(.write=1, .force=1). |
1941 | */ | 1946 | */ |
1942 | if (vma->vm_ops && vma->vm_ops->page_mkwrite) { | 1947 | if (vma->vm_ops && vma->vm_ops->page_mkwrite) { |
1948 | struct vm_fault vmf; | ||
1949 | int tmp; | ||
1950 | |||
1951 | vmf.virtual_address = (void __user *)(address & | ||
1952 | PAGE_MASK); | ||
1953 | vmf.pgoff = old_page->index; | ||
1954 | vmf.flags = FAULT_FLAG_WRITE|FAULT_FLAG_MKWRITE; | ||
1955 | vmf.page = old_page; | ||
1956 | |||
1943 | /* | 1957 | /* |
1944 | * Notify the address space that the page is about to | 1958 | * Notify the address space that the page is about to |
1945 | * become writable so that it can prohibit this or wait | 1959 | * become writable so that it can prohibit this or wait |
@@ -1951,8 +1965,12 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
1951 | page_cache_get(old_page); | 1965 | page_cache_get(old_page); |
1952 | pte_unmap_unlock(page_table, ptl); | 1966 | pte_unmap_unlock(page_table, ptl); |
1953 | 1967 | ||
1954 | if (vma->vm_ops->page_mkwrite(vma, old_page) < 0) | 1968 | tmp = vma->vm_ops->page_mkwrite(vma, &vmf); |
1969 | if (unlikely(tmp & | ||
1970 | (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) { | ||
1971 | ret = tmp; | ||
1955 | goto unwritable_page; | 1972 | goto unwritable_page; |
1973 | } | ||
1956 | 1974 | ||
1957 | /* | 1975 | /* |
1958 | * Since we dropped the lock we need to revalidate | 1976 | * Since we dropped the lock we need to revalidate |
@@ -2101,7 +2119,7 @@ oom: | |||
2101 | 2119 | ||
2102 | unwritable_page: | 2120 | unwritable_page: |
2103 | page_cache_release(old_page); | 2121 | page_cache_release(old_page); |
2104 | return VM_FAULT_SIGBUS; | 2122 | return ret; |
2105 | } | 2123 | } |
2106 | 2124 | ||
2107 | /* | 2125 | /* |
@@ -2435,8 +2453,6 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2435 | count_vm_event(PGMAJFAULT); | 2453 | count_vm_event(PGMAJFAULT); |
2436 | } | 2454 | } |
2437 | 2455 | ||
2438 | mark_page_accessed(page); | ||
2439 | |||
2440 | lock_page(page); | 2456 | lock_page(page); |
2441 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); | 2457 | delayacct_clear_flag(DELAYACCT_PF_SWAPIN); |
2442 | 2458 | ||
@@ -2645,9 +2661,14 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2645 | * to become writable | 2661 | * to become writable |
2646 | */ | 2662 | */ |
2647 | if (vma->vm_ops->page_mkwrite) { | 2663 | if (vma->vm_ops->page_mkwrite) { |
2664 | int tmp; | ||
2665 | |||
2648 | unlock_page(page); | 2666 | unlock_page(page); |
2649 | if (vma->vm_ops->page_mkwrite(vma, page) < 0) { | 2667 | vmf.flags |= FAULT_FLAG_MKWRITE; |
2650 | ret = VM_FAULT_SIGBUS; | 2668 | tmp = vma->vm_ops->page_mkwrite(vma, &vmf); |
2669 | if (unlikely(tmp & | ||
2670 | (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) { | ||
2671 | ret = tmp; | ||
2651 | anon = 1; /* no anon but release vmf.page */ | 2672 | anon = 1; /* no anon but release vmf.page */ |
2652 | goto out_unlocked; | 2673 | goto out_unlocked; |
2653 | } | 2674 | } |
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 40ba05061a4..d3b9bac085b 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -55,7 +55,7 @@ static DEFINE_SPINLOCK(zone_scan_lock); | |||
55 | 55 | ||
56 | unsigned long badness(struct task_struct *p, unsigned long uptime) | 56 | unsigned long badness(struct task_struct *p, unsigned long uptime) |
57 | { | 57 | { |
58 | unsigned long points, cpu_time, run_time, s; | 58 | unsigned long points, cpu_time, run_time; |
59 | struct mm_struct *mm; | 59 | struct mm_struct *mm; |
60 | struct task_struct *child; | 60 | struct task_struct *child; |
61 | 61 | ||
@@ -110,12 +110,10 @@ unsigned long badness(struct task_struct *p, unsigned long uptime) | |||
110 | else | 110 | else |
111 | run_time = 0; | 111 | run_time = 0; |
112 | 112 | ||
113 | s = int_sqrt(cpu_time); | 113 | if (cpu_time) |
114 | if (s) | 114 | points /= int_sqrt(cpu_time); |
115 | points /= s; | 115 | if (run_time) |
116 | s = int_sqrt(int_sqrt(run_time)); | 116 | points /= int_sqrt(int_sqrt(run_time)); |
117 | if (s) | ||
118 | points /= s; | ||
119 | 117 | ||
120 | /* | 118 | /* |
121 | * Niced processes are most likely less important, so double | 119 | * Niced processes are most likely less important, so double |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 40ca7cdb653..30351f0063a 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -92,14 +92,14 @@ int vm_dirty_ratio = 20; | |||
92 | unsigned long vm_dirty_bytes; | 92 | unsigned long vm_dirty_bytes; |
93 | 93 | ||
94 | /* | 94 | /* |
95 | * The interval between `kupdate'-style writebacks, in jiffies | 95 | * The interval between `kupdate'-style writebacks |
96 | */ | 96 | */ |
97 | int dirty_writeback_interval = 5 * HZ; | 97 | unsigned int dirty_writeback_interval = 5 * 100; /* sentiseconds */ |
98 | 98 | ||
99 | /* | 99 | /* |
100 | * The longest number of jiffies for which data is allowed to remain dirty | 100 | * The longest time for which data is allowed to remain dirty |
101 | */ | 101 | */ |
102 | int dirty_expire_interval = 30 * HZ; | 102 | unsigned int dirty_expire_interval = 30 * 100; /* sentiseconds */ |
103 | 103 | ||
104 | /* | 104 | /* |
105 | * Flag that makes the machine dump writes/reads and block dirtyings. | 105 | * Flag that makes the machine dump writes/reads and block dirtyings. |
@@ -770,9 +770,9 @@ static void wb_kupdate(unsigned long arg) | |||
770 | 770 | ||
771 | sync_supers(); | 771 | sync_supers(); |
772 | 772 | ||
773 | oldest_jif = jiffies - dirty_expire_interval; | 773 | oldest_jif = jiffies - msecs_to_jiffies(dirty_expire_interval); |
774 | start_jif = jiffies; | 774 | start_jif = jiffies; |
775 | next_jif = start_jif + dirty_writeback_interval; | 775 | next_jif = start_jif + msecs_to_jiffies(dirty_writeback_interval * 10); |
776 | nr_to_write = global_page_state(NR_FILE_DIRTY) + | 776 | nr_to_write = global_page_state(NR_FILE_DIRTY) + |
777 | global_page_state(NR_UNSTABLE_NFS) + | 777 | global_page_state(NR_UNSTABLE_NFS) + |
778 | (inodes_stat.nr_inodes - inodes_stat.nr_unused); | 778 | (inodes_stat.nr_inodes - inodes_stat.nr_unused); |
@@ -801,9 +801,10 @@ static void wb_kupdate(unsigned long arg) | |||
801 | int dirty_writeback_centisecs_handler(ctl_table *table, int write, | 801 | int dirty_writeback_centisecs_handler(ctl_table *table, int write, |
802 | struct file *file, void __user *buffer, size_t *length, loff_t *ppos) | 802 | struct file *file, void __user *buffer, size_t *length, loff_t *ppos) |
803 | { | 803 | { |
804 | proc_dointvec_userhz_jiffies(table, write, file, buffer, length, ppos); | 804 | proc_dointvec(table, write, file, buffer, length, ppos); |
805 | if (dirty_writeback_interval) | 805 | if (dirty_writeback_interval) |
806 | mod_timer(&wb_timer, jiffies + dirty_writeback_interval); | 806 | mod_timer(&wb_timer, jiffies + |
807 | msecs_to_jiffies(dirty_writeback_interval * 10)); | ||
807 | else | 808 | else |
808 | del_timer(&wb_timer); | 809 | del_timer(&wb_timer); |
809 | return 0; | 810 | return 0; |
@@ -905,7 +906,8 @@ void __init page_writeback_init(void) | |||
905 | { | 906 | { |
906 | int shift; | 907 | int shift; |
907 | 908 | ||
908 | mod_timer(&wb_timer, jiffies + dirty_writeback_interval); | 909 | mod_timer(&wb_timer, |
910 | jiffies + msecs_to_jiffies(dirty_writeback_interval * 10)); | ||
909 | writeback_set_ratelimit(); | 911 | writeback_set_ratelimit(); |
910 | register_cpu_notifier(&ratelimit_nb); | 912 | register_cpu_notifier(&ratelimit_nb); |
911 | 913 | ||
@@ -1198,6 +1200,20 @@ int __set_page_dirty_no_writeback(struct page *page) | |||
1198 | } | 1200 | } |
1199 | 1201 | ||
1200 | /* | 1202 | /* |
1203 | * Helper function for set_page_dirty family. | ||
1204 | * NOTE: This relies on being atomic wrt interrupts. | ||
1205 | */ | ||
1206 | void account_page_dirtied(struct page *page, struct address_space *mapping) | ||
1207 | { | ||
1208 | if (mapping_cap_account_dirty(mapping)) { | ||
1209 | __inc_zone_page_state(page, NR_FILE_DIRTY); | ||
1210 | __inc_bdi_stat(mapping->backing_dev_info, BDI_RECLAIMABLE); | ||
1211 | task_dirty_inc(current); | ||
1212 | task_io_account_write(PAGE_CACHE_SIZE); | ||
1213 | } | ||
1214 | } | ||
1215 | |||
1216 | /* | ||
1201 | * For address_spaces which do not use buffers. Just tag the page as dirty in | 1217 | * For address_spaces which do not use buffers. Just tag the page as dirty in |
1202 | * its radix tree. | 1218 | * its radix tree. |
1203 | * | 1219 | * |
@@ -1226,13 +1242,7 @@ int __set_page_dirty_nobuffers(struct page *page) | |||
1226 | if (mapping2) { /* Race with truncate? */ | 1242 | if (mapping2) { /* Race with truncate? */ |
1227 | BUG_ON(mapping2 != mapping); | 1243 | BUG_ON(mapping2 != mapping); |
1228 | WARN_ON_ONCE(!PagePrivate(page) && !PageUptodate(page)); | 1244 | WARN_ON_ONCE(!PagePrivate(page) && !PageUptodate(page)); |
1229 | if (mapping_cap_account_dirty(mapping)) { | 1245 | account_page_dirtied(page, mapping); |
1230 | __inc_zone_page_state(page, NR_FILE_DIRTY); | ||
1231 | __inc_bdi_stat(mapping->backing_dev_info, | ||
1232 | BDI_RECLAIMABLE); | ||
1233 | task_dirty_inc(current); | ||
1234 | task_io_account_write(PAGE_CACHE_SIZE); | ||
1235 | } | ||
1236 | radix_tree_tag_set(&mapping->page_tree, | 1246 | radix_tree_tag_set(&mapping->page_tree, |
1237 | page_index(page), PAGECACHE_TAG_DIRTY); | 1247 | page_index(page), PAGECACHE_TAG_DIRTY); |
1238 | } | 1248 | } |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index a3803ea8c27..0284e528748 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -922,13 +922,10 @@ static void drain_pages(unsigned int cpu) | |||
922 | unsigned long flags; | 922 | unsigned long flags; |
923 | struct zone *zone; | 923 | struct zone *zone; |
924 | 924 | ||
925 | for_each_zone(zone) { | 925 | for_each_populated_zone(zone) { |
926 | struct per_cpu_pageset *pset; | 926 | struct per_cpu_pageset *pset; |
927 | struct per_cpu_pages *pcp; | 927 | struct per_cpu_pages *pcp; |
928 | 928 | ||
929 | if (!populated_zone(zone)) | ||
930 | continue; | ||
931 | |||
932 | pset = zone_pcp(zone, cpu); | 929 | pset = zone_pcp(zone, cpu); |
933 | 930 | ||
934 | pcp = &pset->pcp; | 931 | pcp = &pset->pcp; |
@@ -1585,7 +1582,8 @@ nofail_alloc: | |||
1585 | reclaim_state.reclaimed_slab = 0; | 1582 | reclaim_state.reclaimed_slab = 0; |
1586 | p->reclaim_state = &reclaim_state; | 1583 | p->reclaim_state = &reclaim_state; |
1587 | 1584 | ||
1588 | did_some_progress = try_to_free_pages(zonelist, order, gfp_mask); | 1585 | did_some_progress = try_to_free_pages(zonelist, order, |
1586 | gfp_mask, nodemask); | ||
1589 | 1587 | ||
1590 | p->reclaim_state = NULL; | 1588 | p->reclaim_state = NULL; |
1591 | lockdep_clear_current_reclaim_state(); | 1589 | lockdep_clear_current_reclaim_state(); |
@@ -1879,10 +1877,7 @@ void show_free_areas(void) | |||
1879 | int cpu; | 1877 | int cpu; |
1880 | struct zone *zone; | 1878 | struct zone *zone; |
1881 | 1879 | ||
1882 | for_each_zone(zone) { | 1880 | for_each_populated_zone(zone) { |
1883 | if (!populated_zone(zone)) | ||
1884 | continue; | ||
1885 | |||
1886 | show_node(zone); | 1881 | show_node(zone); |
1887 | printk("%s per-cpu:\n", zone->name); | 1882 | printk("%s per-cpu:\n", zone->name); |
1888 | 1883 | ||
@@ -1922,12 +1917,9 @@ void show_free_areas(void) | |||
1922 | global_page_state(NR_PAGETABLE), | 1917 | global_page_state(NR_PAGETABLE), |
1923 | global_page_state(NR_BOUNCE)); | 1918 | global_page_state(NR_BOUNCE)); |
1924 | 1919 | ||
1925 | for_each_zone(zone) { | 1920 | for_each_populated_zone(zone) { |
1926 | int i; | 1921 | int i; |
1927 | 1922 | ||
1928 | if (!populated_zone(zone)) | ||
1929 | continue; | ||
1930 | |||
1931 | show_node(zone); | 1923 | show_node(zone); |
1932 | printk("%s" | 1924 | printk("%s" |
1933 | " free:%lukB" | 1925 | " free:%lukB" |
@@ -1967,12 +1959,9 @@ void show_free_areas(void) | |||
1967 | printk("\n"); | 1959 | printk("\n"); |
1968 | } | 1960 | } |
1969 | 1961 | ||
1970 | for_each_zone(zone) { | 1962 | for_each_populated_zone(zone) { |
1971 | unsigned long nr[MAX_ORDER], flags, order, total = 0; | 1963 | unsigned long nr[MAX_ORDER], flags, order, total = 0; |
1972 | 1964 | ||
1973 | if (!populated_zone(zone)) | ||
1974 | continue; | ||
1975 | |||
1976 | show_node(zone); | 1965 | show_node(zone); |
1977 | printk("%s: ", zone->name); | 1966 | printk("%s: ", zone->name); |
1978 | 1967 | ||
@@ -2784,11 +2773,7 @@ static int __cpuinit process_zones(int cpu) | |||
2784 | 2773 | ||
2785 | node_set_state(node, N_CPU); /* this node has a cpu */ | 2774 | node_set_state(node, N_CPU); /* this node has a cpu */ |
2786 | 2775 | ||
2787 | for_each_zone(zone) { | 2776 | for_each_populated_zone(zone) { |
2788 | |||
2789 | if (!populated_zone(zone)) | ||
2790 | continue; | ||
2791 | |||
2792 | zone_pcp(zone, cpu) = kmalloc_node(sizeof(struct per_cpu_pageset), | 2777 | zone_pcp(zone, cpu) = kmalloc_node(sizeof(struct per_cpu_pageset), |
2793 | GFP_KERNEL, node); | 2778 | GFP_KERNEL, node); |
2794 | if (!zone_pcp(zone, cpu)) | 2779 | if (!zone_pcp(zone, cpu)) |
diff --git a/mm/shmem.c b/mm/shmem.c index 7ec78e24a30..d94d2e9146b 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1068,8 +1068,7 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc) | |||
1068 | swap_duplicate(swap); | 1068 | swap_duplicate(swap); |
1069 | BUG_ON(page_mapped(page)); | 1069 | BUG_ON(page_mapped(page)); |
1070 | page_cache_release(page); /* pagecache ref */ | 1070 | page_cache_release(page); /* pagecache ref */ |
1071 | set_page_dirty(page); | 1071 | swap_writepage(page, wbc); |
1072 | unlock_page(page); | ||
1073 | if (inode) { | 1072 | if (inode) { |
1074 | mutex_lock(&shmem_swaplist_mutex); | 1073 | mutex_lock(&shmem_swaplist_mutex); |
1075 | /* move instead of add in case we're racing */ | 1074 | /* move instead of add in case we're racing */ |
diff --git a/mm/sparse.c b/mm/sparse.c index 083f5b63e7a..da432d9f0ae 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
@@ -164,9 +164,7 @@ void __meminit mminit_validate_memmodel_limits(unsigned long *start_pfn, | |||
164 | WARN_ON_ONCE(1); | 164 | WARN_ON_ONCE(1); |
165 | *start_pfn = max_sparsemem_pfn; | 165 | *start_pfn = max_sparsemem_pfn; |
166 | *end_pfn = max_sparsemem_pfn; | 166 | *end_pfn = max_sparsemem_pfn; |
167 | } | 167 | } else if (*end_pfn > max_sparsemem_pfn) { |
168 | |||
169 | if (*end_pfn > max_sparsemem_pfn) { | ||
170 | mminit_dprintk(MMINIT_WARNING, "pfnvalidation", | 168 | mminit_dprintk(MMINIT_WARNING, "pfnvalidation", |
171 | "End of range %lu -> %lu exceeds SPARSEMEM max %lu\n", | 169 | "End of range %lu -> %lu exceeds SPARSEMEM max %lu\n", |
172 | *start_pfn, *end_pfn, max_sparsemem_pfn); | 170 | *start_pfn, *end_pfn, max_sparsemem_pfn); |
@@ -457,29 +457,6 @@ void pagevec_strip(struct pagevec *pvec) | |||
457 | } | 457 | } |
458 | 458 | ||
459 | /** | 459 | /** |
460 | * pagevec_swap_free - try to free swap space from the pages in a pagevec | ||
461 | * @pvec: pagevec with swapcache pages to free the swap space of | ||
462 | * | ||
463 | * The caller needs to hold an extra reference to each page and | ||
464 | * not hold the page lock on the pages. This function uses a | ||
465 | * trylock on the page lock so it may not always free the swap | ||
466 | * space associated with a page. | ||
467 | */ | ||
468 | void pagevec_swap_free(struct pagevec *pvec) | ||
469 | { | ||
470 | int i; | ||
471 | |||
472 | for (i = 0; i < pagevec_count(pvec); i++) { | ||
473 | struct page *page = pvec->pages[i]; | ||
474 | |||
475 | if (PageSwapCache(page) && trylock_page(page)) { | ||
476 | try_to_free_swap(page); | ||
477 | unlock_page(page); | ||
478 | } | ||
479 | } | ||
480 | } | ||
481 | |||
482 | /** | ||
483 | * pagevec_lookup - gang pagecache lookup | 460 | * pagevec_lookup - gang pagecache lookup |
484 | * @pvec: Where the resulting pages are placed | 461 | * @pvec: Where the resulting pages are placed |
485 | * @mapping: The address_space to search | 462 | * @mapping: The address_space to search |
@@ -70,6 +70,36 @@ void *kmemdup(const void *src, size_t len, gfp_t gfp) | |||
70 | EXPORT_SYMBOL(kmemdup); | 70 | EXPORT_SYMBOL(kmemdup); |
71 | 71 | ||
72 | /** | 72 | /** |
73 | * memdup_user - duplicate memory region from user space | ||
74 | * | ||
75 | * @src: source address in user space | ||
76 | * @len: number of bytes to copy | ||
77 | * | ||
78 | * Returns an ERR_PTR() on failure. | ||
79 | */ | ||
80 | void *memdup_user(const void __user *src, size_t len) | ||
81 | { | ||
82 | void *p; | ||
83 | |||
84 | /* | ||
85 | * Always use GFP_KERNEL, since copy_from_user() can sleep and | ||
86 | * cause pagefault, which makes it pointless to use GFP_NOFS | ||
87 | * or GFP_ATOMIC. | ||
88 | */ | ||
89 | p = kmalloc_track_caller(len, GFP_KERNEL); | ||
90 | if (!p) | ||
91 | return ERR_PTR(-ENOMEM); | ||
92 | |||
93 | if (copy_from_user(p, src, len)) { | ||
94 | kfree(p); | ||
95 | return ERR_PTR(-EFAULT); | ||
96 | } | ||
97 | |||
98 | return p; | ||
99 | } | ||
100 | EXPORT_SYMBOL(memdup_user); | ||
101 | |||
102 | /** | ||
73 | * __krealloc - like krealloc() but don't free @p. | 103 | * __krealloc - like krealloc() but don't free @p. |
74 | * @p: object to reallocate memory for. | 104 | * @p: object to reallocate memory for. |
75 | * @new_size: how many bytes of memory are required. | 105 | * @new_size: how many bytes of memory are required. |
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index af58324c361..fab19876b4d 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -671,10 +671,7 @@ struct vmap_block { | |||
671 | DECLARE_BITMAP(alloc_map, VMAP_BBMAP_BITS); | 671 | DECLARE_BITMAP(alloc_map, VMAP_BBMAP_BITS); |
672 | DECLARE_BITMAP(dirty_map, VMAP_BBMAP_BITS); | 672 | DECLARE_BITMAP(dirty_map, VMAP_BBMAP_BITS); |
673 | union { | 673 | union { |
674 | struct { | 674 | struct list_head free_list; |
675 | struct list_head free_list; | ||
676 | struct list_head dirty_list; | ||
677 | }; | ||
678 | struct rcu_head rcu_head; | 675 | struct rcu_head rcu_head; |
679 | }; | 676 | }; |
680 | }; | 677 | }; |
@@ -741,7 +738,6 @@ static struct vmap_block *new_vmap_block(gfp_t gfp_mask) | |||
741 | bitmap_zero(vb->alloc_map, VMAP_BBMAP_BITS); | 738 | bitmap_zero(vb->alloc_map, VMAP_BBMAP_BITS); |
742 | bitmap_zero(vb->dirty_map, VMAP_BBMAP_BITS); | 739 | bitmap_zero(vb->dirty_map, VMAP_BBMAP_BITS); |
743 | INIT_LIST_HEAD(&vb->free_list); | 740 | INIT_LIST_HEAD(&vb->free_list); |
744 | INIT_LIST_HEAD(&vb->dirty_list); | ||
745 | 741 | ||
746 | vb_idx = addr_to_vb_idx(va->va_start); | 742 | vb_idx = addr_to_vb_idx(va->va_start); |
747 | spin_lock(&vmap_block_tree_lock); | 743 | spin_lock(&vmap_block_tree_lock); |
@@ -772,12 +768,7 @@ static void free_vmap_block(struct vmap_block *vb) | |||
772 | struct vmap_block *tmp; | 768 | struct vmap_block *tmp; |
773 | unsigned long vb_idx; | 769 | unsigned long vb_idx; |
774 | 770 | ||
775 | spin_lock(&vb->vbq->lock); | 771 | BUG_ON(!list_empty(&vb->free_list)); |
776 | if (!list_empty(&vb->free_list)) | ||
777 | list_del(&vb->free_list); | ||
778 | if (!list_empty(&vb->dirty_list)) | ||
779 | list_del(&vb->dirty_list); | ||
780 | spin_unlock(&vb->vbq->lock); | ||
781 | 772 | ||
782 | vb_idx = addr_to_vb_idx(vb->va->va_start); | 773 | vb_idx = addr_to_vb_idx(vb->va->va_start); |
783 | spin_lock(&vmap_block_tree_lock); | 774 | spin_lock(&vmap_block_tree_lock); |
@@ -862,11 +853,7 @@ static void vb_free(const void *addr, unsigned long size) | |||
862 | 853 | ||
863 | spin_lock(&vb->lock); | 854 | spin_lock(&vb->lock); |
864 | bitmap_allocate_region(vb->dirty_map, offset >> PAGE_SHIFT, order); | 855 | bitmap_allocate_region(vb->dirty_map, offset >> PAGE_SHIFT, order); |
865 | if (!vb->dirty) { | 856 | |
866 | spin_lock(&vb->vbq->lock); | ||
867 | list_add(&vb->dirty_list, &vb->vbq->dirty); | ||
868 | spin_unlock(&vb->vbq->lock); | ||
869 | } | ||
870 | vb->dirty += 1UL << order; | 857 | vb->dirty += 1UL << order; |
871 | if (vb->dirty == VMAP_BBMAP_BITS) { | 858 | if (vb->dirty == VMAP_BBMAP_BITS) { |
872 | BUG_ON(vb->free || !list_empty(&vb->free_list)); | 859 | BUG_ON(vb->free || !list_empty(&vb->free_list)); |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 479e4671939..06e72693b45 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -60,8 +60,8 @@ struct scan_control { | |||
60 | 60 | ||
61 | int may_writepage; | 61 | int may_writepage; |
62 | 62 | ||
63 | /* Can pages be swapped as part of reclaim? */ | 63 | /* Can mapped pages be reclaimed? */ |
64 | int may_swap; | 64 | int may_unmap; |
65 | 65 | ||
66 | /* This context's SWAP_CLUSTER_MAX. If freeing memory for | 66 | /* This context's SWAP_CLUSTER_MAX. If freeing memory for |
67 | * suspend, we effectively ignore SWAP_CLUSTER_MAX. | 67 | * suspend, we effectively ignore SWAP_CLUSTER_MAX. |
@@ -78,6 +78,12 @@ struct scan_control { | |||
78 | /* Which cgroup do we reclaim from */ | 78 | /* Which cgroup do we reclaim from */ |
79 | struct mem_cgroup *mem_cgroup; | 79 | struct mem_cgroup *mem_cgroup; |
80 | 80 | ||
81 | /* | ||
82 | * Nodemask of nodes allowed by the caller. If NULL, all nodes | ||
83 | * are scanned. | ||
84 | */ | ||
85 | nodemask_t *nodemask; | ||
86 | |||
81 | /* Pluggable isolate pages callback */ | 87 | /* Pluggable isolate pages callback */ |
82 | unsigned long (*isolate_pages)(unsigned long nr, struct list_head *dst, | 88 | unsigned long (*isolate_pages)(unsigned long nr, struct list_head *dst, |
83 | unsigned long *scanned, int order, int mode, | 89 | unsigned long *scanned, int order, int mode, |
@@ -214,8 +220,9 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, | |||
214 | do_div(delta, lru_pages + 1); | 220 | do_div(delta, lru_pages + 1); |
215 | shrinker->nr += delta; | 221 | shrinker->nr += delta; |
216 | if (shrinker->nr < 0) { | 222 | if (shrinker->nr < 0) { |
217 | printk(KERN_ERR "%s: nr=%ld\n", | 223 | printk(KERN_ERR "shrink_slab: %pF negative objects to " |
218 | __func__, shrinker->nr); | 224 | "delete nr=%ld\n", |
225 | shrinker->shrink, shrinker->nr); | ||
219 | shrinker->nr = max_pass; | 226 | shrinker->nr = max_pass; |
220 | } | 227 | } |
221 | 228 | ||
@@ -606,7 +613,7 @@ static unsigned long shrink_page_list(struct list_head *page_list, | |||
606 | if (unlikely(!page_evictable(page, NULL))) | 613 | if (unlikely(!page_evictable(page, NULL))) |
607 | goto cull_mlocked; | 614 | goto cull_mlocked; |
608 | 615 | ||
609 | if (!sc->may_swap && page_mapped(page)) | 616 | if (!sc->may_unmap && page_mapped(page)) |
610 | goto keep_locked; | 617 | goto keep_locked; |
611 | 618 | ||
612 | /* Double the slab pressure for mapped and swapcache pages */ | 619 | /* Double the slab pressure for mapped and swapcache pages */ |
@@ -1298,17 +1305,11 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone, | |||
1298 | } | 1305 | } |
1299 | __mod_zone_page_state(zone, NR_LRU_BASE + lru, pgmoved); | 1306 | __mod_zone_page_state(zone, NR_LRU_BASE + lru, pgmoved); |
1300 | pgdeactivate += pgmoved; | 1307 | pgdeactivate += pgmoved; |
1301 | if (buffer_heads_over_limit) { | ||
1302 | spin_unlock_irq(&zone->lru_lock); | ||
1303 | pagevec_strip(&pvec); | ||
1304 | spin_lock_irq(&zone->lru_lock); | ||
1305 | } | ||
1306 | __count_zone_vm_events(PGREFILL, zone, pgscanned); | 1308 | __count_zone_vm_events(PGREFILL, zone, pgscanned); |
1307 | __count_vm_events(PGDEACTIVATE, pgdeactivate); | 1309 | __count_vm_events(PGDEACTIVATE, pgdeactivate); |
1308 | spin_unlock_irq(&zone->lru_lock); | 1310 | spin_unlock_irq(&zone->lru_lock); |
1309 | if (vm_swap_full()) | 1311 | if (buffer_heads_over_limit) |
1310 | pagevec_swap_free(&pvec); | 1312 | pagevec_strip(&pvec); |
1311 | |||
1312 | pagevec_release(&pvec); | 1313 | pagevec_release(&pvec); |
1313 | } | 1314 | } |
1314 | 1315 | ||
@@ -1543,7 +1544,8 @@ static void shrink_zones(int priority, struct zonelist *zonelist, | |||
1543 | struct zone *zone; | 1544 | struct zone *zone; |
1544 | 1545 | ||
1545 | sc->all_unreclaimable = 1; | 1546 | sc->all_unreclaimable = 1; |
1546 | for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) { | 1547 | for_each_zone_zonelist_nodemask(zone, z, zonelist, high_zoneidx, |
1548 | sc->nodemask) { | ||
1547 | if (!populated_zone(zone)) | 1549 | if (!populated_zone(zone)) |
1548 | continue; | 1550 | continue; |
1549 | /* | 1551 | /* |
@@ -1688,17 +1690,18 @@ out: | |||
1688 | } | 1690 | } |
1689 | 1691 | ||
1690 | unsigned long try_to_free_pages(struct zonelist *zonelist, int order, | 1692 | unsigned long try_to_free_pages(struct zonelist *zonelist, int order, |
1691 | gfp_t gfp_mask) | 1693 | gfp_t gfp_mask, nodemask_t *nodemask) |
1692 | { | 1694 | { |
1693 | struct scan_control sc = { | 1695 | struct scan_control sc = { |
1694 | .gfp_mask = gfp_mask, | 1696 | .gfp_mask = gfp_mask, |
1695 | .may_writepage = !laptop_mode, | 1697 | .may_writepage = !laptop_mode, |
1696 | .swap_cluster_max = SWAP_CLUSTER_MAX, | 1698 | .swap_cluster_max = SWAP_CLUSTER_MAX, |
1697 | .may_swap = 1, | 1699 | .may_unmap = 1, |
1698 | .swappiness = vm_swappiness, | 1700 | .swappiness = vm_swappiness, |
1699 | .order = order, | 1701 | .order = order, |
1700 | .mem_cgroup = NULL, | 1702 | .mem_cgroup = NULL, |
1701 | .isolate_pages = isolate_pages_global, | 1703 | .isolate_pages = isolate_pages_global, |
1704 | .nodemask = nodemask, | ||
1702 | }; | 1705 | }; |
1703 | 1706 | ||
1704 | return do_try_to_free_pages(zonelist, &sc); | 1707 | return do_try_to_free_pages(zonelist, &sc); |
@@ -1713,17 +1716,18 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont, | |||
1713 | { | 1716 | { |
1714 | struct scan_control sc = { | 1717 | struct scan_control sc = { |
1715 | .may_writepage = !laptop_mode, | 1718 | .may_writepage = !laptop_mode, |
1716 | .may_swap = 1, | 1719 | .may_unmap = 1, |
1717 | .swap_cluster_max = SWAP_CLUSTER_MAX, | 1720 | .swap_cluster_max = SWAP_CLUSTER_MAX, |
1718 | .swappiness = swappiness, | 1721 | .swappiness = swappiness, |
1719 | .order = 0, | 1722 | .order = 0, |
1720 | .mem_cgroup = mem_cont, | 1723 | .mem_cgroup = mem_cont, |
1721 | .isolate_pages = mem_cgroup_isolate_pages, | 1724 | .isolate_pages = mem_cgroup_isolate_pages, |
1725 | .nodemask = NULL, /* we don't care the placement */ | ||
1722 | }; | 1726 | }; |
1723 | struct zonelist *zonelist; | 1727 | struct zonelist *zonelist; |
1724 | 1728 | ||
1725 | if (noswap) | 1729 | if (noswap) |
1726 | sc.may_swap = 0; | 1730 | sc.may_unmap = 0; |
1727 | 1731 | ||
1728 | sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) | | 1732 | sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) | |
1729 | (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK); | 1733 | (GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK); |
@@ -1762,7 +1766,7 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order) | |||
1762 | struct reclaim_state *reclaim_state = current->reclaim_state; | 1766 | struct reclaim_state *reclaim_state = current->reclaim_state; |
1763 | struct scan_control sc = { | 1767 | struct scan_control sc = { |
1764 | .gfp_mask = GFP_KERNEL, | 1768 | .gfp_mask = GFP_KERNEL, |
1765 | .may_swap = 1, | 1769 | .may_unmap = 1, |
1766 | .swap_cluster_max = SWAP_CLUSTER_MAX, | 1770 | .swap_cluster_max = SWAP_CLUSTER_MAX, |
1767 | .swappiness = vm_swappiness, | 1771 | .swappiness = vm_swappiness, |
1768 | .order = order, | 1772 | .order = order, |
@@ -2050,22 +2054,19 @@ unsigned long global_lru_pages(void) | |||
2050 | #ifdef CONFIG_PM | 2054 | #ifdef CONFIG_PM |
2051 | /* | 2055 | /* |
2052 | * Helper function for shrink_all_memory(). Tries to reclaim 'nr_pages' pages | 2056 | * Helper function for shrink_all_memory(). Tries to reclaim 'nr_pages' pages |
2053 | * from LRU lists system-wide, for given pass and priority, and returns the | 2057 | * from LRU lists system-wide, for given pass and priority. |
2054 | * number of reclaimed pages | ||
2055 | * | 2058 | * |
2056 | * For pass > 3 we also try to shrink the LRU lists that contain a few pages | 2059 | * For pass > 3 we also try to shrink the LRU lists that contain a few pages |
2057 | */ | 2060 | */ |
2058 | static unsigned long shrink_all_zones(unsigned long nr_pages, int prio, | 2061 | static void shrink_all_zones(unsigned long nr_pages, int prio, |
2059 | int pass, struct scan_control *sc) | 2062 | int pass, struct scan_control *sc) |
2060 | { | 2063 | { |
2061 | struct zone *zone; | 2064 | struct zone *zone; |
2062 | unsigned long ret = 0; | 2065 | unsigned long nr_reclaimed = 0; |
2063 | 2066 | ||
2064 | for_each_zone(zone) { | 2067 | for_each_populated_zone(zone) { |
2065 | enum lru_list l; | 2068 | enum lru_list l; |
2066 | 2069 | ||
2067 | if (!populated_zone(zone)) | ||
2068 | continue; | ||
2069 | if (zone_is_all_unreclaimable(zone) && prio != DEF_PRIORITY) | 2070 | if (zone_is_all_unreclaimable(zone) && prio != DEF_PRIORITY) |
2070 | continue; | 2071 | continue; |
2071 | 2072 | ||
@@ -2084,14 +2085,16 @@ static unsigned long shrink_all_zones(unsigned long nr_pages, int prio, | |||
2084 | 2085 | ||
2085 | zone->lru[l].nr_scan = 0; | 2086 | zone->lru[l].nr_scan = 0; |
2086 | nr_to_scan = min(nr_pages, lru_pages); | 2087 | nr_to_scan = min(nr_pages, lru_pages); |
2087 | ret += shrink_list(l, nr_to_scan, zone, | 2088 | nr_reclaimed += shrink_list(l, nr_to_scan, zone, |
2088 | sc, prio); | 2089 | sc, prio); |
2089 | if (ret >= nr_pages) | 2090 | if (nr_reclaimed >= nr_pages) { |
2090 | return ret; | 2091 | sc->nr_reclaimed = nr_reclaimed; |
2092 | return; | ||
2093 | } | ||
2091 | } | 2094 | } |
2092 | } | 2095 | } |
2093 | } | 2096 | } |
2094 | return ret; | 2097 | sc->nr_reclaimed = nr_reclaimed; |
2095 | } | 2098 | } |
2096 | 2099 | ||
2097 | /* | 2100 | /* |
@@ -2105,13 +2108,11 @@ static unsigned long shrink_all_zones(unsigned long nr_pages, int prio, | |||
2105 | unsigned long shrink_all_memory(unsigned long nr_pages) | 2108 | unsigned long shrink_all_memory(unsigned long nr_pages) |
2106 | { | 2109 | { |
2107 | unsigned long lru_pages, nr_slab; | 2110 | unsigned long lru_pages, nr_slab; |
2108 | unsigned long ret = 0; | ||
2109 | int pass; | 2111 | int pass; |
2110 | struct reclaim_state reclaim_state; | 2112 | struct reclaim_state reclaim_state; |
2111 | struct scan_control sc = { | 2113 | struct scan_control sc = { |
2112 | .gfp_mask = GFP_KERNEL, | 2114 | .gfp_mask = GFP_KERNEL, |
2113 | .may_swap = 0, | 2115 | .may_unmap = 0, |
2114 | .swap_cluster_max = nr_pages, | ||
2115 | .may_writepage = 1, | 2116 | .may_writepage = 1, |
2116 | .isolate_pages = isolate_pages_global, | 2117 | .isolate_pages = isolate_pages_global, |
2117 | }; | 2118 | }; |
@@ -2127,8 +2128,8 @@ unsigned long shrink_all_memory(unsigned long nr_pages) | |||
2127 | if (!reclaim_state.reclaimed_slab) | 2128 | if (!reclaim_state.reclaimed_slab) |
2128 | break; | 2129 | break; |
2129 | 2130 | ||
2130 | ret += reclaim_state.reclaimed_slab; | 2131 | sc.nr_reclaimed += reclaim_state.reclaimed_slab; |
2131 | if (ret >= nr_pages) | 2132 | if (sc.nr_reclaimed >= nr_pages) |
2132 | goto out; | 2133 | goto out; |
2133 | 2134 | ||
2134 | nr_slab -= reclaim_state.reclaimed_slab; | 2135 | nr_slab -= reclaim_state.reclaimed_slab; |
@@ -2147,21 +2148,22 @@ unsigned long shrink_all_memory(unsigned long nr_pages) | |||
2147 | 2148 | ||
2148 | /* Force reclaiming mapped pages in the passes #3 and #4 */ | 2149 | /* Force reclaiming mapped pages in the passes #3 and #4 */ |
2149 | if (pass > 2) | 2150 | if (pass > 2) |
2150 | sc.may_swap = 1; | 2151 | sc.may_unmap = 1; |
2151 | 2152 | ||
2152 | for (prio = DEF_PRIORITY; prio >= 0; prio--) { | 2153 | for (prio = DEF_PRIORITY; prio >= 0; prio--) { |
2153 | unsigned long nr_to_scan = nr_pages - ret; | 2154 | unsigned long nr_to_scan = nr_pages - sc.nr_reclaimed; |
2154 | 2155 | ||
2155 | sc.nr_scanned = 0; | 2156 | sc.nr_scanned = 0; |
2156 | ret += shrink_all_zones(nr_to_scan, prio, pass, &sc); | 2157 | sc.swap_cluster_max = nr_to_scan; |
2157 | if (ret >= nr_pages) | 2158 | shrink_all_zones(nr_to_scan, prio, pass, &sc); |
2159 | if (sc.nr_reclaimed >= nr_pages) | ||
2158 | goto out; | 2160 | goto out; |
2159 | 2161 | ||
2160 | reclaim_state.reclaimed_slab = 0; | 2162 | reclaim_state.reclaimed_slab = 0; |
2161 | shrink_slab(sc.nr_scanned, sc.gfp_mask, | 2163 | shrink_slab(sc.nr_scanned, sc.gfp_mask, |
2162 | global_lru_pages()); | 2164 | global_lru_pages()); |
2163 | ret += reclaim_state.reclaimed_slab; | 2165 | sc.nr_reclaimed += reclaim_state.reclaimed_slab; |
2164 | if (ret >= nr_pages) | 2166 | if (sc.nr_reclaimed >= nr_pages) |
2165 | goto out; | 2167 | goto out; |
2166 | 2168 | ||
2167 | if (sc.nr_scanned && prio < DEF_PRIORITY - 2) | 2169 | if (sc.nr_scanned && prio < DEF_PRIORITY - 2) |
@@ -2170,21 +2172,23 @@ unsigned long shrink_all_memory(unsigned long nr_pages) | |||
2170 | } | 2172 | } |
2171 | 2173 | ||
2172 | /* | 2174 | /* |
2173 | * If ret = 0, we could not shrink LRUs, but there may be something | 2175 | * If sc.nr_reclaimed = 0, we could not shrink LRUs, but there may be |
2174 | * in slab caches | 2176 | * something in slab caches |
2175 | */ | 2177 | */ |
2176 | if (!ret) { | 2178 | if (!sc.nr_reclaimed) { |
2177 | do { | 2179 | do { |
2178 | reclaim_state.reclaimed_slab = 0; | 2180 | reclaim_state.reclaimed_slab = 0; |
2179 | shrink_slab(nr_pages, sc.gfp_mask, global_lru_pages()); | 2181 | shrink_slab(nr_pages, sc.gfp_mask, global_lru_pages()); |
2180 | ret += reclaim_state.reclaimed_slab; | 2182 | sc.nr_reclaimed += reclaim_state.reclaimed_slab; |
2181 | } while (ret < nr_pages && reclaim_state.reclaimed_slab > 0); | 2183 | } while (sc.nr_reclaimed < nr_pages && |
2184 | reclaim_state.reclaimed_slab > 0); | ||
2182 | } | 2185 | } |
2183 | 2186 | ||
2187 | |||
2184 | out: | 2188 | out: |
2185 | current->reclaim_state = NULL; | 2189 | current->reclaim_state = NULL; |
2186 | 2190 | ||
2187 | return ret; | 2191 | return sc.nr_reclaimed; |
2188 | } | 2192 | } |
2189 | #endif | 2193 | #endif |
2190 | 2194 | ||
@@ -2290,11 +2294,12 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order) | |||
2290 | int priority; | 2294 | int priority; |
2291 | struct scan_control sc = { | 2295 | struct scan_control sc = { |
2292 | .may_writepage = !!(zone_reclaim_mode & RECLAIM_WRITE), | 2296 | .may_writepage = !!(zone_reclaim_mode & RECLAIM_WRITE), |
2293 | .may_swap = !!(zone_reclaim_mode & RECLAIM_SWAP), | 2297 | .may_unmap = !!(zone_reclaim_mode & RECLAIM_SWAP), |
2294 | .swap_cluster_max = max_t(unsigned long, nr_pages, | 2298 | .swap_cluster_max = max_t(unsigned long, nr_pages, |
2295 | SWAP_CLUSTER_MAX), | 2299 | SWAP_CLUSTER_MAX), |
2296 | .gfp_mask = gfp_mask, | 2300 | .gfp_mask = gfp_mask, |
2297 | .swappiness = vm_swappiness, | 2301 | .swappiness = vm_swappiness, |
2302 | .order = order, | ||
2298 | .isolate_pages = isolate_pages_global, | 2303 | .isolate_pages = isolate_pages_global, |
2299 | }; | 2304 | }; |
2300 | unsigned long slab_reclaimable; | 2305 | unsigned long slab_reclaimable; |
diff --git a/mm/vmstat.c b/mm/vmstat.c index 8cd81ea1ddc..9826766f127 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -135,11 +135,7 @@ static void refresh_zone_stat_thresholds(void) | |||
135 | int cpu; | 135 | int cpu; |
136 | int threshold; | 136 | int threshold; |
137 | 137 | ||
138 | for_each_zone(zone) { | 138 | for_each_populated_zone(zone) { |
139 | |||
140 | if (!zone->present_pages) | ||
141 | continue; | ||
142 | |||
143 | threshold = calculate_threshold(zone); | 139 | threshold = calculate_threshold(zone); |
144 | 140 | ||
145 | for_each_online_cpu(cpu) | 141 | for_each_online_cpu(cpu) |
@@ -301,12 +297,9 @@ void refresh_cpu_vm_stats(int cpu) | |||
301 | int i; | 297 | int i; |
302 | int global_diff[NR_VM_ZONE_STAT_ITEMS] = { 0, }; | 298 | int global_diff[NR_VM_ZONE_STAT_ITEMS] = { 0, }; |
303 | 299 | ||
304 | for_each_zone(zone) { | 300 | for_each_populated_zone(zone) { |
305 | struct per_cpu_pageset *p; | 301 | struct per_cpu_pageset *p; |
306 | 302 | ||
307 | if (!populated_zone(zone)) | ||
308 | continue; | ||
309 | |||
310 | p = zone_pcp(zone, cpu); | 303 | p = zone_pcp(zone, cpu); |
311 | 304 | ||
312 | for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) | 305 | for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index abdc703a11d..cab71ea2796 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -1093,11 +1093,6 @@ static void rfcomm_tty_hangup(struct tty_struct *tty) | |||
1093 | } | 1093 | } |
1094 | } | 1094 | } |
1095 | 1095 | ||
1096 | static int rfcomm_tty_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *unused) | ||
1097 | { | ||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | static int rfcomm_tty_tiocmget(struct tty_struct *tty, struct file *filp) | 1096 | static int rfcomm_tty_tiocmget(struct tty_struct *tty, struct file *filp) |
1102 | { | 1097 | { |
1103 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; | 1098 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; |
@@ -1156,7 +1151,6 @@ static const struct tty_operations rfcomm_ops = { | |||
1156 | .send_xchar = rfcomm_tty_send_xchar, | 1151 | .send_xchar = rfcomm_tty_send_xchar, |
1157 | .hangup = rfcomm_tty_hangup, | 1152 | .hangup = rfcomm_tty_hangup, |
1158 | .wait_until_sent = rfcomm_tty_wait_until_sent, | 1153 | .wait_until_sent = rfcomm_tty_wait_until_sent, |
1159 | .read_proc = rfcomm_tty_read_proc, | ||
1160 | .tiocmget = rfcomm_tty_tiocmget, | 1154 | .tiocmget = rfcomm_tty_tiocmget, |
1161 | .tiocmset = rfcomm_tty_tiocmset, | 1155 | .tiocmset = rfcomm_tty_tiocmset, |
1162 | }; | 1156 | }; |
diff --git a/net/core/sock.c b/net/core/sock.c index 0620046e4eb..7dbf3ffb35c 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1677,7 +1677,7 @@ static void sock_def_error_report(struct sock *sk) | |||
1677 | { | 1677 | { |
1678 | read_lock(&sk->sk_callback_lock); | 1678 | read_lock(&sk->sk_callback_lock); |
1679 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 1679 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) |
1680 | wake_up_interruptible(sk->sk_sleep); | 1680 | wake_up_interruptible_poll(sk->sk_sleep, POLLERR); |
1681 | sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); | 1681 | sk_wake_async(sk, SOCK_WAKE_IO, POLL_ERR); |
1682 | read_unlock(&sk->sk_callback_lock); | 1682 | read_unlock(&sk->sk_callback_lock); |
1683 | } | 1683 | } |
@@ -1686,7 +1686,8 @@ static void sock_def_readable(struct sock *sk, int len) | |||
1686 | { | 1686 | { |
1687 | read_lock(&sk->sk_callback_lock); | 1687 | read_lock(&sk->sk_callback_lock); |
1688 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 1688 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) |
1689 | wake_up_interruptible_sync(sk->sk_sleep); | 1689 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLIN | |
1690 | POLLRDNORM | POLLRDBAND); | ||
1690 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); | 1691 | sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_IN); |
1691 | read_unlock(&sk->sk_callback_lock); | 1692 | read_unlock(&sk->sk_callback_lock); |
1692 | } | 1693 | } |
@@ -1700,7 +1701,8 @@ static void sock_def_write_space(struct sock *sk) | |||
1700 | */ | 1701 | */ |
1701 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { | 1702 | if ((atomic_read(&sk->sk_wmem_alloc) << 1) <= sk->sk_sndbuf) { |
1702 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) | 1703 | if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) |
1703 | wake_up_interruptible_sync(sk->sk_sleep); | 1704 | wake_up_interruptible_sync_poll(sk->sk_sleep, POLLOUT | |
1705 | POLLWRNORM | POLLWRBAND); | ||
1704 | 1706 | ||
1705 | /* Should agree with poll, otherwise some programs break */ | 1707 | /* Should agree with poll, otherwise some programs break */ |
1706 | if (sock_writeable(sk)) | 1708 | if (sock_writeable(sk)) |
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 086d5ef098f..811984d9324 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
35 | #include <linux/fs.h> | 35 | #include <linux/fs.h> |
36 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
37 | #include <linux/seq_file.h> | ||
37 | #include <linux/termios.h> | 38 | #include <linux/termios.h> |
38 | #include <linux/tty.h> | 39 | #include <linux/tty.h> |
39 | #include <linux/interrupt.h> | 40 | #include <linux/interrupt.h> |
@@ -72,8 +73,7 @@ static int ircomm_tty_control_indication(void *instance, void *sap, | |||
72 | static void ircomm_tty_flow_indication(void *instance, void *sap, | 73 | static void ircomm_tty_flow_indication(void *instance, void *sap, |
73 | LOCAL_FLOW cmd); | 74 | LOCAL_FLOW cmd); |
74 | #ifdef CONFIG_PROC_FS | 75 | #ifdef CONFIG_PROC_FS |
75 | static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len, | 76 | static const struct file_operations ircomm_tty_proc_fops; |
76 | int *eof, void *unused); | ||
77 | #endif /* CONFIG_PROC_FS */ | 77 | #endif /* CONFIG_PROC_FS */ |
78 | static struct tty_driver *driver; | 78 | static struct tty_driver *driver; |
79 | 79 | ||
@@ -98,7 +98,7 @@ static const struct tty_operations ops = { | |||
98 | .hangup = ircomm_tty_hangup, | 98 | .hangup = ircomm_tty_hangup, |
99 | .wait_until_sent = ircomm_tty_wait_until_sent, | 99 | .wait_until_sent = ircomm_tty_wait_until_sent, |
100 | #ifdef CONFIG_PROC_FS | 100 | #ifdef CONFIG_PROC_FS |
101 | .read_proc = ircomm_tty_read_proc, | 101 | .proc_fops = &ircomm_tty_proc_fops, |
102 | #endif /* CONFIG_PROC_FS */ | 102 | #endif /* CONFIG_PROC_FS */ |
103 | }; | 103 | }; |
104 | 104 | ||
@@ -1245,150 +1245,170 @@ static void ircomm_tty_flow_indication(void *instance, void *sap, | |||
1245 | } | 1245 | } |
1246 | 1246 | ||
1247 | #ifdef CONFIG_PROC_FS | 1247 | #ifdef CONFIG_PROC_FS |
1248 | static int ircomm_tty_line_info(struct ircomm_tty_cb *self, char *buf) | 1248 | static void ircomm_tty_line_info(struct ircomm_tty_cb *self, struct seq_file *m) |
1249 | { | 1249 | { |
1250 | int ret=0; | 1250 | char sep; |
1251 | 1251 | ||
1252 | ret += sprintf(buf+ret, "State: %s\n", ircomm_tty_state[self->state]); | 1252 | seq_printf(m, "State: %s\n", ircomm_tty_state[self->state]); |
1253 | 1253 | ||
1254 | ret += sprintf(buf+ret, "Service type: "); | 1254 | seq_puts(m, "Service type: "); |
1255 | if (self->service_type & IRCOMM_9_WIRE) | 1255 | if (self->service_type & IRCOMM_9_WIRE) |
1256 | ret += sprintf(buf+ret, "9_WIRE"); | 1256 | seq_puts(m, "9_WIRE"); |
1257 | else if (self->service_type & IRCOMM_3_WIRE) | 1257 | else if (self->service_type & IRCOMM_3_WIRE) |
1258 | ret += sprintf(buf+ret, "3_WIRE"); | 1258 | seq_puts(m, "3_WIRE"); |
1259 | else if (self->service_type & IRCOMM_3_WIRE_RAW) | 1259 | else if (self->service_type & IRCOMM_3_WIRE_RAW) |
1260 | ret += sprintf(buf+ret, "3_WIRE_RAW"); | 1260 | seq_puts(m, "3_WIRE_RAW"); |
1261 | else | 1261 | else |
1262 | ret += sprintf(buf+ret, "No common service type!\n"); | 1262 | seq_puts(m, "No common service type!\n"); |
1263 | ret += sprintf(buf+ret, "\n"); | 1263 | seq_putc(m, '\n'); |
1264 | 1264 | ||
1265 | ret += sprintf(buf+ret, "Port name: %s\n", self->settings.port_name); | 1265 | seq_printf(m, "Port name: %s\n", self->settings.port_name); |
1266 | 1266 | ||
1267 | ret += sprintf(buf+ret, "DTE status: "); | 1267 | seq_printf(m, "DTE status:"); |
1268 | if (self->settings.dte & IRCOMM_RTS) | 1268 | sep = ' '; |
1269 | ret += sprintf(buf+ret, "RTS|"); | 1269 | if (self->settings.dte & IRCOMM_RTS) { |
1270 | if (self->settings.dte & IRCOMM_DTR) | 1270 | seq_printf(m, "%cRTS", sep); |
1271 | ret += sprintf(buf+ret, "DTR|"); | 1271 | sep = '|'; |
1272 | if (self->settings.dte) | 1272 | } |
1273 | ret--; /* remove the last | */ | 1273 | if (self->settings.dte & IRCOMM_DTR) { |
1274 | ret += sprintf(buf+ret, "\n"); | 1274 | seq_printf(m, "%cDTR", sep); |
1275 | 1275 | sep = '|'; | |
1276 | ret += sprintf(buf+ret, "DCE status: "); | 1276 | } |
1277 | if (self->settings.dce & IRCOMM_CTS) | 1277 | seq_putc(m, '\n'); |
1278 | ret += sprintf(buf+ret, "CTS|"); | 1278 | |
1279 | if (self->settings.dce & IRCOMM_DSR) | 1279 | seq_puts(m, "DCE status:"); |
1280 | ret += sprintf(buf+ret, "DSR|"); | 1280 | sep = ' '; |
1281 | if (self->settings.dce & IRCOMM_CD) | 1281 | if (self->settings.dce & IRCOMM_CTS) { |
1282 | ret += sprintf(buf+ret, "CD|"); | 1282 | seq_printf(m, "%cCTS", sep); |
1283 | if (self->settings.dce & IRCOMM_RI) | 1283 | sep = '|'; |
1284 | ret += sprintf(buf+ret, "RI|"); | 1284 | } |
1285 | if (self->settings.dce) | 1285 | if (self->settings.dce & IRCOMM_DSR) { |
1286 | ret--; /* remove the last | */ | 1286 | seq_printf(m, "%cDSR", sep); |
1287 | ret += sprintf(buf+ret, "\n"); | 1287 | sep = '|'; |
1288 | 1288 | } | |
1289 | ret += sprintf(buf+ret, "Configuration: "); | 1289 | if (self->settings.dce & IRCOMM_CD) { |
1290 | seq_printf(m, "%cCD", sep); | ||
1291 | sep = '|'; | ||
1292 | } | ||
1293 | if (self->settings.dce & IRCOMM_RI) { | ||
1294 | seq_printf(m, "%cRI", sep); | ||
1295 | sep = '|'; | ||
1296 | } | ||
1297 | seq_putc(m, '\n'); | ||
1298 | |||
1299 | seq_puts(m, "Configuration: "); | ||
1290 | if (!self->settings.null_modem) | 1300 | if (!self->settings.null_modem) |
1291 | ret += sprintf(buf+ret, "DTE <-> DCE\n"); | 1301 | seq_puts(m, "DTE <-> DCE\n"); |
1292 | else | 1302 | else |
1293 | ret += sprintf(buf+ret, | 1303 | seq_puts(m, "DTE <-> DTE (null modem emulation)\n"); |
1294 | "DTE <-> DTE (null modem emulation)\n"); | 1304 | |
1295 | 1305 | seq_printf(m, "Data rate: %d\n", self->settings.data_rate); | |
1296 | ret += sprintf(buf+ret, "Data rate: %d\n", self->settings.data_rate); | 1306 | |
1297 | 1307 | seq_puts(m, "Flow control:"); | |
1298 | ret += sprintf(buf+ret, "Flow control: "); | 1308 | sep = ' '; |
1299 | if (self->settings.flow_control & IRCOMM_XON_XOFF_IN) | 1309 | if (self->settings.flow_control & IRCOMM_XON_XOFF_IN) { |
1300 | ret += sprintf(buf+ret, "XON_XOFF_IN|"); | 1310 | seq_printf(m, "%cXON_XOFF_IN", sep); |
1301 | if (self->settings.flow_control & IRCOMM_XON_XOFF_OUT) | 1311 | sep = '|'; |
1302 | ret += sprintf(buf+ret, "XON_XOFF_OUT|"); | 1312 | } |
1303 | if (self->settings.flow_control & IRCOMM_RTS_CTS_IN) | 1313 | if (self->settings.flow_control & IRCOMM_XON_XOFF_OUT) { |
1304 | ret += sprintf(buf+ret, "RTS_CTS_IN|"); | 1314 | seq_printf(m, "%cXON_XOFF_OUT", sep); |
1305 | if (self->settings.flow_control & IRCOMM_RTS_CTS_OUT) | 1315 | sep = '|'; |
1306 | ret += sprintf(buf+ret, "RTS_CTS_OUT|"); | 1316 | } |
1307 | if (self->settings.flow_control & IRCOMM_DSR_DTR_IN) | 1317 | if (self->settings.flow_control & IRCOMM_RTS_CTS_IN) { |
1308 | ret += sprintf(buf+ret, "DSR_DTR_IN|"); | 1318 | seq_printf(m, "%cRTS_CTS_IN", sep); |
1309 | if (self->settings.flow_control & IRCOMM_DSR_DTR_OUT) | 1319 | sep = '|'; |
1310 | ret += sprintf(buf+ret, "DSR_DTR_OUT|"); | 1320 | } |
1311 | if (self->settings.flow_control & IRCOMM_ENQ_ACK_IN) | 1321 | if (self->settings.flow_control & IRCOMM_RTS_CTS_OUT) { |
1312 | ret += sprintf(buf+ret, "ENQ_ACK_IN|"); | 1322 | seq_printf(m, "%cRTS_CTS_OUT", sep); |
1313 | if (self->settings.flow_control & IRCOMM_ENQ_ACK_OUT) | 1323 | sep = '|'; |
1314 | ret += sprintf(buf+ret, "ENQ_ACK_OUT|"); | 1324 | } |
1315 | if (self->settings.flow_control) | 1325 | if (self->settings.flow_control & IRCOMM_DSR_DTR_IN) { |
1316 | ret--; /* remove the last | */ | 1326 | seq_printf(m, "%cDSR_DTR_IN", sep); |
1317 | ret += sprintf(buf+ret, "\n"); | 1327 | sep = '|'; |
1318 | 1328 | } | |
1319 | ret += sprintf(buf+ret, "Flags: "); | 1329 | if (self->settings.flow_control & IRCOMM_DSR_DTR_OUT) { |
1320 | if (self->flags & ASYNC_CTS_FLOW) | 1330 | seq_printf(m, "%cDSR_DTR_OUT", sep); |
1321 | ret += sprintf(buf+ret, "ASYNC_CTS_FLOW|"); | 1331 | sep = '|'; |
1322 | if (self->flags & ASYNC_CHECK_CD) | 1332 | } |
1323 | ret += sprintf(buf+ret, "ASYNC_CHECK_CD|"); | 1333 | if (self->settings.flow_control & IRCOMM_ENQ_ACK_IN) { |
1324 | if (self->flags & ASYNC_INITIALIZED) | 1334 | seq_printf(m, "%cENQ_ACK_IN", sep); |
1325 | ret += sprintf(buf+ret, "ASYNC_INITIALIZED|"); | 1335 | sep = '|'; |
1326 | if (self->flags & ASYNC_LOW_LATENCY) | 1336 | } |
1327 | ret += sprintf(buf+ret, "ASYNC_LOW_LATENCY|"); | 1337 | if (self->settings.flow_control & IRCOMM_ENQ_ACK_OUT) { |
1328 | if (self->flags & ASYNC_CLOSING) | 1338 | seq_printf(m, "%cENQ_ACK_OUT", sep); |
1329 | ret += sprintf(buf+ret, "ASYNC_CLOSING|"); | 1339 | sep = '|'; |
1330 | if (self->flags & ASYNC_NORMAL_ACTIVE) | 1340 | } |
1331 | ret += sprintf(buf+ret, "ASYNC_NORMAL_ACTIVE|"); | 1341 | seq_putc(m, '\n'); |
1332 | if (self->flags) | 1342 | |
1333 | ret--; /* remove the last | */ | 1343 | seq_puts(m, "Flags:"); |
1334 | ret += sprintf(buf+ret, "\n"); | 1344 | sep = ' '; |
1335 | 1345 | if (self->flags & ASYNC_CTS_FLOW) { | |
1336 | ret += sprintf(buf+ret, "Role: %s\n", self->client ? | 1346 | seq_printf(m, "%cASYNC_CTS_FLOW", sep); |
1337 | "client" : "server"); | 1347 | sep = '|'; |
1338 | ret += sprintf(buf+ret, "Open count: %d\n", self->open_count); | 1348 | } |
1339 | ret += sprintf(buf+ret, "Max data size: %d\n", self->max_data_size); | 1349 | if (self->flags & ASYNC_CHECK_CD) { |
1340 | ret += sprintf(buf+ret, "Max header size: %d\n", self->max_header_size); | 1350 | seq_printf(m, "%cASYNC_CHECK_CD", sep); |
1351 | sep = '|'; | ||
1352 | } | ||
1353 | if (self->flags & ASYNC_INITIALIZED) { | ||
1354 | seq_printf(m, "%cASYNC_INITIALIZED", sep); | ||
1355 | sep = '|'; | ||
1356 | } | ||
1357 | if (self->flags & ASYNC_LOW_LATENCY) { | ||
1358 | seq_printf(m, "%cASYNC_LOW_LATENCY", sep); | ||
1359 | sep = '|'; | ||
1360 | } | ||
1361 | if (self->flags & ASYNC_CLOSING) { | ||
1362 | seq_printf(m, "%cASYNC_CLOSING", sep); | ||
1363 | sep = '|'; | ||
1364 | } | ||
1365 | if (self->flags & ASYNC_NORMAL_ACTIVE) { | ||
1366 | seq_printf(m, "%cASYNC_NORMAL_ACTIVE", sep); | ||
1367 | sep = '|'; | ||
1368 | } | ||
1369 | seq_putc(m, '\n'); | ||
1370 | |||
1371 | seq_printf(m, "Role: %s\n", self->client ? "client" : "server"); | ||
1372 | seq_printf(m, "Open count: %d\n", self->open_count); | ||
1373 | seq_printf(m, "Max data size: %d\n", self->max_data_size); | ||
1374 | seq_printf(m, "Max header size: %d\n", self->max_header_size); | ||
1341 | 1375 | ||
1342 | if (self->tty) | 1376 | if (self->tty) |
1343 | ret += sprintf(buf+ret, "Hardware: %s\n", | 1377 | seq_printf(m, "Hardware: %s\n", |
1344 | self->tty->hw_stopped ? "Stopped" : "Running"); | 1378 | self->tty->hw_stopped ? "Stopped" : "Running"); |
1345 | |||
1346 | ret += sprintf(buf+ret, "\n"); | ||
1347 | return ret; | ||
1348 | } | 1379 | } |
1349 | 1380 | ||
1350 | 1381 | static int ircomm_tty_proc_show(struct seq_file *m, void *v) | |
1351 | /* | ||
1352 | * Function ircomm_tty_read_proc (buf, start, offset, len, eof, unused) | ||
1353 | * | ||
1354 | * | ||
1355 | * | ||
1356 | */ | ||
1357 | static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len, | ||
1358 | int *eof, void *unused) | ||
1359 | { | 1382 | { |
1360 | struct ircomm_tty_cb *self; | 1383 | struct ircomm_tty_cb *self; |
1361 | int count = 0, l; | ||
1362 | off_t begin = 0; | ||
1363 | unsigned long flags; | 1384 | unsigned long flags; |
1364 | 1385 | ||
1365 | spin_lock_irqsave(&ircomm_tty->hb_spinlock, flags); | 1386 | spin_lock_irqsave(&ircomm_tty->hb_spinlock, flags); |
1366 | 1387 | ||
1367 | self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty); | 1388 | self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty); |
1368 | while ((self != NULL) && (count < 4000)) { | 1389 | while (self != NULL) { |
1369 | if (self->magic != IRCOMM_TTY_MAGIC) | 1390 | if (self->magic != IRCOMM_TTY_MAGIC) |
1370 | break; | 1391 | break; |
1371 | 1392 | ||
1372 | l = ircomm_tty_line_info(self, buf + count); | 1393 | ircomm_tty_line_info(self, m); |
1373 | count += l; | ||
1374 | if (count+begin > offset+len) | ||
1375 | goto done; | ||
1376 | if (count+begin < offset) { | ||
1377 | begin += count; | ||
1378 | count = 0; | ||
1379 | } | ||
1380 | |||
1381 | self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty); | 1394 | self = (struct ircomm_tty_cb *) hashbin_get_next(ircomm_tty); |
1382 | } | 1395 | } |
1383 | *eof = 1; | ||
1384 | done: | ||
1385 | spin_unlock_irqrestore(&ircomm_tty->hb_spinlock, flags); | 1396 | spin_unlock_irqrestore(&ircomm_tty->hb_spinlock, flags); |
1397 | return 0; | ||
1398 | } | ||
1386 | 1399 | ||
1387 | if (offset >= count+begin) | 1400 | static int ircomm_tty_proc_open(struct inode *inode, struct file *file) |
1388 | return 0; | 1401 | { |
1389 | *start = buf + (offset-begin); | 1402 | return single_open(file, ircomm_tty_proc_show, NULL); |
1390 | return ((len < begin+count-offset) ? len : begin+count-offset); | ||
1391 | } | 1403 | } |
1404 | |||
1405 | static const struct file_operations ircomm_tty_proc_fops = { | ||
1406 | .owner = THIS_MODULE, | ||
1407 | .open = ircomm_tty_proc_open, | ||
1408 | .read = seq_read, | ||
1409 | .llseek = seq_lseek, | ||
1410 | .release = single_release, | ||
1411 | }; | ||
1392 | #endif /* CONFIG_PROC_FS */ | 1412 | #endif /* CONFIG_PROC_FS */ |
1393 | 1413 | ||
1394 | MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); | 1414 | MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); |