diff options
429 files changed, 11643 insertions, 6363 deletions
@@ -2211,6 +2211,15 @@ D: OV511 driver | |||
2211 | S: (address available on request) | 2211 | S: (address available on request) |
2212 | S: USA | 2212 | S: USA |
2213 | 2213 | ||
2214 | N: Ian McDonald | ||
2215 | E: iam4@cs.waikato.ac.nz | ||
2216 | E: imcdnzl@gmail.com | ||
2217 | W: http://wand.net.nz/~iam4 | ||
2218 | W: http://imcdnzl.blogspot.com | ||
2219 | D: DCCP, CCID3 | ||
2220 | S: Hamilton | ||
2221 | S: New Zealand | ||
2222 | |||
2214 | N: Patrick McHardy | 2223 | N: Patrick McHardy |
2215 | E: kaber@trash.net | 2224 | E: kaber@trash.net |
2216 | P: 1024D/12155E80 B128 7DE6 FF0A C2B2 48BE AB4C C9D4 964E 1215 5E80 | 2225 | P: 1024D/12155E80 B128 7DE6 FF0A C2B2 48BE AB4C C9D4 964E 1215 5E80 |
@@ -2246,19 +2255,12 @@ S: D-90453 Nuernberg | |||
2246 | S: Germany | 2255 | S: Germany |
2247 | 2256 | ||
2248 | N: Arnaldo Carvalho de Melo | 2257 | N: Arnaldo Carvalho de Melo |
2249 | E: acme@conectiva.com.br | 2258 | E: acme@mandriva.com |
2250 | E: acme@kernel.org | 2259 | E: acme@ghostprotocols.net |
2251 | E: acme@gnu.org | 2260 | W: http://oops.ghostprotocols.net:81/blog/ |
2252 | W: http://bazar2.conectiva.com.br/~acme | ||
2253 | W: http://advogato.org/person/acme | ||
2254 | P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD 841A B6AB 4681 9224 DF01 | 2261 | P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD 841A B6AB 4681 9224 DF01 |
2255 | D: wanrouter hacking | 2262 | D: IPX, LLC, DCCP, cyc2x, wl3501_cs, net/ hacks |
2256 | D: misc Makefile, Config.in, drivers and network stacks fixes | 2263 | S: Mandriva |
2257 | D: IPX & LLC network stacks maintainer | ||
2258 | D: Cyclom 2X synchronous card driver | ||
2259 | D: wl3501 PCMCIA wireless card driver | ||
2260 | D: i18n for minicom, net-tools, util-linux, fetchmail, etc | ||
2261 | S: Conectiva S.A. | ||
2262 | S: R. Tocantins, 89 - Cristo Rei | 2264 | S: R. Tocantins, 89 - Cristo Rei |
2263 | S: 80050-430 - Curitiba - Paraná | 2265 | S: 80050-430 - Curitiba - Paraná |
2264 | S: Brazil | 2266 | S: Brazil |
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle index 22e5f9036f3c..eb7db3c19227 100644 --- a/Documentation/CodingStyle +++ b/Documentation/CodingStyle | |||
@@ -410,7 +410,26 @@ Kernel messages do not have to be terminated with a period. | |||
410 | Printing numbers in parentheses (%d) adds no value and should be avoided. | 410 | Printing numbers in parentheses (%d) adds no value and should be avoided. |
411 | 411 | ||
412 | 412 | ||
413 | Chapter 13: References | 413 | Chapter 13: Allocating memory |
414 | |||
415 | The kernel provides the following general purpose memory allocators: | ||
416 | kmalloc(), kzalloc(), kcalloc(), and vmalloc(). Please refer to the API | ||
417 | documentation for further information about them. | ||
418 | |||
419 | The preferred form for passing a size of a struct is the following: | ||
420 | |||
421 | p = kmalloc(sizeof(*p), ...); | ||
422 | |||
423 | The alternative form where struct name is spelled out hurts readability and | ||
424 | introduces an opportunity for a bug when the pointer variable type is changed | ||
425 | but the corresponding sizeof that is passed to a memory allocator is not. | ||
426 | |||
427 | Casting the return value which is a void pointer is redundant. The conversion | ||
428 | from void pointer to any other pointer type is guaranteed by the C programming | ||
429 | language. | ||
430 | |||
431 | |||
432 | Chapter 14: References | ||
414 | 433 | ||
415 | The C Programming Language, Second Edition | 434 | The C Programming Language, Second Edition |
416 | by Brian W. Kernighan and Dennis M. Ritchie. | 435 | by Brian W. Kernighan and Dennis M. Ritchie. |
diff --git a/Documentation/DocBook/kernel-hacking.tmpl b/Documentation/DocBook/kernel-hacking.tmpl index 6367bba32d22..582032eea872 100644 --- a/Documentation/DocBook/kernel-hacking.tmpl +++ b/Documentation/DocBook/kernel-hacking.tmpl | |||
@@ -1105,7 +1105,7 @@ static struct block_device_operations opt_fops = { | |||
1105 | </listitem> | 1105 | </listitem> |
1106 | <listitem> | 1106 | <listitem> |
1107 | <para> | 1107 | <para> |
1108 | Function names as strings (__func__). | 1108 | Function names as strings (__FUNCTION__). |
1109 | </para> | 1109 | </para> |
1110 | </listitem> | 1110 | </listitem> |
1111 | <listitem> | 1111 | <listitem> |
diff --git a/Documentation/dell_rbu.txt b/Documentation/dell_rbu.txt index bcfa5c35036b..95d7f62e4dbc 100644 --- a/Documentation/dell_rbu.txt +++ b/Documentation/dell_rbu.txt | |||
@@ -13,6 +13,8 @@ the BIOS on Dell servers (starting from servers sold since 1999), desktops | |||
13 | and notebooks (starting from those sold in 2005). | 13 | and notebooks (starting from those sold in 2005). |
14 | Please go to http://support.dell.com register and you can find info on | 14 | Please go to http://support.dell.com register and you can find info on |
15 | OpenManage and Dell Update packages (DUP). | 15 | OpenManage and Dell Update packages (DUP). |
16 | Libsmbios can also be used to update BIOS on Dell systems go to | ||
17 | http://linux.dell.com/libsmbios/ for details. | ||
16 | 18 | ||
17 | Dell_RBU driver supports BIOS update using the monilothic image and packetized | 19 | Dell_RBU driver supports BIOS update using the monilothic image and packetized |
18 | image methods. In case of moniolithic the driver allocates a contiguous chunk | 20 | image methods. In case of moniolithic the driver allocates a contiguous chunk |
@@ -22,8 +24,8 @@ would place each packet in contiguous physical memory. The driver also | |||
22 | maintains a link list of packets for reading them back. | 24 | maintains a link list of packets for reading them back. |
23 | If the dell_rbu driver is unloaded all the allocated memory is freed. | 25 | If the dell_rbu driver is unloaded all the allocated memory is freed. |
24 | 26 | ||
25 | The rbu driver needs to have an application which will inform the BIOS to | 27 | The rbu driver needs to have an application (as mentioned above)which will |
26 | enable the update in the next system reboot. | 28 | inform the BIOS to enable the update in the next system reboot. |
27 | 29 | ||
28 | The user should not unload the rbu driver after downloading the BIOS image | 30 | The user should not unload the rbu driver after downloading the BIOS image |
29 | or updating. | 31 | or updating. |
@@ -42,9 +44,11 @@ In case of packet mechanism the single memory can be broken in smaller chuks | |||
42 | of contiguous memory and the BIOS image is scattered in these packets. | 44 | of contiguous memory and the BIOS image is scattered in these packets. |
43 | 45 | ||
44 | By default the driver uses monolithic memory for the update type. This can be | 46 | By default the driver uses monolithic memory for the update type. This can be |
45 | changed to contiguous during the driver load time by specifying the load | 47 | changed to packets during the driver load time by specifying the load |
46 | parameter image_type=packet. This can also be changed later as below | 48 | parameter image_type=packet. This can also be changed later as below |
47 | echo packet > /sys/devices/platform/dell_rbu/image_type | 49 | echo packet > /sys/devices/platform/dell_rbu/image_type |
50 | Also echoing either mono ,packet or init in to image_type will free up the | ||
51 | memory allocated by the driver. | ||
48 | 52 | ||
49 | Do the steps below to download the BIOS image. | 53 | Do the steps below to download the BIOS image. |
50 | 1) echo 1 > /sys/class/firmware/dell_rbu/loading | 54 | 1) echo 1 > /sys/class/firmware/dell_rbu/loading |
@@ -53,9 +57,13 @@ Do the steps below to download the BIOS image. | |||
53 | 57 | ||
54 | The /sys/class/firmware/dell_rbu/ entries will remain till the following is | 58 | The /sys/class/firmware/dell_rbu/ entries will remain till the following is |
55 | done. | 59 | done. |
56 | echo -1 > /sys/class/firmware/dell_rbu/loading | 60 | echo -1 > /sys/class/firmware/dell_rbu/loading. |
57 | |||
58 | Until this step is completed the drivr cannot be unloaded. | 61 | Until this step is completed the drivr cannot be unloaded. |
62 | If an user by accident executes steps 1 and 3 above without executing step 2; | ||
63 | it will make the /sys/class/firmware/dell_rbu/ entries to disappear. | ||
64 | The entries can be recreated by doing the following | ||
65 | echo init > /sys/devices/platform/dell_rbu/image_type | ||
66 | NOTE: echoing init in image_type does not change it original value. | ||
59 | 67 | ||
60 | Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to | 68 | Also the driver provides /sys/devices/platform/dell_rbu/data readonly file to |
61 | read back the image downloaded. This is useful in case of packet update | 69 | read back the image downloaded. This is useful in case of packet update |
diff --git a/Documentation/filesystems/relayfs.txt b/Documentation/filesystems/relayfs.txt index d24e1b0d4f39..d803abed29f0 100644 --- a/Documentation/filesystems/relayfs.txt +++ b/Documentation/filesystems/relayfs.txt | |||
@@ -15,7 +15,7 @@ retrieve the data as it becomes available. | |||
15 | 15 | ||
16 | The format of the data logged into the channel buffers is completely | 16 | The format of the data logged into the channel buffers is completely |
17 | up to the relayfs client; relayfs does however provide hooks which | 17 | up to the relayfs client; relayfs does however provide hooks which |
18 | allow clients to impose some stucture on the buffer data. Nor does | 18 | allow clients to impose some structure on the buffer data. Nor does |
19 | relayfs implement any form of data filtering - this also is left to | 19 | relayfs implement any form of data filtering - this also is left to |
20 | the client. The purpose is to keep relayfs as simple as possible. | 20 | the client. The purpose is to keep relayfs as simple as possible. |
21 | 21 | ||
diff --git a/Documentation/ia64/mca.txt b/Documentation/ia64/mca.txt new file mode 100644 index 000000000000..a71cc6a67ef7 --- /dev/null +++ b/Documentation/ia64/mca.txt | |||
@@ -0,0 +1,194 @@ | |||
1 | An ad-hoc collection of notes on IA64 MCA and INIT processing. Feel | ||
2 | free to update it with notes about any area that is not clear. | ||
3 | |||
4 | --- | ||
5 | |||
6 | MCA/INIT are completely asynchronous. They can occur at any time, when | ||
7 | the OS is in any state. Including when one of the cpus is already | ||
8 | holding a spinlock. Trying to get any lock from MCA/INIT state is | ||
9 | asking for deadlock. Also the state of structures that are protected | ||
10 | by locks is indeterminate, including linked lists. | ||
11 | |||
12 | --- | ||
13 | |||
14 | The complicated ia64 MCA process. All of this is mandated by Intel's | ||
15 | specification for ia64 SAL, error recovery and and unwind, it is not as | ||
16 | if we have a choice here. | ||
17 | |||
18 | * MCA occurs on one cpu, usually due to a double bit memory error. | ||
19 | This is the monarch cpu. | ||
20 | |||
21 | * SAL sends an MCA rendezvous interrupt (which is a normal interrupt) | ||
22 | to all the other cpus, the slaves. | ||
23 | |||
24 | * Slave cpus that receive the MCA interrupt call down into SAL, they | ||
25 | end up spinning disabled while the MCA is being serviced. | ||
26 | |||
27 | * If any slave cpu was already spinning disabled when the MCA occurred | ||
28 | then it cannot service the MCA interrupt. SAL waits ~20 seconds then | ||
29 | sends an unmaskable INIT event to the slave cpus that have not | ||
30 | already rendezvoused. | ||
31 | |||
32 | * Because MCA/INIT can be delivered at any time, including when the cpu | ||
33 | is down in PAL in physical mode, the registers at the time of the | ||
34 | event are _completely_ undefined. In particular the MCA/INIT | ||
35 | handlers cannot rely on the thread pointer, PAL physical mode can | ||
36 | (and does) modify TP. It is allowed to do that as long as it resets | ||
37 | TP on return. However MCA/INIT events expose us to these PAL | ||
38 | internal TP changes. Hence curr_task(). | ||
39 | |||
40 | * If an MCA/INIT event occurs while the kernel was running (not user | ||
41 | space) and the kernel has called PAL then the MCA/INIT handler cannot | ||
42 | assume that the kernel stack is in a fit state to be used. Mainly | ||
43 | because PAL may or may not maintain the stack pointer internally. | ||
44 | Because the MCA/INIT handlers cannot trust the kernel stack, they | ||
45 | have to use their own, per-cpu stacks. The MCA/INIT stacks are | ||
46 | preformatted with just enough task state to let the relevant handlers | ||
47 | do their job. | ||
48 | |||
49 | * Unlike most other architectures, the ia64 struct task is embedded in | ||
50 | the kernel stack[1]. So switching to a new kernel stack means that | ||
51 | we switch to a new task as well. Because various bits of the kernel | ||
52 | assume that current points into the struct task, switching to a new | ||
53 | stack also means a new value for current. | ||
54 | |||
55 | * Once all slaves have rendezvoused and are spinning disabled, the | ||
56 | monarch is entered. The monarch now tries to diagnose the problem | ||
57 | and decide if it can recover or not. | ||
58 | |||
59 | * Part of the monarch's job is to look at the state of all the other | ||
60 | tasks. The only way to do that on ia64 is to call the unwinder, | ||
61 | as mandated by Intel. | ||
62 | |||
63 | * The starting point for the unwind depends on whether a task is | ||
64 | running or not. That is, whether it is on a cpu or is blocked. The | ||
65 | monarch has to determine whether or not a task is on a cpu before it | ||
66 | knows how to start unwinding it. The tasks that received an MCA or | ||
67 | INIT event are no longer running, they have been converted to blocked | ||
68 | tasks. But (and its a big but), the cpus that received the MCA | ||
69 | rendezvous interrupt are still running on their normal kernel stacks! | ||
70 | |||
71 | * To distinguish between these two cases, the monarch must know which | ||
72 | tasks are on a cpu and which are not. Hence each slave cpu that | ||
73 | switches to an MCA/INIT stack, registers its new stack using | ||
74 | set_curr_task(), so the monarch can tell that the _original_ task is | ||
75 | no longer running on that cpu. That gives us a decent chance of | ||
76 | getting a valid backtrace of the _original_ task. | ||
77 | |||
78 | * MCA/INIT can be nested, to a depth of 2 on any cpu. In the case of a | ||
79 | nested error, we want diagnostics on the MCA/INIT handler that | ||
80 | failed, not on the task that was originally running. Again this | ||
81 | requires set_curr_task() so the MCA/INIT handlers can register their | ||
82 | own stack as running on that cpu. Then a recursive error gets a | ||
83 | trace of the failing handler's "task". | ||
84 | |||
85 | [1] My (Keith Owens) original design called for ia64 to separate its | ||
86 | struct task and the kernel stacks. Then the MCA/INIT data would be | ||
87 | chained stacks like i386 interrupt stacks. But that required | ||
88 | radical surgery on the rest of ia64, plus extra hard wired TLB | ||
89 | entries with its associated performance degradation. David | ||
90 | Mosberger vetoed that approach. Which meant that separate kernel | ||
91 | stacks meant separate "tasks" for the MCA/INIT handlers. | ||
92 | |||
93 | --- | ||
94 | |||
95 | INIT is less complicated than MCA. Pressing the nmi button or using | ||
96 | the equivalent command on the management console sends INIT to all | ||
97 | cpus. SAL picks one one of the cpus as the monarch and the rest are | ||
98 | slaves. All the OS INIT handlers are entered at approximately the same | ||
99 | time. The OS monarch prints the state of all tasks and returns, after | ||
100 | which the slaves return and the system resumes. | ||
101 | |||
102 | At least that is what is supposed to happen. Alas there are broken | ||
103 | versions of SAL out there. Some drive all the cpus as monarchs. Some | ||
104 | drive them all as slaves. Some drive one cpu as monarch, wait for that | ||
105 | cpu to return from the OS then drive the rest as slaves. Some versions | ||
106 | of SAL cannot even cope with returning from the OS, they spin inside | ||
107 | SAL on resume. The OS INIT code has workarounds for some of these | ||
108 | broken SAL symptoms, but some simply cannot be fixed from the OS side. | ||
109 | |||
110 | --- | ||
111 | |||
112 | The scheduler hooks used by ia64 (curr_task, set_curr_task) are layer | ||
113 | violations. Unfortunately MCA/INIT start off as massive layer | ||
114 | violations (can occur at _any_ time) and they build from there. | ||
115 | |||
116 | At least ia64 makes an attempt at recovering from hardware errors, but | ||
117 | it is a difficult problem because of the asynchronous nature of these | ||
118 | errors. When processing an unmaskable interrupt we sometimes need | ||
119 | special code to cope with our inability to take any locks. | ||
120 | |||
121 | --- | ||
122 | |||
123 | How is ia64 MCA/INIT different from x86 NMI? | ||
124 | |||
125 | * x86 NMI typically gets delivered to one cpu. MCA/INIT gets sent to | ||
126 | all cpus. | ||
127 | |||
128 | * x86 NMI cannot be nested. MCA/INIT can be nested, to a depth of 2 | ||
129 | per cpu. | ||
130 | |||
131 | * x86 has a separate struct task which points to one of multiple kernel | ||
132 | stacks. ia64 has the struct task embedded in the single kernel | ||
133 | stack, so switching stack means switching task. | ||
134 | |||
135 | * x86 does not call the BIOS so the NMI handler does not have to worry | ||
136 | about any registers having changed. MCA/INIT can occur while the cpu | ||
137 | is in PAL in physical mode, with undefined registers and an undefined | ||
138 | kernel stack. | ||
139 | |||
140 | * i386 backtrace is not very sensitive to whether a process is running | ||
141 | or not. ia64 unwind is very, very sensitive to whether a process is | ||
142 | running or not. | ||
143 | |||
144 | --- | ||
145 | |||
146 | What happens when MCA/INIT is delivered what a cpu is running user | ||
147 | space code? | ||
148 | |||
149 | The user mode registers are stored in the RSE area of the MCA/INIT on | ||
150 | entry to the OS and are restored from there on return to SAL, so user | ||
151 | mode registers are preserved across a recoverable MCA/INIT. Since the | ||
152 | OS has no idea what unwind data is available for the user space stack, | ||
153 | MCA/INIT never tries to backtrace user space. Which means that the OS | ||
154 | does not bother making the user space process look like a blocked task, | ||
155 | i.e. the OS does not copy pt_regs and switch_stack to the user space | ||
156 | stack. Also the OS has no idea how big the user space RSE and memory | ||
157 | stacks are, which makes it too risky to copy the saved state to a user | ||
158 | mode stack. | ||
159 | |||
160 | --- | ||
161 | |||
162 | How do we get a backtrace on the tasks that were running when MCA/INIT | ||
163 | was delivered? | ||
164 | |||
165 | mca.c:::ia64_mca_modify_original_stack(). That identifies and | ||
166 | verifies the original kernel stack, copies the dirty registers from | ||
167 | the MCA/INIT stack's RSE to the original stack's RSE, copies the | ||
168 | skeleton struct pt_regs and switch_stack to the original stack, fills | ||
169 | in the skeleton structures from the PAL minstate area and updates the | ||
170 | original stack's thread.ksp. That makes the original stack look | ||
171 | exactly like any other blocked task, i.e. it now appears to be | ||
172 | sleeping. To get a backtrace, just start with thread.ksp for the | ||
173 | original task and unwind like any other sleeping task. | ||
174 | |||
175 | --- | ||
176 | |||
177 | How do we identify the tasks that were running when MCA/INIT was | ||
178 | delivered? | ||
179 | |||
180 | If the previous task has been verified and converted to a blocked | ||
181 | state, then sos->prev_task on the MCA/INIT stack is updated to point to | ||
182 | the previous task. You can look at that field in dumps or debuggers. | ||
183 | To help distinguish between the handler and the original tasks, | ||
184 | handlers have _TIF_MCA_INIT set in thread_info.flags. | ||
185 | |||
186 | The sos data is always in the MCA/INIT handler stack, at offset | ||
187 | MCA_SOS_OFFSET. You can get that value from mca_asm.h or calculate it | ||
188 | as KERNEL_STACK_SIZE - sizeof(struct pt_regs) - sizeof(struct | ||
189 | ia64_sal_os_state), with 16 byte alignment for all structures. | ||
190 | |||
191 | Also the comm field of the MCA/INIT task is modified to include the pid | ||
192 | of the original task, for humans to use. For example, a comm field of | ||
193 | 'MCA 12159' means that pid 12159 was running when the MCA was | ||
194 | delivered. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index d1e0eb46d201..ade7415d2467 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -686,6 +686,13 @@ P: Guennadi Liakhovetski | |||
686 | M: g.liakhovetski@gmx.de | 686 | M: g.liakhovetski@gmx.de |
687 | S: Maintained | 687 | S: Maintained |
688 | 688 | ||
689 | DCCP PROTOCOL | ||
690 | P: Arnaldo Carvalho de Melo | ||
691 | M: acme@mandriva.com | ||
692 | L: dccp@vger.kernel.org | ||
693 | W: http://www.wlug.org.nz/DCCP | ||
694 | S: Maintained | ||
695 | |||
689 | DECnet NETWORK LAYER | 696 | DECnet NETWORK LAYER |
690 | P: Patrick Caulfield | 697 | P: Patrick Caulfield |
691 | M: patrick@tykepenguin.com | 698 | M: patrick@tykepenguin.com |
@@ -2259,6 +2266,12 @@ M: kristen.c.accardi@intel.com | |||
2259 | L: pcihpd-discuss@lists.sourceforge.net | 2266 | L: pcihpd-discuss@lists.sourceforge.net |
2260 | S: Maintained | 2267 | S: Maintained |
2261 | 2268 | ||
2269 | SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS | ||
2270 | P: Stephen Hemminger | ||
2271 | M: shemminger@osdl.org | ||
2272 | L: netdev@vger.kernel.org | ||
2273 | S: Maintained | ||
2274 | |||
2262 | SPARC (sparc32): | 2275 | SPARC (sparc32): |
2263 | P: William L. Irwin | 2276 | P: William L. Irwin |
2264 | M: wli@holomorphy.com | 2277 | M: wli@holomorphy.com |
@@ -2271,12 +2284,6 @@ M: R.E.Wolff@BitWizard.nl | |||
2271 | L: linux-kernel@vger.kernel.org ? | 2284 | L: linux-kernel@vger.kernel.org ? |
2272 | S: Supported | 2285 | S: Supported |
2273 | 2286 | ||
2274 | SPX NETWORK LAYER | ||
2275 | P: Jay Schulist | ||
2276 | M: jschlst@samba.org | ||
2277 | L: netdev@vger.kernel.org | ||
2278 | S: Supported | ||
2279 | |||
2280 | SRM (Alpha) environment access | 2287 | SRM (Alpha) environment access |
2281 | P: Jan-Benedict Glaw | 2288 | P: Jan-Benedict Glaw |
2282 | M: jbglaw@lug-owl.de | 2289 | M: jbglaw@lug-owl.de |
@@ -1,7 +1,7 @@ | |||
1 | VERSION = 2 | 1 | VERSION = 2 |
2 | PATCHLEVEL = 6 | 2 | PATCHLEVEL = 6 |
3 | SUBLEVEL = 14 | 3 | SUBLEVEL = 14 |
4 | EXTRAVERSION =-rc1 | 4 | EXTRAVERSION =-rc2 |
5 | NAME=Affluent Albatross | 5 | NAME=Affluent Albatross |
6 | 6 | ||
7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
@@ -149,6 +149,9 @@ CONFIGURING the kernel: | |||
149 | "make gconfig" X windows (Gtk) based configuration tool. | 149 | "make gconfig" X windows (Gtk) based configuration tool. |
150 | "make oldconfig" Default all questions based on the contents of | 150 | "make oldconfig" Default all questions based on the contents of |
151 | your existing ./.config file. | 151 | your existing ./.config file. |
152 | "make silentoldconfig" | ||
153 | Like above, but avoids cluttering the screen | ||
154 | with question already answered. | ||
152 | 155 | ||
153 | NOTES on "make config": | 156 | NOTES on "make config": |
154 | - having unnecessary drivers will make the kernel bigger, and can | 157 | - having unnecessary drivers will make the kernel bigger, and can |
@@ -169,9 +172,6 @@ CONFIGURING the kernel: | |||
169 | should probably answer 'n' to the questions for | 172 | should probably answer 'n' to the questions for |
170 | "development", "experimental", or "debugging" features. | 173 | "development", "experimental", or "debugging" features. |
171 | 174 | ||
172 | - Check the top Makefile for further site-dependent configuration | ||
173 | (default SVGA mode etc). | ||
174 | |||
175 | COMPILING the kernel: | 175 | COMPILING the kernel: |
176 | 176 | ||
177 | - Make sure you have gcc 2.95.3 available. | 177 | - Make sure you have gcc 2.95.3 available. |
@@ -199,6 +199,9 @@ COMPILING the kernel: | |||
199 | are installing a new kernel with the same version number as your | 199 | are installing a new kernel with the same version number as your |
200 | working kernel, make a backup of your modules directory before you | 200 | working kernel, make a backup of your modules directory before you |
201 | do a "make modules_install". | 201 | do a "make modules_install". |
202 | In alternative, before compiling, edit your Makefile and change the | ||
203 | "EXTRAVERSION" line - its content is appended to the regular kernel | ||
204 | version. | ||
202 | 205 | ||
203 | - In order to boot your new kernel, you'll need to copy the kernel | 206 | - In order to boot your new kernel, you'll need to copy the kernel |
204 | image (e.g. .../linux/arch/i386/boot/bzImage after compilation) | 207 | image (e.g. .../linux/arch/i386/boot/bzImage after compilation) |
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 0636116210d2..01fe990d3e54 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/namei.h> | 37 | #include <linux/namei.h> |
38 | #include <linux/uio.h> | 38 | #include <linux/uio.h> |
39 | #include <linux/vfs.h> | 39 | #include <linux/vfs.h> |
40 | #include <linux/rcupdate.h> | ||
40 | 41 | ||
41 | #include <asm/fpu.h> | 42 | #include <asm/fpu.h> |
42 | #include <asm/io.h> | 43 | #include <asm/io.h> |
@@ -975,6 +976,7 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, | |||
975 | long timeout; | 976 | long timeout; |
976 | int ret = -EINVAL; | 977 | int ret = -EINVAL; |
977 | struct fdtable *fdt; | 978 | struct fdtable *fdt; |
979 | int max_fdset; | ||
978 | 980 | ||
979 | timeout = MAX_SCHEDULE_TIMEOUT; | 981 | timeout = MAX_SCHEDULE_TIMEOUT; |
980 | if (tvp) { | 982 | if (tvp) { |
@@ -996,8 +998,11 @@ osf_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, | |||
996 | } | 998 | } |
997 | } | 999 | } |
998 | 1000 | ||
1001 | rcu_read_lock(); | ||
999 | fdt = files_fdtable(current->files); | 1002 | fdt = files_fdtable(current->files); |
1000 | if (n < 0 || n > fdt->max_fdset) | 1003 | max_fdset = fdt->max_fdset; |
1004 | rcu_read_unlock(); | ||
1005 | if (n < 0 || n > max_fdset) | ||
1001 | goto out_nofds; | 1006 | goto out_nofds; |
1002 | 1007 | ||
1003 | /* | 1008 | /* |
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c index 9e36b07fa940..d5da6b1b28ee 100644 --- a/arch/alpha/kernel/sys_dp264.c +++ b/arch/alpha/kernel/sys_dp264.c | |||
@@ -395,6 +395,22 @@ clipper_init_irq(void) | |||
395 | */ | 395 | */ |
396 | 396 | ||
397 | static int __init | 397 | static int __init |
398 | isa_irq_fixup(struct pci_dev *dev, int irq) | ||
399 | { | ||
400 | u8 irq8; | ||
401 | |||
402 | if (irq > 0) | ||
403 | return irq; | ||
404 | |||
405 | /* This interrupt is routed via ISA bridge, so we'll | ||
406 | just have to trust whatever value the console might | ||
407 | have assigned. */ | ||
408 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq8); | ||
409 | |||
410 | return irq8 & 0xf; | ||
411 | } | ||
412 | |||
413 | static int __init | ||
398 | dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | 414 | dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin) |
399 | { | 415 | { |
400 | static char irq_tab[6][5] __initdata = { | 416 | static char irq_tab[6][5] __initdata = { |
@@ -407,25 +423,13 @@ dp264_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | |||
407 | { 16+ 3, 16+ 3, 16+ 2, 16+ 1, 16+ 0} /* IdSel 10 slot 3 */ | 423 | { 16+ 3, 16+ 3, 16+ 2, 16+ 1, 16+ 0} /* IdSel 10 slot 3 */ |
408 | }; | 424 | }; |
409 | const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5; | 425 | const long min_idsel = 5, max_idsel = 10, irqs_per_slot = 5; |
410 | |||
411 | struct pci_controller *hose = dev->sysdata; | 426 | struct pci_controller *hose = dev->sysdata; |
412 | int irq = COMMON_TABLE_LOOKUP; | 427 | int irq = COMMON_TABLE_LOOKUP; |
413 | 428 | ||
414 | if (irq > 0) { | 429 | if (irq > 0) |
415 | irq += 16 * hose->index; | 430 | irq += 16 * hose->index; |
416 | } else { | ||
417 | /* ??? The Contaq IDE controller on the ISA bridge uses | ||
418 | "legacy" interrupts 14 and 15. I don't know if anything | ||
419 | can wind up at the same slot+pin on hose1, so we'll | ||
420 | just have to trust whatever value the console might | ||
421 | have assigned. */ | ||
422 | |||
423 | u8 irq8; | ||
424 | pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq8); | ||
425 | irq = irq8; | ||
426 | } | ||
427 | 431 | ||
428 | return irq; | 432 | return isa_irq_fixup(dev, irq); |
429 | } | 433 | } |
430 | 434 | ||
431 | static int __init | 435 | static int __init |
@@ -453,7 +457,8 @@ monet_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | |||
453 | { 24, 24, 25, 26, 27} /* IdSel 15 slot 5 PCI2*/ | 457 | { 24, 24, 25, 26, 27} /* IdSel 15 slot 5 PCI2*/ |
454 | }; | 458 | }; |
455 | const long min_idsel = 3, max_idsel = 15, irqs_per_slot = 5; | 459 | const long min_idsel = 3, max_idsel = 15, irqs_per_slot = 5; |
456 | return COMMON_TABLE_LOOKUP; | 460 | |
461 | return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP); | ||
457 | } | 462 | } |
458 | 463 | ||
459 | static u8 __init | 464 | static u8 __init |
@@ -507,7 +512,8 @@ webbrick_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | |||
507 | { 47, 47, 46, 45, 44}, /* IdSel 17 slot 3 */ | 512 | { 47, 47, 46, 45, 44}, /* IdSel 17 slot 3 */ |
508 | }; | 513 | }; |
509 | const long min_idsel = 7, max_idsel = 17, irqs_per_slot = 5; | 514 | const long min_idsel = 7, max_idsel = 17, irqs_per_slot = 5; |
510 | return COMMON_TABLE_LOOKUP; | 515 | |
516 | return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP); | ||
511 | } | 517 | } |
512 | 518 | ||
513 | static int __init | 519 | static int __init |
@@ -524,14 +530,13 @@ clipper_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | |||
524 | { -1, -1, -1, -1, -1} /* IdSel 7 ISA Bridge */ | 530 | { -1, -1, -1, -1, -1} /* IdSel 7 ISA Bridge */ |
525 | }; | 531 | }; |
526 | const long min_idsel = 1, max_idsel = 7, irqs_per_slot = 5; | 532 | const long min_idsel = 1, max_idsel = 7, irqs_per_slot = 5; |
527 | |||
528 | struct pci_controller *hose = dev->sysdata; | 533 | struct pci_controller *hose = dev->sysdata; |
529 | int irq = COMMON_TABLE_LOOKUP; | 534 | int irq = COMMON_TABLE_LOOKUP; |
530 | 535 | ||
531 | if (irq > 0) | 536 | if (irq > 0) |
532 | irq += 16 * hose->index; | 537 | irq += 16 * hose->index; |
533 | 538 | ||
534 | return irq; | 539 | return isa_irq_fixup(dev, irq); |
535 | } | 540 | } |
536 | 541 | ||
537 | static void __init | 542 | static void __init |
diff --git a/arch/arm/boot/compressed/ofw-shark.c b/arch/arm/boot/compressed/ofw-shark.c index 7f6f5db0d060..465c54b6b128 100644 --- a/arch/arm/boot/compressed/ofw-shark.c +++ b/arch/arm/boot/compressed/ofw-shark.c | |||
@@ -256,5 +256,5 @@ asmlinkage void ofw_init(ofw_handle_t o, int *nomr, int *pointer) | |||
256 | temp[11]='\0'; | 256 | temp[11]='\0'; |
257 | mem_len = OF_getproplen(o,phandle, temp); | 257 | mem_len = OF_getproplen(o,phandle, temp); |
258 | OF_getprop(o,phandle, temp, buffer, mem_len); | 258 | OF_getprop(o,phandle, temp, buffer, mem_len); |
259 | (unsigned char) pointer[32] = ((unsigned char *) buffer)[mem_len-2]; | 259 | * ((unsigned char *) &pointer[32]) = ((unsigned char *) buffer)[mem_len-2]; |
260 | } | 260 | } |
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 2786f7c34b3f..a7bd85700152 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c | |||
@@ -551,7 +551,7 @@ struct locomo_save_data { | |||
551 | u16 LCM_SPIMD; | 551 | u16 LCM_SPIMD; |
552 | }; | 552 | }; |
553 | 553 | ||
554 | static int locomo_suspend(struct device *dev, u32 pm_message_t, u32 level) | 554 | static int locomo_suspend(struct device *dev, pm_message_t state, u32 level) |
555 | { | 555 | { |
556 | struct locomo *lchip = dev_get_drvdata(dev); | 556 | struct locomo *lchip = dev_get_drvdata(dev); |
557 | struct locomo_save_data *save; | 557 | struct locomo_save_data *save; |
diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig index f67ca01b4982..30e6444f9aaa 100644 --- a/arch/arm/configs/enp2611_defconfig +++ b/arch/arm/configs/enp2611_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.13-rc2 | 3 | # Linux kernel version: 2.6.13 |
4 | # Thu Jul 7 16:41:21 2005 | 4 | # Wed Sep 14 10:51:52 2005 |
5 | # | 5 | # |
6 | CONFIG_ARM=y | 6 | CONFIG_ARM=y |
7 | CONFIG_MMU=y | 7 | CONFIG_MMU=y |
@@ -135,7 +135,6 @@ CONFIG_PCI_NAMES=y | |||
135 | # | 135 | # |
136 | # Kernel Features | 136 | # Kernel Features |
137 | # | 137 | # |
138 | # CONFIG_SMP is not set | ||
139 | # CONFIG_PREEMPT is not set | 138 | # CONFIG_PREEMPT is not set |
140 | # CONFIG_NO_IDLE_HZ is not set | 139 | # CONFIG_NO_IDLE_HZ is not set |
141 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set | 140 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set |
@@ -179,6 +178,68 @@ CONFIG_BINFMT_ELF=y | |||
179 | # CONFIG_PM is not set | 178 | # CONFIG_PM is not set |
180 | 179 | ||
181 | # | 180 | # |
181 | # Networking | ||
182 | # | ||
183 | CONFIG_NET=y | ||
184 | |||
185 | # | ||
186 | # Networking options | ||
187 | # | ||
188 | CONFIG_PACKET=y | ||
189 | CONFIG_PACKET_MMAP=y | ||
190 | CONFIG_UNIX=y | ||
191 | # CONFIG_NET_KEY is not set | ||
192 | CONFIG_INET=y | ||
193 | # CONFIG_IP_MULTICAST is not set | ||
194 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
195 | CONFIG_IP_FIB_HASH=y | ||
196 | CONFIG_IP_PNP=y | ||
197 | CONFIG_IP_PNP_DHCP=y | ||
198 | CONFIG_IP_PNP_BOOTP=y | ||
199 | # CONFIG_IP_PNP_RARP is not set | ||
200 | # CONFIG_NET_IPIP is not set | ||
201 | # CONFIG_NET_IPGRE is not set | ||
202 | # CONFIG_ARPD is not set | ||
203 | CONFIG_SYN_COOKIES=y | ||
204 | # CONFIG_INET_AH is not set | ||
205 | # CONFIG_INET_ESP is not set | ||
206 | # CONFIG_INET_IPCOMP is not set | ||
207 | # CONFIG_INET_TUNNEL is not set | ||
208 | # CONFIG_IP_TCPDIAG is not set | ||
209 | # CONFIG_IP_TCPDIAG_IPV6 is not set | ||
210 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
211 | CONFIG_TCP_CONG_BIC=y | ||
212 | # CONFIG_IPV6 is not set | ||
213 | # CONFIG_NETFILTER is not set | ||
214 | |||
215 | # | ||
216 | # SCTP Configuration (EXPERIMENTAL) | ||
217 | # | ||
218 | # CONFIG_IP_SCTP is not set | ||
219 | # CONFIG_ATM is not set | ||
220 | # CONFIG_BRIDGE is not set | ||
221 | # CONFIG_VLAN_8021Q is not set | ||
222 | # CONFIG_DECNET is not set | ||
223 | # CONFIG_LLC2 is not set | ||
224 | # CONFIG_IPX is not set | ||
225 | # CONFIG_ATALK is not set | ||
226 | # CONFIG_X25 is not set | ||
227 | # CONFIG_LAPB is not set | ||
228 | # CONFIG_NET_DIVERT is not set | ||
229 | # CONFIG_ECONET is not set | ||
230 | # CONFIG_WAN_ROUTER is not set | ||
231 | # CONFIG_NET_SCHED is not set | ||
232 | # CONFIG_NET_CLS_ROUTE is not set | ||
233 | |||
234 | # | ||
235 | # Network testing | ||
236 | # | ||
237 | # CONFIG_NET_PKTGEN is not set | ||
238 | # CONFIG_HAMRADIO is not set | ||
239 | # CONFIG_IRDA is not set | ||
240 | # CONFIG_BT is not set | ||
241 | |||
242 | # | ||
182 | # Device Drivers | 243 | # Device Drivers |
183 | # | 244 | # |
184 | 245 | ||
@@ -248,6 +309,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y | |||
248 | CONFIG_MTD_IXP2000=y | 309 | CONFIG_MTD_IXP2000=y |
249 | # CONFIG_MTD_EDB7312 is not set | 310 | # CONFIG_MTD_EDB7312 is not set |
250 | # CONFIG_MTD_PCI is not set | 311 | # CONFIG_MTD_PCI is not set |
312 | # CONFIG_MTD_PLATRAM is not set | ||
251 | 313 | ||
252 | # | 314 | # |
253 | # Self-contained MTD device drivers | 315 | # Self-contained MTD device drivers |
@@ -334,72 +396,8 @@ CONFIG_IOSCHED_CFQ=y | |||
334 | # CONFIG_I2O is not set | 396 | # CONFIG_I2O is not set |
335 | 397 | ||
336 | # | 398 | # |
337 | # Networking support | 399 | # Network device support |
338 | # | ||
339 | CONFIG_NET=y | ||
340 | |||
341 | # | ||
342 | # Networking options | ||
343 | # | ||
344 | CONFIG_PACKET=y | ||
345 | CONFIG_PACKET_MMAP=y | ||
346 | CONFIG_UNIX=y | ||
347 | # CONFIG_NET_KEY is not set | ||
348 | CONFIG_INET=y | ||
349 | # CONFIG_IP_MULTICAST is not set | ||
350 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
351 | CONFIG_IP_FIB_HASH=y | ||
352 | CONFIG_IP_PNP=y | ||
353 | CONFIG_IP_PNP_DHCP=y | ||
354 | CONFIG_IP_PNP_BOOTP=y | ||
355 | # CONFIG_IP_PNP_RARP is not set | ||
356 | # CONFIG_NET_IPIP is not set | ||
357 | # CONFIG_NET_IPGRE is not set | ||
358 | # CONFIG_ARPD is not set | ||
359 | CONFIG_SYN_COOKIES=y | ||
360 | # CONFIG_INET_AH is not set | ||
361 | # CONFIG_INET_ESP is not set | ||
362 | # CONFIG_INET_IPCOMP is not set | ||
363 | # CONFIG_INET_TUNNEL is not set | ||
364 | # CONFIG_IP_TCPDIAG is not set | ||
365 | # CONFIG_IP_TCPDIAG_IPV6 is not set | ||
366 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
367 | CONFIG_TCP_CONG_BIC=y | ||
368 | # CONFIG_IPV6 is not set | ||
369 | # CONFIG_NETFILTER is not set | ||
370 | |||
371 | # | ||
372 | # SCTP Configuration (EXPERIMENTAL) | ||
373 | # | ||
374 | # CONFIG_IP_SCTP is not set | ||
375 | # CONFIG_ATM is not set | ||
376 | # CONFIG_BRIDGE is not set | ||
377 | # CONFIG_VLAN_8021Q is not set | ||
378 | # CONFIG_DECNET is not set | ||
379 | # CONFIG_LLC2 is not set | ||
380 | # CONFIG_IPX is not set | ||
381 | # CONFIG_ATALK is not set | ||
382 | # CONFIG_X25 is not set | ||
383 | # CONFIG_LAPB is not set | ||
384 | # CONFIG_NET_DIVERT is not set | ||
385 | # CONFIG_ECONET is not set | ||
386 | # CONFIG_WAN_ROUTER is not set | ||
387 | |||
388 | # | ||
389 | # QoS and/or fair queueing | ||
390 | # | ||
391 | # CONFIG_NET_SCHED is not set | ||
392 | # CONFIG_NET_CLS_ROUTE is not set | ||
393 | |||
394 | # | ||
395 | # Network testing | ||
396 | # | 400 | # |
397 | # CONFIG_NET_PKTGEN is not set | ||
398 | # CONFIG_NETPOLL is not set | ||
399 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
400 | # CONFIG_HAMRADIO is not set | ||
401 | # CONFIG_IRDA is not set | ||
402 | # CONFIG_BT is not set | ||
403 | CONFIG_NETDEVICES=y | 401 | CONFIG_NETDEVICES=y |
404 | CONFIG_DUMMY=y | 402 | CONFIG_DUMMY=y |
405 | # CONFIG_BONDING is not set | 403 | # CONFIG_BONDING is not set |
@@ -509,6 +507,8 @@ CONFIG_DLCI_MAX=8 | |||
509 | # CONFIG_SLIP is not set | 507 | # CONFIG_SLIP is not set |
510 | # CONFIG_SHAPER is not set | 508 | # CONFIG_SHAPER is not set |
511 | # CONFIG_NETCONSOLE is not set | 509 | # CONFIG_NETCONSOLE is not set |
510 | # CONFIG_NETPOLL is not set | ||
511 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
512 | 512 | ||
513 | # | 513 | # |
514 | # ISDN subsystem | 514 | # ISDN subsystem |
@@ -635,7 +635,7 @@ CONFIG_I2C_ALGOBIT=y | |||
635 | # CONFIG_I2C_I810 is not set | 635 | # CONFIG_I2C_I810 is not set |
636 | # CONFIG_I2C_PIIX4 is not set | 636 | # CONFIG_I2C_PIIX4 is not set |
637 | # CONFIG_I2C_ISA is not set | 637 | # CONFIG_I2C_ISA is not set |
638 | # CONFIG_I2C_IXP2000 is not set | 638 | CONFIG_I2C_IXP2000=y |
639 | # CONFIG_I2C_NFORCE2 is not set | 639 | # CONFIG_I2C_NFORCE2 is not set |
640 | # CONFIG_I2C_PARPORT_LIGHT is not set | 640 | # CONFIG_I2C_PARPORT_LIGHT is not set |
641 | # CONFIG_I2C_PROSAVAGE is not set | 641 | # CONFIG_I2C_PROSAVAGE is not set |
@@ -649,11 +649,28 @@ CONFIG_I2C_ALGOBIT=y | |||
649 | # CONFIG_I2C_VIAPRO is not set | 649 | # CONFIG_I2C_VIAPRO is not set |
650 | # CONFIG_I2C_VOODOO3 is not set | 650 | # CONFIG_I2C_VOODOO3 is not set |
651 | # CONFIG_I2C_PCA_ISA is not set | 651 | # CONFIG_I2C_PCA_ISA is not set |
652 | CONFIG_I2C_SENSOR=y | ||
652 | 653 | ||
653 | # | 654 | # |
654 | # Hardware Sensors Chip support | 655 | # Miscellaneous I2C Chip support |
655 | # | 656 | # |
656 | CONFIG_I2C_SENSOR=y | 657 | # CONFIG_SENSORS_DS1337 is not set |
658 | # CONFIG_SENSORS_DS1374 is not set | ||
659 | CONFIG_SENSORS_EEPROM=y | ||
660 | # CONFIG_SENSORS_PCF8574 is not set | ||
661 | # CONFIG_SENSORS_PCA9539 is not set | ||
662 | # CONFIG_SENSORS_PCF8591 is not set | ||
663 | # CONFIG_SENSORS_RTC8564 is not set | ||
664 | # CONFIG_SENSORS_MAX6875 is not set | ||
665 | # CONFIG_I2C_DEBUG_CORE is not set | ||
666 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
667 | # CONFIG_I2C_DEBUG_BUS is not set | ||
668 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
669 | |||
670 | # | ||
671 | # Hardware Monitoring support | ||
672 | # | ||
673 | CONFIG_HWMON=y | ||
657 | # CONFIG_SENSORS_ADM1021 is not set | 674 | # CONFIG_SENSORS_ADM1021 is not set |
658 | # CONFIG_SENSORS_ADM1025 is not set | 675 | # CONFIG_SENSORS_ADM1025 is not set |
659 | # CONFIG_SENSORS_ADM1026 is not set | 676 | # CONFIG_SENSORS_ADM1026 is not set |
@@ -679,30 +696,15 @@ CONFIG_I2C_SENSOR=y | |||
679 | # CONFIG_SENSORS_LM92 is not set | 696 | # CONFIG_SENSORS_LM92 is not set |
680 | # CONFIG_SENSORS_MAX1619 is not set | 697 | # CONFIG_SENSORS_MAX1619 is not set |
681 | # CONFIG_SENSORS_PC87360 is not set | 698 | # CONFIG_SENSORS_PC87360 is not set |
682 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
683 | # CONFIG_SENSORS_SIS5595 is not set | 699 | # CONFIG_SENSORS_SIS5595 is not set |
684 | # CONFIG_SENSORS_SMSC47M1 is not set | 700 | # CONFIG_SENSORS_SMSC47M1 is not set |
701 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
685 | # CONFIG_SENSORS_VIA686A is not set | 702 | # CONFIG_SENSORS_VIA686A is not set |
686 | # CONFIG_SENSORS_W83781D is not set | 703 | # CONFIG_SENSORS_W83781D is not set |
687 | # CONFIG_SENSORS_W83L785TS is not set | 704 | # CONFIG_SENSORS_W83L785TS is not set |
688 | # CONFIG_SENSORS_W83627HF is not set | 705 | # CONFIG_SENSORS_W83627HF is not set |
689 | # CONFIG_SENSORS_W83627EHF is not set | 706 | # CONFIG_SENSORS_W83627EHF is not set |
690 | 707 | # CONFIG_HWMON_DEBUG_CHIP is not set | |
691 | # | ||
692 | # Other I2C Chip support | ||
693 | # | ||
694 | # CONFIG_SENSORS_DS1337 is not set | ||
695 | # CONFIG_SENSORS_DS1374 is not set | ||
696 | CONFIG_SENSORS_EEPROM=y | ||
697 | # CONFIG_SENSORS_PCF8574 is not set | ||
698 | # CONFIG_SENSORS_PCA9539 is not set | ||
699 | # CONFIG_SENSORS_PCF8591 is not set | ||
700 | # CONFIG_SENSORS_RTC8564 is not set | ||
701 | # CONFIG_SENSORS_MAX6875 is not set | ||
702 | # CONFIG_I2C_DEBUG_CORE is not set | ||
703 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
704 | # CONFIG_I2C_DEBUG_BUS is not set | ||
705 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
706 | 708 | ||
707 | # | 709 | # |
708 | # Misc devices | 710 | # Misc devices |
@@ -770,6 +772,7 @@ CONFIG_FS_POSIX_ACL=y | |||
770 | # CONFIG_XFS_FS is not set | 772 | # CONFIG_XFS_FS is not set |
771 | # CONFIG_MINIX_FS is not set | 773 | # CONFIG_MINIX_FS is not set |
772 | # CONFIG_ROMFS_FS is not set | 774 | # CONFIG_ROMFS_FS is not set |
775 | CONFIG_INOTIFY=y | ||
773 | # CONFIG_QUOTA is not set | 776 | # CONFIG_QUOTA is not set |
774 | CONFIG_DNOTIFY=y | 777 | CONFIG_DNOTIFY=y |
775 | # CONFIG_AUTOFS_FS is not set | 778 | # CONFIG_AUTOFS_FS is not set |
@@ -812,8 +815,7 @@ CONFIG_RAMFS=y | |||
812 | # CONFIG_JFFS_FS is not set | 815 | # CONFIG_JFFS_FS is not set |
813 | CONFIG_JFFS2_FS=y | 816 | CONFIG_JFFS2_FS=y |
814 | CONFIG_JFFS2_FS_DEBUG=0 | 817 | CONFIG_JFFS2_FS_DEBUG=0 |
815 | # CONFIG_JFFS2_FS_NAND is not set | 818 | CONFIG_JFFS2_FS_WRITEBUFFER=y |
816 | # CONFIG_JFFS2_FS_NOR_ECC is not set | ||
817 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set | 819 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set |
818 | CONFIG_JFFS2_ZLIB=y | 820 | CONFIG_JFFS2_ZLIB=y |
819 | CONFIG_JFFS2_RTIME=y | 821 | CONFIG_JFFS2_RTIME=y |
diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig index 5c6c928215d0..678720fa2e2e 100644 --- a/arch/arm/configs/ixdp2400_defconfig +++ b/arch/arm/configs/ixdp2400_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.13-rc2 | 3 | # Linux kernel version: 2.6.13 |
4 | # Thu Jul 7 16:49:01 2005 | 4 | # Wed Sep 14 10:52:01 2005 |
5 | # | 5 | # |
6 | CONFIG_ARM=y | 6 | CONFIG_ARM=y |
7 | CONFIG_MMU=y | 7 | CONFIG_MMU=y |
@@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y | |||
136 | # | 136 | # |
137 | # Kernel Features | 137 | # Kernel Features |
138 | # | 138 | # |
139 | # CONFIG_SMP is not set | ||
140 | # CONFIG_PREEMPT is not set | 139 | # CONFIG_PREEMPT is not set |
141 | # CONFIG_NO_IDLE_HZ is not set | 140 | # CONFIG_NO_IDLE_HZ is not set |
142 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set | 141 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set |
@@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y | |||
180 | # CONFIG_PM is not set | 179 | # CONFIG_PM is not set |
181 | 180 | ||
182 | # | 181 | # |
182 | # Networking | ||
183 | # | ||
184 | CONFIG_NET=y | ||
185 | |||
186 | # | ||
187 | # Networking options | ||
188 | # | ||
189 | CONFIG_PACKET=y | ||
190 | CONFIG_PACKET_MMAP=y | ||
191 | CONFIG_UNIX=y | ||
192 | # CONFIG_NET_KEY is not set | ||
193 | CONFIG_INET=y | ||
194 | # CONFIG_IP_MULTICAST is not set | ||
195 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
196 | CONFIG_IP_FIB_HASH=y | ||
197 | CONFIG_IP_PNP=y | ||
198 | CONFIG_IP_PNP_DHCP=y | ||
199 | CONFIG_IP_PNP_BOOTP=y | ||
200 | # CONFIG_IP_PNP_RARP is not set | ||
201 | # CONFIG_NET_IPIP is not set | ||
202 | # CONFIG_NET_IPGRE is not set | ||
203 | # CONFIG_ARPD is not set | ||
204 | CONFIG_SYN_COOKIES=y | ||
205 | # CONFIG_INET_AH is not set | ||
206 | # CONFIG_INET_ESP is not set | ||
207 | # CONFIG_INET_IPCOMP is not set | ||
208 | # CONFIG_INET_TUNNEL is not set | ||
209 | # CONFIG_IP_TCPDIAG is not set | ||
210 | # CONFIG_IP_TCPDIAG_IPV6 is not set | ||
211 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
212 | CONFIG_TCP_CONG_BIC=y | ||
213 | # CONFIG_IPV6 is not set | ||
214 | # CONFIG_NETFILTER is not set | ||
215 | |||
216 | # | ||
217 | # SCTP Configuration (EXPERIMENTAL) | ||
218 | # | ||
219 | # CONFIG_IP_SCTP is not set | ||
220 | # CONFIG_ATM is not set | ||
221 | # CONFIG_BRIDGE is not set | ||
222 | # CONFIG_VLAN_8021Q is not set | ||
223 | # CONFIG_DECNET is not set | ||
224 | # CONFIG_LLC2 is not set | ||
225 | # CONFIG_IPX is not set | ||
226 | # CONFIG_ATALK is not set | ||
227 | # CONFIG_X25 is not set | ||
228 | # CONFIG_LAPB is not set | ||
229 | # CONFIG_NET_DIVERT is not set | ||
230 | # CONFIG_ECONET is not set | ||
231 | # CONFIG_WAN_ROUTER is not set | ||
232 | # CONFIG_NET_SCHED is not set | ||
233 | # CONFIG_NET_CLS_ROUTE is not set | ||
234 | |||
235 | # | ||
236 | # Network testing | ||
237 | # | ||
238 | # CONFIG_NET_PKTGEN is not set | ||
239 | # CONFIG_HAMRADIO is not set | ||
240 | # CONFIG_IRDA is not set | ||
241 | # CONFIG_BT is not set | ||
242 | |||
243 | # | ||
183 | # Device Drivers | 244 | # Device Drivers |
184 | # | 245 | # |
185 | 246 | ||
@@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y | |||
249 | CONFIG_MTD_IXP2000=y | 310 | CONFIG_MTD_IXP2000=y |
250 | # CONFIG_MTD_EDB7312 is not set | 311 | # CONFIG_MTD_EDB7312 is not set |
251 | # CONFIG_MTD_PCI is not set | 312 | # CONFIG_MTD_PCI is not set |
313 | # CONFIG_MTD_PLATRAM is not set | ||
252 | 314 | ||
253 | # | 315 | # |
254 | # Self-contained MTD device drivers | 316 | # Self-contained MTD device drivers |
@@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y | |||
335 | # CONFIG_I2O is not set | 397 | # CONFIG_I2O is not set |
336 | 398 | ||
337 | # | 399 | # |
338 | # Networking support | 400 | # Network device support |
339 | # | ||
340 | CONFIG_NET=y | ||
341 | |||
342 | # | ||
343 | # Networking options | ||
344 | # | ||
345 | CONFIG_PACKET=y | ||
346 | CONFIG_PACKET_MMAP=y | ||
347 | CONFIG_UNIX=y | ||
348 | # CONFIG_NET_KEY is not set | ||
349 | CONFIG_INET=y | ||
350 | # CONFIG_IP_MULTICAST is not set | ||
351 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
352 | CONFIG_IP_FIB_HASH=y | ||
353 | CONFIG_IP_PNP=y | ||
354 | CONFIG_IP_PNP_DHCP=y | ||
355 | CONFIG_IP_PNP_BOOTP=y | ||
356 | # CONFIG_IP_PNP_RARP is not set | ||
357 | # CONFIG_NET_IPIP is not set | ||
358 | # CONFIG_NET_IPGRE is not set | ||
359 | # CONFIG_ARPD is not set | ||
360 | CONFIG_SYN_COOKIES=y | ||
361 | # CONFIG_INET_AH is not set | ||
362 | # CONFIG_INET_ESP is not set | ||
363 | # CONFIG_INET_IPCOMP is not set | ||
364 | # CONFIG_INET_TUNNEL is not set | ||
365 | # CONFIG_IP_TCPDIAG is not set | ||
366 | # CONFIG_IP_TCPDIAG_IPV6 is not set | ||
367 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
368 | CONFIG_TCP_CONG_BIC=y | ||
369 | # CONFIG_IPV6 is not set | ||
370 | # CONFIG_NETFILTER is not set | ||
371 | |||
372 | # | ||
373 | # SCTP Configuration (EXPERIMENTAL) | ||
374 | # | ||
375 | # CONFIG_IP_SCTP is not set | ||
376 | # CONFIG_ATM is not set | ||
377 | # CONFIG_BRIDGE is not set | ||
378 | # CONFIG_VLAN_8021Q is not set | ||
379 | # CONFIG_DECNET is not set | ||
380 | # CONFIG_LLC2 is not set | ||
381 | # CONFIG_IPX is not set | ||
382 | # CONFIG_ATALK is not set | ||
383 | # CONFIG_X25 is not set | ||
384 | # CONFIG_LAPB is not set | ||
385 | # CONFIG_NET_DIVERT is not set | ||
386 | # CONFIG_ECONET is not set | ||
387 | # CONFIG_WAN_ROUTER is not set | ||
388 | |||
389 | # | ||
390 | # QoS and/or fair queueing | ||
391 | # | ||
392 | # CONFIG_NET_SCHED is not set | ||
393 | # CONFIG_NET_CLS_ROUTE is not set | ||
394 | |||
395 | # | ||
396 | # Network testing | ||
397 | # | 401 | # |
398 | # CONFIG_NET_PKTGEN is not set | ||
399 | # CONFIG_NETPOLL is not set | ||
400 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
401 | # CONFIG_HAMRADIO is not set | ||
402 | # CONFIG_IRDA is not set | ||
403 | # CONFIG_BT is not set | ||
404 | CONFIG_NETDEVICES=y | 402 | CONFIG_NETDEVICES=y |
405 | CONFIG_DUMMY=y | 403 | CONFIG_DUMMY=y |
406 | # CONFIG_BONDING is not set | 404 | # CONFIG_BONDING is not set |
@@ -510,6 +508,8 @@ CONFIG_DLCI_MAX=8 | |||
510 | # CONFIG_SLIP is not set | 508 | # CONFIG_SLIP is not set |
511 | # CONFIG_SHAPER is not set | 509 | # CONFIG_SHAPER is not set |
512 | # CONFIG_NETCONSOLE is not set | 510 | # CONFIG_NETCONSOLE is not set |
511 | # CONFIG_NETPOLL is not set | ||
512 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
513 | 513 | ||
514 | # | 514 | # |
515 | # ISDN subsystem | 515 | # ISDN subsystem |
@@ -636,7 +636,7 @@ CONFIG_I2C_ALGOBIT=y | |||
636 | # CONFIG_I2C_I810 is not set | 636 | # CONFIG_I2C_I810 is not set |
637 | # CONFIG_I2C_PIIX4 is not set | 637 | # CONFIG_I2C_PIIX4 is not set |
638 | # CONFIG_I2C_ISA is not set | 638 | # CONFIG_I2C_ISA is not set |
639 | # CONFIG_I2C_IXP2000 is not set | 639 | CONFIG_I2C_IXP2000=y |
640 | # CONFIG_I2C_NFORCE2 is not set | 640 | # CONFIG_I2C_NFORCE2 is not set |
641 | # CONFIG_I2C_PARPORT_LIGHT is not set | 641 | # CONFIG_I2C_PARPORT_LIGHT is not set |
642 | # CONFIG_I2C_PROSAVAGE is not set | 642 | # CONFIG_I2C_PROSAVAGE is not set |
@@ -650,11 +650,28 @@ CONFIG_I2C_ALGOBIT=y | |||
650 | # CONFIG_I2C_VIAPRO is not set | 650 | # CONFIG_I2C_VIAPRO is not set |
651 | # CONFIG_I2C_VOODOO3 is not set | 651 | # CONFIG_I2C_VOODOO3 is not set |
652 | # CONFIG_I2C_PCA_ISA is not set | 652 | # CONFIG_I2C_PCA_ISA is not set |
653 | CONFIG_I2C_SENSOR=y | ||
653 | 654 | ||
654 | # | 655 | # |
655 | # Hardware Sensors Chip support | 656 | # Miscellaneous I2C Chip support |
656 | # | 657 | # |
657 | CONFIG_I2C_SENSOR=y | 658 | # CONFIG_SENSORS_DS1337 is not set |
659 | # CONFIG_SENSORS_DS1374 is not set | ||
660 | CONFIG_SENSORS_EEPROM=y | ||
661 | # CONFIG_SENSORS_PCF8574 is not set | ||
662 | # CONFIG_SENSORS_PCA9539 is not set | ||
663 | # CONFIG_SENSORS_PCF8591 is not set | ||
664 | # CONFIG_SENSORS_RTC8564 is not set | ||
665 | # CONFIG_SENSORS_MAX6875 is not set | ||
666 | # CONFIG_I2C_DEBUG_CORE is not set | ||
667 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
668 | # CONFIG_I2C_DEBUG_BUS is not set | ||
669 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
670 | |||
671 | # | ||
672 | # Hardware Monitoring support | ||
673 | # | ||
674 | CONFIG_HWMON=y | ||
658 | # CONFIG_SENSORS_ADM1021 is not set | 675 | # CONFIG_SENSORS_ADM1021 is not set |
659 | # CONFIG_SENSORS_ADM1025 is not set | 676 | # CONFIG_SENSORS_ADM1025 is not set |
660 | # CONFIG_SENSORS_ADM1026 is not set | 677 | # CONFIG_SENSORS_ADM1026 is not set |
@@ -680,30 +697,15 @@ CONFIG_I2C_SENSOR=y | |||
680 | # CONFIG_SENSORS_LM92 is not set | 697 | # CONFIG_SENSORS_LM92 is not set |
681 | # CONFIG_SENSORS_MAX1619 is not set | 698 | # CONFIG_SENSORS_MAX1619 is not set |
682 | # CONFIG_SENSORS_PC87360 is not set | 699 | # CONFIG_SENSORS_PC87360 is not set |
683 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
684 | # CONFIG_SENSORS_SIS5595 is not set | 700 | # CONFIG_SENSORS_SIS5595 is not set |
685 | # CONFIG_SENSORS_SMSC47M1 is not set | 701 | # CONFIG_SENSORS_SMSC47M1 is not set |
702 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
686 | # CONFIG_SENSORS_VIA686A is not set | 703 | # CONFIG_SENSORS_VIA686A is not set |
687 | # CONFIG_SENSORS_W83781D is not set | 704 | # CONFIG_SENSORS_W83781D is not set |
688 | # CONFIG_SENSORS_W83L785TS is not set | 705 | # CONFIG_SENSORS_W83L785TS is not set |
689 | # CONFIG_SENSORS_W83627HF is not set | 706 | # CONFIG_SENSORS_W83627HF is not set |
690 | # CONFIG_SENSORS_W83627EHF is not set | 707 | # CONFIG_SENSORS_W83627EHF is not set |
691 | 708 | # CONFIG_HWMON_DEBUG_CHIP is not set | |
692 | # | ||
693 | # Other I2C Chip support | ||
694 | # | ||
695 | # CONFIG_SENSORS_DS1337 is not set | ||
696 | # CONFIG_SENSORS_DS1374 is not set | ||
697 | CONFIG_SENSORS_EEPROM=y | ||
698 | # CONFIG_SENSORS_PCF8574 is not set | ||
699 | # CONFIG_SENSORS_PCA9539 is not set | ||
700 | # CONFIG_SENSORS_PCF8591 is not set | ||
701 | # CONFIG_SENSORS_RTC8564 is not set | ||
702 | # CONFIG_SENSORS_MAX6875 is not set | ||
703 | # CONFIG_I2C_DEBUG_CORE is not set | ||
704 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
705 | # CONFIG_I2C_DEBUG_BUS is not set | ||
706 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
707 | 709 | ||
708 | # | 710 | # |
709 | # Misc devices | 711 | # Misc devices |
@@ -771,6 +773,7 @@ CONFIG_FS_POSIX_ACL=y | |||
771 | # CONFIG_XFS_FS is not set | 773 | # CONFIG_XFS_FS is not set |
772 | # CONFIG_MINIX_FS is not set | 774 | # CONFIG_MINIX_FS is not set |
773 | # CONFIG_ROMFS_FS is not set | 775 | # CONFIG_ROMFS_FS is not set |
776 | CONFIG_INOTIFY=y | ||
774 | # CONFIG_QUOTA is not set | 777 | # CONFIG_QUOTA is not set |
775 | CONFIG_DNOTIFY=y | 778 | CONFIG_DNOTIFY=y |
776 | # CONFIG_AUTOFS_FS is not set | 779 | # CONFIG_AUTOFS_FS is not set |
@@ -813,8 +816,7 @@ CONFIG_RAMFS=y | |||
813 | # CONFIG_JFFS_FS is not set | 816 | # CONFIG_JFFS_FS is not set |
814 | CONFIG_JFFS2_FS=y | 817 | CONFIG_JFFS2_FS=y |
815 | CONFIG_JFFS2_FS_DEBUG=0 | 818 | CONFIG_JFFS2_FS_DEBUG=0 |
816 | # CONFIG_JFFS2_FS_NAND is not set | 819 | CONFIG_JFFS2_FS_WRITEBUFFER=y |
817 | # CONFIG_JFFS2_FS_NOR_ECC is not set | ||
818 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set | 820 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set |
819 | CONFIG_JFFS2_ZLIB=y | 821 | CONFIG_JFFS2_ZLIB=y |
820 | CONFIG_JFFS2_RTIME=y | 822 | CONFIG_JFFS2_RTIME=y |
diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig index 6dc40f6be0ef..38c9a721d5c9 100644 --- a/arch/arm/configs/ixdp2401_defconfig +++ b/arch/arm/configs/ixdp2401_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.13-rc2 | 3 | # Linux kernel version: 2.6.13 |
4 | # Thu Jul 7 16:49:08 2005 | 4 | # Wed Sep 14 10:52:10 2005 |
5 | # | 5 | # |
6 | CONFIG_ARM=y | 6 | CONFIG_ARM=y |
7 | CONFIG_MMU=y | 7 | CONFIG_MMU=y |
@@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y | |||
136 | # | 136 | # |
137 | # Kernel Features | 137 | # Kernel Features |
138 | # | 138 | # |
139 | # CONFIG_SMP is not set | ||
140 | # CONFIG_PREEMPT is not set | 139 | # CONFIG_PREEMPT is not set |
141 | # CONFIG_NO_IDLE_HZ is not set | 140 | # CONFIG_NO_IDLE_HZ is not set |
142 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set | 141 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set |
@@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y | |||
180 | # CONFIG_PM is not set | 179 | # CONFIG_PM is not set |
181 | 180 | ||
182 | # | 181 | # |
182 | # Networking | ||
183 | # | ||
184 | CONFIG_NET=y | ||
185 | |||
186 | # | ||
187 | # Networking options | ||
188 | # | ||
189 | CONFIG_PACKET=y | ||
190 | CONFIG_PACKET_MMAP=y | ||
191 | CONFIG_UNIX=y | ||
192 | # CONFIG_NET_KEY is not set | ||
193 | CONFIG_INET=y | ||
194 | # CONFIG_IP_MULTICAST is not set | ||
195 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
196 | CONFIG_IP_FIB_HASH=y | ||
197 | CONFIG_IP_PNP=y | ||
198 | CONFIG_IP_PNP_DHCP=y | ||
199 | CONFIG_IP_PNP_BOOTP=y | ||
200 | # CONFIG_IP_PNP_RARP is not set | ||
201 | # CONFIG_NET_IPIP is not set | ||
202 | # CONFIG_NET_IPGRE is not set | ||
203 | # CONFIG_ARPD is not set | ||
204 | CONFIG_SYN_COOKIES=y | ||
205 | # CONFIG_INET_AH is not set | ||
206 | # CONFIG_INET_ESP is not set | ||
207 | # CONFIG_INET_IPCOMP is not set | ||
208 | # CONFIG_INET_TUNNEL is not set | ||
209 | CONFIG_IP_TCPDIAG=y | ||
210 | # CONFIG_IP_TCPDIAG_IPV6 is not set | ||
211 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
212 | CONFIG_TCP_CONG_BIC=y | ||
213 | # CONFIG_IPV6 is not set | ||
214 | # CONFIG_NETFILTER is not set | ||
215 | |||
216 | # | ||
217 | # SCTP Configuration (EXPERIMENTAL) | ||
218 | # | ||
219 | # CONFIG_IP_SCTP is not set | ||
220 | # CONFIG_ATM is not set | ||
221 | # CONFIG_BRIDGE is not set | ||
222 | # CONFIG_VLAN_8021Q is not set | ||
223 | # CONFIG_DECNET is not set | ||
224 | # CONFIG_LLC2 is not set | ||
225 | # CONFIG_IPX is not set | ||
226 | # CONFIG_ATALK is not set | ||
227 | # CONFIG_X25 is not set | ||
228 | # CONFIG_LAPB is not set | ||
229 | # CONFIG_NET_DIVERT is not set | ||
230 | # CONFIG_ECONET is not set | ||
231 | # CONFIG_WAN_ROUTER is not set | ||
232 | # CONFIG_NET_SCHED is not set | ||
233 | # CONFIG_NET_CLS_ROUTE is not set | ||
234 | |||
235 | # | ||
236 | # Network testing | ||
237 | # | ||
238 | # CONFIG_NET_PKTGEN is not set | ||
239 | # CONFIG_HAMRADIO is not set | ||
240 | # CONFIG_IRDA is not set | ||
241 | # CONFIG_BT is not set | ||
242 | |||
243 | # | ||
183 | # Device Drivers | 244 | # Device Drivers |
184 | # | 245 | # |
185 | 246 | ||
@@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y | |||
249 | CONFIG_MTD_IXP2000=y | 310 | CONFIG_MTD_IXP2000=y |
250 | # CONFIG_MTD_EDB7312 is not set | 311 | # CONFIG_MTD_EDB7312 is not set |
251 | # CONFIG_MTD_PCI is not set | 312 | # CONFIG_MTD_PCI is not set |
313 | # CONFIG_MTD_PLATRAM is not set | ||
252 | 314 | ||
253 | # | 315 | # |
254 | # Self-contained MTD device drivers | 316 | # Self-contained MTD device drivers |
@@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y | |||
335 | # CONFIG_I2O is not set | 397 | # CONFIG_I2O is not set |
336 | 398 | ||
337 | # | 399 | # |
338 | # Networking support | 400 | # Network device support |
339 | # | ||
340 | CONFIG_NET=y | ||
341 | |||
342 | # | ||
343 | # Networking options | ||
344 | # | ||
345 | CONFIG_PACKET=y | ||
346 | CONFIG_PACKET_MMAP=y | ||
347 | CONFIG_UNIX=y | ||
348 | # CONFIG_NET_KEY is not set | ||
349 | CONFIG_INET=y | ||
350 | # CONFIG_IP_MULTICAST is not set | ||
351 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
352 | CONFIG_IP_FIB_HASH=y | ||
353 | CONFIG_IP_PNP=y | ||
354 | CONFIG_IP_PNP_DHCP=y | ||
355 | CONFIG_IP_PNP_BOOTP=y | ||
356 | # CONFIG_IP_PNP_RARP is not set | ||
357 | # CONFIG_NET_IPIP is not set | ||
358 | # CONFIG_NET_IPGRE is not set | ||
359 | # CONFIG_ARPD is not set | ||
360 | CONFIG_SYN_COOKIES=y | ||
361 | # CONFIG_INET_AH is not set | ||
362 | # CONFIG_INET_ESP is not set | ||
363 | # CONFIG_INET_IPCOMP is not set | ||
364 | # CONFIG_INET_TUNNEL is not set | ||
365 | CONFIG_IP_TCPDIAG=y | ||
366 | # CONFIG_IP_TCPDIAG_IPV6 is not set | ||
367 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
368 | CONFIG_TCP_CONG_BIC=y | ||
369 | # CONFIG_IPV6 is not set | ||
370 | # CONFIG_NETFILTER is not set | ||
371 | |||
372 | # | ||
373 | # SCTP Configuration (EXPERIMENTAL) | ||
374 | # | ||
375 | # CONFIG_IP_SCTP is not set | ||
376 | # CONFIG_ATM is not set | ||
377 | # CONFIG_BRIDGE is not set | ||
378 | # CONFIG_VLAN_8021Q is not set | ||
379 | # CONFIG_DECNET is not set | ||
380 | # CONFIG_LLC2 is not set | ||
381 | # CONFIG_IPX is not set | ||
382 | # CONFIG_ATALK is not set | ||
383 | # CONFIG_X25 is not set | ||
384 | # CONFIG_LAPB is not set | ||
385 | # CONFIG_NET_DIVERT is not set | ||
386 | # CONFIG_ECONET is not set | ||
387 | # CONFIG_WAN_ROUTER is not set | ||
388 | |||
389 | # | ||
390 | # QoS and/or fair queueing | ||
391 | # | ||
392 | # CONFIG_NET_SCHED is not set | ||
393 | # CONFIG_NET_CLS_ROUTE is not set | ||
394 | |||
395 | # | ||
396 | # Network testing | ||
397 | # | 401 | # |
398 | # CONFIG_NET_PKTGEN is not set | ||
399 | # CONFIG_NETPOLL is not set | ||
400 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
401 | # CONFIG_HAMRADIO is not set | ||
402 | # CONFIG_IRDA is not set | ||
403 | # CONFIG_BT is not set | ||
404 | CONFIG_NETDEVICES=y | 402 | CONFIG_NETDEVICES=y |
405 | CONFIG_DUMMY=y | 403 | CONFIG_DUMMY=y |
406 | # CONFIG_BONDING is not set | 404 | # CONFIG_BONDING is not set |
@@ -511,6 +509,8 @@ CONFIG_DLCI_MAX=8 | |||
511 | # CONFIG_SLIP is not set | 509 | # CONFIG_SLIP is not set |
512 | # CONFIG_SHAPER is not set | 510 | # CONFIG_SHAPER is not set |
513 | # CONFIG_NETCONSOLE is not set | 511 | # CONFIG_NETCONSOLE is not set |
512 | # CONFIG_NETPOLL is not set | ||
513 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
514 | 514 | ||
515 | # | 515 | # |
516 | # ISDN subsystem | 516 | # ISDN subsystem |
@@ -637,7 +637,7 @@ CONFIG_I2C_ALGOBIT=y | |||
637 | # CONFIG_I2C_I810 is not set | 637 | # CONFIG_I2C_I810 is not set |
638 | # CONFIG_I2C_PIIX4 is not set | 638 | # CONFIG_I2C_PIIX4 is not set |
639 | # CONFIG_I2C_ISA is not set | 639 | # CONFIG_I2C_ISA is not set |
640 | # CONFIG_I2C_IXP2000 is not set | 640 | CONFIG_I2C_IXP2000=y |
641 | # CONFIG_I2C_NFORCE2 is not set | 641 | # CONFIG_I2C_NFORCE2 is not set |
642 | # CONFIG_I2C_PARPORT_LIGHT is not set | 642 | # CONFIG_I2C_PARPORT_LIGHT is not set |
643 | # CONFIG_I2C_PROSAVAGE is not set | 643 | # CONFIG_I2C_PROSAVAGE is not set |
@@ -651,11 +651,28 @@ CONFIG_I2C_ALGOBIT=y | |||
651 | # CONFIG_I2C_VIAPRO is not set | 651 | # CONFIG_I2C_VIAPRO is not set |
652 | # CONFIG_I2C_VOODOO3 is not set | 652 | # CONFIG_I2C_VOODOO3 is not set |
653 | # CONFIG_I2C_PCA_ISA is not set | 653 | # CONFIG_I2C_PCA_ISA is not set |
654 | CONFIG_I2C_SENSOR=y | ||
654 | 655 | ||
655 | # | 656 | # |
656 | # Hardware Sensors Chip support | 657 | # Miscellaneous I2C Chip support |
657 | # | 658 | # |
658 | CONFIG_I2C_SENSOR=y | 659 | # CONFIG_SENSORS_DS1337 is not set |
660 | # CONFIG_SENSORS_DS1374 is not set | ||
661 | CONFIG_SENSORS_EEPROM=y | ||
662 | # CONFIG_SENSORS_PCF8574 is not set | ||
663 | # CONFIG_SENSORS_PCA9539 is not set | ||
664 | # CONFIG_SENSORS_PCF8591 is not set | ||
665 | # CONFIG_SENSORS_RTC8564 is not set | ||
666 | # CONFIG_SENSORS_MAX6875 is not set | ||
667 | # CONFIG_I2C_DEBUG_CORE is not set | ||
668 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
669 | # CONFIG_I2C_DEBUG_BUS is not set | ||
670 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
671 | |||
672 | # | ||
673 | # Hardware Monitoring support | ||
674 | # | ||
675 | CONFIG_HWMON=y | ||
659 | # CONFIG_SENSORS_ADM1021 is not set | 676 | # CONFIG_SENSORS_ADM1021 is not set |
660 | # CONFIG_SENSORS_ADM1025 is not set | 677 | # CONFIG_SENSORS_ADM1025 is not set |
661 | # CONFIG_SENSORS_ADM1026 is not set | 678 | # CONFIG_SENSORS_ADM1026 is not set |
@@ -681,30 +698,15 @@ CONFIG_I2C_SENSOR=y | |||
681 | # CONFIG_SENSORS_LM92 is not set | 698 | # CONFIG_SENSORS_LM92 is not set |
682 | # CONFIG_SENSORS_MAX1619 is not set | 699 | # CONFIG_SENSORS_MAX1619 is not set |
683 | # CONFIG_SENSORS_PC87360 is not set | 700 | # CONFIG_SENSORS_PC87360 is not set |
684 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
685 | # CONFIG_SENSORS_SIS5595 is not set | 701 | # CONFIG_SENSORS_SIS5595 is not set |
686 | # CONFIG_SENSORS_SMSC47M1 is not set | 702 | # CONFIG_SENSORS_SMSC47M1 is not set |
703 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
687 | # CONFIG_SENSORS_VIA686A is not set | 704 | # CONFIG_SENSORS_VIA686A is not set |
688 | # CONFIG_SENSORS_W83781D is not set | 705 | # CONFIG_SENSORS_W83781D is not set |
689 | # CONFIG_SENSORS_W83L785TS is not set | 706 | # CONFIG_SENSORS_W83L785TS is not set |
690 | # CONFIG_SENSORS_W83627HF is not set | 707 | # CONFIG_SENSORS_W83627HF is not set |
691 | # CONFIG_SENSORS_W83627EHF is not set | 708 | # CONFIG_SENSORS_W83627EHF is not set |
692 | 709 | # CONFIG_HWMON_DEBUG_CHIP is not set | |
693 | # | ||
694 | # Other I2C Chip support | ||
695 | # | ||
696 | # CONFIG_SENSORS_DS1337 is not set | ||
697 | # CONFIG_SENSORS_DS1374 is not set | ||
698 | CONFIG_SENSORS_EEPROM=y | ||
699 | # CONFIG_SENSORS_PCF8574 is not set | ||
700 | # CONFIG_SENSORS_PCA9539 is not set | ||
701 | # CONFIG_SENSORS_PCF8591 is not set | ||
702 | # CONFIG_SENSORS_RTC8564 is not set | ||
703 | # CONFIG_SENSORS_MAX6875 is not set | ||
704 | # CONFIG_I2C_DEBUG_CORE is not set | ||
705 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
706 | # CONFIG_I2C_DEBUG_BUS is not set | ||
707 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
708 | 710 | ||
709 | # | 711 | # |
710 | # Misc devices | 712 | # Misc devices |
@@ -772,6 +774,7 @@ CONFIG_FS_POSIX_ACL=y | |||
772 | # CONFIG_XFS_FS is not set | 774 | # CONFIG_XFS_FS is not set |
773 | # CONFIG_MINIX_FS is not set | 775 | # CONFIG_MINIX_FS is not set |
774 | # CONFIG_ROMFS_FS is not set | 776 | # CONFIG_ROMFS_FS is not set |
777 | CONFIG_INOTIFY=y | ||
775 | # CONFIG_QUOTA is not set | 778 | # CONFIG_QUOTA is not set |
776 | CONFIG_DNOTIFY=y | 779 | CONFIG_DNOTIFY=y |
777 | # CONFIG_AUTOFS_FS is not set | 780 | # CONFIG_AUTOFS_FS is not set |
@@ -814,8 +817,7 @@ CONFIG_RAMFS=y | |||
814 | # CONFIG_JFFS_FS is not set | 817 | # CONFIG_JFFS_FS is not set |
815 | CONFIG_JFFS2_FS=y | 818 | CONFIG_JFFS2_FS=y |
816 | CONFIG_JFFS2_FS_DEBUG=0 | 819 | CONFIG_JFFS2_FS_DEBUG=0 |
817 | # CONFIG_JFFS2_FS_NAND is not set | 820 | CONFIG_JFFS2_FS_WRITEBUFFER=y |
818 | # CONFIG_JFFS2_FS_NOR_ECC is not set | ||
819 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set | 821 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set |
820 | CONFIG_JFFS2_ZLIB=y | 822 | CONFIG_JFFS2_ZLIB=y |
821 | CONFIG_JFFS2_RTIME=y | 823 | CONFIG_JFFS2_RTIME=y |
diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig index d2bb0b7153fe..261e2343903b 100644 --- a/arch/arm/configs/ixdp2800_defconfig +++ b/arch/arm/configs/ixdp2800_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.13-rc2 | 3 | # Linux kernel version: 2.6.13 |
4 | # Thu Jul 7 16:49:20 2005 | 4 | # Wed Sep 14 10:52:23 2005 |
5 | # | 5 | # |
6 | CONFIG_ARM=y | 6 | CONFIG_ARM=y |
7 | CONFIG_MMU=y | 7 | CONFIG_MMU=y |
@@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y | |||
136 | # | 136 | # |
137 | # Kernel Features | 137 | # Kernel Features |
138 | # | 138 | # |
139 | # CONFIG_SMP is not set | ||
140 | # CONFIG_PREEMPT is not set | 139 | # CONFIG_PREEMPT is not set |
141 | # CONFIG_NO_IDLE_HZ is not set | 140 | # CONFIG_NO_IDLE_HZ is not set |
142 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set | 141 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set |
@@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y | |||
180 | # CONFIG_PM is not set | 179 | # CONFIG_PM is not set |
181 | 180 | ||
182 | # | 181 | # |
182 | # Networking | ||
183 | # | ||
184 | CONFIG_NET=y | ||
185 | |||
186 | # | ||
187 | # Networking options | ||
188 | # | ||
189 | CONFIG_PACKET=y | ||
190 | CONFIG_PACKET_MMAP=y | ||
191 | CONFIG_UNIX=y | ||
192 | # CONFIG_NET_KEY is not set | ||
193 | CONFIG_INET=y | ||
194 | # CONFIG_IP_MULTICAST is not set | ||
195 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
196 | CONFIG_IP_FIB_HASH=y | ||
197 | CONFIG_IP_PNP=y | ||
198 | CONFIG_IP_PNP_DHCP=y | ||
199 | CONFIG_IP_PNP_BOOTP=y | ||
200 | # CONFIG_IP_PNP_RARP is not set | ||
201 | # CONFIG_NET_IPIP is not set | ||
202 | # CONFIG_NET_IPGRE is not set | ||
203 | # CONFIG_ARPD is not set | ||
204 | CONFIG_SYN_COOKIES=y | ||
205 | # CONFIG_INET_AH is not set | ||
206 | # CONFIG_INET_ESP is not set | ||
207 | # CONFIG_INET_IPCOMP is not set | ||
208 | # CONFIG_INET_TUNNEL is not set | ||
209 | # CONFIG_IP_TCPDIAG is not set | ||
210 | # CONFIG_IP_TCPDIAG_IPV6 is not set | ||
211 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
212 | CONFIG_TCP_CONG_BIC=y | ||
213 | # CONFIG_IPV6 is not set | ||
214 | # CONFIG_NETFILTER is not set | ||
215 | |||
216 | # | ||
217 | # SCTP Configuration (EXPERIMENTAL) | ||
218 | # | ||
219 | # CONFIG_IP_SCTP is not set | ||
220 | # CONFIG_ATM is not set | ||
221 | # CONFIG_BRIDGE is not set | ||
222 | # CONFIG_VLAN_8021Q is not set | ||
223 | # CONFIG_DECNET is not set | ||
224 | # CONFIG_LLC2 is not set | ||
225 | # CONFIG_IPX is not set | ||
226 | # CONFIG_ATALK is not set | ||
227 | # CONFIG_X25 is not set | ||
228 | # CONFIG_LAPB is not set | ||
229 | # CONFIG_NET_DIVERT is not set | ||
230 | # CONFIG_ECONET is not set | ||
231 | # CONFIG_WAN_ROUTER is not set | ||
232 | # CONFIG_NET_SCHED is not set | ||
233 | # CONFIG_NET_CLS_ROUTE is not set | ||
234 | |||
235 | # | ||
236 | # Network testing | ||
237 | # | ||
238 | # CONFIG_NET_PKTGEN is not set | ||
239 | # CONFIG_HAMRADIO is not set | ||
240 | # CONFIG_IRDA is not set | ||
241 | # CONFIG_BT is not set | ||
242 | |||
243 | # | ||
183 | # Device Drivers | 244 | # Device Drivers |
184 | # | 245 | # |
185 | 246 | ||
@@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y | |||
249 | CONFIG_MTD_IXP2000=y | 310 | CONFIG_MTD_IXP2000=y |
250 | # CONFIG_MTD_EDB7312 is not set | 311 | # CONFIG_MTD_EDB7312 is not set |
251 | # CONFIG_MTD_PCI is not set | 312 | # CONFIG_MTD_PCI is not set |
313 | # CONFIG_MTD_PLATRAM is not set | ||
252 | 314 | ||
253 | # | 315 | # |
254 | # Self-contained MTD device drivers | 316 | # Self-contained MTD device drivers |
@@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y | |||
335 | # CONFIG_I2O is not set | 397 | # CONFIG_I2O is not set |
336 | 398 | ||
337 | # | 399 | # |
338 | # Networking support | 400 | # Network device support |
339 | # | ||
340 | CONFIG_NET=y | ||
341 | |||
342 | # | ||
343 | # Networking options | ||
344 | # | ||
345 | CONFIG_PACKET=y | ||
346 | CONFIG_PACKET_MMAP=y | ||
347 | CONFIG_UNIX=y | ||
348 | # CONFIG_NET_KEY is not set | ||
349 | CONFIG_INET=y | ||
350 | # CONFIG_IP_MULTICAST is not set | ||
351 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
352 | CONFIG_IP_FIB_HASH=y | ||
353 | CONFIG_IP_PNP=y | ||
354 | CONFIG_IP_PNP_DHCP=y | ||
355 | CONFIG_IP_PNP_BOOTP=y | ||
356 | # CONFIG_IP_PNP_RARP is not set | ||
357 | # CONFIG_NET_IPIP is not set | ||
358 | # CONFIG_NET_IPGRE is not set | ||
359 | # CONFIG_ARPD is not set | ||
360 | CONFIG_SYN_COOKIES=y | ||
361 | # CONFIG_INET_AH is not set | ||
362 | # CONFIG_INET_ESP is not set | ||
363 | # CONFIG_INET_IPCOMP is not set | ||
364 | # CONFIG_INET_TUNNEL is not set | ||
365 | # CONFIG_IP_TCPDIAG is not set | ||
366 | # CONFIG_IP_TCPDIAG_IPV6 is not set | ||
367 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
368 | CONFIG_TCP_CONG_BIC=y | ||
369 | # CONFIG_IPV6 is not set | ||
370 | # CONFIG_NETFILTER is not set | ||
371 | |||
372 | # | ||
373 | # SCTP Configuration (EXPERIMENTAL) | ||
374 | # | ||
375 | # CONFIG_IP_SCTP is not set | ||
376 | # CONFIG_ATM is not set | ||
377 | # CONFIG_BRIDGE is not set | ||
378 | # CONFIG_VLAN_8021Q is not set | ||
379 | # CONFIG_DECNET is not set | ||
380 | # CONFIG_LLC2 is not set | ||
381 | # CONFIG_IPX is not set | ||
382 | # CONFIG_ATALK is not set | ||
383 | # CONFIG_X25 is not set | ||
384 | # CONFIG_LAPB is not set | ||
385 | # CONFIG_NET_DIVERT is not set | ||
386 | # CONFIG_ECONET is not set | ||
387 | # CONFIG_WAN_ROUTER is not set | ||
388 | |||
389 | # | ||
390 | # QoS and/or fair queueing | ||
391 | # | ||
392 | # CONFIG_NET_SCHED is not set | ||
393 | # CONFIG_NET_CLS_ROUTE is not set | ||
394 | |||
395 | # | ||
396 | # Network testing | ||
397 | # | 401 | # |
398 | # CONFIG_NET_PKTGEN is not set | ||
399 | # CONFIG_NETPOLL is not set | ||
400 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
401 | # CONFIG_HAMRADIO is not set | ||
402 | # CONFIG_IRDA is not set | ||
403 | # CONFIG_BT is not set | ||
404 | CONFIG_NETDEVICES=y | 402 | CONFIG_NETDEVICES=y |
405 | CONFIG_DUMMY=y | 403 | CONFIG_DUMMY=y |
406 | # CONFIG_BONDING is not set | 404 | # CONFIG_BONDING is not set |
@@ -510,6 +508,8 @@ CONFIG_DLCI_MAX=8 | |||
510 | # CONFIG_SLIP is not set | 508 | # CONFIG_SLIP is not set |
511 | # CONFIG_SHAPER is not set | 509 | # CONFIG_SHAPER is not set |
512 | # CONFIG_NETCONSOLE is not set | 510 | # CONFIG_NETCONSOLE is not set |
511 | # CONFIG_NETPOLL is not set | ||
512 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
513 | 513 | ||
514 | # | 514 | # |
515 | # ISDN subsystem | 515 | # ISDN subsystem |
@@ -636,7 +636,7 @@ CONFIG_I2C_ALGOBIT=y | |||
636 | # CONFIG_I2C_I810 is not set | 636 | # CONFIG_I2C_I810 is not set |
637 | # CONFIG_I2C_PIIX4 is not set | 637 | # CONFIG_I2C_PIIX4 is not set |
638 | # CONFIG_I2C_ISA is not set | 638 | # CONFIG_I2C_ISA is not set |
639 | # CONFIG_I2C_IXP2000 is not set | 639 | CONFIG_I2C_IXP2000=y |
640 | # CONFIG_I2C_NFORCE2 is not set | 640 | # CONFIG_I2C_NFORCE2 is not set |
641 | # CONFIG_I2C_PARPORT_LIGHT is not set | 641 | # CONFIG_I2C_PARPORT_LIGHT is not set |
642 | # CONFIG_I2C_PROSAVAGE is not set | 642 | # CONFIG_I2C_PROSAVAGE is not set |
@@ -650,11 +650,28 @@ CONFIG_I2C_ALGOBIT=y | |||
650 | # CONFIG_I2C_VIAPRO is not set | 650 | # CONFIG_I2C_VIAPRO is not set |
651 | # CONFIG_I2C_VOODOO3 is not set | 651 | # CONFIG_I2C_VOODOO3 is not set |
652 | # CONFIG_I2C_PCA_ISA is not set | 652 | # CONFIG_I2C_PCA_ISA is not set |
653 | CONFIG_I2C_SENSOR=y | ||
653 | 654 | ||
654 | # | 655 | # |
655 | # Hardware Sensors Chip support | 656 | # Miscellaneous I2C Chip support |
656 | # | 657 | # |
657 | CONFIG_I2C_SENSOR=y | 658 | # CONFIG_SENSORS_DS1337 is not set |
659 | # CONFIG_SENSORS_DS1374 is not set | ||
660 | CONFIG_SENSORS_EEPROM=y | ||
661 | # CONFIG_SENSORS_PCF8574 is not set | ||
662 | # CONFIG_SENSORS_PCA9539 is not set | ||
663 | # CONFIG_SENSORS_PCF8591 is not set | ||
664 | # CONFIG_SENSORS_RTC8564 is not set | ||
665 | # CONFIG_SENSORS_MAX6875 is not set | ||
666 | # CONFIG_I2C_DEBUG_CORE is not set | ||
667 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
668 | # CONFIG_I2C_DEBUG_BUS is not set | ||
669 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
670 | |||
671 | # | ||
672 | # Hardware Monitoring support | ||
673 | # | ||
674 | CONFIG_HWMON=y | ||
658 | # CONFIG_SENSORS_ADM1021 is not set | 675 | # CONFIG_SENSORS_ADM1021 is not set |
659 | # CONFIG_SENSORS_ADM1025 is not set | 676 | # CONFIG_SENSORS_ADM1025 is not set |
660 | # CONFIG_SENSORS_ADM1026 is not set | 677 | # CONFIG_SENSORS_ADM1026 is not set |
@@ -680,30 +697,15 @@ CONFIG_I2C_SENSOR=y | |||
680 | # CONFIG_SENSORS_LM92 is not set | 697 | # CONFIG_SENSORS_LM92 is not set |
681 | # CONFIG_SENSORS_MAX1619 is not set | 698 | # CONFIG_SENSORS_MAX1619 is not set |
682 | # CONFIG_SENSORS_PC87360 is not set | 699 | # CONFIG_SENSORS_PC87360 is not set |
683 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
684 | # CONFIG_SENSORS_SIS5595 is not set | 700 | # CONFIG_SENSORS_SIS5595 is not set |
685 | # CONFIG_SENSORS_SMSC47M1 is not set | 701 | # CONFIG_SENSORS_SMSC47M1 is not set |
702 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
686 | # CONFIG_SENSORS_VIA686A is not set | 703 | # CONFIG_SENSORS_VIA686A is not set |
687 | # CONFIG_SENSORS_W83781D is not set | 704 | # CONFIG_SENSORS_W83781D is not set |
688 | # CONFIG_SENSORS_W83L785TS is not set | 705 | # CONFIG_SENSORS_W83L785TS is not set |
689 | # CONFIG_SENSORS_W83627HF is not set | 706 | # CONFIG_SENSORS_W83627HF is not set |
690 | # CONFIG_SENSORS_W83627EHF is not set | 707 | # CONFIG_SENSORS_W83627EHF is not set |
691 | 708 | # CONFIG_HWMON_DEBUG_CHIP is not set | |
692 | # | ||
693 | # Other I2C Chip support | ||
694 | # | ||
695 | # CONFIG_SENSORS_DS1337 is not set | ||
696 | # CONFIG_SENSORS_DS1374 is not set | ||
697 | CONFIG_SENSORS_EEPROM=y | ||
698 | # CONFIG_SENSORS_PCF8574 is not set | ||
699 | # CONFIG_SENSORS_PCA9539 is not set | ||
700 | # CONFIG_SENSORS_PCF8591 is not set | ||
701 | # CONFIG_SENSORS_RTC8564 is not set | ||
702 | # CONFIG_SENSORS_MAX6875 is not set | ||
703 | # CONFIG_I2C_DEBUG_CORE is not set | ||
704 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
705 | # CONFIG_I2C_DEBUG_BUS is not set | ||
706 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
707 | 709 | ||
708 | # | 710 | # |
709 | # Misc devices | 711 | # Misc devices |
@@ -771,6 +773,7 @@ CONFIG_FS_POSIX_ACL=y | |||
771 | # CONFIG_XFS_FS is not set | 773 | # CONFIG_XFS_FS is not set |
772 | # CONFIG_MINIX_FS is not set | 774 | # CONFIG_MINIX_FS is not set |
773 | # CONFIG_ROMFS_FS is not set | 775 | # CONFIG_ROMFS_FS is not set |
776 | CONFIG_INOTIFY=y | ||
774 | # CONFIG_QUOTA is not set | 777 | # CONFIG_QUOTA is not set |
775 | CONFIG_DNOTIFY=y | 778 | CONFIG_DNOTIFY=y |
776 | # CONFIG_AUTOFS_FS is not set | 779 | # CONFIG_AUTOFS_FS is not set |
@@ -813,8 +816,7 @@ CONFIG_RAMFS=y | |||
813 | # CONFIG_JFFS_FS is not set | 816 | # CONFIG_JFFS_FS is not set |
814 | CONFIG_JFFS2_FS=y | 817 | CONFIG_JFFS2_FS=y |
815 | CONFIG_JFFS2_FS_DEBUG=0 | 818 | CONFIG_JFFS2_FS_DEBUG=0 |
816 | # CONFIG_JFFS2_FS_NAND is not set | 819 | CONFIG_JFFS2_FS_WRITEBUFFER=y |
817 | # CONFIG_JFFS2_FS_NOR_ECC is not set | ||
818 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set | 820 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set |
819 | CONFIG_JFFS2_ZLIB=y | 821 | CONFIG_JFFS2_ZLIB=y |
820 | CONFIG_JFFS2_RTIME=y | 822 | CONFIG_JFFS2_RTIME=y |
diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig index 2d6f960e3395..12ef23d1c016 100644 --- a/arch/arm/configs/ixdp2801_defconfig +++ b/arch/arm/configs/ixdp2801_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.13-rc2 | 3 | # Linux kernel version: 2.6.13 |
4 | # Thu Jul 7 16:49:13 2005 | 4 | # Wed Sep 14 10:52:16 2005 |
5 | # | 5 | # |
6 | CONFIG_ARM=y | 6 | CONFIG_ARM=y |
7 | CONFIG_MMU=y | 7 | CONFIG_MMU=y |
@@ -136,7 +136,6 @@ CONFIG_PCI_NAMES=y | |||
136 | # | 136 | # |
137 | # Kernel Features | 137 | # Kernel Features |
138 | # | 138 | # |
139 | # CONFIG_SMP is not set | ||
140 | # CONFIG_PREEMPT is not set | 139 | # CONFIG_PREEMPT is not set |
141 | # CONFIG_NO_IDLE_HZ is not set | 140 | # CONFIG_NO_IDLE_HZ is not set |
142 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set | 141 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set |
@@ -180,6 +179,68 @@ CONFIG_BINFMT_ELF=y | |||
180 | # CONFIG_PM is not set | 179 | # CONFIG_PM is not set |
181 | 180 | ||
182 | # | 181 | # |
182 | # Networking | ||
183 | # | ||
184 | CONFIG_NET=y | ||
185 | |||
186 | # | ||
187 | # Networking options | ||
188 | # | ||
189 | CONFIG_PACKET=y | ||
190 | CONFIG_PACKET_MMAP=y | ||
191 | CONFIG_UNIX=y | ||
192 | # CONFIG_NET_KEY is not set | ||
193 | CONFIG_INET=y | ||
194 | # CONFIG_IP_MULTICAST is not set | ||
195 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
196 | CONFIG_IP_FIB_HASH=y | ||
197 | CONFIG_IP_PNP=y | ||
198 | CONFIG_IP_PNP_DHCP=y | ||
199 | CONFIG_IP_PNP_BOOTP=y | ||
200 | # CONFIG_IP_PNP_RARP is not set | ||
201 | # CONFIG_NET_IPIP is not set | ||
202 | # CONFIG_NET_IPGRE is not set | ||
203 | # CONFIG_ARPD is not set | ||
204 | CONFIG_SYN_COOKIES=y | ||
205 | # CONFIG_INET_AH is not set | ||
206 | # CONFIG_INET_ESP is not set | ||
207 | # CONFIG_INET_IPCOMP is not set | ||
208 | # CONFIG_INET_TUNNEL is not set | ||
209 | # CONFIG_IP_TCPDIAG is not set | ||
210 | # CONFIG_IP_TCPDIAG_IPV6 is not set | ||
211 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
212 | CONFIG_TCP_CONG_BIC=y | ||
213 | # CONFIG_IPV6 is not set | ||
214 | # CONFIG_NETFILTER is not set | ||
215 | |||
216 | # | ||
217 | # SCTP Configuration (EXPERIMENTAL) | ||
218 | # | ||
219 | # CONFIG_IP_SCTP is not set | ||
220 | # CONFIG_ATM is not set | ||
221 | # CONFIG_BRIDGE is not set | ||
222 | # CONFIG_VLAN_8021Q is not set | ||
223 | # CONFIG_DECNET is not set | ||
224 | # CONFIG_LLC2 is not set | ||
225 | # CONFIG_IPX is not set | ||
226 | # CONFIG_ATALK is not set | ||
227 | # CONFIG_X25 is not set | ||
228 | # CONFIG_LAPB is not set | ||
229 | # CONFIG_NET_DIVERT is not set | ||
230 | # CONFIG_ECONET is not set | ||
231 | # CONFIG_WAN_ROUTER is not set | ||
232 | # CONFIG_NET_SCHED is not set | ||
233 | # CONFIG_NET_CLS_ROUTE is not set | ||
234 | |||
235 | # | ||
236 | # Network testing | ||
237 | # | ||
238 | # CONFIG_NET_PKTGEN is not set | ||
239 | # CONFIG_HAMRADIO is not set | ||
240 | # CONFIG_IRDA is not set | ||
241 | # CONFIG_BT is not set | ||
242 | |||
243 | # | ||
183 | # Device Drivers | 244 | # Device Drivers |
184 | # | 245 | # |
185 | 246 | ||
@@ -249,6 +310,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y | |||
249 | CONFIG_MTD_IXP2000=y | 310 | CONFIG_MTD_IXP2000=y |
250 | # CONFIG_MTD_EDB7312 is not set | 311 | # CONFIG_MTD_EDB7312 is not set |
251 | # CONFIG_MTD_PCI is not set | 312 | # CONFIG_MTD_PCI is not set |
313 | # CONFIG_MTD_PLATRAM is not set | ||
252 | 314 | ||
253 | # | 315 | # |
254 | # Self-contained MTD device drivers | 316 | # Self-contained MTD device drivers |
@@ -335,72 +397,8 @@ CONFIG_IOSCHED_CFQ=y | |||
335 | # CONFIG_I2O is not set | 397 | # CONFIG_I2O is not set |
336 | 398 | ||
337 | # | 399 | # |
338 | # Networking support | 400 | # Network device support |
339 | # | ||
340 | CONFIG_NET=y | ||
341 | |||
342 | # | ||
343 | # Networking options | ||
344 | # | ||
345 | CONFIG_PACKET=y | ||
346 | CONFIG_PACKET_MMAP=y | ||
347 | CONFIG_UNIX=y | ||
348 | # CONFIG_NET_KEY is not set | ||
349 | CONFIG_INET=y | ||
350 | # CONFIG_IP_MULTICAST is not set | ||
351 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
352 | CONFIG_IP_FIB_HASH=y | ||
353 | CONFIG_IP_PNP=y | ||
354 | CONFIG_IP_PNP_DHCP=y | ||
355 | CONFIG_IP_PNP_BOOTP=y | ||
356 | # CONFIG_IP_PNP_RARP is not set | ||
357 | # CONFIG_NET_IPIP is not set | ||
358 | # CONFIG_NET_IPGRE is not set | ||
359 | # CONFIG_ARPD is not set | ||
360 | CONFIG_SYN_COOKIES=y | ||
361 | # CONFIG_INET_AH is not set | ||
362 | # CONFIG_INET_ESP is not set | ||
363 | # CONFIG_INET_IPCOMP is not set | ||
364 | # CONFIG_INET_TUNNEL is not set | ||
365 | # CONFIG_IP_TCPDIAG is not set | ||
366 | # CONFIG_IP_TCPDIAG_IPV6 is not set | ||
367 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
368 | CONFIG_TCP_CONG_BIC=y | ||
369 | # CONFIG_IPV6 is not set | ||
370 | # CONFIG_NETFILTER is not set | ||
371 | |||
372 | # | ||
373 | # SCTP Configuration (EXPERIMENTAL) | ||
374 | # | ||
375 | # CONFIG_IP_SCTP is not set | ||
376 | # CONFIG_ATM is not set | ||
377 | # CONFIG_BRIDGE is not set | ||
378 | # CONFIG_VLAN_8021Q is not set | ||
379 | # CONFIG_DECNET is not set | ||
380 | # CONFIG_LLC2 is not set | ||
381 | # CONFIG_IPX is not set | ||
382 | # CONFIG_ATALK is not set | ||
383 | # CONFIG_X25 is not set | ||
384 | # CONFIG_LAPB is not set | ||
385 | # CONFIG_NET_DIVERT is not set | ||
386 | # CONFIG_ECONET is not set | ||
387 | # CONFIG_WAN_ROUTER is not set | ||
388 | |||
389 | # | ||
390 | # QoS and/or fair queueing | ||
391 | # | ||
392 | # CONFIG_NET_SCHED is not set | ||
393 | # CONFIG_NET_CLS_ROUTE is not set | ||
394 | |||
395 | # | ||
396 | # Network testing | ||
397 | # | 401 | # |
398 | # CONFIG_NET_PKTGEN is not set | ||
399 | # CONFIG_NETPOLL is not set | ||
400 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
401 | # CONFIG_HAMRADIO is not set | ||
402 | # CONFIG_IRDA is not set | ||
403 | # CONFIG_BT is not set | ||
404 | CONFIG_NETDEVICES=y | 402 | CONFIG_NETDEVICES=y |
405 | CONFIG_DUMMY=y | 403 | CONFIG_DUMMY=y |
406 | # CONFIG_BONDING is not set | 404 | # CONFIG_BONDING is not set |
@@ -511,6 +509,8 @@ CONFIG_DLCI_MAX=8 | |||
511 | # CONFIG_SLIP is not set | 509 | # CONFIG_SLIP is not set |
512 | # CONFIG_SHAPER is not set | 510 | # CONFIG_SHAPER is not set |
513 | # CONFIG_NETCONSOLE is not set | 511 | # CONFIG_NETCONSOLE is not set |
512 | # CONFIG_NETPOLL is not set | ||
513 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
514 | 514 | ||
515 | # | 515 | # |
516 | # ISDN subsystem | 516 | # ISDN subsystem |
@@ -637,7 +637,7 @@ CONFIG_I2C_ALGOBIT=y | |||
637 | # CONFIG_I2C_I810 is not set | 637 | # CONFIG_I2C_I810 is not set |
638 | # CONFIG_I2C_PIIX4 is not set | 638 | # CONFIG_I2C_PIIX4 is not set |
639 | # CONFIG_I2C_ISA is not set | 639 | # CONFIG_I2C_ISA is not set |
640 | # CONFIG_I2C_IXP2000 is not set | 640 | CONFIG_I2C_IXP2000=y |
641 | # CONFIG_I2C_NFORCE2 is not set | 641 | # CONFIG_I2C_NFORCE2 is not set |
642 | # CONFIG_I2C_PARPORT_LIGHT is not set | 642 | # CONFIG_I2C_PARPORT_LIGHT is not set |
643 | # CONFIG_I2C_PROSAVAGE is not set | 643 | # CONFIG_I2C_PROSAVAGE is not set |
@@ -651,11 +651,28 @@ CONFIG_I2C_ALGOBIT=y | |||
651 | # CONFIG_I2C_VIAPRO is not set | 651 | # CONFIG_I2C_VIAPRO is not set |
652 | # CONFIG_I2C_VOODOO3 is not set | 652 | # CONFIG_I2C_VOODOO3 is not set |
653 | # CONFIG_I2C_PCA_ISA is not set | 653 | # CONFIG_I2C_PCA_ISA is not set |
654 | CONFIG_I2C_SENSOR=y | ||
654 | 655 | ||
655 | # | 656 | # |
656 | # Hardware Sensors Chip support | 657 | # Miscellaneous I2C Chip support |
657 | # | 658 | # |
658 | CONFIG_I2C_SENSOR=y | 659 | # CONFIG_SENSORS_DS1337 is not set |
660 | # CONFIG_SENSORS_DS1374 is not set | ||
661 | CONFIG_SENSORS_EEPROM=y | ||
662 | # CONFIG_SENSORS_PCF8574 is not set | ||
663 | # CONFIG_SENSORS_PCA9539 is not set | ||
664 | # CONFIG_SENSORS_PCF8591 is not set | ||
665 | # CONFIG_SENSORS_RTC8564 is not set | ||
666 | # CONFIG_SENSORS_MAX6875 is not set | ||
667 | # CONFIG_I2C_DEBUG_CORE is not set | ||
668 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
669 | # CONFIG_I2C_DEBUG_BUS is not set | ||
670 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
671 | |||
672 | # | ||
673 | # Hardware Monitoring support | ||
674 | # | ||
675 | CONFIG_HWMON=y | ||
659 | # CONFIG_SENSORS_ADM1021 is not set | 676 | # CONFIG_SENSORS_ADM1021 is not set |
660 | # CONFIG_SENSORS_ADM1025 is not set | 677 | # CONFIG_SENSORS_ADM1025 is not set |
661 | # CONFIG_SENSORS_ADM1026 is not set | 678 | # CONFIG_SENSORS_ADM1026 is not set |
@@ -681,30 +698,15 @@ CONFIG_I2C_SENSOR=y | |||
681 | # CONFIG_SENSORS_LM92 is not set | 698 | # CONFIG_SENSORS_LM92 is not set |
682 | # CONFIG_SENSORS_MAX1619 is not set | 699 | # CONFIG_SENSORS_MAX1619 is not set |
683 | # CONFIG_SENSORS_PC87360 is not set | 700 | # CONFIG_SENSORS_PC87360 is not set |
684 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
685 | # CONFIG_SENSORS_SIS5595 is not set | 701 | # CONFIG_SENSORS_SIS5595 is not set |
686 | # CONFIG_SENSORS_SMSC47M1 is not set | 702 | # CONFIG_SENSORS_SMSC47M1 is not set |
703 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
687 | # CONFIG_SENSORS_VIA686A is not set | 704 | # CONFIG_SENSORS_VIA686A is not set |
688 | # CONFIG_SENSORS_W83781D is not set | 705 | # CONFIG_SENSORS_W83781D is not set |
689 | # CONFIG_SENSORS_W83L785TS is not set | 706 | # CONFIG_SENSORS_W83L785TS is not set |
690 | # CONFIG_SENSORS_W83627HF is not set | 707 | # CONFIG_SENSORS_W83627HF is not set |
691 | # CONFIG_SENSORS_W83627EHF is not set | 708 | # CONFIG_SENSORS_W83627EHF is not set |
692 | 709 | # CONFIG_HWMON_DEBUG_CHIP is not set | |
693 | # | ||
694 | # Other I2C Chip support | ||
695 | # | ||
696 | # CONFIG_SENSORS_DS1337 is not set | ||
697 | # CONFIG_SENSORS_DS1374 is not set | ||
698 | CONFIG_SENSORS_EEPROM=y | ||
699 | # CONFIG_SENSORS_PCF8574 is not set | ||
700 | # CONFIG_SENSORS_PCA9539 is not set | ||
701 | # CONFIG_SENSORS_PCF8591 is not set | ||
702 | # CONFIG_SENSORS_RTC8564 is not set | ||
703 | # CONFIG_SENSORS_MAX6875 is not set | ||
704 | # CONFIG_I2C_DEBUG_CORE is not set | ||
705 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
706 | # CONFIG_I2C_DEBUG_BUS is not set | ||
707 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
708 | 710 | ||
709 | # | 711 | # |
710 | # Misc devices | 712 | # Misc devices |
@@ -772,6 +774,7 @@ CONFIG_FS_POSIX_ACL=y | |||
772 | # CONFIG_XFS_FS is not set | 774 | # CONFIG_XFS_FS is not set |
773 | # CONFIG_MINIX_FS is not set | 775 | # CONFIG_MINIX_FS is not set |
774 | # CONFIG_ROMFS_FS is not set | 776 | # CONFIG_ROMFS_FS is not set |
777 | CONFIG_INOTIFY=y | ||
775 | # CONFIG_QUOTA is not set | 778 | # CONFIG_QUOTA is not set |
776 | CONFIG_DNOTIFY=y | 779 | CONFIG_DNOTIFY=y |
777 | # CONFIG_AUTOFS_FS is not set | 780 | # CONFIG_AUTOFS_FS is not set |
@@ -814,8 +817,7 @@ CONFIG_RAMFS=y | |||
814 | # CONFIG_JFFS_FS is not set | 817 | # CONFIG_JFFS_FS is not set |
815 | CONFIG_JFFS2_FS=y | 818 | CONFIG_JFFS2_FS=y |
816 | CONFIG_JFFS2_FS_DEBUG=0 | 819 | CONFIG_JFFS2_FS_DEBUG=0 |
817 | # CONFIG_JFFS2_FS_NAND is not set | 820 | CONFIG_JFFS2_FS_WRITEBUFFER=y |
818 | # CONFIG_JFFS2_FS_NOR_ECC is not set | ||
819 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set | 821 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set |
820 | CONFIG_JFFS2_ZLIB=y | 822 | CONFIG_JFFS2_ZLIB=y |
821 | CONFIG_JFFS2_RTIME=y | 823 | CONFIG_JFFS2_RTIME=y |
diff --git a/arch/arm/kernel/semaphore.c b/arch/arm/kernel/semaphore.c index ac423e3e224b..4c31f2923055 100644 --- a/arch/arm/kernel/semaphore.c +++ b/arch/arm/kernel/semaphore.c | |||
@@ -178,7 +178,7 @@ int __down_trylock(struct semaphore * sem) | |||
178 | * registers (r0 to r3 and lr), but not ip, as we use it as a return | 178 | * registers (r0 to r3 and lr), but not ip, as we use it as a return |
179 | * value in some cases.. | 179 | * value in some cases.. |
180 | */ | 180 | */ |
181 | asm(" .section .sched.text,\"ax\" \n\ | 181 | asm(" .section .sched.text,\"ax\",%progbits \n\ |
182 | .align 5 \n\ | 182 | .align 5 \n\ |
183 | .globl __down_failed \n\ | 183 | .globl __down_failed \n\ |
184 | __down_failed: \n\ | 184 | __down_failed: \n\ |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 4554c961251c..e7d22dbcb691 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -624,6 +624,9 @@ void __attribute__((noreturn)) __bug(const char *file, int line, void *data) | |||
624 | printk(" - extra data = %p", data); | 624 | printk(" - extra data = %p", data); |
625 | printk("\n"); | 625 | printk("\n"); |
626 | *(int *)0 = 0; | 626 | *(int *)0 = 0; |
627 | |||
628 | /* Avoid "noreturn function does return" */ | ||
629 | for (;;); | ||
627 | } | 630 | } |
628 | EXPORT_SYMBOL(__bug); | 631 | EXPORT_SYMBOL(__bug); |
629 | 632 | ||
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index ad2d66c93a5c..08e58ecd44be 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -23,20 +23,20 @@ SECTIONS | |||
23 | *(.init.text) | 23 | *(.init.text) |
24 | _einittext = .; | 24 | _einittext = .; |
25 | __proc_info_begin = .; | 25 | __proc_info_begin = .; |
26 | *(.proc.info) | 26 | *(.proc.info.init) |
27 | __proc_info_end = .; | 27 | __proc_info_end = .; |
28 | __arch_info_begin = .; | 28 | __arch_info_begin = .; |
29 | *(.arch.info) | 29 | *(.arch.info.init) |
30 | __arch_info_end = .; | 30 | __arch_info_end = .; |
31 | __tagtable_begin = .; | 31 | __tagtable_begin = .; |
32 | *(.taglist) | 32 | *(.taglist.init) |
33 | __tagtable_end = .; | 33 | __tagtable_end = .; |
34 | . = ALIGN(16); | 34 | . = ALIGN(16); |
35 | __setup_start = .; | 35 | __setup_start = .; |
36 | *(.init.setup) | 36 | *(.init.setup) |
37 | __setup_end = .; | 37 | __setup_end = .; |
38 | __early_begin = .; | 38 | __early_begin = .; |
39 | *(__early_param) | 39 | *(.early_param.init) |
40 | __early_end = .; | 40 | __early_end = .; |
41 | __initcall_start = .; | 41 | __initcall_start = .; |
42 | *(.initcall1.init) | 42 | *(.initcall1.init) |
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index ae1fa099d5fa..39b06ed80646 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c | |||
@@ -123,6 +123,7 @@ static void __init ixdp425_init(void) | |||
123 | platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices)); | 123 | platform_add_devices(ixdp425_devices, ARRAY_SIZE(ixdp425_devices)); |
124 | } | 124 | } |
125 | 125 | ||
126 | #ifdef CONFIG_ARCH_IXDP465 | ||
126 | MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") | 127 | MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") |
127 | /* Maintainer: MontaVista Software, Inc. */ | 128 | /* Maintainer: MontaVista Software, Inc. */ |
128 | .phys_ram = PHYS_OFFSET, | 129 | .phys_ram = PHYS_OFFSET, |
@@ -134,7 +135,9 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") | |||
134 | .boot_params = 0x0100, | 135 | .boot_params = 0x0100, |
135 | .init_machine = ixdp425_init, | 136 | .init_machine = ixdp425_init, |
136 | MACHINE_END | 137 | MACHINE_END |
138 | #endif | ||
137 | 139 | ||
140 | #ifdef CONFIG_MACH_IXDP465 | ||
138 | MACHINE_START(IXDP465, "Intel IXDP465 Development Platform") | 141 | MACHINE_START(IXDP465, "Intel IXDP465 Development Platform") |
139 | /* Maintainer: MontaVista Software, Inc. */ | 142 | /* Maintainer: MontaVista Software, Inc. */ |
140 | .phys_ram = PHYS_OFFSET, | 143 | .phys_ram = PHYS_OFFSET, |
@@ -146,7 +149,9 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform") | |||
146 | .boot_params = 0x0100, | 149 | .boot_params = 0x0100, |
147 | .init_machine = ixdp425_init, | 150 | .init_machine = ixdp425_init, |
148 | MACHINE_END | 151 | MACHINE_END |
152 | #endif | ||
149 | 153 | ||
154 | #ifdef CONFIG_ARCH_PRPMC1100 | ||
150 | MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") | 155 | MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") |
151 | /* Maintainer: MontaVista Software, Inc. */ | 156 | /* Maintainer: MontaVista Software, Inc. */ |
152 | .phys_ram = PHYS_OFFSET, | 157 | .phys_ram = PHYS_OFFSET, |
@@ -158,6 +163,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") | |||
158 | .boot_params = 0x0100, | 163 | .boot_params = 0x0100, |
159 | .init_machine = ixdp425_init, | 164 | .init_machine = ixdp425_init, |
160 | MACHINE_END | 165 | MACHINE_END |
166 | #endif | ||
161 | 167 | ||
162 | /* | 168 | /* |
163 | * Avila is functionally equivalent to IXDP425 except that it adds | 169 | * Avila is functionally equivalent to IXDP425 except that it adds |
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 426c2bc517eb..be37586cb1b0 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c | |||
@@ -198,13 +198,10 @@ static void corgi_mci_setpower(struct device *dev, unsigned int vdd) | |||
198 | { | 198 | { |
199 | struct pxamci_platform_data* p_d = dev->platform_data; | 199 | struct pxamci_platform_data* p_d = dev->platform_data; |
200 | 200 | ||
201 | if (( 1 << vdd) & p_d->ocr_mask) { | 201 | if (( 1 << vdd) & p_d->ocr_mask) |
202 | printk(KERN_DEBUG "%s: on\n", __FUNCTION__); | ||
203 | GPSR1 = GPIO_bit(CORGI_GPIO_SD_PWR); | 202 | GPSR1 = GPIO_bit(CORGI_GPIO_SD_PWR); |
204 | } else { | 203 | else |
205 | printk(KERN_DEBUG "%s: off\n", __FUNCTION__); | ||
206 | GPCR1 = GPIO_bit(CORGI_GPIO_SD_PWR); | 204 | GPCR1 = GPIO_bit(CORGI_GPIO_SD_PWR); |
207 | } | ||
208 | } | 205 | } |
209 | 206 | ||
210 | static int corgi_mci_get_ro(struct device *dev) | 207 | static int corgi_mci_get_ro(struct device *dev) |
@@ -259,6 +256,16 @@ static struct platform_device *devices[] __initdata = { | |||
259 | 256 | ||
260 | static void __init corgi_init(void) | 257 | static void __init corgi_init(void) |
261 | { | 258 | { |
259 | /* setup sleep mode values */ | ||
260 | PWER = 0x00000002; | ||
261 | PFER = 0x00000000; | ||
262 | PRER = 0x00000002; | ||
263 | PGSR0 = 0x0158C000; | ||
264 | PGSR1 = 0x00FF0080; | ||
265 | PGSR2 = 0x0001C004; | ||
266 | /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ | ||
267 | PCFR |= PCFR_OPDE; | ||
268 | |||
262 | corgi_ssp_set_machinfo(&corgi_ssp_machinfo); | 269 | corgi_ssp_set_machinfo(&corgi_ssp_machinfo); |
263 | 270 | ||
264 | pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT); | 271 | pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT); |
@@ -285,42 +292,14 @@ static void __init fixup_corgi(struct machine_desc *desc, | |||
285 | mi->bank[0].size = (64*1024*1024); | 292 | mi->bank[0].size = (64*1024*1024); |
286 | } | 293 | } |
287 | 294 | ||
288 | static void __init corgi_init_irq(void) | ||
289 | { | ||
290 | pxa_init_irq(); | ||
291 | } | ||
292 | |||
293 | static struct map_desc corgi_io_desc[] __initdata = { | ||
294 | /* virtual physical length */ | ||
295 | /* { 0xf1000000, 0x08000000, 0x01000000, MT_DEVICE },*/ /* LCDC (readable for Qt driver) */ | ||
296 | /* { 0xef700000, 0x10800000, 0x00001000, MT_DEVICE },*/ /* SCOOP */ | ||
297 | { 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */ | ||
298 | }; | ||
299 | |||
300 | static void __init corgi_map_io(void) | ||
301 | { | ||
302 | pxa_map_io(); | ||
303 | iotable_init(corgi_io_desc,ARRAY_SIZE(corgi_io_desc)); | ||
304 | |||
305 | /* setup sleep mode values */ | ||
306 | PWER = 0x00000002; | ||
307 | PFER = 0x00000000; | ||
308 | PRER = 0x00000002; | ||
309 | PGSR0 = 0x0158C000; | ||
310 | PGSR1 = 0x00FF0080; | ||
311 | PGSR2 = 0x0001C004; | ||
312 | /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ | ||
313 | PCFR |= PCFR_OPDE; | ||
314 | } | ||
315 | |||
316 | #ifdef CONFIG_MACH_CORGI | 295 | #ifdef CONFIG_MACH_CORGI |
317 | MACHINE_START(CORGI, "SHARP Corgi") | 296 | MACHINE_START(CORGI, "SHARP Corgi") |
318 | .phys_ram = 0xa0000000, | 297 | .phys_ram = 0xa0000000, |
319 | .phys_io = 0x40000000, | 298 | .phys_io = 0x40000000, |
320 | .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, | 299 | .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, |
321 | .fixup = fixup_corgi, | 300 | .fixup = fixup_corgi, |
322 | .map_io = corgi_map_io, | 301 | .map_io = pxa_map_io, |
323 | .init_irq = corgi_init_irq, | 302 | .init_irq = pxa_init_irq, |
324 | .init_machine = corgi_init, | 303 | .init_machine = corgi_init, |
325 | .timer = &pxa_timer, | 304 | .timer = &pxa_timer, |
326 | MACHINE_END | 305 | MACHINE_END |
@@ -332,8 +311,8 @@ MACHINE_START(SHEPHERD, "SHARP Shepherd") | |||
332 | .phys_io = 0x40000000, | 311 | .phys_io = 0x40000000, |
333 | .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, | 312 | .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, |
334 | .fixup = fixup_corgi, | 313 | .fixup = fixup_corgi, |
335 | .map_io = corgi_map_io, | 314 | .map_io = pxa_map_io, |
336 | .init_irq = corgi_init_irq, | 315 | .init_irq = pxa_init_irq, |
337 | .init_machine = corgi_init, | 316 | .init_machine = corgi_init, |
338 | .timer = &pxa_timer, | 317 | .timer = &pxa_timer, |
339 | MACHINE_END | 318 | MACHINE_END |
@@ -345,8 +324,8 @@ MACHINE_START(HUSKY, "SHARP Husky") | |||
345 | .phys_io = 0x40000000, | 324 | .phys_io = 0x40000000, |
346 | .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, | 325 | .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, |
347 | .fixup = fixup_corgi, | 326 | .fixup = fixup_corgi, |
348 | .map_io = corgi_map_io, | 327 | .map_io = pxa_map_io, |
349 | .init_irq = corgi_init_irq, | 328 | .init_irq = pxa_init_irq, |
350 | .init_machine = corgi_init, | 329 | .init_machine = corgi_init, |
351 | .timer = &pxa_timer, | 330 | .timer = &pxa_timer, |
352 | MACHINE_END | 331 | MACHINE_END |
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 923f6eb774c0..1f38033921e9 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c | |||
@@ -146,6 +146,11 @@ static struct pxa2xx_udc_mach_info udc_info __initdata = { | |||
146 | // no D+ pullup; lubbock can't connect/disconnect in software | 146 | // no D+ pullup; lubbock can't connect/disconnect in software |
147 | }; | 147 | }; |
148 | 148 | ||
149 | static struct platform_device lub_audio_device = { | ||
150 | .name = "pxa2xx-ac97", | ||
151 | .id = -1, | ||
152 | }; | ||
153 | |||
149 | static struct resource sa1111_resources[] = { | 154 | static struct resource sa1111_resources[] = { |
150 | [0] = { | 155 | [0] = { |
151 | .start = 0x10000000, | 156 | .start = 0x10000000, |
@@ -195,6 +200,7 @@ static struct platform_device smc91x_device = { | |||
195 | 200 | ||
196 | static struct platform_device *devices[] __initdata = { | 201 | static struct platform_device *devices[] __initdata = { |
197 | &sa1111_device, | 202 | &sa1111_device, |
203 | &lub_audio_device, | ||
198 | &smc91x_device, | 204 | &smc91x_device, |
199 | }; | 205 | }; |
200 | 206 | ||
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 47cfb8bb8318..f25638810017 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c | |||
@@ -30,6 +30,8 @@ | |||
30 | 30 | ||
31 | #include <asm/arch/pxa-regs.h> | 31 | #include <asm/arch/pxa-regs.h> |
32 | #include <asm/arch/irq.h> | 32 | #include <asm/arch/irq.h> |
33 | #include <asm/arch/mmc.h> | ||
34 | #include <asm/arch/udc.h> | ||
33 | #include <asm/arch/poodle.h> | 35 | #include <asm/arch/poodle.h> |
34 | #include <asm/arch/pxafb.h> | 36 | #include <asm/arch/pxafb.h> |
35 | 37 | ||
@@ -93,6 +95,83 @@ static struct platform_device locomo_device = { | |||
93 | .resource = locomo_resources, | 95 | .resource = locomo_resources, |
94 | }; | 96 | }; |
95 | 97 | ||
98 | |||
99 | /* | ||
100 | * MMC/SD Device | ||
101 | * | ||
102 | * The card detect interrupt isn't debounced so we delay it by 250ms | ||
103 | * to give the card a chance to fully insert/eject. | ||
104 | */ | ||
105 | static struct pxamci_platform_data poodle_mci_platform_data; | ||
106 | |||
107 | static int poodle_mci_init(struct device *dev, irqreturn_t (*poodle_detect_int)(int, void *, struct pt_regs *), void *data) | ||
108 | { | ||
109 | int err; | ||
110 | |||
111 | /* setup GPIO for PXA25x MMC controller */ | ||
112 | pxa_gpio_mode(GPIO6_MMCCLK_MD); | ||
113 | pxa_gpio_mode(GPIO8_MMCCS0_MD); | ||
114 | pxa_gpio_mode(POODLE_GPIO_nSD_DETECT | GPIO_IN); | ||
115 | pxa_gpio_mode(POODLE_GPIO_SD_PWR | GPIO_OUT); | ||
116 | |||
117 | poodle_mci_platform_data.detect_delay = msecs_to_jiffies(250); | ||
118 | |||
119 | err = request_irq(POODLE_IRQ_GPIO_nSD_DETECT, poodle_detect_int, SA_INTERRUPT, | ||
120 | "MMC card detect", data); | ||
121 | if (err) { | ||
122 | printk(KERN_ERR "poodle_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); | ||
123 | return -1; | ||
124 | } | ||
125 | |||
126 | set_irq_type(POODLE_IRQ_GPIO_nSD_DETECT, IRQT_BOTHEDGE); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static void poodle_mci_setpower(struct device *dev, unsigned int vdd) | ||
132 | { | ||
133 | struct pxamci_platform_data* p_d = dev->platform_data; | ||
134 | |||
135 | if (( 1 << vdd) & p_d->ocr_mask) | ||
136 | GPSR1 = GPIO_bit(POODLE_GPIO_SD_PWR); | ||
137 | else | ||
138 | GPCR1 = GPIO_bit(POODLE_GPIO_SD_PWR); | ||
139 | } | ||
140 | |||
141 | static void poodle_mci_exit(struct device *dev, void *data) | ||
142 | { | ||
143 | free_irq(POODLE_IRQ_GPIO_nSD_DETECT, data); | ||
144 | } | ||
145 | |||
146 | static struct pxamci_platform_data poodle_mci_platform_data = { | ||
147 | .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, | ||
148 | .init = poodle_mci_init, | ||
149 | .setpower = poodle_mci_setpower, | ||
150 | .exit = poodle_mci_exit, | ||
151 | }; | ||
152 | |||
153 | |||
154 | /* | ||
155 | * USB Device Controller | ||
156 | */ | ||
157 | static void poodle_udc_command(int cmd) | ||
158 | { | ||
159 | switch(cmd) { | ||
160 | case PXA2XX_UDC_CMD_CONNECT: | ||
161 | GPSR(POODLE_GPIO_USB_PULLUP) = GPIO_bit(POODLE_GPIO_USB_PULLUP); | ||
162 | break; | ||
163 | case PXA2XX_UDC_CMD_DISCONNECT: | ||
164 | GPCR(POODLE_GPIO_USB_PULLUP) = GPIO_bit(POODLE_GPIO_USB_PULLUP); | ||
165 | break; | ||
166 | } | ||
167 | } | ||
168 | |||
169 | static struct pxa2xx_udc_mach_info udc_info __initdata = { | ||
170 | /* no connect GPIO; poodle can't tell connection status */ | ||
171 | .udc_command = poodle_udc_command, | ||
172 | }; | ||
173 | |||
174 | |||
96 | /* PXAFB device */ | 175 | /* PXAFB device */ |
97 | static struct pxafb_mach_info poodle_fb_info __initdata = { | 176 | static struct pxafb_mach_info poodle_fb_info __initdata = { |
98 | .pixclock = 144700, | 177 | .pixclock = 144700, |
@@ -126,6 +205,15 @@ static void __init poodle_init(void) | |||
126 | { | 205 | { |
127 | int ret = 0; | 206 | int ret = 0; |
128 | 207 | ||
208 | /* setup sleep mode values */ | ||
209 | PWER = 0x00000002; | ||
210 | PFER = 0x00000000; | ||
211 | PRER = 0x00000002; | ||
212 | PGSR0 = 0x00008000; | ||
213 | PGSR1 = 0x003F0202; | ||
214 | PGSR2 = 0x0001C000; | ||
215 | PCFR |= PCFR_OPDE; | ||
216 | |||
129 | /* cpu initialize */ | 217 | /* cpu initialize */ |
130 | /* Pgsr Register */ | 218 | /* Pgsr Register */ |
131 | PGSR0 = 0x0146dd80; | 219 | PGSR0 = 0x0146dd80; |
@@ -155,6 +243,9 @@ static void __init poodle_init(void) | |||
155 | GPSR2 = 0x00000000; | 243 | GPSR2 = 0x00000000; |
156 | 244 | ||
157 | set_pxa_fb_info(&poodle_fb_info); | 245 | set_pxa_fb_info(&poodle_fb_info); |
246 | pxa_gpio_mode(POODLE_GPIO_USB_PULLUP | GPIO_OUT); | ||
247 | pxa_set_udc_info(&udc_info); | ||
248 | pxa_set_mci_info(&poodle_mci_platform_data); | ||
158 | 249 | ||
159 | scoop_num = 1; | 250 | scoop_num = 1; |
160 | scoop_devs = &poodle_pcmcia_scoop[0]; | 251 | scoop_devs = &poodle_pcmcia_scoop[0]; |
@@ -171,32 +262,12 @@ static void __init fixup_poodle(struct machine_desc *desc, | |||
171 | sharpsl_save_param(); | 262 | sharpsl_save_param(); |
172 | } | 263 | } |
173 | 264 | ||
174 | static struct map_desc poodle_io_desc[] __initdata = { | ||
175 | /* virtual physical length */ | ||
176 | { 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */ | ||
177 | }; | ||
178 | |||
179 | static void __init poodle_map_io(void) | ||
180 | { | ||
181 | pxa_map_io(); | ||
182 | iotable_init(poodle_io_desc, ARRAY_SIZE(poodle_io_desc)); | ||
183 | |||
184 | /* setup sleep mode values */ | ||
185 | PWER = 0x00000002; | ||
186 | PFER = 0x00000000; | ||
187 | PRER = 0x00000002; | ||
188 | PGSR0 = 0x00008000; | ||
189 | PGSR1 = 0x003F0202; | ||
190 | PGSR2 = 0x0001C000; | ||
191 | PCFR |= PCFR_OPDE; | ||
192 | } | ||
193 | |||
194 | MACHINE_START(POODLE, "SHARP Poodle") | 265 | MACHINE_START(POODLE, "SHARP Poodle") |
195 | .phys_ram = 0xa0000000, | 266 | .phys_ram = 0xa0000000, |
196 | .phys_io = 0x40000000, | 267 | .phys_io = 0x40000000, |
197 | .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, | 268 | .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, |
198 | .fixup = fixup_poodle, | 269 | .fixup = fixup_poodle, |
199 | .map_io = poodle_map_io, | 270 | .map_io = pxa_map_io, |
200 | .init_irq = pxa_init_irq, | 271 | .init_irq = pxa_init_irq, |
201 | .timer = &pxa_timer, | 272 | .timer = &pxa_timer, |
202 | .init_machine = poodle_init, | 273 | .init_machine = poodle_init, |
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c index f87aa0b669ad..7c05f27fe1d6 100644 --- a/arch/arm/mach-s3c2410/mach-anubis.c +++ b/arch/arm/mach-s3c2410/mach-anubis.c | |||
@@ -12,6 +12,7 @@ | |||
12 | * | 12 | * |
13 | * Modifications: | 13 | * Modifications: |
14 | * 02-May-2005 BJD Copied from mach-bast.c | 14 | * 02-May-2005 BJD Copied from mach-bast.c |
15 | * 20-Sep-2005 BJD Added static to non-exported items | ||
15 | */ | 16 | */ |
16 | 17 | ||
17 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
@@ -232,7 +233,7 @@ static struct s3c24xx_board anubis_board __initdata = { | |||
232 | .clocks_count = ARRAY_SIZE(anubis_clocks) | 233 | .clocks_count = ARRAY_SIZE(anubis_clocks) |
233 | }; | 234 | }; |
234 | 235 | ||
235 | void __init anubis_map_io(void) | 236 | static void __init anubis_map_io(void) |
236 | { | 237 | { |
237 | /* initialise the clocks */ | 238 | /* initialise the clocks */ |
238 | 239 | ||
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 1a3367da6408..ed1f07d7252f 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c | |||
@@ -31,6 +31,7 @@ | |||
31 | * 17-Jul-2005 BJD Changed to platform device for SuperIO 16550s | 31 | * 17-Jul-2005 BJD Changed to platform device for SuperIO 16550s |
32 | * 25-Jul-2005 BJD Removed ASIX static mappings | 32 | * 25-Jul-2005 BJD Removed ASIX static mappings |
33 | * 27-Jul-2005 BJD Ensure maximum frequency of i2c bus | 33 | * 27-Jul-2005 BJD Ensure maximum frequency of i2c bus |
34 | * 20-Sep-2005 BJD Added static to non-exported items | ||
34 | */ | 35 | */ |
35 | 36 | ||
36 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
@@ -428,7 +429,7 @@ static struct s3c24xx_board bast_board __initdata = { | |||
428 | .clocks_count = ARRAY_SIZE(bast_clocks) | 429 | .clocks_count = ARRAY_SIZE(bast_clocks) |
429 | }; | 430 | }; |
430 | 431 | ||
431 | void __init bast_map_io(void) | 432 | static void __init bast_map_io(void) |
432 | { | 433 | { |
433 | /* initialise the clocks */ | 434 | /* initialise the clocks */ |
434 | 435 | ||
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c index 6ff1889fbd21..fb3cb01266e5 100644 --- a/arch/arm/mach-s3c2410/mach-h1940.c +++ b/arch/arm/mach-s3c2410/mach-h1940.c | |||
@@ -24,6 +24,7 @@ | |||
24 | * 10-Jan-2005 BJD Removed include of s3c2410.h | 24 | * 10-Jan-2005 BJD Removed include of s3c2410.h |
25 | * 14-Jan-2005 BJD Added clock init | 25 | * 14-Jan-2005 BJD Added clock init |
26 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA | 26 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA |
27 | * 20-Sep-2005 BJD Added static to non-exported items | ||
27 | */ | 28 | */ |
28 | 29 | ||
29 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
@@ -147,7 +148,7 @@ static struct s3c24xx_board h1940_board __initdata = { | |||
147 | .devices_count = ARRAY_SIZE(h1940_devices) | 148 | .devices_count = ARRAY_SIZE(h1940_devices) |
148 | }; | 149 | }; |
149 | 150 | ||
150 | void __init h1940_map_io(void) | 151 | static void __init h1940_map_io(void) |
151 | { | 152 | { |
152 | s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc)); | 153 | s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc)); |
153 | s3c24xx_init_clocks(0); | 154 | s3c24xx_init_clocks(0); |
@@ -155,13 +156,13 @@ void __init h1940_map_io(void) | |||
155 | s3c24xx_set_board(&h1940_board); | 156 | s3c24xx_set_board(&h1940_board); |
156 | } | 157 | } |
157 | 158 | ||
158 | void __init h1940_init_irq(void) | 159 | static void __init h1940_init_irq(void) |
159 | { | 160 | { |
160 | s3c24xx_init_irq(); | 161 | s3c24xx_init_irq(); |
161 | 162 | ||
162 | } | 163 | } |
163 | 164 | ||
164 | void __init h1940_init(void) | 165 | static void __init h1940_init(void) |
165 | { | 166 | { |
166 | set_s3c2410fb_info(&h1940_lcdcfg); | 167 | set_s3c2410fb_info(&h1940_lcdcfg); |
167 | } | 168 | } |
diff --git a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c index 66bf5bb2b3db..5c0f2b091f95 100644 --- a/arch/arm/mach-s3c2410/mach-n30.c +++ b/arch/arm/mach-s3c2410/mach-n30.c | |||
@@ -97,7 +97,7 @@ static struct s3c24xx_board n30_board __initdata = { | |||
97 | .devices_count = ARRAY_SIZE(n30_devices) | 97 | .devices_count = ARRAY_SIZE(n30_devices) |
98 | }; | 98 | }; |
99 | 99 | ||
100 | void __init n30_map_io(void) | 100 | static void __init n30_map_io(void) |
101 | { | 101 | { |
102 | s3c24xx_init_io(n30_iodesc, ARRAY_SIZE(n30_iodesc)); | 102 | s3c24xx_init_io(n30_iodesc, ARRAY_SIZE(n30_iodesc)); |
103 | s3c24xx_init_clocks(0); | 103 | s3c24xx_init_clocks(0); |
@@ -105,14 +105,14 @@ void __init n30_map_io(void) | |||
105 | s3c24xx_set_board(&n30_board); | 105 | s3c24xx_set_board(&n30_board); |
106 | } | 106 | } |
107 | 107 | ||
108 | void __init n30_init_irq(void) | 108 | static void __init n30_init_irq(void) |
109 | { | 109 | { |
110 | s3c24xx_init_irq(); | 110 | s3c24xx_init_irq(); |
111 | } | 111 | } |
112 | 112 | ||
113 | /* GPB3 is the line that controls the pull-up for the USB D+ line */ | 113 | /* GPB3 is the line that controls the pull-up for the USB D+ line */ |
114 | 114 | ||
115 | void __init n30_init(void) | 115 | static void __init n30_init(void) |
116 | { | 116 | { |
117 | s3c_device_i2c.dev.platform_data = &n30_i2ccfg; | 117 | s3c_device_i2c.dev.platform_data = &n30_i2ccfg; |
118 | 118 | ||
diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2410/mach-nexcoder.c index d24c242414ca..c22f8216032d 100644 --- a/arch/arm/mach-s3c2410/mach-nexcoder.c +++ b/arch/arm/mach-s3c2410/mach-nexcoder.c | |||
@@ -136,7 +136,7 @@ static void __init nexcoder_sensorboard_init(void) | |||
136 | s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_OUTP); // CAM_GPIO6 => CAM_PWRDN | 136 | s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_OUTP); // CAM_GPIO6 => CAM_PWRDN |
137 | } | 137 | } |
138 | 138 | ||
139 | void __init nexcoder_map_io(void) | 139 | static void __init nexcoder_map_io(void) |
140 | { | 140 | { |
141 | s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc)); | 141 | s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc)); |
142 | s3c24xx_init_clocks(0); | 142 | s3c24xx_init_clocks(0); |
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c index d901ed492ff5..ad1459e402e2 100644 --- a/arch/arm/mach-s3c2410/mach-otom.c +++ b/arch/arm/mach-s3c2410/mach-otom.c | |||
@@ -105,7 +105,7 @@ static struct s3c24xx_board otom11_board __initdata = { | |||
105 | }; | 105 | }; |
106 | 106 | ||
107 | 107 | ||
108 | void __init otom11_map_io(void) | 108 | static void __init otom11_map_io(void) |
109 | { | 109 | { |
110 | s3c24xx_init_io(otom11_iodesc, ARRAY_SIZE(otom11_iodesc)); | 110 | s3c24xx_init_io(otom11_iodesc, ARRAY_SIZE(otom11_iodesc)); |
111 | s3c24xx_init_clocks(0); | 111 | s3c24xx_init_clocks(0); |
diff --git a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c index a73d61c1de46..22d9e070fd68 100644 --- a/arch/arm/mach-s3c2410/mach-rx3715.c +++ b/arch/arm/mach-s3c2410/mach-rx3715.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * 14-Jan-2005 BJD Added new clock init | 16 | * 14-Jan-2005 BJD Added new clock init |
17 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA | 17 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA |
18 | * 14-Mar-2005 BJD Fixed __iomem warnings | 18 | * 14-Mar-2005 BJD Fixed __iomem warnings |
19 | * 20-Sep-2005 BJD Added static to non-exported items | ||
19 | */ | 20 | */ |
20 | 21 | ||
21 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
@@ -108,7 +109,7 @@ static struct s3c24xx_board rx3715_board __initdata = { | |||
108 | .devices_count = ARRAY_SIZE(rx3715_devices) | 109 | .devices_count = ARRAY_SIZE(rx3715_devices) |
109 | }; | 110 | }; |
110 | 111 | ||
111 | void __init rx3715_map_io(void) | 112 | static void __init rx3715_map_io(void) |
112 | { | 113 | { |
113 | s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc)); | 114 | s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc)); |
114 | s3c24xx_init_clocks(16934000); | 115 | s3c24xx_init_clocks(16934000); |
@@ -116,7 +117,7 @@ void __init rx3715_map_io(void) | |||
116 | s3c24xx_set_board(&rx3715_board); | 117 | s3c24xx_set_board(&rx3715_board); |
117 | } | 118 | } |
118 | 119 | ||
119 | void __init rx3715_init_irq(void) | 120 | static void __init rx3715_init_irq(void) |
120 | { | 121 | { |
121 | s3c24xx_init_irq(); | 122 | s3c24xx_init_irq(); |
122 | } | 123 | } |
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c index 67e903a700d3..2eda55a6b678 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2410.c +++ b/arch/arm/mach-s3c2410/mach-smdk2410.c | |||
@@ -28,6 +28,7 @@ | |||
28 | * Ben Dooks <ben@simtec.co.uk> | 28 | * Ben Dooks <ben@simtec.co.uk> |
29 | * | 29 | * |
30 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA | 30 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA |
31 | * 20-Sep-2005 BJD Added static to non-exported items | ||
31 | * | 32 | * |
32 | ***********************************************************************/ | 33 | ***********************************************************************/ |
33 | 34 | ||
@@ -97,7 +98,7 @@ static struct s3c24xx_board smdk2410_board __initdata = { | |||
97 | .devices_count = ARRAY_SIZE(smdk2410_devices) | 98 | .devices_count = ARRAY_SIZE(smdk2410_devices) |
98 | }; | 99 | }; |
99 | 100 | ||
100 | void __init smdk2410_map_io(void) | 101 | static void __init smdk2410_map_io(void) |
101 | { | 102 | { |
102 | s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc)); | 103 | s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc)); |
103 | s3c24xx_init_clocks(0); | 104 | s3c24xx_init_clocks(0); |
@@ -105,7 +106,7 @@ void __init smdk2410_map_io(void) | |||
105 | s3c24xx_set_board(&smdk2410_board); | 106 | s3c24xx_set_board(&smdk2410_board); |
106 | } | 107 | } |
107 | 108 | ||
108 | void __init smdk2410_init_irq(void) | 109 | static void __init smdk2410_init_irq(void) |
109 | { | 110 | { |
110 | s3c24xx_init_irq(); | 111 | s3c24xx_init_irq(); |
111 | } | 112 | } |
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c index 357522106f68..722ef46b630a 100644 --- a/arch/arm/mach-s3c2410/mach-smdk2440.c +++ b/arch/arm/mach-s3c2410/mach-smdk2440.c | |||
@@ -18,6 +18,7 @@ | |||
18 | * 22-Feb-2005 BJD Updated for 2.6.11-rc5 relesa | 18 | * 22-Feb-2005 BJD Updated for 2.6.11-rc5 relesa |
19 | * 10-Mar-2005 LCVR Replaced S3C2410_VA by S3C24XX_VA | 19 | * 10-Mar-2005 LCVR Replaced S3C2410_VA by S3C24XX_VA |
20 | * 14-Mar-2005 BJD void __iomem fixes | 20 | * 14-Mar-2005 BJD void __iomem fixes |
21 | * 20-Sep-2005 BJD Added static to non-exported items | ||
21 | */ | 22 | */ |
22 | 23 | ||
23 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
@@ -98,7 +99,7 @@ static struct s3c24xx_board smdk2440_board __initdata = { | |||
98 | .devices_count = ARRAY_SIZE(smdk2440_devices) | 99 | .devices_count = ARRAY_SIZE(smdk2440_devices) |
99 | }; | 100 | }; |
100 | 101 | ||
101 | void __init smdk2440_map_io(void) | 102 | static void __init smdk2440_map_io(void) |
102 | { | 103 | { |
103 | s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc)); | 104 | s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc)); |
104 | s3c24xx_init_clocks(16934400); | 105 | s3c24xx_init_clocks(16934400); |
@@ -106,7 +107,7 @@ void __init smdk2440_map_io(void) | |||
106 | s3c24xx_set_board(&smdk2440_board); | 107 | s3c24xx_set_board(&smdk2440_board); |
107 | } | 108 | } |
108 | 109 | ||
109 | void __init smdk2440_machine_init(void) | 110 | static void __init smdk2440_machine_init(void) |
110 | { | 111 | { |
111 | /* Configure the LEDs (even if we have no LED support)*/ | 112 | /* Configure the LEDs (even if we have no LED support)*/ |
112 | 113 | ||
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index 8f9ab2893df4..663a7f98fc0b 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c | |||
@@ -28,6 +28,7 @@ | |||
28 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA | 28 | * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA |
29 | * 14-Mar-2006 BJD void __iomem fixes | 29 | * 14-Mar-2006 BJD void __iomem fixes |
30 | * 22-Jun-2006 BJD Added DM9000 platform information | 30 | * 22-Jun-2006 BJD Added DM9000 platform information |
31 | * 20-Sep-2005 BJD Added static to non-exported items | ||
31 | */ | 32 | */ |
32 | 33 | ||
33 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
@@ -347,7 +348,7 @@ static void vr1000_power_off(void) | |||
347 | s3c2410_gpio_setpin(S3C2410_GPB9, 1); | 348 | s3c2410_gpio_setpin(S3C2410_GPB9, 1); |
348 | } | 349 | } |
349 | 350 | ||
350 | void __init vr1000_map_io(void) | 351 | static void __init vr1000_map_io(void) |
351 | { | 352 | { |
352 | /* initialise clock sources */ | 353 | /* initialise clock sources */ |
353 | 354 | ||
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 8cb69113a57c..25d6a4e27533 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c | |||
@@ -111,12 +111,11 @@ static struct mtd_partition collie_partitions[] = { | |||
111 | 111 | ||
112 | static void collie_set_vpp(int vpp) | 112 | static void collie_set_vpp(int vpp) |
113 | { | 113 | { |
114 | write_scoop_reg(SCOOP_GPCR, read_scoop_reg(SCOOP_GPCR) | COLLIE_SCP_VPEN); | 114 | write_scoop_reg(&colliescoop_device.dev, SCOOP_GPCR, read_scoop_reg(SCOOP_GPCR) | COLLIE_SCP_VPEN); |
115 | if (vpp) { | 115 | if (vpp) |
116 | write_scoop_reg(SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) | COLLIE_SCP_VPEN); | 116 | write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) | COLLIE_SCP_VPEN); |
117 | } else { | 117 | else |
118 | write_scoop_reg(SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) & ~COLLIE_SCP_VPEN); | 118 | write_scoop_reg(&colliescoop_device.dev, SCOOP_GPWR, read_scoop_reg(SCOOP_GPWR) & ~COLLIE_SCP_VPEN); |
119 | } | ||
120 | } | 119 | } |
121 | 120 | ||
122 | static struct flash_platform_data collie_flash_data = { | 121 | static struct flash_platform_data collie_flash_data = { |
diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h index 279e3afa3c39..f085d68e568e 100644 --- a/arch/arm/mach-sa1100/generic.h +++ b/arch/arm/mach-sa1100/generic.h | |||
@@ -39,3 +39,6 @@ extern void sa11x0_set_ssp_data(struct sa11x0_ssp_plat_ops *ops); | |||
39 | 39 | ||
40 | struct irda_platform_data; | 40 | struct irda_platform_data; |
41 | void sa11x0_set_irda_data(struct irda_platform_data *irda); | 41 | void sa11x0_set_irda_data(struct irda_platform_data *irda); |
42 | |||
43 | struct mcp_plat_data; | ||
44 | void sa11x0_set_mcp_data(struct mcp_plat_data *data); | ||
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 0b6c4db44e08..4a884baf3b9c 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -233,7 +233,17 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) | |||
233 | if (in_interrupt() || !mm) | 233 | if (in_interrupt() || !mm) |
234 | goto no_context; | 234 | goto no_context; |
235 | 235 | ||
236 | down_read(&mm->mmap_sem); | 236 | /* |
237 | * As per x86, we may deadlock here. However, since the kernel only | ||
238 | * validly references user space from well defined areas of the code, | ||
239 | * we can bug out early if this is from code which shouldn't. | ||
240 | */ | ||
241 | if (!down_read_trylock(&mm->mmap_sem)) { | ||
242 | if (!user_mode(regs) && !search_exception_tables(regs->ARM_pc)) | ||
243 | goto no_context; | ||
244 | down_read(&mm->mmap_sem); | ||
245 | } | ||
246 | |||
237 | fault = __do_page_fault(mm, addr, fsr, tsk); | 247 | fault = __do_page_fault(mm, addr, fsr, tsk); |
238 | up_read(&mm->mmap_sem); | 248 | up_read(&mm->mmap_sem); |
239 | 249 | ||
diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index 1d739d282a45..82ec954e45b6 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S | |||
@@ -509,7 +509,7 @@ cpu_arm1020_name: | |||
509 | 509 | ||
510 | .align | 510 | .align |
511 | 511 | ||
512 | .section ".proc.info", #alloc, #execinstr | 512 | .section ".proc.info.init", #alloc, #execinstr |
513 | 513 | ||
514 | .type __arm1020_proc_info,#object | 514 | .type __arm1020_proc_info,#object |
515 | __arm1020_proc_info: | 515 | __arm1020_proc_info: |
diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S index 9b725665b5c7..7375fe930f72 100644 --- a/arch/arm/mm/proc-arm1020e.S +++ b/arch/arm/mm/proc-arm1020e.S | |||
@@ -491,7 +491,7 @@ cpu_arm1020e_name: | |||
491 | 491 | ||
492 | .align | 492 | .align |
493 | 493 | ||
494 | .section ".proc.info", #alloc, #execinstr | 494 | .section ".proc.info.init", #alloc, #execinstr |
495 | 495 | ||
496 | .type __arm1020e_proc_info,#object | 496 | .type __arm1020e_proc_info,#object |
497 | __arm1020e_proc_info: | 497 | __arm1020e_proc_info: |
diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S index 37b70fa21c76..6ca639094d6f 100644 --- a/arch/arm/mm/proc-arm1022.S +++ b/arch/arm/mm/proc-arm1022.S | |||
@@ -473,7 +473,7 @@ cpu_arm1022_name: | |||
473 | 473 | ||
474 | .align | 474 | .align |
475 | 475 | ||
476 | .section ".proc.info", #alloc, #execinstr | 476 | .section ".proc.info.init", #alloc, #execinstr |
477 | 477 | ||
478 | .type __arm1022_proc_info,#object | 478 | .type __arm1022_proc_info,#object |
479 | __arm1022_proc_info: | 479 | __arm1022_proc_info: |
diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S index 931b690d1be2..10317e4f55d2 100644 --- a/arch/arm/mm/proc-arm1026.S +++ b/arch/arm/mm/proc-arm1026.S | |||
@@ -469,7 +469,7 @@ cpu_arm1026_name: | |||
469 | 469 | ||
470 | .align | 470 | .align |
471 | 471 | ||
472 | .section ".proc.info", #alloc, #execinstr | 472 | .section ".proc.info.init", #alloc, #execinstr |
473 | 473 | ||
474 | .type __arm1026_proc_info,#object | 474 | .type __arm1026_proc_info,#object |
475 | __arm1026_proc_info: | 475 | __arm1026_proc_info: |
diff --git a/arch/arm/mm/proc-arm6_7.S b/arch/arm/mm/proc-arm6_7.S index d0f1bbb48f6c..8e7e1e70ab05 100644 --- a/arch/arm/mm/proc-arm6_7.S +++ b/arch/arm/mm/proc-arm6_7.S | |||
@@ -332,7 +332,7 @@ cpu_arm710_name: | |||
332 | 332 | ||
333 | .align | 333 | .align |
334 | 334 | ||
335 | .section ".proc.info", #alloc, #execinstr | 335 | .section ".proc.info.init", #alloc, #execinstr |
336 | 336 | ||
337 | .type __arm6_proc_info, #object | 337 | .type __arm6_proc_info, #object |
338 | __arm6_proc_info: | 338 | __arm6_proc_info: |
diff --git a/arch/arm/mm/proc-arm720.S b/arch/arm/mm/proc-arm720.S index c69c9de32391..a13e0184d343 100644 --- a/arch/arm/mm/proc-arm720.S +++ b/arch/arm/mm/proc-arm720.S | |||
@@ -222,7 +222,7 @@ cpu_arm720_name: | |||
222 | * See linux/include/asm-arm/procinfo.h for a definition of this structure. | 222 | * See linux/include/asm-arm/procinfo.h for a definition of this structure. |
223 | */ | 223 | */ |
224 | 224 | ||
225 | .section ".proc.info", #alloc, #execinstr | 225 | .section ".proc.info.init", #alloc, #execinstr |
226 | 226 | ||
227 | .type __arm710_proc_info, #object | 227 | .type __arm710_proc_info, #object |
228 | __arm710_proc_info: | 228 | __arm710_proc_info: |
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index 0f490a0fcb71..d16513899999 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S | |||
@@ -452,7 +452,7 @@ cpu_arm920_name: | |||
452 | 452 | ||
453 | .align | 453 | .align |
454 | 454 | ||
455 | .section ".proc.info", #alloc, #execinstr | 455 | .section ".proc.info.init", #alloc, #execinstr |
456 | 456 | ||
457 | .type __arm920_proc_info,#object | 457 | .type __arm920_proc_info,#object |
458 | __arm920_proc_info: | 458 | __arm920_proc_info: |
diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index 62bc34a139ee..23b8ed97f4e3 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S | |||
@@ -456,7 +456,7 @@ cpu_arm922_name: | |||
456 | 456 | ||
457 | .align | 457 | .align |
458 | 458 | ||
459 | .section ".proc.info", #alloc, #execinstr | 459 | .section ".proc.info.init", #alloc, #execinstr |
460 | 460 | ||
461 | .type __arm922_proc_info,#object | 461 | .type __arm922_proc_info,#object |
462 | __arm922_proc_info: | 462 | __arm922_proc_info: |
diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S index ee49aa2ca781..ee95c52db513 100644 --- a/arch/arm/mm/proc-arm925.S +++ b/arch/arm/mm/proc-arm925.S | |||
@@ -521,7 +521,7 @@ cpu_arm925_name: | |||
521 | 521 | ||
522 | .align | 522 | .align |
523 | 523 | ||
524 | .section ".proc.info", #alloc, #execinstr | 524 | .section ".proc.info.init", #alloc, #execinstr |
525 | 525 | ||
526 | .type __arm925_proc_info,#object | 526 | .type __arm925_proc_info,#object |
527 | __arm925_proc_info: | 527 | __arm925_proc_info: |
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index bb95cc9fed03..7d042dc20c47 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S | |||
@@ -471,7 +471,7 @@ cpu_arm926_name: | |||
471 | 471 | ||
472 | .align | 472 | .align |
473 | 473 | ||
474 | .section ".proc.info", #alloc, #execinstr | 474 | .section ".proc.info.init", #alloc, #execinstr |
475 | 475 | ||
476 | .type __arm926_proc_info,#object | 476 | .type __arm926_proc_info,#object |
477 | __arm926_proc_info: | 477 | __arm926_proc_info: |
diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S index 34f7e7d3f419..bd330c4075a1 100644 --- a/arch/arm/mm/proc-sa110.S +++ b/arch/arm/mm/proc-sa110.S | |||
@@ -249,7 +249,7 @@ cpu_sa110_name: | |||
249 | 249 | ||
250 | .align | 250 | .align |
251 | 251 | ||
252 | .section ".proc.info", #alloc, #execinstr | 252 | .section ".proc.info.init", #alloc, #execinstr |
253 | 253 | ||
254 | .type __sa110_proc_info,#object | 254 | .type __sa110_proc_info,#object |
255 | __sa110_proc_info: | 255 | __sa110_proc_info: |
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S index ca14f80d5ab4..91b89124c0d7 100644 --- a/arch/arm/mm/proc-sa1100.S +++ b/arch/arm/mm/proc-sa1100.S | |||
@@ -280,7 +280,7 @@ cpu_sa1110_name: | |||
280 | 280 | ||
281 | .align | 281 | .align |
282 | 282 | ||
283 | .section ".proc.info", #alloc, #execinstr | 283 | .section ".proc.info.init", #alloc, #execinstr |
284 | 284 | ||
285 | .type __sa1100_proc_info,#object | 285 | .type __sa1100_proc_info,#object |
286 | __sa1100_proc_info: | 286 | __sa1100_proc_info: |
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index eb34823c9dbf..caf3b19b167f 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S | |||
@@ -240,7 +240,7 @@ cpu_elf_name: | |||
240 | .size cpu_elf_name, . - cpu_elf_name | 240 | .size cpu_elf_name, . - cpu_elf_name |
241 | .align | 241 | .align |
242 | 242 | ||
243 | .section ".proc.info", #alloc, #execinstr | 243 | .section ".proc.info.init", #alloc, #execinstr |
244 | 244 | ||
245 | /* | 245 | /* |
246 | * Match any ARMv6 processor core. | 246 | * Match any ARMv6 processor core. |
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index b88de2700146..861b35947280 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S | |||
@@ -578,7 +578,7 @@ cpu_pxa270_name: | |||
578 | 578 | ||
579 | .align | 579 | .align |
580 | 580 | ||
581 | .section ".proc.info", #alloc, #execinstr | 581 | .section ".proc.info.init", #alloc, #execinstr |
582 | 582 | ||
583 | .type __80200_proc_info,#object | 583 | .type __80200_proc_info,#object |
584 | __80200_proc_info: | 584 | __80200_proc_info: |
diff --git a/arch/arm26/boot/compressed/hw-bse.c b/arch/arm26/boot/compressed/hw-bse.c deleted file mode 100644 index 3e8f07f8e08a..000000000000 --- a/arch/arm26/boot/compressed/hw-bse.c +++ /dev/null | |||
@@ -1,74 +0,0 @@ | |||
1 | /* | ||
2 | * Bright Star Engineering Inc. | ||
3 | * | ||
4 | * code for readng parameters from the | ||
5 | * parameter blocks of the boot block | ||
6 | * flash memory | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | static int strcmp(const char *s1, const char *s2) | ||
11 | { | ||
12 | while (*s1 != '\0' && *s1 == *s2) | ||
13 | { | ||
14 | s1++; | ||
15 | s2++; | ||
16 | } | ||
17 | |||
18 | return (*(unsigned char *) s1) - (*(unsigned char *) s2); | ||
19 | } | ||
20 | |||
21 | struct pblk_t { | ||
22 | char type; | ||
23 | unsigned short size; | ||
24 | }; | ||
25 | |||
26 | static char *bse_getflashparam(char *name) { | ||
27 | unsigned int esize; | ||
28 | char *q,*r; | ||
29 | unsigned char *p,*e; | ||
30 | struct pblk_t *thepb = (struct pblk_t *) 0x00004000; | ||
31 | struct pblk_t *altpb = (struct pblk_t *) 0x00006000; | ||
32 | if (thepb->type&1) { | ||
33 | if (altpb->type&1) { | ||
34 | /* no valid param block */ | ||
35 | return (char*)0; | ||
36 | } else { | ||
37 | /* altpb is valid */ | ||
38 | struct pblk_t *tmp; | ||
39 | tmp = thepb; | ||
40 | thepb = altpb; | ||
41 | altpb = tmp; | ||
42 | } | ||
43 | } | ||
44 | p = (char*)thepb + sizeof(struct pblk_t); | ||
45 | e = p + thepb->size; | ||
46 | while (p < e) { | ||
47 | q = p; | ||
48 | esize = *p; | ||
49 | if (esize == 0xFF) break; | ||
50 | if (esize == 0) break; | ||
51 | if (esize > 127) { | ||
52 | esize = (esize&0x7F)<<8 | p[1]; | ||
53 | q++; | ||
54 | } | ||
55 | q++; | ||
56 | r=q; | ||
57 | if (*r && ((name == 0) || (!strcmp(name,r)))) { | ||
58 | while (*q++) ; | ||
59 | return q; | ||
60 | } | ||
61 | p+=esize; | ||
62 | } | ||
63 | return (char*)0; | ||
64 | } | ||
65 | |||
66 | void bse_setup(void) { | ||
67 | /* extract the linux cmdline from flash */ | ||
68 | char *name=bse_getflashparam("linuxboot"); | ||
69 | char *x = (char *)0xc0000100; | ||
70 | if (name) { | ||
71 | while (*name) *x++=*name++; | ||
72 | } | ||
73 | *x=0; | ||
74 | } | ||
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index b22f003eaa6d..d2703cda61ea 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig | |||
@@ -908,11 +908,6 @@ config IRQBALANCE | |||
908 | The default yes will allow the kernel to do irq load balancing. | 908 | The default yes will allow the kernel to do irq load balancing. |
909 | Saying no will keep the kernel from doing irq load balancing. | 909 | Saying no will keep the kernel from doing irq load balancing. |
910 | 910 | ||
911 | config HAVE_DEC_LOCK | ||
912 | bool | ||
913 | depends on (SMP || PREEMPT) && X86_CMPXCHG | ||
914 | default y | ||
915 | |||
916 | # turning this on wastes a bunch of space. | 911 | # turning this on wastes a bunch of space. |
917 | # Summit needs it only when NUMA is on | 912 | # Summit needs it only when NUMA is on |
918 | config BOOT_IOREMAP | 913 | config BOOT_IOREMAP |
diff --git a/arch/i386/kernel/acpi/earlyquirk.c b/arch/i386/kernel/acpi/earlyquirk.c index 1ae2aeeda18b..f1b9d2a46dab 100644 --- a/arch/i386/kernel/acpi/earlyquirk.c +++ b/arch/i386/kernel/acpi/earlyquirk.c | |||
@@ -7,7 +7,6 @@ | |||
7 | #include <linux/pci.h> | 7 | #include <linux/pci.h> |
8 | #include <asm/pci-direct.h> | 8 | #include <asm/pci-direct.h> |
9 | #include <asm/acpi.h> | 9 | #include <asm/acpi.h> |
10 | #include <asm/apic.h> | ||
11 | 10 | ||
12 | static int __init check_bridge(int vendor, int device) | 11 | static int __init check_bridge(int vendor, int device) |
13 | { | 12 | { |
@@ -16,15 +15,6 @@ static int __init check_bridge(int vendor, int device) | |||
16 | if (vendor == PCI_VENDOR_ID_NVIDIA) { | 15 | if (vendor == PCI_VENDOR_ID_NVIDIA) { |
17 | acpi_skip_timer_override = 1; | 16 | acpi_skip_timer_override = 1; |
18 | } | 17 | } |
19 | #ifdef CONFIG_X86_LOCAL_APIC | ||
20 | /* | ||
21 | * ATI IXP chipsets get double timer interrupts. | ||
22 | * For now just do this for all ATI chipsets. | ||
23 | * FIXME: this needs to be checked for the non ACPI case too. | ||
24 | */ | ||
25 | if (vendor == PCI_VENDOR_ID_ATI) | ||
26 | disable_timer_pin_1 = 1; | ||
27 | #endif | ||
28 | return 0; | 18 | return 0; |
29 | } | 19 | } |
30 | 20 | ||
diff --git a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile index 7b1932d20f96..914933e9ec3d 100644 --- a/arch/i386/lib/Makefile +++ b/arch/i386/lib/Makefile | |||
@@ -7,4 +7,3 @@ lib-y = checksum.o delay.o usercopy.o getuser.o putuser.o memcpy.o strstr.o \ | |||
7 | bitops.o | 7 | bitops.o |
8 | 8 | ||
9 | lib-$(CONFIG_X86_USE_3DNOW) += mmx.o | 9 | lib-$(CONFIG_X86_USE_3DNOW) += mmx.o |
10 | lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o | ||
diff --git a/arch/i386/lib/dec_and_lock.c b/arch/i386/lib/dec_and_lock.c deleted file mode 100644 index 8b81b2524fa6..000000000000 --- a/arch/i386/lib/dec_and_lock.c +++ /dev/null | |||
@@ -1,42 +0,0 @@ | |||
1 | /* | ||
2 | * x86 version of "atomic_dec_and_lock()" using | ||
3 | * the atomic "cmpxchg" instruction. | ||
4 | * | ||
5 | * (For CPU's lacking cmpxchg, we use the slow | ||
6 | * generic version, and this one never even gets | ||
7 | * compiled). | ||
8 | */ | ||
9 | |||
10 | #include <linux/spinlock.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <asm/atomic.h> | ||
13 | |||
14 | int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) | ||
15 | { | ||
16 | int counter; | ||
17 | int newcount; | ||
18 | |||
19 | repeat: | ||
20 | counter = atomic_read(atomic); | ||
21 | newcount = counter-1; | ||
22 | |||
23 | if (!newcount) | ||
24 | goto slow_path; | ||
25 | |||
26 | asm volatile("lock; cmpxchgl %1,%2" | ||
27 | :"=a" (newcount) | ||
28 | :"r" (newcount), "m" (atomic->counter), "0" (counter)); | ||
29 | |||
30 | /* If the above failed, "eax" will have changed */ | ||
31 | if (newcount != counter) | ||
32 | goto repeat; | ||
33 | return 0; | ||
34 | |||
35 | slow_path: | ||
36 | spin_lock(lock); | ||
37 | if (atomic_dec_and_test(atomic)) | ||
38 | return 1; | ||
39 | spin_unlock(lock); | ||
40 | return 0; | ||
41 | } | ||
42 | EXPORT_SYMBOL(_atomic_dec_and_lock); | ||
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index ed25d66c8d50..945c15a0722b 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig | |||
@@ -298,11 +298,6 @@ config PREEMPT | |||
298 | 298 | ||
299 | source "mm/Kconfig" | 299 | source "mm/Kconfig" |
300 | 300 | ||
301 | config HAVE_DEC_LOCK | ||
302 | bool | ||
303 | depends on (SMP || PREEMPT) | ||
304 | default y | ||
305 | |||
306 | config IA32_SUPPORT | 301 | config IA32_SUPPORT |
307 | bool "Support for Linux/x86 binaries" | 302 | bool "Support for Linux/x86 binaries" |
308 | help | 303 | help |
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 70f8ed2748d1..67932ad53082 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile | |||
@@ -82,17 +82,7 @@ unwcheck: vmlinux | |||
82 | archclean: | 82 | archclean: |
83 | $(Q)$(MAKE) $(clean)=$(boot) | 83 | $(Q)$(MAKE) $(clean)=$(boot) |
84 | 84 | ||
85 | archprepare: include/asm-ia64/.offsets.h.stamp | 85 | CLEAN_FILES += vmlinux.gz bootloader |
86 | |||
87 | include/asm-ia64/.offsets.h.stamp: | ||
88 | mkdir -p include/asm-ia64 | ||
89 | [ -s include/asm-ia64/asm-offsets.h ] \ | ||
90 | || echo "#define IA64_TASK_SIZE 0" > include/asm-ia64/asm-offsets.h | ||
91 | touch $@ | ||
92 | |||
93 | |||
94 | |||
95 | CLEAN_FILES += vmlinux.gz bootloader include/asm-ia64/.offsets.h.stamp | ||
96 | 86 | ||
97 | boot: lib/lib.a vmlinux | 87 | boot: lib/lib.a vmlinux |
98 | $(Q)$(MAKE) $(build)=$(boot) $@ | 88 | $(Q)$(MAKE) $(build)=$(boot) $@ |
diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c index 31de70b7c67f..a7280d9f6c16 100644 --- a/arch/ia64/ia32/binfmt_elf32.c +++ b/arch/ia64/ia32/binfmt_elf32.c | |||
@@ -216,12 +216,6 @@ ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack) | |||
216 | if (!mpnt) | 216 | if (!mpnt) |
217 | return -ENOMEM; | 217 | return -ENOMEM; |
218 | 218 | ||
219 | if (security_vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p)) | ||
220 | >> PAGE_SHIFT)) { | ||
221 | kmem_cache_free(vm_area_cachep, mpnt); | ||
222 | return -ENOMEM; | ||
223 | } | ||
224 | |||
225 | memset(mpnt, 0, sizeof(*mpnt)); | 219 | memset(mpnt, 0, sizeof(*mpnt)); |
226 | 220 | ||
227 | down_write(¤t->mm->mmap_sem); | 221 | down_write(¤t->mm->mmap_sem); |
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 28a4529fdd60..7e926471e4ec 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c | |||
@@ -899,7 +899,7 @@ int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base) | |||
899 | if ((err = iosapic_init(phys_addr, gsi_base))) | 899 | if ((err = iosapic_init(phys_addr, gsi_base))) |
900 | return err; | 900 | return err; |
901 | 901 | ||
902 | #if CONFIG_ACPI_NUMA | 902 | #ifdef CONFIG_ACPI_NUMA |
903 | acpi_map_iosapic(handle, 0, NULL, NULL); | 903 | acpi_map_iosapic(handle, 0, NULL, NULL); |
904 | #endif /* CONFIG_ACPI_NUMA */ | 904 | #endif /* CONFIG_ACPI_NUMA */ |
905 | 905 | ||
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c index f6a234289341..77225659e968 100644 --- a/arch/ia64/kernel/asm-offsets.c +++ b/arch/ia64/kernel/asm-offsets.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * to extract and format the required data. | 4 | * to extract and format the required data. |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #define ASM_OFFSETS_C 1 | ||
7 | #include <linux/config.h> | 8 | #include <linux/config.h> |
8 | 9 | ||
9 | #include <linux/sched.h> | 10 | #include <linux/sched.h> |
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index ba0b6a1f429f..0741b066b98f 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
@@ -491,7 +491,7 @@ GLOBAL_ENTRY(prefetch_stack) | |||
491 | ;; | 491 | ;; |
492 | lfetch.fault [r16], 128 | 492 | lfetch.fault [r16], 128 |
493 | br.ret.sptk.many rp | 493 | br.ret.sptk.many rp |
494 | END(prefetch_switch_stack) | 494 | END(prefetch_stack) |
495 | 495 | ||
496 | GLOBAL_ENTRY(execve) | 496 | GLOBAL_ENTRY(execve) |
497 | mov r15=__NR_execve // put syscall number in place | 497 | mov r15=__NR_execve // put syscall number in place |
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index 6e683745af49..80f83d6cdbfc 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c | |||
@@ -84,23 +84,23 @@ mca_page_isolate(unsigned long paddr) | |||
84 | struct page *p; | 84 | struct page *p; |
85 | 85 | ||
86 | /* whether physical address is valid or not */ | 86 | /* whether physical address is valid or not */ |
87 | if ( !ia64_phys_addr_valid(paddr) ) | 87 | if (!ia64_phys_addr_valid(paddr)) |
88 | return ISOLATE_NG; | 88 | return ISOLATE_NG; |
89 | 89 | ||
90 | /* convert physical address to physical page number */ | 90 | /* convert physical address to physical page number */ |
91 | p = pfn_to_page(paddr>>PAGE_SHIFT); | 91 | p = pfn_to_page(paddr>>PAGE_SHIFT); |
92 | 92 | ||
93 | /* check whether a page number have been already registered or not */ | 93 | /* check whether a page number have been already registered or not */ |
94 | for( i = 0; i < num_page_isolate; i++ ) | 94 | for (i = 0; i < num_page_isolate; i++) |
95 | if( page_isolate[i] == p ) | 95 | if (page_isolate[i] == p) |
96 | return ISOLATE_OK; /* already listed */ | 96 | return ISOLATE_OK; /* already listed */ |
97 | 97 | ||
98 | /* limitation check */ | 98 | /* limitation check */ |
99 | if( num_page_isolate == MAX_PAGE_ISOLATE ) | 99 | if (num_page_isolate == MAX_PAGE_ISOLATE) |
100 | return ISOLATE_NG; | 100 | return ISOLATE_NG; |
101 | 101 | ||
102 | /* kick pages having attribute 'SLAB' or 'Reserved' */ | 102 | /* kick pages having attribute 'SLAB' or 'Reserved' */ |
103 | if( PageSlab(p) || PageReserved(p) ) | 103 | if (PageSlab(p) || PageReserved(p)) |
104 | return ISOLATE_NG; | 104 | return ISOLATE_NG; |
105 | 105 | ||
106 | /* add attribute 'Reserved' and register the page */ | 106 | /* add attribute 'Reserved' and register the page */ |
@@ -139,10 +139,10 @@ mca_handler_bh(unsigned long paddr) | |||
139 | * @peidx: pointer to index of processor error section | 139 | * @peidx: pointer to index of processor error section |
140 | */ | 140 | */ |
141 | 141 | ||
142 | static void | 142 | static void |
143 | mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx) | 143 | mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx) |
144 | { | 144 | { |
145 | /* | 145 | /* |
146 | * calculate the start address of | 146 | * calculate the start address of |
147 | * "struct cpuid_info" and "sal_processor_static_info_t". | 147 | * "struct cpuid_info" and "sal_processor_static_info_t". |
148 | */ | 148 | */ |
@@ -164,7 +164,7 @@ mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx) | |||
164 | } | 164 | } |
165 | 165 | ||
166 | /** | 166 | /** |
167 | * mca_make_slidx - Make index of SAL error record | 167 | * mca_make_slidx - Make index of SAL error record |
168 | * @buffer: pointer to SAL error record | 168 | * @buffer: pointer to SAL error record |
169 | * @slidx: pointer to index of SAL error record | 169 | * @slidx: pointer to index of SAL error record |
170 | * | 170 | * |
@@ -172,12 +172,12 @@ mca_make_peidx(sal_log_processor_info_t *slpi, peidx_table_t *peidx) | |||
172 | * 1 if record has platform error / 0 if not | 172 | * 1 if record has platform error / 0 if not |
173 | */ | 173 | */ |
174 | #define LOG_INDEX_ADD_SECT_PTR(sect, ptr) \ | 174 | #define LOG_INDEX_ADD_SECT_PTR(sect, ptr) \ |
175 | { slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \ | 175 | {slidx_list_t *hl = &slidx_pool.buffer[slidx_pool.cur_idx]; \ |
176 | hl->hdr = ptr; \ | 176 | hl->hdr = ptr; \ |
177 | list_add(&hl->list, &(sect)); \ | 177 | list_add(&hl->list, &(sect)); \ |
178 | slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; } | 178 | slidx_pool.cur_idx = (slidx_pool.cur_idx + 1)%slidx_pool.max_idx; } |
179 | 179 | ||
180 | static int | 180 | static int |
181 | mca_make_slidx(void *buffer, slidx_table_t *slidx) | 181 | mca_make_slidx(void *buffer, slidx_table_t *slidx) |
182 | { | 182 | { |
183 | int platform_err = 0; | 183 | int platform_err = 0; |
@@ -214,28 +214,36 @@ mca_make_slidx(void *buffer, slidx_table_t *slidx) | |||
214 | sp = (sal_log_section_hdr_t *)((char*)buffer + ercd_pos); | 214 | sp = (sal_log_section_hdr_t *)((char*)buffer + ercd_pos); |
215 | if (!efi_guidcmp(sp->guid, SAL_PROC_DEV_ERR_SECT_GUID)) { | 215 | if (!efi_guidcmp(sp->guid, SAL_PROC_DEV_ERR_SECT_GUID)) { |
216 | LOG_INDEX_ADD_SECT_PTR(slidx->proc_err, sp); | 216 | LOG_INDEX_ADD_SECT_PTR(slidx->proc_err, sp); |
217 | } else if (!efi_guidcmp(sp->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) { | 217 | } else if (!efi_guidcmp(sp->guid, |
218 | SAL_PLAT_MEM_DEV_ERR_SECT_GUID)) { | ||
218 | platform_err = 1; | 219 | platform_err = 1; |
219 | LOG_INDEX_ADD_SECT_PTR(slidx->mem_dev_err, sp); | 220 | LOG_INDEX_ADD_SECT_PTR(slidx->mem_dev_err, sp); |
220 | } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) { | 221 | } else if (!efi_guidcmp(sp->guid, |
222 | SAL_PLAT_SEL_DEV_ERR_SECT_GUID)) { | ||
221 | platform_err = 1; | 223 | platform_err = 1; |
222 | LOG_INDEX_ADD_SECT_PTR(slidx->sel_dev_err, sp); | 224 | LOG_INDEX_ADD_SECT_PTR(slidx->sel_dev_err, sp); |
223 | } else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) { | 225 | } else if (!efi_guidcmp(sp->guid, |
226 | SAL_PLAT_PCI_BUS_ERR_SECT_GUID)) { | ||
224 | platform_err = 1; | 227 | platform_err = 1; |
225 | LOG_INDEX_ADD_SECT_PTR(slidx->pci_bus_err, sp); | 228 | LOG_INDEX_ADD_SECT_PTR(slidx->pci_bus_err, sp); |
226 | } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) { | 229 | } else if (!efi_guidcmp(sp->guid, |
230 | SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID)) { | ||
227 | platform_err = 1; | 231 | platform_err = 1; |
228 | LOG_INDEX_ADD_SECT_PTR(slidx->smbios_dev_err, sp); | 232 | LOG_INDEX_ADD_SECT_PTR(slidx->smbios_dev_err, sp); |
229 | } else if (!efi_guidcmp(sp->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) { | 233 | } else if (!efi_guidcmp(sp->guid, |
234 | SAL_PLAT_PCI_COMP_ERR_SECT_GUID)) { | ||
230 | platform_err = 1; | 235 | platform_err = 1; |
231 | LOG_INDEX_ADD_SECT_PTR(slidx->pci_comp_err, sp); | 236 | LOG_INDEX_ADD_SECT_PTR(slidx->pci_comp_err, sp); |
232 | } else if (!efi_guidcmp(sp->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) { | 237 | } else if (!efi_guidcmp(sp->guid, |
238 | SAL_PLAT_SPECIFIC_ERR_SECT_GUID)) { | ||
233 | platform_err = 1; | 239 | platform_err = 1; |
234 | LOG_INDEX_ADD_SECT_PTR(slidx->plat_specific_err, sp); | 240 | LOG_INDEX_ADD_SECT_PTR(slidx->plat_specific_err, sp); |
235 | } else if (!efi_guidcmp(sp->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) { | 241 | } else if (!efi_guidcmp(sp->guid, |
242 | SAL_PLAT_HOST_CTLR_ERR_SECT_GUID)) { | ||
236 | platform_err = 1; | 243 | platform_err = 1; |
237 | LOG_INDEX_ADD_SECT_PTR(slidx->host_ctlr_err, sp); | 244 | LOG_INDEX_ADD_SECT_PTR(slidx->host_ctlr_err, sp); |
238 | } else if (!efi_guidcmp(sp->guid, SAL_PLAT_BUS_ERR_SECT_GUID)) { | 245 | } else if (!efi_guidcmp(sp->guid, |
246 | SAL_PLAT_BUS_ERR_SECT_GUID)) { | ||
239 | platform_err = 1; | 247 | platform_err = 1; |
240 | LOG_INDEX_ADD_SECT_PTR(slidx->plat_bus_err, sp); | 248 | LOG_INDEX_ADD_SECT_PTR(slidx->plat_bus_err, sp); |
241 | } else { | 249 | } else { |
@@ -253,15 +261,16 @@ mca_make_slidx(void *buffer, slidx_table_t *slidx) | |||
253 | * Return value: | 261 | * Return value: |
254 | * 0 on Success / -ENOMEM on Failure | 262 | * 0 on Success / -ENOMEM on Failure |
255 | */ | 263 | */ |
256 | static int | 264 | static int |
257 | init_record_index_pools(void) | 265 | init_record_index_pools(void) |
258 | { | 266 | { |
259 | int i; | 267 | int i; |
260 | int rec_max_size; /* Maximum size of SAL error records */ | 268 | int rec_max_size; /* Maximum size of SAL error records */ |
261 | int sect_min_size; /* Minimum size of SAL error sections */ | 269 | int sect_min_size; /* Minimum size of SAL error sections */ |
262 | /* minimum size table of each section */ | 270 | /* minimum size table of each section */ |
263 | static int sal_log_sect_min_sizes[] = { | 271 | static int sal_log_sect_min_sizes[] = { |
264 | sizeof(sal_log_processor_info_t) + sizeof(sal_processor_static_info_t), | 272 | sizeof(sal_log_processor_info_t) |
273 | + sizeof(sal_processor_static_info_t), | ||
265 | sizeof(sal_log_mem_dev_err_info_t), | 274 | sizeof(sal_log_mem_dev_err_info_t), |
266 | sizeof(sal_log_sel_dev_err_info_t), | 275 | sizeof(sal_log_sel_dev_err_info_t), |
267 | sizeof(sal_log_pci_bus_err_info_t), | 276 | sizeof(sal_log_pci_bus_err_info_t), |
@@ -294,7 +303,8 @@ init_record_index_pools(void) | |||
294 | 303 | ||
295 | /* - 3 - */ | 304 | /* - 3 - */ |
296 | slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1; | 305 | slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1; |
297 | slidx_pool.buffer = (slidx_list_t *) kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL); | 306 | slidx_pool.buffer = (slidx_list_t *) |
307 | kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL); | ||
298 | 308 | ||
299 | return slidx_pool.buffer ? 0 : -ENOMEM; | 309 | return slidx_pool.buffer ? 0 : -ENOMEM; |
300 | } | 310 | } |
@@ -308,6 +318,7 @@ init_record_index_pools(void) | |||
308 | * is_mca_global - Check whether this MCA is global or not | 318 | * is_mca_global - Check whether this MCA is global or not |
309 | * @peidx: pointer of index of processor error section | 319 | * @peidx: pointer of index of processor error section |
310 | * @pbci: pointer to pal_bus_check_info_t | 320 | * @pbci: pointer to pal_bus_check_info_t |
321 | * @sos: pointer to hand off struct between SAL and OS | ||
311 | * | 322 | * |
312 | * Return value: | 323 | * Return value: |
313 | * MCA_IS_LOCAL / MCA_IS_GLOBAL | 324 | * MCA_IS_LOCAL / MCA_IS_GLOBAL |
@@ -317,11 +328,12 @@ static mca_type_t | |||
317 | is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci, | 328 | is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci, |
318 | struct ia64_sal_os_state *sos) | 329 | struct ia64_sal_os_state *sos) |
319 | { | 330 | { |
320 | pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx); | 331 | pal_processor_state_info_t *psp = |
332 | (pal_processor_state_info_t*)peidx_psp(peidx); | ||
321 | 333 | ||
322 | /* | 334 | /* |
323 | * PAL can request a rendezvous, if the MCA has a global scope. | 335 | * PAL can request a rendezvous, if the MCA has a global scope. |
324 | * If "rz_always" flag is set, SAL requests MCA rendezvous | 336 | * If "rz_always" flag is set, SAL requests MCA rendezvous |
325 | * in spite of global MCA. | 337 | * in spite of global MCA. |
326 | * Therefore it is local MCA when rendezvous has not been requested. | 338 | * Therefore it is local MCA when rendezvous has not been requested. |
327 | * Failed to rendezvous, the system must be down. | 339 | * Failed to rendezvous, the system must be down. |
@@ -381,13 +393,15 @@ is_mca_global(peidx_table_t *peidx, pal_bus_check_info_t *pbci, | |||
381 | * @slidx: pointer of index of SAL error record | 393 | * @slidx: pointer of index of SAL error record |
382 | * @peidx: pointer of index of processor error section | 394 | * @peidx: pointer of index of processor error section |
383 | * @pbci: pointer of pal_bus_check_info | 395 | * @pbci: pointer of pal_bus_check_info |
396 | * @sos: pointer to hand off struct between SAL and OS | ||
384 | * | 397 | * |
385 | * Return value: | 398 | * Return value: |
386 | * 1 on Success / 0 on Failure | 399 | * 1 on Success / 0 on Failure |
387 | */ | 400 | */ |
388 | 401 | ||
389 | static int | 402 | static int |
390 | recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci, | 403 | recover_from_read_error(slidx_table_t *slidx, |
404 | peidx_table_t *peidx, pal_bus_check_info_t *pbci, | ||
391 | struct ia64_sal_os_state *sos) | 405 | struct ia64_sal_os_state *sos) |
392 | { | 406 | { |
393 | sal_log_mod_error_info_t *smei; | 407 | sal_log_mod_error_info_t *smei; |
@@ -453,24 +467,28 @@ recover_from_read_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_chec | |||
453 | * @slidx: pointer of index of SAL error record | 467 | * @slidx: pointer of index of SAL error record |
454 | * @peidx: pointer of index of processor error section | 468 | * @peidx: pointer of index of processor error section |
455 | * @pbci: pointer of pal_bus_check_info | 469 | * @pbci: pointer of pal_bus_check_info |
470 | * @sos: pointer to hand off struct between SAL and OS | ||
456 | * | 471 | * |
457 | * Return value: | 472 | * Return value: |
458 | * 1 on Success / 0 on Failure | 473 | * 1 on Success / 0 on Failure |
459 | */ | 474 | */ |
460 | 475 | ||
461 | static int | 476 | static int |
462 | recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci, | 477 | recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, |
478 | pal_bus_check_info_t *pbci, | ||
463 | struct ia64_sal_os_state *sos) | 479 | struct ia64_sal_os_state *sos) |
464 | { | 480 | { |
465 | int status = 0; | 481 | int status = 0; |
466 | pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx); | 482 | pal_processor_state_info_t *psp = |
483 | (pal_processor_state_info_t*)peidx_psp(peidx); | ||
467 | 484 | ||
468 | if (psp->bc && pbci->eb && pbci->bsi == 0) { | 485 | if (psp->bc && pbci->eb && pbci->bsi == 0) { |
469 | switch(pbci->type) { | 486 | switch(pbci->type) { |
470 | case 1: /* partial read */ | 487 | case 1: /* partial read */ |
471 | case 3: /* full line(cpu) read */ | 488 | case 3: /* full line(cpu) read */ |
472 | case 9: /* I/O space read */ | 489 | case 9: /* I/O space read */ |
473 | status = recover_from_read_error(slidx, peidx, pbci, sos); | 490 | status = recover_from_read_error(slidx, peidx, pbci, |
491 | sos); | ||
474 | break; | 492 | break; |
475 | case 0: /* unknown */ | 493 | case 0: /* unknown */ |
476 | case 2: /* partial write */ | 494 | case 2: /* partial write */ |
@@ -481,7 +499,8 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_ | |||
481 | case 8: /* write coalescing transactions */ | 499 | case 8: /* write coalescing transactions */ |
482 | case 10: /* I/O space write */ | 500 | case 10: /* I/O space write */ |
483 | case 11: /* inter-processor interrupt message(IPI) */ | 501 | case 11: /* inter-processor interrupt message(IPI) */ |
484 | case 12: /* interrupt acknowledge or external task priority cycle */ | 502 | case 12: /* interrupt acknowledge or |
503 | external task priority cycle */ | ||
485 | default: | 504 | default: |
486 | break; | 505 | break; |
487 | } | 506 | } |
@@ -496,6 +515,7 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_ | |||
496 | * @slidx: pointer of index of SAL error record | 515 | * @slidx: pointer of index of SAL error record |
497 | * @peidx: pointer of index of processor error section | 516 | * @peidx: pointer of index of processor error section |
498 | * @pbci: pointer of pal_bus_check_info | 517 | * @pbci: pointer of pal_bus_check_info |
518 | * @sos: pointer to hand off struct between SAL and OS | ||
499 | * | 519 | * |
500 | * Return value: | 520 | * Return value: |
501 | * 1 on Success / 0 on Failure | 521 | * 1 on Success / 0 on Failure |
@@ -509,15 +529,17 @@ recover_from_platform_error(slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_ | |||
509 | */ | 529 | */ |
510 | 530 | ||
511 | static int | 531 | static int |
512 | recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t *peidx, pal_bus_check_info_t *pbci, | 532 | recover_from_processor_error(int platform, slidx_table_t *slidx, |
533 | peidx_table_t *peidx, pal_bus_check_info_t *pbci, | ||
513 | struct ia64_sal_os_state *sos) | 534 | struct ia64_sal_os_state *sos) |
514 | { | 535 | { |
515 | pal_processor_state_info_t *psp = (pal_processor_state_info_t*)peidx_psp(peidx); | 536 | pal_processor_state_info_t *psp = |
537 | (pal_processor_state_info_t*)peidx_psp(peidx); | ||
516 | 538 | ||
517 | /* | 539 | /* |
518 | * We cannot recover errors with other than bus_check. | 540 | * We cannot recover errors with other than bus_check. |
519 | */ | 541 | */ |
520 | if (psp->cc || psp->rc || psp->uc) | 542 | if (psp->cc || psp->rc || psp->uc) |
521 | return 0; | 543 | return 0; |
522 | 544 | ||
523 | /* | 545 | /* |
@@ -546,10 +568,10 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t * | |||
546 | * (e.g. a load from poisoned memory) | 568 | * (e.g. a load from poisoned memory) |
547 | * This means "there are some platform errors". | 569 | * This means "there are some platform errors". |
548 | */ | 570 | */ |
549 | if (platform) | 571 | if (platform) |
550 | return recover_from_platform_error(slidx, peidx, pbci, sos); | 572 | return recover_from_platform_error(slidx, peidx, pbci, sos); |
551 | /* | 573 | /* |
552 | * On account of strange SAL error record, we cannot recover. | 574 | * On account of strange SAL error record, we cannot recover. |
553 | */ | 575 | */ |
554 | return 0; | 576 | return 0; |
555 | } | 577 | } |
@@ -557,14 +579,14 @@ recover_from_processor_error(int platform, slidx_table_t *slidx, peidx_table_t * | |||
557 | /** | 579 | /** |
558 | * mca_try_to_recover - Try to recover from MCA | 580 | * mca_try_to_recover - Try to recover from MCA |
559 | * @rec: pointer to a SAL error record | 581 | * @rec: pointer to a SAL error record |
582 | * @sos: pointer to hand off struct between SAL and OS | ||
560 | * | 583 | * |
561 | * Return value: | 584 | * Return value: |
562 | * 1 on Success / 0 on Failure | 585 | * 1 on Success / 0 on Failure |
563 | */ | 586 | */ |
564 | 587 | ||
565 | static int | 588 | static int |
566 | mca_try_to_recover(void *rec, | 589 | mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos) |
567 | struct ia64_sal_os_state *sos) | ||
568 | { | 590 | { |
569 | int platform_err; | 591 | int platform_err; |
570 | int n_proc_err; | 592 | int n_proc_err; |
@@ -588,7 +610,8 @@ mca_try_to_recover(void *rec, | |||
588 | } | 610 | } |
589 | 611 | ||
590 | /* Make index of processor error section */ | 612 | /* Make index of processor error section */ |
591 | mca_make_peidx((sal_log_processor_info_t*)slidx_first_entry(&slidx.proc_err)->hdr, &peidx); | 613 | mca_make_peidx((sal_log_processor_info_t*) |
614 | slidx_first_entry(&slidx.proc_err)->hdr, &peidx); | ||
592 | 615 | ||
593 | /* Extract Processor BUS_CHECK[0] */ | 616 | /* Extract Processor BUS_CHECK[0] */ |
594 | *((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0); | 617 | *((u64*)&pbci) = peidx_check_info(&peidx, bus_check, 0); |
@@ -598,7 +621,8 @@ mca_try_to_recover(void *rec, | |||
598 | return 0; | 621 | return 0; |
599 | 622 | ||
600 | /* Try to recover a processor error */ | 623 | /* Try to recover a processor error */ |
601 | return recover_from_processor_error(platform_err, &slidx, &peidx, &pbci, sos); | 624 | return recover_from_processor_error(platform_err, &slidx, &peidx, |
625 | &pbci, sos); | ||
602 | } | 626 | } |
603 | 627 | ||
604 | /* | 628 | /* |
@@ -611,7 +635,7 @@ int __init mca_external_handler_init(void) | |||
611 | return -ENOMEM; | 635 | return -ENOMEM; |
612 | 636 | ||
613 | /* register external mca handlers */ | 637 | /* register external mca handlers */ |
614 | if (ia64_reg_MCA_extension(mca_try_to_recover)){ | 638 | if (ia64_reg_MCA_extension(mca_try_to_recover)) { |
615 | printk(KERN_ERR "ia64_reg_MCA_extension failed.\n"); | 639 | printk(KERN_ERR "ia64_reg_MCA_extension failed.\n"); |
616 | kfree(slidx_pool.buffer); | 640 | kfree(slidx_pool.buffer); |
617 | return -EFAULT; | 641 | return -EFAULT; |
diff --git a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h index 0227b761f2c4..e2f6fa1e0ef6 100644 --- a/arch/ia64/kernel/mca_drv.h +++ b/arch/ia64/kernel/mca_drv.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com) | 6 | * Copyright (C) Hidetoshi Seto (seto.hidetoshi@jp.fujitsu.com) |
7 | */ | 7 | */ |
8 | /* | 8 | /* |
9 | * Processor error section: | 9 | * Processor error section: |
10 | * | 10 | * |
11 | * +-sal_log_processor_info_t *info-------------+ | 11 | * +-sal_log_processor_info_t *info-------------+ |
12 | * | sal_log_section_hdr_t header; | | 12 | * | sal_log_section_hdr_t header; | |
diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S index 2d7e0217638d..3f298ee4d00c 100644 --- a/arch/ia64/kernel/mca_drv_asm.S +++ b/arch/ia64/kernel/mca_drv_asm.S | |||
@@ -13,45 +13,45 @@ | |||
13 | #include <asm/ptrace.h> | 13 | #include <asm/ptrace.h> |
14 | 14 | ||
15 | GLOBAL_ENTRY(mca_handler_bhhook) | 15 | GLOBAL_ENTRY(mca_handler_bhhook) |
16 | invala // clear RSE ? | 16 | invala // clear RSE ? |
17 | ;; // | 17 | ;; |
18 | cover // | 18 | cover |
19 | ;; // | 19 | ;; |
20 | clrrrb // | 20 | clrrrb |
21 | ;; | 21 | ;; |
22 | alloc r16=ar.pfs,0,2,1,0 // make a new frame | 22 | alloc r16=ar.pfs,0,2,1,0 // make a new frame |
23 | ;; | 23 | ;; |
24 | mov ar.rsc=0 | 24 | mov ar.rsc=0 |
25 | ;; | 25 | ;; |
26 | mov r13=IA64_KR(CURRENT) // current task pointer | 26 | mov r13=IA64_KR(CURRENT) // current task pointer |
27 | ;; | 27 | ;; |
28 | mov r2=r13 | 28 | mov r2=r13 |
29 | ;; | 29 | ;; |
30 | addl r22=IA64_RBS_OFFSET,r2 | 30 | addl r22=IA64_RBS_OFFSET,r2 |
31 | ;; | 31 | ;; |
32 | mov ar.bspstore=r22 | 32 | mov ar.bspstore=r22 |
33 | ;; | 33 | ;; |
34 | addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2 | 34 | addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r2 |
35 | ;; | 35 | ;; |
36 | adds r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 | 36 | adds r2=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 |
37 | ;; | 37 | ;; |
38 | st1 [r2]=r0 // clear current->thread.on_ustack flag | 38 | st1 [r2]=r0 // clear current->thread.on_ustack flag |
39 | mov loc0=r16 | 39 | mov loc0=r16 |
40 | movl loc1=mca_handler_bh // recovery C function | 40 | movl loc1=mca_handler_bh // recovery C function |
41 | ;; | 41 | ;; |
42 | mov out0=r8 // poisoned address | 42 | mov out0=r8 // poisoned address |
43 | mov b6=loc1 | 43 | mov b6=loc1 |
44 | ;; | 44 | ;; |
45 | mov loc1=rp | 45 | mov loc1=rp |
46 | ;; | 46 | ;; |
47 | ssm psr.i | 47 | ssm psr.i |
48 | ;; | 48 | ;; |
49 | br.call.sptk.many rp=b6 // does not return ... | 49 | br.call.sptk.many rp=b6 // does not return ... |
50 | ;; | 50 | ;; |
51 | mov ar.pfs=loc0 | 51 | mov ar.pfs=loc0 |
52 | mov rp=loc1 | 52 | mov rp=loc1 |
53 | ;; | 53 | ;; |
54 | mov r8=r0 | 54 | mov r8=r0 |
55 | br.ret.sptk.many rp | 55 | br.ret.sptk.many rp |
56 | ;; | 56 | ;; |
57 | END(mca_handler_bhhook) | 57 | END(mca_handler_bhhook) |
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 1650353e3f77..d71731ee5b61 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c | |||
@@ -574,7 +574,7 @@ pfm_protect_ctx_ctxsw(pfm_context_t *x) | |||
574 | return 0UL; | 574 | return 0UL; |
575 | } | 575 | } |
576 | 576 | ||
577 | static inline unsigned long | 577 | static inline void |
578 | pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f) | 578 | pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f) |
579 | { | 579 | { |
580 | spin_unlock(&(x)->ctx_lock); | 580 | spin_unlock(&(x)->ctx_lock); |
@@ -2218,12 +2218,13 @@ static void | |||
2218 | pfm_free_fd(int fd, struct file *file) | 2218 | pfm_free_fd(int fd, struct file *file) |
2219 | { | 2219 | { |
2220 | struct files_struct *files = current->files; | 2220 | struct files_struct *files = current->files; |
2221 | struct fdtable *fdt = files_fdtable(files); | 2221 | struct fdtable *fdt; |
2222 | 2222 | ||
2223 | /* | 2223 | /* |
2224 | * there ie no fd_uninstall(), so we do it here | 2224 | * there ie no fd_uninstall(), so we do it here |
2225 | */ | 2225 | */ |
2226 | spin_lock(&files->file_lock); | 2226 | spin_lock(&files->file_lock); |
2227 | fdt = files_fdtable(files); | ||
2227 | rcu_assign_pointer(fdt->fd[fd], NULL); | 2228 | rcu_assign_pointer(fdt->fd[fd], NULL); |
2228 | spin_unlock(&files->file_lock); | 2229 | spin_unlock(&files->file_lock); |
2229 | 2230 | ||
diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile index 799407e7726f..cb1af597370b 100644 --- a/arch/ia64/lib/Makefile +++ b/arch/ia64/lib/Makefile | |||
@@ -15,7 +15,6 @@ lib-$(CONFIG_ITANIUM) += copy_page.o copy_user.o memcpy.o | |||
15 | lib-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o | 15 | lib-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o |
16 | lib-$(CONFIG_PERFMON) += carta_random.o | 16 | lib-$(CONFIG_PERFMON) += carta_random.o |
17 | lib-$(CONFIG_MD_RAID5) += xor.o | 17 | lib-$(CONFIG_MD_RAID5) += xor.o |
18 | lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o | ||
19 | 18 | ||
20 | AFLAGS___divdi3.o = | 19 | AFLAGS___divdi3.o = |
21 | AFLAGS___udivdi3.o = -DUNSIGNED | 20 | AFLAGS___udivdi3.o = -DUNSIGNED |
diff --git a/arch/ia64/lib/dec_and_lock.c b/arch/ia64/lib/dec_and_lock.c deleted file mode 100644 index c7ce92f968f1..000000000000 --- a/arch/ia64/lib/dec_and_lock.c +++ /dev/null | |||
@@ -1,42 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003 Jerome Marchand, Bull S.A. | ||
3 | * Cleaned up by David Mosberger-Tang <davidm@hpl.hp.com> | ||
4 | * | ||
5 | * This file is released under the GPLv2, or at your option any later version. | ||
6 | * | ||
7 | * ia64 version of "atomic_dec_and_lock()" using the atomic "cmpxchg" instruction. This | ||
8 | * code is an adaptation of the x86 version of "atomic_dec_and_lock()". | ||
9 | */ | ||
10 | |||
11 | #include <linux/compiler.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/spinlock.h> | ||
14 | #include <asm/atomic.h> | ||
15 | |||
16 | /* | ||
17 | * Decrement REFCOUNT and if the count reaches zero, acquire the spinlock. Both of these | ||
18 | * operations have to be done atomically, so that the count doesn't drop to zero without | ||
19 | * acquiring the spinlock first. | ||
20 | */ | ||
21 | int | ||
22 | _atomic_dec_and_lock (atomic_t *refcount, spinlock_t *lock) | ||
23 | { | ||
24 | int old, new; | ||
25 | |||
26 | do { | ||
27 | old = atomic_read(refcount); | ||
28 | new = old - 1; | ||
29 | |||
30 | if (unlikely (old == 1)) { | ||
31 | /* oops, we may be decrementing to zero, do it the slow way... */ | ||
32 | spin_lock(lock); | ||
33 | if (atomic_dec_and_test(refcount)) | ||
34 | return 1; | ||
35 | spin_unlock(lock); | ||
36 | return 0; | ||
37 | } | ||
38 | } while (cmpxchg(&refcount->counter, old, new) != old); | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | EXPORT_SYMBOL(_atomic_dec_and_lock); | ||
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index 1ef3987ebc6a..4d100f3886e1 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig | |||
@@ -220,11 +220,6 @@ config PREEMPT | |||
220 | Say Y here if you are building a kernel for a desktop, embedded | 220 | Say Y here if you are building a kernel for a desktop, embedded |
221 | or real-time system. Say N if you are unsure. | 221 | or real-time system. Say N if you are unsure. |
222 | 222 | ||
223 | config HAVE_DEC_LOCK | ||
224 | bool | ||
225 | depends on (SMP || PREEMPT) | ||
226 | default n | ||
227 | |||
228 | config SMP | 223 | config SMP |
229 | bool "Symmetric multi-processing support" | 224 | bool "Symmetric multi-processing support" |
230 | ---help--- | 225 | ---help--- |
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 0eb71ac303af..4cd724c05700 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -1009,10 +1009,6 @@ config GENERIC_CALIBRATE_DELAY | |||
1009 | bool | 1009 | bool |
1010 | default y | 1010 | default y |
1011 | 1011 | ||
1012 | config HAVE_DEC_LOCK | ||
1013 | bool | ||
1014 | default y | ||
1015 | |||
1016 | # | 1012 | # |
1017 | # Select some configuration options automatically based on user selections. | 1013 | # Select some configuration options automatically based on user selections. |
1018 | # | 1014 | # |
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index 4de155699c4f..7ae4af476974 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c | |||
@@ -581,18 +581,13 @@ asmlinkage int irix_brk(unsigned long brk) | |||
581 | } | 581 | } |
582 | 582 | ||
583 | /* | 583 | /* |
584 | * Check if we have enough memory.. | 584 | * Ok, looks good - let it rip. |
585 | */ | 585 | */ |
586 | if (security_vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) { | 586 | if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk) { |
587 | ret = -ENOMEM; | 587 | ret = -ENOMEM; |
588 | goto out; | 588 | goto out; |
589 | } | 589 | } |
590 | |||
591 | /* | ||
592 | * Ok, looks good - let it rip. | ||
593 | */ | ||
594 | mm->brk = brk; | 590 | mm->brk = brk; |
595 | do_brk(oldbrk, newbrk-oldbrk); | ||
596 | ret = 0; | 591 | ret = 0; |
597 | 592 | ||
598 | out: | 593 | out: |
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 21b92b9dd013..037303412909 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for MIPS-specific library files.. | 2 | # Makefile for MIPS-specific library files.. |
3 | # | 3 | # |
4 | 4 | ||
5 | lib-y += csum_partial_copy.o dec_and_lock.o memcpy.o promlib.o \ | 5 | lib-y += csum_partial_copy.o memcpy.o promlib.o \ |
6 | strlen_user.o strncpy_user.o strnlen_user.o | 6 | strlen_user.o strncpy_user.o strnlen_user.o |
7 | 7 | ||
8 | obj-y += iomap.o | 8 | obj-y += iomap.o |
diff --git a/arch/mips/lib/dec_and_lock.c b/arch/mips/lib/dec_and_lock.c deleted file mode 100644 index fd82c84a93b7..000000000000 --- a/arch/mips/lib/dec_and_lock.c +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | /* | ||
2 | * MIPS version of atomic_dec_and_lock() using cmpxchg | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/spinlock.h> | ||
12 | #include <asm/atomic.h> | ||
13 | #include <asm/system.h> | ||
14 | |||
15 | /* | ||
16 | * This is an implementation of the notion of "decrement a | ||
17 | * reference count, and return locked if it decremented to zero". | ||
18 | * | ||
19 | * This implementation can be used on any architecture that | ||
20 | * has a cmpxchg, and where atomic->value is an int holding | ||
21 | * the value of the atomic (i.e. the high bits aren't used | ||
22 | * for a lock or anything like that). | ||
23 | */ | ||
24 | int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) | ||
25 | { | ||
26 | int counter; | ||
27 | int newcount; | ||
28 | |||
29 | for (;;) { | ||
30 | counter = atomic_read(atomic); | ||
31 | newcount = counter - 1; | ||
32 | if (!newcount) | ||
33 | break; /* do it the slow way */ | ||
34 | |||
35 | newcount = cmpxchg(&atomic->counter, counter, newcount); | ||
36 | if (newcount == counter) | ||
37 | return 0; | ||
38 | } | ||
39 | |||
40 | spin_lock(lock); | ||
41 | if (atomic_dec_and_test(atomic)) | ||
42 | return 1; | ||
43 | spin_unlock(lock); | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | EXPORT_SYMBOL(_atomic_dec_and_lock); | ||
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 347ea284140b..776941c75672 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig | |||
@@ -26,10 +26,6 @@ config GENERIC_CALIBRATE_DELAY | |||
26 | bool | 26 | bool |
27 | default y | 27 | default y |
28 | 28 | ||
29 | config HAVE_DEC_LOCK | ||
30 | bool | ||
31 | default y | ||
32 | |||
33 | config PPC | 29 | config PPC |
34 | bool | 30 | bool |
35 | default y | 31 | default y |
diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile index f1e1fb4144f0..50358e4ea159 100644 --- a/arch/ppc/lib/Makefile +++ b/arch/ppc/lib/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for ppc-specific library files.. | 2 | # Makefile for ppc-specific library files.. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := checksum.o string.o strcase.o dec_and_lock.o div64.o | 5 | obj-y := checksum.o string.o strcase.o div64.o |
6 | 6 | ||
7 | obj-$(CONFIG_8xx) += rheap.o | 7 | obj-$(CONFIG_8xx) += rheap.o |
8 | obj-$(CONFIG_CPM2) += rheap.o | 8 | obj-$(CONFIG_CPM2) += rheap.o |
diff --git a/arch/ppc/lib/dec_and_lock.c b/arch/ppc/lib/dec_and_lock.c deleted file mode 100644 index b18f0d9a00fc..000000000000 --- a/arch/ppc/lib/dec_and_lock.c +++ /dev/null | |||
@@ -1,38 +0,0 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/spinlock.h> | ||
3 | #include <asm/atomic.h> | ||
4 | #include <asm/system.h> | ||
5 | |||
6 | /* | ||
7 | * This is an implementation of the notion of "decrement a | ||
8 | * reference count, and return locked if it decremented to zero". | ||
9 | * | ||
10 | * This implementation can be used on any architecture that | ||
11 | * has a cmpxchg, and where atomic->value is an int holding | ||
12 | * the value of the atomic (i.e. the high bits aren't used | ||
13 | * for a lock or anything like that). | ||
14 | */ | ||
15 | int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) | ||
16 | { | ||
17 | int counter; | ||
18 | int newcount; | ||
19 | |||
20 | for (;;) { | ||
21 | counter = atomic_read(atomic); | ||
22 | newcount = counter - 1; | ||
23 | if (!newcount) | ||
24 | break; /* do it the slow way */ | ||
25 | |||
26 | newcount = cmpxchg(&atomic->counter, counter, newcount); | ||
27 | if (newcount == counter) | ||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | spin_lock(lock); | ||
32 | if (atomic_dec_and_test(atomic)) | ||
33 | return 1; | ||
34 | spin_unlock(lock); | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | EXPORT_SYMBOL(_atomic_dec_and_lock); | ||
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 8b9b226005d1..b8d08f33f7ee 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile | |||
@@ -34,7 +34,8 @@ ifeq ($(CONFIG_40x),y) | |||
34 | obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o ppc405_pci.o | 34 | obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o ppc405_pci.o |
35 | endif | 35 | endif |
36 | endif | 36 | endif |
37 | obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) | 37 | obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \ |
38 | ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o | ||
38 | ifeq ($(CONFIG_8xx),y) | 39 | ifeq ($(CONFIG_8xx),y) |
39 | obj-$(CONFIG_PCI) += qspan_pci.o i8259.o | 40 | obj-$(CONFIG_PCI) += qspan_pci.o i8259.o |
40 | endif | 41 | endif |
diff --git a/arch/ppc/syslib/mpc8xx_devices.c b/arch/ppc/syslib/mpc8xx_devices.c new file mode 100644 index 000000000000..2b5f0e701687 --- /dev/null +++ b/arch/ppc/syslib/mpc8xx_devices.c | |||
@@ -0,0 +1,224 @@ | |||
1 | /* | ||
2 | * arch/ppc/syslib/mpc8xx_devices.c | ||
3 | * | ||
4 | * MPC8xx Device descriptions | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug<vbordug@ru.mvista.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/init.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/serial_8250.h> | ||
20 | #include <linux/mii.h> | ||
21 | #include <asm/commproc.h> | ||
22 | #include <asm/mpc8xx.h> | ||
23 | #include <asm/irq.h> | ||
24 | #include <asm/ppc_sys.h> | ||
25 | |||
26 | /* We use offsets for IORESOURCE_MEM to do not set dependences at compile time. | ||
27 | * They will get fixed up by mach_mpc8xx_fixup | ||
28 | */ | ||
29 | |||
30 | struct platform_device ppc_sys_platform_devices[] = { | ||
31 | [MPC8xx_CPM_FEC1] = { | ||
32 | .name = "fsl-cpm-fec", | ||
33 | .id = 1, | ||
34 | .num_resources = 2, | ||
35 | .resource = (struct resource[]) { | ||
36 | { | ||
37 | .name = "regs", | ||
38 | .start = 0xe00, | ||
39 | .end = 0xe88, | ||
40 | .flags = IORESOURCE_MEM, | ||
41 | }, | ||
42 | { | ||
43 | .name = "interrupt", | ||
44 | .start = MPC8xx_INT_FEC1, | ||
45 | .end = MPC8xx_INT_FEC1, | ||
46 | .flags = IORESOURCE_IRQ, | ||
47 | }, | ||
48 | }, | ||
49 | }, | ||
50 | [MPC8xx_CPM_FEC2] = { | ||
51 | .name = "fsl-cpm-fec", | ||
52 | .id = 2, | ||
53 | .num_resources = 2, | ||
54 | .resource = (struct resource[]) { | ||
55 | { | ||
56 | .name = "regs", | ||
57 | .start = 0x1e00, | ||
58 | .end = 0x1e88, | ||
59 | .flags = IORESOURCE_MEM, | ||
60 | }, | ||
61 | { | ||
62 | .name = "interrupt", | ||
63 | .start = MPC8xx_INT_FEC2, | ||
64 | .end = MPC8xx_INT_FEC2, | ||
65 | .flags = IORESOURCE_IRQ, | ||
66 | }, | ||
67 | }, | ||
68 | }, | ||
69 | [MPC8xx_CPM_SCC1] = { | ||
70 | .name = "fsl-cpm-scc", | ||
71 | .id = 1, | ||
72 | .num_resources = 3, | ||
73 | .resource = (struct resource[]) { | ||
74 | { | ||
75 | .name = "regs", | ||
76 | .start = 0xa00, | ||
77 | .end = 0xa18, | ||
78 | .flags = IORESOURCE_MEM, | ||
79 | }, | ||
80 | { | ||
81 | .name = "pram", | ||
82 | .start = 0x3c00, | ||
83 | .end = 0x3c80, | ||
84 | .flags = IORESOURCE_MEM, | ||
85 | }, | ||
86 | { | ||
87 | .name = "interrupt", | ||
88 | .start = MPC8xx_INT_SCC1, | ||
89 | .end = MPC8xx_INT_SCC1, | ||
90 | .flags = IORESOURCE_IRQ, | ||
91 | }, | ||
92 | }, | ||
93 | }, | ||
94 | [MPC8xx_CPM_SCC2] = { | ||
95 | .name = "fsl-cpm-scc", | ||
96 | .id = 2, | ||
97 | .num_resources = 3, | ||
98 | .resource = (struct resource[]) { | ||
99 | { | ||
100 | .name = "regs", | ||
101 | .start = 0xa20, | ||
102 | .end = 0xa38, | ||
103 | .flags = IORESOURCE_MEM, | ||
104 | }, | ||
105 | { | ||
106 | .name = "pram", | ||
107 | .start = 0x3d00, | ||
108 | .end = 0x3d80, | ||
109 | .flags = IORESOURCE_MEM, | ||
110 | }, | ||
111 | |||
112 | { | ||
113 | .name = "interrupt", | ||
114 | .start = MPC8xx_INT_SCC2, | ||
115 | .end = MPC8xx_INT_SCC2, | ||
116 | .flags = IORESOURCE_IRQ, | ||
117 | }, | ||
118 | }, | ||
119 | }, | ||
120 | [MPC8xx_CPM_SCC3] = { | ||
121 | .name = "fsl-cpm-scc", | ||
122 | .id = 3, | ||
123 | .num_resources = 3, | ||
124 | .resource = (struct resource[]) { | ||
125 | { | ||
126 | .name = "regs", | ||
127 | .start = 0xa40, | ||
128 | .end = 0xa58, | ||
129 | .flags = IORESOURCE_MEM, | ||
130 | }, | ||
131 | { | ||
132 | .name = "pram", | ||
133 | .start = 0x3e00, | ||
134 | .end = 0x3e80, | ||
135 | .flags = IORESOURCE_MEM, | ||
136 | }, | ||
137 | |||
138 | { | ||
139 | .name = "interrupt", | ||
140 | .start = MPC8xx_INT_SCC3, | ||
141 | .end = MPC8xx_INT_SCC3, | ||
142 | .flags = IORESOURCE_IRQ, | ||
143 | }, | ||
144 | }, | ||
145 | }, | ||
146 | [MPC8xx_CPM_SCC4] = { | ||
147 | .name = "fsl-cpm-scc", | ||
148 | .id = 4, | ||
149 | .num_resources = 3, | ||
150 | .resource = (struct resource[]) { | ||
151 | { | ||
152 | .name = "regs", | ||
153 | .start = 0xa60, | ||
154 | .end = 0xa78, | ||
155 | .flags = IORESOURCE_MEM, | ||
156 | }, | ||
157 | { | ||
158 | .name = "pram", | ||
159 | .start = 0x3f00, | ||
160 | .end = 0x3f80, | ||
161 | .flags = IORESOURCE_MEM, | ||
162 | }, | ||
163 | |||
164 | { | ||
165 | .name = "interrupt", | ||
166 | .start = MPC8xx_INT_SCC4, | ||
167 | .end = MPC8xx_INT_SCC4, | ||
168 | .flags = IORESOURCE_IRQ, | ||
169 | }, | ||
170 | }, | ||
171 | }, | ||
172 | [MPC8xx_CPM_SMC1] = { | ||
173 | .name = "fsl-cpm-smc", | ||
174 | .id = 1, | ||
175 | .num_resources = 2, | ||
176 | .resource = (struct resource[]) { | ||
177 | { | ||
178 | .name = "regs", | ||
179 | .start = 0xa82, | ||
180 | .end = 0xa91, | ||
181 | .flags = IORESOURCE_MEM, | ||
182 | }, | ||
183 | { | ||
184 | .name = "interrupt", | ||
185 | .start = MPC8xx_INT_SMC1, | ||
186 | .end = MPC8xx_INT_SMC1, | ||
187 | .flags = IORESOURCE_IRQ, | ||
188 | }, | ||
189 | }, | ||
190 | }, | ||
191 | [MPC8xx_CPM_SMC2] = { | ||
192 | .name = "fsl-cpm-smc", | ||
193 | .id = 2, | ||
194 | .num_resources = 2, | ||
195 | .resource = (struct resource[]) { | ||
196 | { | ||
197 | .name = "regs", | ||
198 | .start = 0xa92, | ||
199 | .end = 0xaa1, | ||
200 | .flags = IORESOURCE_MEM, | ||
201 | }, | ||
202 | { | ||
203 | .name = "interrupt", | ||
204 | .start = MPC8xx_INT_SMC2, | ||
205 | .end = MPC8xx_INT_SMC2, | ||
206 | .flags = IORESOURCE_IRQ, | ||
207 | }, | ||
208 | }, | ||
209 | }, | ||
210 | }; | ||
211 | |||
212 | static int __init mach_mpc8xx_fixup(struct platform_device *pdev) | ||
213 | { | ||
214 | ppc_sys_fixup_mem_resource (pdev, IMAP_ADDR); | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int __init mach_mpc8xx_init(void) | ||
219 | { | ||
220 | ppc_sys_device_fixup = mach_mpc8xx_fixup; | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | postcore_initcall(mach_mpc8xx_init); | ||
diff --git a/arch/ppc/syslib/mpc8xx_sys.c b/arch/ppc/syslib/mpc8xx_sys.c new file mode 100644 index 000000000000..a532ccc861c0 --- /dev/null +++ b/arch/ppc/syslib/mpc8xx_sys.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/mpc8xx_sys.c | ||
3 | * | ||
4 | * MPC8xx System descriptions | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/init.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <asm/ppc_sys.h> | ||
20 | |||
21 | struct ppc_sys_spec *cur_ppc_sys_spec; | ||
22 | struct ppc_sys_spec ppc_sys_specs[] = { | ||
23 | { | ||
24 | .ppc_sys_name = "MPC86X", | ||
25 | .mask = 0xFFFFFFFF, | ||
26 | .value = 0x00000000, | ||
27 | .num_devices = 2, | ||
28 | .device_list = (enum ppc_sys_devices[]) | ||
29 | { | ||
30 | MPC8xx_CPM_FEC1, | ||
31 | MPC8xx_CPM_SCC1, | ||
32 | MPC8xx_CPM_SCC2, | ||
33 | MPC8xx_CPM_SCC3, | ||
34 | MPC8xx_CPM_SCC4, | ||
35 | MPC8xx_CPM_SMC1, | ||
36 | MPC8xx_CPM_SMC2, | ||
37 | }, | ||
38 | }, | ||
39 | { | ||
40 | .ppc_sys_name = "MPC885", | ||
41 | .mask = 0xFFFFFFFF, | ||
42 | .value = 0x00000000, | ||
43 | .num_devices = 3, | ||
44 | .device_list = (enum ppc_sys_devices[]) | ||
45 | { | ||
46 | MPC8xx_CPM_FEC1, | ||
47 | MPC8xx_CPM_FEC2, | ||
48 | MPC8xx_CPM_SCC1, | ||
49 | MPC8xx_CPM_SCC2, | ||
50 | MPC8xx_CPM_SCC3, | ||
51 | MPC8xx_CPM_SCC4, | ||
52 | MPC8xx_CPM_SMC1, | ||
53 | MPC8xx_CPM_SMC2, | ||
54 | }, | ||
55 | }, | ||
56 | { /* default match */ | ||
57 | .ppc_sys_name = "", | ||
58 | .mask = 0x00000000, | ||
59 | .value = 0x00000000, | ||
60 | }, | ||
61 | }; | ||
diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c index 2e0ea92144f6..9a7e8748e2b2 100644 --- a/arch/ppc/syslib/open_pic2.c +++ b/arch/ppc/syslib/open_pic2.c | |||
@@ -575,7 +575,7 @@ static void openpic2_cached_disable_irq(u_int irq) | |||
575 | * we need something better to deal with that... Maybe switch to S1 for | 575 | * we need something better to deal with that... Maybe switch to S1 for |
576 | * cpufreq changes | 576 | * cpufreq changes |
577 | */ | 577 | */ |
578 | int openpic2_suspend(struct sys_device *sysdev, u32 state) | 578 | int openpic2_suspend(struct sys_device *sysdev, pm_message_t state) |
579 | { | 579 | { |
580 | int i; | 580 | int i; |
581 | unsigned long flags; | 581 | unsigned long flags; |
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig index deca68ad644a..c658650af429 100644 --- a/arch/ppc64/Kconfig +++ b/arch/ppc64/Kconfig | |||
@@ -28,10 +28,6 @@ config GENERIC_ISA_DMA | |||
28 | bool | 28 | bool |
29 | default y | 29 | default y |
30 | 30 | ||
31 | config HAVE_DEC_LOCK | ||
32 | bool | ||
33 | default y | ||
34 | |||
35 | config EARLY_PRINTK | 31 | config EARLY_PRINTK |
36 | bool | 32 | bool |
37 | default y | 33 | default y |
diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile index 17d2c1eac3b8..521c2a5a2862 100644 --- a/arch/ppc64/Makefile +++ b/arch/ppc64/Makefile | |||
@@ -107,7 +107,7 @@ install: vmlinux | |||
107 | $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ | 107 | $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ |
108 | 108 | ||
109 | defaultimage-$(CONFIG_PPC_PSERIES) := zImage | 109 | defaultimage-$(CONFIG_PPC_PSERIES) := zImage |
110 | defaultimage-$(CONFIG_PPC_PMAC) := vmlinux | 110 | defaultimage-$(CONFIG_PPC_PMAC) := zImage.vmode |
111 | defaultimage-$(CONFIG_PPC_MAPLE) := zImage | 111 | defaultimage-$(CONFIG_PPC_MAPLE) := zImage |
112 | defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux | 112 | defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux |
113 | KBUILD_IMAGE := $(defaultimage-y) | 113 | KBUILD_IMAGE := $(defaultimage-y) |
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index 58c314738c99..72c61041151a 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S | |||
@@ -1649,7 +1649,7 @@ _GLOBAL(__secondary_start) | |||
1649 | ld r3,0(r3) | 1649 | ld r3,0(r3) |
1650 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | 1650 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ |
1651 | andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ | 1651 | andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ |
1652 | bne 98f | 1652 | beq 98f /* branch if result is 0 */ |
1653 | mfspr r3,PVR | 1653 | mfspr r3,PVR |
1654 | srwi r3,r3,16 | 1654 | srwi r3,r3,16 |
1655 | cmpwi r3,0x37 /* SStar */ | 1655 | cmpwi r3,0x37 /* SStar */ |
@@ -1813,7 +1813,7 @@ _STATIC(start_here_multiplatform) | |||
1813 | ld r3,0(r3) | 1813 | ld r3,0(r3) |
1814 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | 1814 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ |
1815 | andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ | 1815 | andi. r3,r3,PLATFORM_LPAR /* Test if bit 0 is set (LPAR bit) */ |
1816 | bne 98f | 1816 | beq 98f /* branch if result is 0 */ |
1817 | mfspr r3,PVR | 1817 | mfspr r3,PVR |
1818 | srwi r3,r3,16 | 1818 | srwi r3,r3,16 |
1819 | cmpwi r3,0x37 /* SStar */ | 1819 | cmpwi r3,0x37 /* SStar */ |
@@ -1834,7 +1834,7 @@ _STATIC(start_here_multiplatform) | |||
1834 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ | 1834 | lwz r3,PLATFORM(r3) /* r3 = platform flags */ |
1835 | /* Test if bit 0 is set (LPAR bit) */ | 1835 | /* Test if bit 0 is set (LPAR bit) */ |
1836 | andi. r3,r3,PLATFORM_LPAR | 1836 | andi. r3,r3,PLATFORM_LPAR |
1837 | bne 98f | 1837 | bne 98f /* branch if result is !0 */ |
1838 | LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ | 1838 | LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ |
1839 | sub r6,r6,r26 | 1839 | sub r6,r6,r26 |
1840 | ld r6,0(r6) /* get the value of _SDR1 */ | 1840 | ld r6,0(r6) /* get the value of _SDR1 */ |
diff --git a/arch/ppc64/kernel/pSeries_iommu.c b/arch/ppc64/kernel/pSeries_iommu.c index f0fd7fbd6531..8c6313e7e145 100644 --- a/arch/ppc64/kernel/pSeries_iommu.c +++ b/arch/ppc64/kernel/pSeries_iommu.c | |||
@@ -265,8 +265,10 @@ static void iommu_table_setparms(struct pci_controller *phb, | |||
265 | tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT; | 265 | tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT; |
266 | 266 | ||
267 | /* Test if we are going over 2GB of DMA space */ | 267 | /* Test if we are going over 2GB of DMA space */ |
268 | if (phb->dma_window_base_cur + phb->dma_window_size > (1L << 31)) | 268 | if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) { |
269 | udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); | ||
269 | panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); | 270 | panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); |
271 | } | ||
270 | 272 | ||
271 | phb->dma_window_base_cur += phb->dma_window_size; | 273 | phb->dma_window_base_cur += phb->dma_window_size; |
272 | 274 | ||
@@ -310,92 +312,84 @@ static void iommu_table_setparms_lpar(struct pci_controller *phb, | |||
310 | 312 | ||
311 | static void iommu_bus_setup_pSeries(struct pci_bus *bus) | 313 | static void iommu_bus_setup_pSeries(struct pci_bus *bus) |
312 | { | 314 | { |
313 | struct device_node *dn, *pdn; | 315 | struct device_node *dn; |
314 | struct pci_dn *pci; | ||
315 | struct iommu_table *tbl; | 316 | struct iommu_table *tbl; |
317 | struct device_node *isa_dn, *isa_dn_orig; | ||
318 | struct device_node *tmp; | ||
319 | struct pci_dn *pci; | ||
320 | int children; | ||
316 | 321 | ||
317 | DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); | 322 | DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self); |
318 | 323 | ||
319 | /* For each (root) bus, we carve up the available DMA space in 256MB | 324 | dn = pci_bus_to_OF_node(bus); |
320 | * pieces. Since each piece is used by one (sub) bus/device, that would | 325 | pci = PCI_DN(dn); |
321 | * give a maximum of 7 devices per PHB. In most cases, this is plenty. | 326 | |
322 | * | 327 | if (bus->self) { |
323 | * The exception is on Python PHBs (pre-POWER4). Here we don't have EADS | 328 | /* This is not a root bus, any setup will be done for the |
324 | * bridges below the PHB to allocate the sectioned tables to, so instead | 329 | * device-side of the bridge in iommu_dev_setup_pSeries(). |
325 | * we allocate a 1GB table at the PHB level. | 330 | */ |
331 | return; | ||
332 | } | ||
333 | |||
334 | /* Check if the ISA bus on the system is under | ||
335 | * this PHB. | ||
326 | */ | 336 | */ |
337 | isa_dn = isa_dn_orig = of_find_node_by_type(NULL, "isa"); | ||
327 | 338 | ||
328 | dn = pci_bus_to_OF_node(bus); | 339 | while (isa_dn && isa_dn != dn) |
329 | pci = dn->data; | 340 | isa_dn = isa_dn->parent; |
330 | 341 | ||
331 | if (!bus->self) { | 342 | if (isa_dn_orig) |
332 | /* Root bus */ | 343 | of_node_put(isa_dn_orig); |
333 | if (is_python(dn)) { | ||
334 | unsigned int *iohole; | ||
335 | |||
336 | DBG("Python root bus %s\n", bus->name); | ||
337 | |||
338 | iohole = (unsigned int *)get_property(dn, "io-hole", 0); | ||
339 | |||
340 | if (iohole) { | ||
341 | /* On first bus we need to leave room for the | ||
342 | * ISA address space. Just skip the first 256MB | ||
343 | * alltogether. This leaves 768MB for the window. | ||
344 | */ | ||
345 | DBG("PHB has io-hole, reserving 256MB\n"); | ||
346 | pci->phb->dma_window_size = 3 << 28; | ||
347 | pci->phb->dma_window_base_cur = 1 << 28; | ||
348 | } else { | ||
349 | /* 1GB window by default */ | ||
350 | pci->phb->dma_window_size = 1 << 30; | ||
351 | pci->phb->dma_window_base_cur = 0; | ||
352 | } | ||
353 | |||
354 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | ||
355 | |||
356 | iommu_table_setparms(pci->phb, dn, tbl); | ||
357 | pci->iommu_table = iommu_init_table(tbl); | ||
358 | } else { | ||
359 | /* Do a 128MB table at root. This is used for the IDE | ||
360 | * controller on some SMP-mode POWER4 machines. It | ||
361 | * doesn't hurt to allocate it on other machines | ||
362 | * -- it'll just be unused since new tables are | ||
363 | * allocated on the EADS level. | ||
364 | * | ||
365 | * Allocate at offset 128MB to avoid having to deal | ||
366 | * with ISA holes; 128MB table for IDE is plenty. | ||
367 | */ | ||
368 | pci->phb->dma_window_size = 1 << 27; | ||
369 | pci->phb->dma_window_base_cur = 1 << 27; | ||
370 | |||
371 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | ||
372 | |||
373 | iommu_table_setparms(pci->phb, dn, tbl); | ||
374 | pci->iommu_table = iommu_init_table(tbl); | ||
375 | |||
376 | /* All child buses have 256MB tables */ | ||
377 | pci->phb->dma_window_size = 1 << 28; | ||
378 | } | ||
379 | } else { | ||
380 | pdn = pci_bus_to_OF_node(bus->parent); | ||
381 | 344 | ||
382 | if (!bus->parent->self && !is_python(pdn)) { | 345 | /* Count number of direct PCI children of the PHB. |
383 | struct iommu_table *tbl; | 346 | * All PCI device nodes have class-code property, so it's |
384 | /* First child and not python means this is the EADS | 347 | * an easy way to find them. |
385 | * level. Allocate new table for this slot with 256MB | 348 | */ |
386 | * window. | 349 | for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling) |
387 | */ | 350 | if (get_property(tmp, "class-code", NULL)) |
351 | children++; | ||
388 | 352 | ||
389 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | 353 | DBG("Children: %d\n", children); |
390 | 354 | ||
391 | iommu_table_setparms(pci->phb, dn, tbl); | 355 | /* Calculate amount of DMA window per slot. Each window must be |
356 | * a power of two (due to pci_alloc_consistent requirements). | ||
357 | * | ||
358 | * Keep 256MB aside for PHBs with ISA. | ||
359 | */ | ||
392 | 360 | ||
393 | pci->iommu_table = iommu_init_table(tbl); | 361 | if (!isa_dn) { |
394 | } else { | 362 | /* No ISA/IDE - just set window size and return */ |
395 | /* Lower than first child or under python, use parent table */ | 363 | pci->phb->dma_window_size = 0x80000000ul; /* To be divided */ |
396 | pci->iommu_table = PCI_DN(pdn)->iommu_table; | 364 | |
397 | } | 365 | while (pci->phb->dma_window_size * children > 0x80000000ul) |
366 | pci->phb->dma_window_size >>= 1; | ||
367 | DBG("No ISA/IDE, window size is %x\n", pci->phb->dma_window_size); | ||
368 | pci->phb->dma_window_base_cur = 0; | ||
369 | |||
370 | return; | ||
398 | } | 371 | } |
372 | |||
373 | /* If we have ISA, then we probably have an IDE | ||
374 | * controller too. Allocate a 128MB table but | ||
375 | * skip the first 128MB to avoid stepping on ISA | ||
376 | * space. | ||
377 | */ | ||
378 | pci->phb->dma_window_size = 0x8000000ul; | ||
379 | pci->phb->dma_window_base_cur = 0x8000000ul; | ||
380 | |||
381 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | ||
382 | |||
383 | iommu_table_setparms(pci->phb, dn, tbl); | ||
384 | pci->iommu_table = iommu_init_table(tbl); | ||
385 | |||
386 | /* Divide the rest (1.75GB) among the children */ | ||
387 | pci->phb->dma_window_size = 0x80000000ul; | ||
388 | while (pci->phb->dma_window_size * children > 0x70000000ul) | ||
389 | pci->phb->dma_window_size >>= 1; | ||
390 | |||
391 | DBG("ISA/IDE, window size is %x\n", pci->phb->dma_window_size); | ||
392 | |||
399 | } | 393 | } |
400 | 394 | ||
401 | 395 | ||
@@ -446,14 +440,29 @@ static void iommu_bus_setup_pSeriesLP(struct pci_bus *bus) | |||
446 | static void iommu_dev_setup_pSeries(struct pci_dev *dev) | 440 | static void iommu_dev_setup_pSeries(struct pci_dev *dev) |
447 | { | 441 | { |
448 | struct device_node *dn, *mydn; | 442 | struct device_node *dn, *mydn; |
443 | struct iommu_table *tbl; | ||
449 | 444 | ||
450 | DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, dev->pretty_name); | 445 | DBG("iommu_dev_setup_pSeries, dev %p (%s)\n", dev, dev->pretty_name); |
451 | /* Now copy the iommu_table ptr from the bus device down to the | 446 | |
452 | * pci device_node. This means get_iommu_table() won't need to search | ||
453 | * up the device tree to find it. | ||
454 | */ | ||
455 | mydn = dn = pci_device_to_OF_node(dev); | 447 | mydn = dn = pci_device_to_OF_node(dev); |
456 | 448 | ||
449 | /* If we're the direct child of a root bus, then we need to allocate | ||
450 | * an iommu table ourselves. The bus setup code should have setup | ||
451 | * the window sizes already. | ||
452 | */ | ||
453 | if (!dev->bus->self) { | ||
454 | DBG(" --> first child, no bridge. Allocating iommu table.\n"); | ||
455 | tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL); | ||
456 | iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl); | ||
457 | PCI_DN(mydn)->iommu_table = iommu_init_table(tbl); | ||
458 | |||
459 | return; | ||
460 | } | ||
461 | |||
462 | /* If this device is further down the bus tree, search upwards until | ||
463 | * an already allocated iommu table is found and use that. | ||
464 | */ | ||
465 | |||
457 | while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL) | 466 | while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL) |
458 | dn = dn->parent; | 467 | dn = dn->parent; |
459 | 468 | ||
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index 861138ad092c..ff4be1da69d5 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c | |||
@@ -246,11 +246,14 @@ static unsigned int pci_parse_of_flags(u32 addr0) | |||
246 | unsigned int flags = 0; | 246 | unsigned int flags = 0; |
247 | 247 | ||
248 | if (addr0 & 0x02000000) { | 248 | if (addr0 & 0x02000000) { |
249 | flags |= IORESOURCE_MEM; | 249 | flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY; |
250 | flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64; | ||
251 | flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M; | ||
250 | if (addr0 & 0x40000000) | 252 | if (addr0 & 0x40000000) |
251 | flags |= IORESOURCE_PREFETCH; | 253 | flags |= IORESOURCE_PREFETCH |
254 | | PCI_BASE_ADDRESS_MEM_PREFETCH; | ||
252 | } else if (addr0 & 0x01000000) | 255 | } else if (addr0 & 0x01000000) |
253 | flags |= IORESOURCE_IO; | 256 | flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO; |
254 | return flags; | 257 | return flags; |
255 | } | 258 | } |
256 | 259 | ||
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index 9979919cdf92..f252670874a4 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c | |||
@@ -1711,6 +1711,7 @@ static void __init flatten_device_tree(void) | |||
1711 | unsigned long offset = reloc_offset(); | 1711 | unsigned long offset = reloc_offset(); |
1712 | unsigned long mem_start, mem_end, room; | 1712 | unsigned long mem_start, mem_end, room; |
1713 | struct boot_param_header *hdr; | 1713 | struct boot_param_header *hdr; |
1714 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1714 | char *namep; | 1715 | char *namep; |
1715 | u64 *rsvmap; | 1716 | u64 *rsvmap; |
1716 | 1717 | ||
@@ -1765,6 +1766,7 @@ static void __init flatten_device_tree(void) | |||
1765 | RELOC(dt_struct_end) = PAGE_ALIGN(mem_start); | 1766 | RELOC(dt_struct_end) = PAGE_ALIGN(mem_start); |
1766 | 1767 | ||
1767 | /* Finish header */ | 1768 | /* Finish header */ |
1769 | hdr->boot_cpuid_phys = _prom->cpu; | ||
1768 | hdr->magic = OF_DT_HEADER; | 1770 | hdr->magic = OF_DT_HEADER; |
1769 | hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start); | 1771 | hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start); |
1770 | hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start); | 1772 | hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start); |
@@ -1854,7 +1856,6 @@ static void __init prom_find_boot_cpu(void) | |||
1854 | 1856 | ||
1855 | cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu); | 1857 | cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu); |
1856 | 1858 | ||
1857 | prom_setprop(cpu_pkg, "linux,boot-cpu", NULL, 0); | ||
1858 | prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval)); | 1859 | prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval)); |
1859 | _prom->cpu = getprop_rval; | 1860 | _prom->cpu = getprop_rval; |
1860 | 1861 | ||
diff --git a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c index 4777676365fe..efa985f05aca 100644 --- a/arch/ppc64/kernel/vdso.c +++ b/arch/ppc64/kernel/vdso.c | |||
@@ -224,10 +224,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack) | |||
224 | vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); | 224 | vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); |
225 | if (vma == NULL) | 225 | if (vma == NULL) |
226 | return -ENOMEM; | 226 | return -ENOMEM; |
227 | if (security_vm_enough_memory(vdso_pages)) { | 227 | |
228 | kmem_cache_free(vm_area_cachep, vma); | ||
229 | return -ENOMEM; | ||
230 | } | ||
231 | memset(vma, 0, sizeof(*vma)); | 228 | memset(vma, 0, sizeof(*vma)); |
232 | 229 | ||
233 | /* | 230 | /* |
@@ -237,8 +234,10 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack) | |||
237 | */ | 234 | */ |
238 | vdso_base = get_unmapped_area(NULL, vdso_base, | 235 | vdso_base = get_unmapped_area(NULL, vdso_base, |
239 | vdso_pages << PAGE_SHIFT, 0, 0); | 236 | vdso_pages << PAGE_SHIFT, 0, 0); |
240 | if (vdso_base & ~PAGE_MASK) | 237 | if (vdso_base & ~PAGE_MASK) { |
238 | kmem_cache_free(vm_area_cachep, vma); | ||
241 | return (int)vdso_base; | 239 | return (int)vdso_base; |
240 | } | ||
242 | 241 | ||
243 | current->thread.vdso_base = vdso_base; | 242 | current->thread.vdso_base = vdso_base; |
244 | 243 | ||
@@ -266,7 +265,11 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack) | |||
266 | vma->vm_ops = &vdso_vmops; | 265 | vma->vm_ops = &vdso_vmops; |
267 | 266 | ||
268 | down_write(&mm->mmap_sem); | 267 | down_write(&mm->mmap_sem); |
269 | insert_vm_struct(mm, vma); | 268 | if (insert_vm_struct(mm, vma)) { |
269 | up_write(&mm->mmap_sem); | ||
270 | kmem_cache_free(vm_area_cachep, vma); | ||
271 | return -ENOMEM; | ||
272 | } | ||
270 | mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; | 273 | mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; |
271 | up_write(&mm->mmap_sem); | 274 | up_write(&mm->mmap_sem); |
272 | 275 | ||
diff --git a/arch/ppc64/lib/Makefile b/arch/ppc64/lib/Makefile index 76fbfa9f706f..0b6e967de948 100644 --- a/arch/ppc64/lib/Makefile +++ b/arch/ppc64/lib/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for ppc64-specific library files.. | 2 | # Makefile for ppc64-specific library files.. |
3 | # | 3 | # |
4 | 4 | ||
5 | lib-y := checksum.o dec_and_lock.o string.o strcase.o | 5 | lib-y := checksum.o string.o strcase.o |
6 | lib-y += copypage.o memcpy.o copyuser.o usercopy.o | 6 | lib-y += copypage.o memcpy.o copyuser.o usercopy.o |
7 | 7 | ||
8 | # Lock primitives are defined as no-ops in include/linux/spinlock.h | 8 | # Lock primitives are defined as no-ops in include/linux/spinlock.h |
diff --git a/arch/ppc64/lib/dec_and_lock.c b/arch/ppc64/lib/dec_and_lock.c deleted file mode 100644 index 7b9d4da5cf92..000000000000 --- a/arch/ppc64/lib/dec_and_lock.c +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | /* | ||
2 | * ppc64 version of atomic_dec_and_lock() using cmpxchg | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/spinlock.h> | ||
12 | #include <asm/atomic.h> | ||
13 | #include <asm/system.h> | ||
14 | |||
15 | /* | ||
16 | * This is an implementation of the notion of "decrement a | ||
17 | * reference count, and return locked if it decremented to zero". | ||
18 | * | ||
19 | * This implementation can be used on any architecture that | ||
20 | * has a cmpxchg, and where atomic->value is an int holding | ||
21 | * the value of the atomic (i.e. the high bits aren't used | ||
22 | * for a lock or anything like that). | ||
23 | */ | ||
24 | int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) | ||
25 | { | ||
26 | int counter; | ||
27 | int newcount; | ||
28 | |||
29 | for (;;) { | ||
30 | counter = atomic_read(atomic); | ||
31 | newcount = counter - 1; | ||
32 | if (!newcount) | ||
33 | break; /* do it the slow way */ | ||
34 | |||
35 | newcount = cmpxchg(&atomic->counter, counter, newcount); | ||
36 | if (newcount == counter) | ||
37 | return 0; | ||
38 | } | ||
39 | |||
40 | spin_lock(lock); | ||
41 | if (atomic_dec_and_test(atomic)) | ||
42 | return 1; | ||
43 | spin_unlock(lock); | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | EXPORT_SYMBOL(_atomic_dec_and_lock); | ||
diff --git a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c index 7fbc68bbb739..be3f25cf3e9f 100644 --- a/arch/ppc64/mm/fault.c +++ b/arch/ppc64/mm/fault.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/system.h> | 38 | #include <asm/system.h> |
39 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
40 | #include <asm/kdebug.h> | 40 | #include <asm/kdebug.h> |
41 | #include <asm/siginfo.h> | ||
41 | 42 | ||
42 | /* | 43 | /* |
43 | * Check whether the instruction at regs->nip is a store using | 44 | * Check whether the instruction at regs->nip is a store using |
diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 0865251a3f44..45d44c6bb39d 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.13-rc4 | 3 | # Linux kernel version: 2.6.14-rc1 |
4 | # Fri Jul 29 14:49:30 2005 | 4 | # Wed Sep 14 16:46:19 2005 |
5 | # | 5 | # |
6 | CONFIG_MMU=y | 6 | CONFIG_MMU=y |
7 | CONFIG_RWSEM_XCHGADD_ALGORITHM=y | 7 | CONFIG_RWSEM_XCHGADD_ALGORITHM=y |
@@ -21,6 +21,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 | |||
21 | # General setup | 21 | # General setup |
22 | # | 22 | # |
23 | CONFIG_LOCALVERSION="" | 23 | CONFIG_LOCALVERSION="" |
24 | CONFIG_LOCALVERSION_AUTO=y | ||
24 | CONFIG_SWAP=y | 25 | CONFIG_SWAP=y |
25 | CONFIG_SYSVIPC=y | 26 | CONFIG_SYSVIPC=y |
26 | CONFIG_POSIX_MQUEUE=y | 27 | CONFIG_POSIX_MQUEUE=y |
@@ -33,6 +34,7 @@ CONFIG_KOBJECT_UEVENT=y | |||
33 | CONFIG_IKCONFIG=y | 34 | CONFIG_IKCONFIG=y |
34 | CONFIG_IKCONFIG_PROC=y | 35 | CONFIG_IKCONFIG_PROC=y |
35 | # CONFIG_CPUSETS is not set | 36 | # CONFIG_CPUSETS is not set |
37 | CONFIG_INITRAMFS_SOURCE="" | ||
36 | # CONFIG_EMBEDDED is not set | 38 | # CONFIG_EMBEDDED is not set |
37 | CONFIG_KALLSYMS=y | 39 | CONFIG_KALLSYMS=y |
38 | # CONFIG_KALLSYMS_ALL is not set | 40 | # CONFIG_KALLSYMS_ALL is not set |
@@ -94,6 +96,7 @@ CONFIG_FLATMEM_MANUAL=y | |||
94 | # CONFIG_SPARSEMEM_MANUAL is not set | 96 | # CONFIG_SPARSEMEM_MANUAL is not set |
95 | CONFIG_FLATMEM=y | 97 | CONFIG_FLATMEM=y |
96 | CONFIG_FLAT_NODE_MEM_MAP=y | 98 | CONFIG_FLAT_NODE_MEM_MAP=y |
99 | # CONFIG_SPARSEMEM_STATIC is not set | ||
97 | 100 | ||
98 | # | 101 | # |
99 | # I/O subsystem configuration | 102 | # I/O subsystem configuration |
@@ -151,8 +154,8 @@ CONFIG_IP_FIB_HASH=y | |||
151 | # CONFIG_INET_ESP is not set | 154 | # CONFIG_INET_ESP is not set |
152 | # CONFIG_INET_IPCOMP is not set | 155 | # CONFIG_INET_IPCOMP is not set |
153 | # CONFIG_INET_TUNNEL is not set | 156 | # CONFIG_INET_TUNNEL is not set |
154 | CONFIG_IP_TCPDIAG=y | 157 | CONFIG_INET_DIAG=y |
155 | CONFIG_IP_TCPDIAG_IPV6=y | 158 | CONFIG_INET_TCP_DIAG=y |
156 | # CONFIG_TCP_CONG_ADVANCED is not set | 159 | # CONFIG_TCP_CONG_ADVANCED is not set |
157 | CONFIG_TCP_CONG_BIC=y | 160 | CONFIG_TCP_CONG_BIC=y |
158 | CONFIG_IPV6=y | 161 | CONFIG_IPV6=y |
@@ -165,6 +168,11 @@ CONFIG_IPV6=y | |||
165 | # CONFIG_NETFILTER is not set | 168 | # CONFIG_NETFILTER is not set |
166 | 169 | ||
167 | # | 170 | # |
171 | # DCCP Configuration (EXPERIMENTAL) | ||
172 | # | ||
173 | # CONFIG_IP_DCCP is not set | ||
174 | |||
175 | # | ||
168 | # SCTP Configuration (EXPERIMENTAL) | 176 | # SCTP Configuration (EXPERIMENTAL) |
169 | # | 177 | # |
170 | # CONFIG_IP_SCTP is not set | 178 | # CONFIG_IP_SCTP is not set |
@@ -217,9 +225,11 @@ CONFIG_NET_CLS_POLICE=y | |||
217 | # Network testing | 225 | # Network testing |
218 | # | 226 | # |
219 | # CONFIG_NET_PKTGEN is not set | 227 | # CONFIG_NET_PKTGEN is not set |
228 | # CONFIG_NETFILTER_NETLINK is not set | ||
220 | # CONFIG_HAMRADIO is not set | 229 | # CONFIG_HAMRADIO is not set |
221 | # CONFIG_IRDA is not set | 230 | # CONFIG_IRDA is not set |
222 | # CONFIG_BT is not set | 231 | # CONFIG_BT is not set |
232 | # CONFIG_IEEE80211 is not set | ||
223 | # CONFIG_PCMCIA is not set | 233 | # CONFIG_PCMCIA is not set |
224 | 234 | ||
225 | # | 235 | # |
@@ -233,6 +243,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y | |||
233 | # | 243 | # |
234 | # SCSI device support | 244 | # SCSI device support |
235 | # | 245 | # |
246 | # CONFIG_RAID_ATTRS is not set | ||
236 | CONFIG_SCSI=y | 247 | CONFIG_SCSI=y |
237 | CONFIG_SCSI_PROC_FS=y | 248 | CONFIG_SCSI_PROC_FS=y |
238 | 249 | ||
@@ -260,6 +271,7 @@ CONFIG_SCSI_LOGGING=y | |||
260 | # CONFIG_SCSI_SPI_ATTRS is not set | 271 | # CONFIG_SCSI_SPI_ATTRS is not set |
261 | CONFIG_SCSI_FC_ATTRS=y | 272 | CONFIG_SCSI_FC_ATTRS=y |
262 | # CONFIG_SCSI_ISCSI_ATTRS is not set | 273 | # CONFIG_SCSI_ISCSI_ATTRS is not set |
274 | # CONFIG_SCSI_SAS_ATTRS is not set | ||
263 | 275 | ||
264 | # | 276 | # |
265 | # SCSI low-level drivers | 277 | # SCSI low-level drivers |
@@ -280,7 +292,6 @@ CONFIG_BLK_DEV_RAM=y | |||
280 | CONFIG_BLK_DEV_RAM_COUNT=16 | 292 | CONFIG_BLK_DEV_RAM_COUNT=16 |
281 | CONFIG_BLK_DEV_RAM_SIZE=4096 | 293 | CONFIG_BLK_DEV_RAM_SIZE=4096 |
282 | CONFIG_BLK_DEV_INITRD=y | 294 | CONFIG_BLK_DEV_INITRD=y |
283 | CONFIG_INITRAMFS_SOURCE="" | ||
284 | # CONFIG_LBD is not set | 295 | # CONFIG_LBD is not set |
285 | # CONFIG_CDROM_PKTCDVD is not set | 296 | # CONFIG_CDROM_PKTCDVD is not set |
286 | 297 | ||
@@ -384,6 +395,10 @@ CONFIG_EQUALIZER=m | |||
384 | CONFIG_TUN=m | 395 | CONFIG_TUN=m |
385 | 396 | ||
386 | # | 397 | # |
398 | # PHY device support | ||
399 | # | ||
400 | |||
401 | # | ||
387 | # Ethernet (10 or 100Mbit) | 402 | # Ethernet (10 or 100Mbit) |
388 | # | 403 | # |
389 | CONFIG_NET_ETHERNET=y | 404 | CONFIG_NET_ETHERNET=y |
@@ -453,10 +468,6 @@ CONFIG_FS_MBCACHE=y | |||
453 | # CONFIG_REISERFS_FS is not set | 468 | # CONFIG_REISERFS_FS is not set |
454 | # CONFIG_JFS_FS is not set | 469 | # CONFIG_JFS_FS is not set |
455 | # CONFIG_FS_POSIX_ACL is not set | 470 | # CONFIG_FS_POSIX_ACL is not set |
456 | |||
457 | # | ||
458 | # XFS support | ||
459 | # | ||
460 | # CONFIG_XFS_FS is not set | 471 | # CONFIG_XFS_FS is not set |
461 | # CONFIG_MINIX_FS is not set | 472 | # CONFIG_MINIX_FS is not set |
462 | # CONFIG_ROMFS_FS is not set | 473 | # CONFIG_ROMFS_FS is not set |
@@ -465,6 +476,7 @@ CONFIG_INOTIFY=y | |||
465 | CONFIG_DNOTIFY=y | 476 | CONFIG_DNOTIFY=y |
466 | # CONFIG_AUTOFS_FS is not set | 477 | # CONFIG_AUTOFS_FS is not set |
467 | # CONFIG_AUTOFS4_FS is not set | 478 | # CONFIG_AUTOFS4_FS is not set |
479 | # CONFIG_FUSE_FS is not set | ||
468 | 480 | ||
469 | # | 481 | # |
470 | # CD-ROM/DVD Filesystems | 482 | # CD-ROM/DVD Filesystems |
@@ -485,11 +497,10 @@ CONFIG_DNOTIFY=y | |||
485 | CONFIG_PROC_FS=y | 497 | CONFIG_PROC_FS=y |
486 | CONFIG_PROC_KCORE=y | 498 | CONFIG_PROC_KCORE=y |
487 | CONFIG_SYSFS=y | 499 | CONFIG_SYSFS=y |
488 | # CONFIG_DEVPTS_FS_XATTR is not set | ||
489 | CONFIG_TMPFS=y | 500 | CONFIG_TMPFS=y |
490 | # CONFIG_TMPFS_XATTR is not set | ||
491 | # CONFIG_HUGETLB_PAGE is not set | 501 | # CONFIG_HUGETLB_PAGE is not set |
492 | CONFIG_RAMFS=y | 502 | CONFIG_RAMFS=y |
503 | # CONFIG_RELAYFS_FS is not set | ||
493 | 504 | ||
494 | # | 505 | # |
495 | # Miscellaneous filesystems | 506 | # Miscellaneous filesystems |
@@ -533,6 +544,7 @@ CONFIG_SUNRPC=y | |||
533 | # CONFIG_NCP_FS is not set | 544 | # CONFIG_NCP_FS is not set |
534 | # CONFIG_CODA_FS is not set | 545 | # CONFIG_CODA_FS is not set |
535 | # CONFIG_AFS_FS is not set | 546 | # CONFIG_AFS_FS is not set |
547 | # CONFIG_9P_FS is not set | ||
536 | 548 | ||
537 | # | 549 | # |
538 | # Partition Types | 550 | # Partition Types |
@@ -572,6 +584,7 @@ CONFIG_MSDOS_PARTITION=y | |||
572 | CONFIG_DEBUG_KERNEL=y | 584 | CONFIG_DEBUG_KERNEL=y |
573 | CONFIG_MAGIC_SYSRQ=y | 585 | CONFIG_MAGIC_SYSRQ=y |
574 | CONFIG_LOG_BUF_SHIFT=17 | 586 | CONFIG_LOG_BUF_SHIFT=17 |
587 | CONFIG_DETECT_SOFTLOCKUP=y | ||
575 | # CONFIG_SCHEDSTATS is not set | 588 | # CONFIG_SCHEDSTATS is not set |
576 | # CONFIG_DEBUG_SLAB is not set | 589 | # CONFIG_DEBUG_SLAB is not set |
577 | CONFIG_DEBUG_PREEMPT=y | 590 | CONFIG_DEBUG_PREEMPT=y |
@@ -626,5 +639,6 @@ CONFIG_CRYPTO=y | |||
626 | # Library routines | 639 | # Library routines |
627 | # | 640 | # |
628 | # CONFIG_CRC_CCITT is not set | 641 | # CONFIG_CRC_CCITT is not set |
642 | # CONFIG_CRC16 is not set | ||
629 | CONFIG_CRC32=m | 643 | CONFIG_CRC32=m |
630 | # CONFIG_LIBCRC32C is not set | 644 | # CONFIG_LIBCRC32C is not set |
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index ab1e49d2e518..8584dd823218 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile | |||
@@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional | |||
6 | 6 | ||
7 | obj-y := bitmap.o traps.o time.o process.o \ | 7 | obj-y := bitmap.o traps.o time.o process.o \ |
8 | setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ | 8 | setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \ |
9 | semaphore.o s390_ext.o debug.o profile.o irq.o | 9 | semaphore.o s390_ext.o debug.o profile.o irq.o reipl_diag.o |
10 | 10 | ||
11 | extra-$(CONFIG_ARCH_S390_31) += head.o | 11 | extra-$(CONFIG_ARCH_S390_31) += head.o |
12 | extra-$(CONFIG_ARCH_S390X) += head64.o | 12 | extra-$(CONFIG_ARCH_S390X) += head64.o |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 58fc7fbcb40e..9b30f4cf32c4 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -108,7 +108,7 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
108 | bl BASED(0f) | 108 | bl BASED(0f) |
109 | l %r14,BASED(.Lcleanup_critical) | 109 | l %r14,BASED(.Lcleanup_critical) |
110 | basr %r14,%r14 | 110 | basr %r14,%r14 |
111 | tm 0(%r12),0x01 # retest problem state after cleanup | 111 | tm 1(%r12),0x01 # retest problem state after cleanup |
112 | bnz BASED(1f) | 112 | bnz BASED(1f) |
113 | 0: l %r14,__LC_ASYNC_STACK # are we already on the async stack ? | 113 | 0: l %r14,__LC_ASYNC_STACK # are we already on the async stack ? |
114 | slr %r14,%r15 | 114 | slr %r14,%r15 |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index d0c9ffaa25db..7b9b4a2ba1d7 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -101,7 +101,7 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) | |||
101 | clc \psworg+8(8),BASED(.Lcritical_start) | 101 | clc \psworg+8(8),BASED(.Lcritical_start) |
102 | jl 0f | 102 | jl 0f |
103 | brasl %r14,cleanup_critical | 103 | brasl %r14,cleanup_critical |
104 | tm 0(%r12),0x01 # retest problem state after cleanup | 104 | tm 1(%r12),0x01 # retest problem state after cleanup |
105 | jnz 1f | 105 | jnz 1f |
106 | 0: lg %r14,__LC_ASYNC_STACK # are we already on the async. stack ? | 106 | 0: lg %r14,__LC_ASYNC_STACK # are we already on the async. stack ? |
107 | slgr %r14,%r15 | 107 | slgr %r14,%r15 |
diff --git a/arch/s390/kernel/reipl_diag.c b/arch/s390/kernel/reipl_diag.c new file mode 100644 index 000000000000..83cb42bc0b76 --- /dev/null +++ b/arch/s390/kernel/reipl_diag.c | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * This file contains the implementation of the | ||
3 | * Linux re-IPL support | ||
4 | * | ||
5 | * (C) Copyright IBM Corp. 2005 | ||
6 | * | ||
7 | * Author(s): Volker Sameske (sameske@de.ibm.com) | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | |||
13 | static unsigned int reipl_diag_rc1; | ||
14 | static unsigned int reipl_diag_rc2; | ||
15 | |||
16 | /* | ||
17 | * re-IPL the system using the last used IPL parameters | ||
18 | */ | ||
19 | void reipl_diag(void) | ||
20 | { | ||
21 | asm volatile ( | ||
22 | " la %%r4,0\n" | ||
23 | " la %%r5,0\n" | ||
24 | " diag %%r4,%2,0x308\n" | ||
25 | "0:\n" | ||
26 | " st %%r4,%0\n" | ||
27 | " st %%r5,%1\n" | ||
28 | ".section __ex_table,\"a\"\n" | ||
29 | #ifdef __s390x__ | ||
30 | " .align 8\n" | ||
31 | " .quad 0b, 0b\n" | ||
32 | #else | ||
33 | " .align 4\n" | ||
34 | " .long 0b, 0b\n" | ||
35 | #endif | ||
36 | ".previous\n" | ||
37 | : "=m" (reipl_diag_rc1), "=m" (reipl_diag_rc2) | ||
38 | : "d" (3) : "cc", "4", "5" ); | ||
39 | } | ||
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 5ba5a5485da9..5204778b8e5e 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -261,8 +261,11 @@ void (*_machine_power_off)(void) = machine_power_off_smp; | |||
261 | * Reboot, halt and power_off routines for non SMP. | 261 | * Reboot, halt and power_off routines for non SMP. |
262 | */ | 262 | */ |
263 | extern void reipl(unsigned long devno); | 263 | extern void reipl(unsigned long devno); |
264 | extern void reipl_diag(void); | ||
264 | static void do_machine_restart_nonsmp(char * __unused) | 265 | static void do_machine_restart_nonsmp(char * __unused) |
265 | { | 266 | { |
267 | reipl_diag(); | ||
268 | |||
266 | if (MACHINE_IS_VM) | 269 | if (MACHINE_IS_VM) |
267 | cpcmd ("IPL", NULL, 0); | 270 | cpcmd ("IPL", NULL, 0); |
268 | else | 271 | else |
@@ -634,6 +637,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
634 | struct cpuinfo_S390 *cpuinfo; | 637 | struct cpuinfo_S390 *cpuinfo; |
635 | unsigned long n = (unsigned long) v - 1; | 638 | unsigned long n = (unsigned long) v - 1; |
636 | 639 | ||
640 | preempt_disable(); | ||
637 | if (!n) { | 641 | if (!n) { |
638 | seq_printf(m, "vendor_id : IBM/S390\n" | 642 | seq_printf(m, "vendor_id : IBM/S390\n" |
639 | "# processors : %i\n" | 643 | "# processors : %i\n" |
@@ -658,6 +662,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
658 | cpuinfo->cpu_id.ident, | 662 | cpuinfo->cpu_id.ident, |
659 | cpuinfo->cpu_id.machine); | 663 | cpuinfo->cpu_id.machine); |
660 | } | 664 | } |
665 | preempt_enable(); | ||
661 | return 0; | 666 | return 0; |
662 | } | 667 | } |
663 | 668 | ||
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 85222fee4361..e13c87b446b2 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -65,6 +65,7 @@ extern char vmhalt_cmd[]; | |||
65 | extern char vmpoff_cmd[]; | 65 | extern char vmpoff_cmd[]; |
66 | 66 | ||
67 | extern void reipl(unsigned long devno); | 67 | extern void reipl(unsigned long devno); |
68 | extern void reipl_diag(void); | ||
68 | 69 | ||
69 | static void smp_ext_bitcall(int, ec_bit_sig); | 70 | static void smp_ext_bitcall(int, ec_bit_sig); |
70 | static void smp_ext_bitcall_others(ec_bit_sig); | 71 | static void smp_ext_bitcall_others(ec_bit_sig); |
@@ -283,6 +284,8 @@ static void do_machine_restart(void * __unused) | |||
283 | * interrupted by an external interrupt and s390irq | 284 | * interrupted by an external interrupt and s390irq |
284 | * locks are always held disabled). | 285 | * locks are always held disabled). |
285 | */ | 286 | */ |
287 | reipl_diag(); | ||
288 | |||
286 | if (MACHINE_IS_VM) | 289 | if (MACHINE_IS_VM) |
287 | cpcmd ("IPL", NULL, 0, NULL); | 290 | cpcmd ("IPL", NULL, 0, NULL); |
288 | else | 291 | else |
diff --git a/arch/sparc64/Kconfig.debug b/arch/sparc64/Kconfig.debug index cd8d39fb954d..af0e9411b83e 100644 --- a/arch/sparc64/Kconfig.debug +++ b/arch/sparc64/Kconfig.debug | |||
@@ -33,14 +33,6 @@ config DEBUG_BOOTMEM | |||
33 | depends on DEBUG_KERNEL | 33 | depends on DEBUG_KERNEL |
34 | bool "Debug BOOTMEM initialization" | 34 | bool "Debug BOOTMEM initialization" |
35 | 35 | ||
36 | # We have a custom atomic_dec_and_lock() implementation but it's not | ||
37 | # compatible with spinlock debugging so we need to fall back on | ||
38 | # the generic version in that case. | ||
39 | config HAVE_DEC_LOCK | ||
40 | bool | ||
41 | depends on SMP && !DEBUG_SPINLOCK | ||
42 | default y | ||
43 | |||
44 | config MCOUNT | 36 | config MCOUNT |
45 | bool | 37 | bool |
46 | depends on STACK_DEBUG | 38 | depends on STACK_DEBUG |
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 3e0badb820c5..b48349527853 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S | |||
@@ -42,19 +42,15 @@ | |||
42 | * executing (see inherit_locked_prom_mappings() rant). | 42 | * executing (see inherit_locked_prom_mappings() rant). |
43 | */ | 43 | */ |
44 | sparc64_vpte_nucleus: | 44 | sparc64_vpte_nucleus: |
45 | /* Load 0xf0000000, which is LOW_OBP_ADDRESS. */ | 45 | /* Note that kvmap below has verified that the address is |
46 | mov 0xf, %g5 | 46 | * in the range MODULES_VADDR --> VMALLOC_END already. So |
47 | sllx %g5, 28, %g5 | 47 | * here we need only check if it is an OBP address or not. |
48 | 48 | */ | |
49 | /* Is addr >= LOW_OBP_ADDRESS? */ | 49 | sethi %hi(LOW_OBP_ADDRESS), %g5 |
50 | cmp %g4, %g5 | 50 | cmp %g4, %g5 |
51 | blu,pn %xcc, sparc64_vpte_patchme1 | 51 | blu,pn %xcc, sparc64_vpte_patchme1 |
52 | mov 0x1, %g5 | 52 | mov 0x1, %g5 |
53 | |||
54 | /* Load 0x100000000, which is HI_OBP_ADDRESS. */ | ||
55 | sllx %g5, 32, %g5 | 53 | sllx %g5, 32, %g5 |
56 | |||
57 | /* Is addr < HI_OBP_ADDRESS? */ | ||
58 | cmp %g4, %g5 | 54 | cmp %g4, %g5 |
59 | blu,pn %xcc, obp_iaddr_patch | 55 | blu,pn %xcc, obp_iaddr_patch |
60 | nop | 56 | nop |
@@ -156,26 +152,29 @@ obp_daddr_patch: | |||
156 | * rather, use information saved during inherit_prom_mappings() using 8k | 152 | * rather, use information saved during inherit_prom_mappings() using 8k |
157 | * pagesize. | 153 | * pagesize. |
158 | */ | 154 | */ |
155 | .align 32 | ||
159 | kvmap: | 156 | kvmap: |
160 | /* Load 0xf0000000, which is LOW_OBP_ADDRESS. */ | 157 | sethi %hi(MODULES_VADDR), %g5 |
161 | mov 0xf, %g5 | 158 | cmp %g4, %g5 |
162 | sllx %g5, 28, %g5 | 159 | blu,pn %xcc, longpath |
160 | mov (VMALLOC_END >> 24), %g5 | ||
161 | sllx %g5, 24, %g5 | ||
162 | cmp %g4, %g5 | ||
163 | bgeu,pn %xcc, longpath | ||
164 | nop | ||
163 | 165 | ||
164 | /* Is addr >= LOW_OBP_ADDRESS? */ | 166 | kvmap_check_obp: |
167 | sethi %hi(LOW_OBP_ADDRESS), %g5 | ||
165 | cmp %g4, %g5 | 168 | cmp %g4, %g5 |
166 | blu,pn %xcc, vmalloc_addr | 169 | blu,pn %xcc, kvmap_vmalloc_addr |
167 | mov 0x1, %g5 | 170 | mov 0x1, %g5 |
168 | |||
169 | /* Load 0x100000000, which is HI_OBP_ADDRESS. */ | ||
170 | sllx %g5, 32, %g5 | 171 | sllx %g5, 32, %g5 |
171 | |||
172 | /* Is addr < HI_OBP_ADDRESS? */ | ||
173 | cmp %g4, %g5 | 172 | cmp %g4, %g5 |
174 | blu,pn %xcc, obp_daddr_patch | 173 | blu,pn %xcc, obp_daddr_patch |
175 | nop | 174 | nop |
176 | 175 | ||
177 | vmalloc_addr: | 176 | kvmap_vmalloc_addr: |
178 | /* If we get here, a vmalloc addr accessed, load kernel VPTE. */ | 177 | /* If we get here, a vmalloc addr was accessed, load kernel VPTE. */ |
179 | ldxa [%g3 + %g6] ASI_N, %g5 | 178 | ldxa [%g3 + %g6] ASI_N, %g5 |
180 | brgez,pn %g5, longpath | 179 | brgez,pn %g5, longpath |
181 | nop | 180 | nop |
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index 23ad839d113f..5efbff90d668 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <asm/psrcompat.h> | 30 | #include <asm/psrcompat.h> |
31 | #include <asm/visasm.h> | 31 | #include <asm/visasm.h> |
32 | #include <asm/spitfire.h> | 32 | #include <asm/spitfire.h> |
33 | #include <asm/page.h> | ||
33 | 34 | ||
34 | /* Returning from ptrace is a bit tricky because the syscall return | 35 | /* Returning from ptrace is a bit tricky because the syscall return |
35 | * low level code assumes any value returned which is negative and | 36 | * low level code assumes any value returned which is negative and |
@@ -128,20 +129,20 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page, | |||
128 | * is mapped to in the user's address space, we can skip the | 129 | * is mapped to in the user's address space, we can skip the |
129 | * D-cache flush. | 130 | * D-cache flush. |
130 | */ | 131 | */ |
131 | if ((uaddr ^ kaddr) & (1UL << 13)) { | 132 | if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) { |
132 | unsigned long start = __pa(kaddr); | 133 | unsigned long start = __pa(kaddr); |
133 | unsigned long end = start + len; | 134 | unsigned long end = start + len; |
134 | 135 | ||
135 | if (tlb_type == spitfire) { | 136 | if (tlb_type == spitfire) { |
136 | for (; start < end; start += 32) | 137 | for (; start < end; start += 32) |
137 | spitfire_put_dcache_tag(va & 0x3fe0, 0x0); | 138 | spitfire_put_dcache_tag(start & 0x3fe0, 0x0); |
138 | } else { | 139 | } else { |
139 | for (; start < end; start += 32) | 140 | for (; start < end; start += 32) |
140 | __asm__ __volatile__( | 141 | __asm__ __volatile__( |
141 | "stxa %%g0, [%0] %1\n\t" | 142 | "stxa %%g0, [%0] %1\n\t" |
142 | "membar #Sync" | 143 | "membar #Sync" |
143 | : /* no outputs */ | 144 | : /* no outputs */ |
144 | : "r" (va), | 145 | : "r" (start), |
145 | "i" (ASI_DCACHE_INVALIDATE)); | 146 | "i" (ASI_DCACHE_INVALIDATE)); |
146 | } | 147 | } |
147 | } | 148 | } |
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index cbb5e59824e5..fb7a5370dbfc 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c | |||
@@ -163,9 +163,6 @@ EXPORT_SYMBOL(atomic64_add); | |||
163 | EXPORT_SYMBOL(atomic64_add_ret); | 163 | EXPORT_SYMBOL(atomic64_add_ret); |
164 | EXPORT_SYMBOL(atomic64_sub); | 164 | EXPORT_SYMBOL(atomic64_sub); |
165 | EXPORT_SYMBOL(atomic64_sub_ret); | 165 | EXPORT_SYMBOL(atomic64_sub_ret); |
166 | #ifdef CONFIG_SMP | ||
167 | EXPORT_SYMBOL(_atomic_dec_and_lock); | ||
168 | #endif | ||
169 | 166 | ||
170 | /* Atomic bit operations. */ | 167 | /* Atomic bit operations. */ |
171 | EXPORT_SYMBOL(test_and_set_bit); | 168 | EXPORT_SYMBOL(test_and_set_bit); |
diff --git a/arch/sparc64/kernel/una_asm.S b/arch/sparc64/kernel/una_asm.S index cbb40585253c..da48400bcc95 100644 --- a/arch/sparc64/kernel/una_asm.S +++ b/arch/sparc64/kernel/una_asm.S | |||
@@ -17,7 +17,7 @@ kernel_unaligned_trap_fault: | |||
17 | __do_int_store: | 17 | __do_int_store: |
18 | rd %asi, %o4 | 18 | rd %asi, %o4 |
19 | wr %o3, 0, %asi | 19 | wr %o3, 0, %asi |
20 | ldx [%o2], %g3 | 20 | mov %o2, %g3 |
21 | cmp %o1, 2 | 21 | cmp %o1, 2 |
22 | be,pn %icc, 2f | 22 | be,pn %icc, 2f |
23 | cmp %o1, 4 | 23 | cmp %o1, 4 |
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c index da9739f0d437..42718f6a7d36 100644 --- a/arch/sparc64/kernel/unaligned.c +++ b/arch/sparc64/kernel/unaligned.c | |||
@@ -184,13 +184,14 @@ extern void do_int_load(unsigned long *dest_reg, int size, | |||
184 | unsigned long *saddr, int is_signed, int asi); | 184 | unsigned long *saddr, int is_signed, int asi); |
185 | 185 | ||
186 | extern void __do_int_store(unsigned long *dst_addr, int size, | 186 | extern void __do_int_store(unsigned long *dst_addr, int size, |
187 | unsigned long *src_val, int asi); | 187 | unsigned long src_val, int asi); |
188 | 188 | ||
189 | static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, | 189 | static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, |
190 | struct pt_regs *regs, int asi) | 190 | struct pt_regs *regs, int asi, int orig_asi) |
191 | { | 191 | { |
192 | unsigned long zero = 0; | 192 | unsigned long zero = 0; |
193 | unsigned long *src_val = &zero; | 193 | unsigned long *src_val_p = &zero; |
194 | unsigned long src_val; | ||
194 | 195 | ||
195 | if (size == 16) { | 196 | if (size == 16) { |
196 | size = 8; | 197 | size = 8; |
@@ -198,7 +199,25 @@ static inline void do_int_store(int reg_num, int size, unsigned long *dst_addr, | |||
198 | (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) | | 199 | (unsigned)fetch_reg(reg_num, regs) : 0)) << 32) | |
199 | (unsigned)fetch_reg(reg_num + 1, regs); | 200 | (unsigned)fetch_reg(reg_num + 1, regs); |
200 | } else if (reg_num) { | 201 | } else if (reg_num) { |
201 | src_val = fetch_reg_addr(reg_num, regs); | 202 | src_val_p = fetch_reg_addr(reg_num, regs); |
203 | } | ||
204 | src_val = *src_val_p; | ||
205 | if (unlikely(asi != orig_asi)) { | ||
206 | switch (size) { | ||
207 | case 2: | ||
208 | src_val = swab16(src_val); | ||
209 | break; | ||
210 | case 4: | ||
211 | src_val = swab32(src_val); | ||
212 | break; | ||
213 | case 8: | ||
214 | src_val = swab64(src_val); | ||
215 | break; | ||
216 | case 16: | ||
217 | default: | ||
218 | BUG(); | ||
219 | break; | ||
220 | }; | ||
202 | } | 221 | } |
203 | __do_int_store(dst_addr, size, src_val, asi); | 222 | __do_int_store(dst_addr, size, src_val, asi); |
204 | } | 223 | } |
@@ -276,6 +295,7 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u | |||
276 | kernel_mna_trap_fault(); | 295 | kernel_mna_trap_fault(); |
277 | } else { | 296 | } else { |
278 | unsigned long addr; | 297 | unsigned long addr; |
298 | int orig_asi, asi; | ||
279 | 299 | ||
280 | addr = compute_effective_address(regs, insn, | 300 | addr = compute_effective_address(regs, insn, |
281 | ((insn >> 25) & 0x1f)); | 301 | ((insn >> 25) & 0x1f)); |
@@ -285,18 +305,48 @@ asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn, u | |||
285 | regs->tpc, dirstrings[dir], addr, size, | 305 | regs->tpc, dirstrings[dir], addr, size, |
286 | regs->u_regs[UREG_RETPC]); | 306 | regs->u_regs[UREG_RETPC]); |
287 | #endif | 307 | #endif |
308 | orig_asi = asi = decode_asi(insn, regs); | ||
309 | switch (asi) { | ||
310 | case ASI_NL: | ||
311 | case ASI_AIUPL: | ||
312 | case ASI_AIUSL: | ||
313 | case ASI_PL: | ||
314 | case ASI_SL: | ||
315 | case ASI_PNFL: | ||
316 | case ASI_SNFL: | ||
317 | asi &= ~0x08; | ||
318 | break; | ||
319 | }; | ||
288 | switch (dir) { | 320 | switch (dir) { |
289 | case load: | 321 | case load: |
290 | do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs), | 322 | do_int_load(fetch_reg_addr(((insn>>25)&0x1f), regs), |
291 | size, (unsigned long *) addr, | 323 | size, (unsigned long *) addr, |
292 | decode_signedness(insn), | 324 | decode_signedness(insn), asi); |
293 | decode_asi(insn, regs)); | 325 | if (unlikely(asi != orig_asi)) { |
326 | unsigned long val_in = *(unsigned long *) addr; | ||
327 | switch (size) { | ||
328 | case 2: | ||
329 | val_in = swab16(val_in); | ||
330 | break; | ||
331 | case 4: | ||
332 | val_in = swab32(val_in); | ||
333 | break; | ||
334 | case 8: | ||
335 | val_in = swab64(val_in); | ||
336 | break; | ||
337 | case 16: | ||
338 | default: | ||
339 | BUG(); | ||
340 | break; | ||
341 | }; | ||
342 | *(unsigned long *) addr = val_in; | ||
343 | } | ||
294 | break; | 344 | break; |
295 | 345 | ||
296 | case store: | 346 | case store: |
297 | do_int_store(((insn>>25)&0x1f), size, | 347 | do_int_store(((insn>>25)&0x1f), size, |
298 | (unsigned long *) addr, regs, | 348 | (unsigned long *) addr, regs, |
299 | decode_asi(insn, regs)); | 349 | asi, orig_asi); |
300 | break; | 350 | break; |
301 | 351 | ||
302 | default: | 352 | default: |
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile index d968aebe83b2..c295806500f7 100644 --- a/arch/sparc64/lib/Makefile +++ b/arch/sparc64/lib/Makefile | |||
@@ -14,6 +14,4 @@ lib-y := PeeCeeI.o copy_page.o clear_page.o strlen.o strncmp.o \ | |||
14 | copy_in_user.o user_fixup.o memmove.o \ | 14 | copy_in_user.o user_fixup.o memmove.o \ |
15 | mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o | 15 | mcount.o ipcsum.o rwsem.o xor.o find_bit.o delay.o |
16 | 16 | ||
17 | lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o | ||
18 | |||
19 | obj-y += iomap.o | 17 | obj-y += iomap.o |
diff --git a/arch/sparc64/lib/dec_and_lock.S b/arch/sparc64/lib/dec_and_lock.S deleted file mode 100644 index 8ee288dd0afc..000000000000 --- a/arch/sparc64/lib/dec_and_lock.S +++ /dev/null | |||
@@ -1,80 +0,0 @@ | |||
1 | /* $Id: dec_and_lock.S,v 1.5 2001/11/18 00:12:56 davem Exp $ | ||
2 | * dec_and_lock.S: Sparc64 version of "atomic_dec_and_lock()" | ||
3 | * using cas and ldstub instructions. | ||
4 | * | ||
5 | * Copyright (C) 2000 David S. Miller (davem@redhat.com) | ||
6 | */ | ||
7 | #include <linux/config.h> | ||
8 | #include <asm/thread_info.h> | ||
9 | |||
10 | .text | ||
11 | .align 64 | ||
12 | |||
13 | /* CAS basically works like this: | ||
14 | * | ||
15 | * void CAS(MEM, REG1, REG2) | ||
16 | * { | ||
17 | * START_ATOMIC(); | ||
18 | * if (*(MEM) == REG1) { | ||
19 | * TMP = *(MEM); | ||
20 | * *(MEM) = REG2; | ||
21 | * REG2 = TMP; | ||
22 | * } else | ||
23 | * REG2 = *(MEM); | ||
24 | * END_ATOMIC(); | ||
25 | * } | ||
26 | */ | ||
27 | |||
28 | .globl _atomic_dec_and_lock | ||
29 | _atomic_dec_and_lock: /* %o0 = counter, %o1 = lock */ | ||
30 | loop1: lduw [%o0], %g2 | ||
31 | subcc %g2, 1, %g7 | ||
32 | be,pn %icc, start_to_zero | ||
33 | nop | ||
34 | nzero: cas [%o0], %g2, %g7 | ||
35 | cmp %g2, %g7 | ||
36 | bne,pn %icc, loop1 | ||
37 | mov 0, %g1 | ||
38 | |||
39 | out: | ||
40 | membar #StoreLoad | #StoreStore | ||
41 | retl | ||
42 | mov %g1, %o0 | ||
43 | start_to_zero: | ||
44 | #ifdef CONFIG_PREEMPT | ||
45 | ldsw [%g6 + TI_PRE_COUNT], %g3 | ||
46 | add %g3, 1, %g3 | ||
47 | stw %g3, [%g6 + TI_PRE_COUNT] | ||
48 | #endif | ||
49 | to_zero: | ||
50 | ldstub [%o1], %g3 | ||
51 | membar #StoreLoad | #StoreStore | ||
52 | brnz,pn %g3, spin_on_lock | ||
53 | nop | ||
54 | loop2: cas [%o0], %g2, %g7 /* ASSERT(g7 == 0) */ | ||
55 | cmp %g2, %g7 | ||
56 | |||
57 | be,pt %icc, out | ||
58 | mov 1, %g1 | ||
59 | lduw [%o0], %g2 | ||
60 | subcc %g2, 1, %g7 | ||
61 | be,pn %icc, loop2 | ||
62 | nop | ||
63 | membar #StoreStore | #LoadStore | ||
64 | stb %g0, [%o1] | ||
65 | #ifdef CONFIG_PREEMPT | ||
66 | ldsw [%g6 + TI_PRE_COUNT], %g3 | ||
67 | sub %g3, 1, %g3 | ||
68 | stw %g3, [%g6 + TI_PRE_COUNT] | ||
69 | #endif | ||
70 | |||
71 | b,pt %xcc, nzero | ||
72 | nop | ||
73 | spin_on_lock: | ||
74 | ldub [%o1], %g3 | ||
75 | membar #LoadLoad | ||
76 | brnz,pt %g3, spin_on_lock | ||
77 | nop | ||
78 | ba,pt %xcc, to_zero | ||
79 | nop | ||
80 | nop | ||
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index 8ad156a00499..5d92cacd56c6 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 | |||
@@ -42,3 +42,7 @@ config ARCH_HAS_SC_SIGNALS | |||
42 | config ARCH_REUSE_HOST_VSYSCALL_AREA | 42 | config ARCH_REUSE_HOST_VSYSCALL_AREA |
43 | bool | 43 | bool |
44 | default y | 44 | default y |
45 | |||
46 | config X86_CMPXCHG | ||
47 | bool | ||
48 | default y | ||
diff --git a/arch/um/Makefile b/arch/um/Makefile index ce987266dac6..5b5af95721ab 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile | |||
@@ -53,9 +53,13 @@ SYS_DIR := $(ARCH_DIR)/include/sysdep-$(SUBARCH) | |||
53 | 53 | ||
54 | # -Dvmap=kernel_vmap affects everything, and prevents anything from | 54 | # -Dvmap=kernel_vmap affects everything, and prevents anything from |
55 | # referencing the libpcap.o symbol so named. | 55 | # referencing the libpcap.o symbol so named. |
56 | # | ||
57 | # Same things for in6addr_loopback - found in libc. | ||
56 | 58 | ||
57 | CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ | 59 | CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ |
58 | $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap | 60 | $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ |
61 | -Din6addr_loopback=kernel_in6addr_loopback | ||
62 | |||
59 | AFLAGS += $(ARCH_INCLUDE) | 63 | AFLAGS += $(ARCH_INCLUDE) |
60 | 64 | ||
61 | USER_CFLAGS := $(patsubst -I%,,$(CFLAGS)) | 65 | USER_CFLAGS := $(patsubst -I%,,$(CFLAGS)) |
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 7a0d115b29d0..5db136e2651c 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include <errno.h> | 14 | #include <errno.h> |
15 | #include <unistd.h> | 15 | #include <unistd.h> |
16 | #include <linux/inet.h> | ||
17 | #include <sys/socket.h> | 16 | #include <sys/socket.h> |
18 | #include <sys/un.h> | 17 | #include <sys/un.h> |
19 | #include <sys/time.h> | 18 | #include <sys/time.h> |
@@ -55,7 +54,7 @@ static int mcast_open(void *data) | |||
55 | struct mcast_data *pri = data; | 54 | struct mcast_data *pri = data; |
56 | struct sockaddr_in *sin = pri->mcast_addr; | 55 | struct sockaddr_in *sin = pri->mcast_addr; |
57 | struct ip_mreq mreq; | 56 | struct ip_mreq mreq; |
58 | int fd = -EINVAL, yes = 1, err = -EINVAL;; | 57 | int fd, yes = 1, err = 0; |
59 | 58 | ||
60 | 59 | ||
61 | if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) | 60 | if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) |
@@ -66,13 +65,14 @@ static int mcast_open(void *data) | |||
66 | if (fd < 0){ | 65 | if (fd < 0){ |
67 | printk("mcast_open : data socket failed, errno = %d\n", | 66 | printk("mcast_open : data socket failed, errno = %d\n", |
68 | errno); | 67 | errno); |
69 | fd = -errno; | 68 | err = -errno; |
70 | goto out; | 69 | goto out; |
71 | } | 70 | } |
72 | 71 | ||
73 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { | 72 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { |
74 | printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", | 73 | printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", |
75 | errno); | 74 | errno); |
75 | err = -errno; | ||
76 | goto out_close; | 76 | goto out_close; |
77 | } | 77 | } |
78 | 78 | ||
@@ -81,6 +81,7 @@ static int mcast_open(void *data) | |||
81 | sizeof(pri->ttl)) < 0) { | 81 | sizeof(pri->ttl)) < 0) { |
82 | printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", | 82 | printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", |
83 | errno); | 83 | errno); |
84 | err = -errno; | ||
84 | goto out_close; | 85 | goto out_close; |
85 | } | 86 | } |
86 | 87 | ||
@@ -88,12 +89,14 @@ static int mcast_open(void *data) | |||
88 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { | 89 | if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { |
89 | printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", | 90 | printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", |
90 | errno); | 91 | errno); |
92 | err = -errno; | ||
91 | goto out_close; | 93 | goto out_close; |
92 | } | 94 | } |
93 | 95 | ||
94 | /* bind socket to mcast address */ | 96 | /* bind socket to mcast address */ |
95 | if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { | 97 | if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { |
96 | printk("mcast_open : data bind failed, errno = %d\n", errno); | 98 | printk("mcast_open : data bind failed, errno = %d\n", errno); |
99 | err = -errno; | ||
97 | goto out_close; | 100 | goto out_close; |
98 | } | 101 | } |
99 | 102 | ||
@@ -108,14 +111,15 @@ static int mcast_open(void *data) | |||
108 | "interface on the host.\n"); | 111 | "interface on the host.\n"); |
109 | printk("eth0 should be configured in order to use the " | 112 | printk("eth0 should be configured in order to use the " |
110 | "multicast transport.\n"); | 113 | "multicast transport.\n"); |
114 | err = -errno; | ||
111 | goto out_close; | 115 | goto out_close; |
112 | } | 116 | } |
113 | 117 | ||
114 | out: | ||
115 | return fd; | 118 | return fd; |
116 | 119 | ||
117 | out_close: | 120 | out_close: |
118 | os_close_file(fd); | 121 | os_close_file(fd); |
122 | out: | ||
119 | return err; | 123 | return err; |
120 | } | 124 | } |
121 | 125 | ||
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index c190c2414197..12c95368124a 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "os.h" | 32 | #include "os.h" |
33 | #include "umid.h" | 33 | #include "umid.h" |
34 | #include "irq_kern.h" | 34 | #include "irq_kern.h" |
35 | #include "choose-mode.h" | ||
35 | 36 | ||
36 | static int do_unlink_socket(struct notifier_block *notifier, | 37 | static int do_unlink_socket(struct notifier_block *notifier, |
37 | unsigned long what, void *data) | 38 | unsigned long what, void *data) |
@@ -276,6 +277,7 @@ void mconsole_proc(struct mc_request *req) | |||
276 | go - continue the UML after a 'stop' \n\ | 277 | go - continue the UML after a 'stop' \n\ |
277 | log <string> - make UML enter <string> into the kernel log\n\ | 278 | log <string> - make UML enter <string> into the kernel log\n\ |
278 | proc <file> - returns the contents of the UML's /proc/<file>\n\ | 279 | proc <file> - returns the contents of the UML's /proc/<file>\n\ |
280 | stack <pid> - returns the stack of the specified pid\n\ | ||
279 | " | 281 | " |
280 | 282 | ||
281 | void mconsole_help(struct mc_request *req) | 283 | void mconsole_help(struct mc_request *req) |
@@ -479,6 +481,56 @@ void mconsole_sysrq(struct mc_request *req) | |||
479 | } | 481 | } |
480 | #endif | 482 | #endif |
481 | 483 | ||
484 | /* Mconsole stack trace | ||
485 | * Added by Allan Graves, Jeff Dike | ||
486 | * Dumps a stacks registers to the linux console. | ||
487 | * Usage stack <pid>. | ||
488 | */ | ||
489 | void do_stack(struct mc_request *req) | ||
490 | { | ||
491 | char *ptr = req->request.data; | ||
492 | int pid_requested= -1; | ||
493 | struct task_struct *from = NULL; | ||
494 | struct task_struct *to = NULL; | ||
495 | |||
496 | /* Would be nice: | ||
497 | * 1) Send showregs output to mconsole. | ||
498 | * 2) Add a way to stack dump all pids. | ||
499 | */ | ||
500 | |||
501 | ptr += strlen("stack"); | ||
502 | while(isspace(*ptr)) ptr++; | ||
503 | |||
504 | /* Should really check for multiple pids or reject bad args here */ | ||
505 | /* What do the arguments in mconsole_reply mean? */ | ||
506 | if(sscanf(ptr, "%d", &pid_requested) == 0){ | ||
507 | mconsole_reply(req, "Please specify a pid", 1, 0); | ||
508 | return; | ||
509 | } | ||
510 | |||
511 | from = current; | ||
512 | to = find_task_by_pid(pid_requested); | ||
513 | |||
514 | if((to == NULL) || (pid_requested == 0)) { | ||
515 | mconsole_reply(req, "Couldn't find that pid", 1, 0); | ||
516 | return; | ||
517 | } | ||
518 | to->thread.saved_task = current; | ||
519 | |||
520 | switch_to(from, to, from); | ||
521 | mconsole_reply(req, "Stack Dumped to console and message log", 0, 0); | ||
522 | } | ||
523 | |||
524 | void mconsole_stack(struct mc_request *req) | ||
525 | { | ||
526 | /* This command doesn't work in TT mode, so let's check and then | ||
527 | * get out of here | ||
528 | */ | ||
529 | CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode", | ||
530 | 1, 0), | ||
531 | do_stack(req)); | ||
532 | } | ||
533 | |||
482 | /* Changed by mconsole_setup, which is __setup, and called before SMP is | 534 | /* Changed by mconsole_setup, which is __setup, and called before SMP is |
483 | * active. | 535 | * active. |
484 | */ | 536 | */ |
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index fe5afb13252c..310c1f823f26 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c | |||
@@ -30,6 +30,7 @@ static struct mconsole_command commands[] = { | |||
30 | { "go", mconsole_go, MCONSOLE_INTR }, | 30 | { "go", mconsole_go, MCONSOLE_INTR }, |
31 | { "log", mconsole_log, MCONSOLE_INTR }, | 31 | { "log", mconsole_log, MCONSOLE_INTR }, |
32 | { "proc", mconsole_proc, MCONSOLE_PROC }, | 32 | { "proc", mconsole_proc, MCONSOLE_PROC }, |
33 | { "stack", mconsole_stack, MCONSOLE_INTR }, | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | /* Initialized in mconsole_init, which is an initcall */ | 36 | /* Initialized in mconsole_init, which is an initcall */ |
@@ -172,9 +173,9 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len) | |||
172 | if(notify_sock < 0){ | 173 | if(notify_sock < 0){ |
173 | notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); | 174 | notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0); |
174 | if(notify_sock < 0){ | 175 | if(notify_sock < 0){ |
175 | printk("mconsole_notify - socket failed, errno = %d\n", | ||
176 | errno); | ||
177 | err = -errno; | 176 | err = -errno; |
177 | printk("mconsole_notify - socket failed, errno = %d\n", | ||
178 | err); | ||
178 | } | 179 | } |
179 | } | 180 | } |
180 | unlock_notify(); | 181 | unlock_notify(); |
@@ -197,8 +198,8 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len) | |||
197 | n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, | 198 | n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target, |
198 | sizeof(target)); | 199 | sizeof(target)); |
199 | if(n < 0){ | 200 | if(n < 0){ |
200 | printk("mconsole_notify - sendto failed, errno = %d\n", errno); | ||
201 | err = -errno; | 201 | err = -errno; |
202 | printk("mconsole_notify - sendto failed, errno = %d\n", errno); | ||
202 | } | 203 | } |
203 | return(err); | 204 | return(err); |
204 | } | 205 | } |
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index ed84d01df6cc..0306a1b215b7 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c | |||
@@ -43,8 +43,9 @@ static int pts_open(int input, int output, int primary, void *d, | |||
43 | 43 | ||
44 | fd = get_pty(); | 44 | fd = get_pty(); |
45 | if(fd < 0){ | 45 | if(fd < 0){ |
46 | err = -errno; | ||
46 | printk("open_pts : Failed to open pts\n"); | 47 | printk("open_pts : Failed to open pts\n"); |
47 | return(-errno); | 48 | return err; |
48 | } | 49 | } |
49 | if(data->raw){ | 50 | if(data->raw){ |
50 | CATCH_EINTR(err = tcgetattr(fd, &data->tt)); | 51 | CATCH_EINTR(err = tcgetattr(fd, &data->tt)); |
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c deleted file mode 100644 index b94d2bc4fe06..000000000000 --- a/arch/um/drivers/ubd_user.c +++ /dev/null | |||
@@ -1,75 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Copyright (C) 2001 Ridgerun,Inc (glonnon@ridgerun.com) | ||
4 | * Licensed under the GPL | ||
5 | */ | ||
6 | |||
7 | #include <stddef.h> | ||
8 | #include <unistd.h> | ||
9 | #include <errno.h> | ||
10 | #include <sched.h> | ||
11 | #include <signal.h> | ||
12 | #include <string.h> | ||
13 | #include <netinet/in.h> | ||
14 | #include <sys/time.h> | ||
15 | #include <sys/socket.h> | ||
16 | #include <sys/mman.h> | ||
17 | #include <sys/param.h> | ||
18 | #include "asm/types.h" | ||
19 | #include "user_util.h" | ||
20 | #include "kern_util.h" | ||
21 | #include "user.h" | ||
22 | #include "ubd_user.h" | ||
23 | #include "os.h" | ||
24 | #include "cow.h" | ||
25 | |||
26 | #include <endian.h> | ||
27 | #include <byteswap.h> | ||
28 | |||
29 | void ignore_sigwinch_sig(void) | ||
30 | { | ||
31 | signal(SIGWINCH, SIG_IGN); | ||
32 | } | ||
33 | |||
34 | int start_io_thread(unsigned long sp, int *fd_out) | ||
35 | { | ||
36 | int pid, fds[2], err; | ||
37 | |||
38 | err = os_pipe(fds, 1, 1); | ||
39 | if(err < 0){ | ||
40 | printk("start_io_thread - os_pipe failed, err = %d\n", -err); | ||
41 | goto out; | ||
42 | } | ||
43 | |||
44 | kernel_fd = fds[0]; | ||
45 | *fd_out = fds[1]; | ||
46 | |||
47 | pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD, | ||
48 | NULL); | ||
49 | if(pid < 0){ | ||
50 | printk("start_io_thread - clone failed : errno = %d\n", errno); | ||
51 | err = -errno; | ||
52 | goto out_close; | ||
53 | } | ||
54 | |||
55 | return(pid); | ||
56 | |||
57 | out_close: | ||
58 | os_close_file(fds[0]); | ||
59 | os_close_file(fds[1]); | ||
60 | kernel_fd = -1; | ||
61 | *fd_out = -1; | ||
62 | out: | ||
63 | return(err); | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
68 | * Emacs will notice this stuff at the end of the file and automatically | ||
69 | * adjust the settings for this buffer only. This must remain at the end | ||
70 | * of the file. | ||
71 | * --------------------------------------------------------------------------- | ||
72 | * Local variables: | ||
73 | * c-file-style: "linux" | ||
74 | * End: | ||
75 | */ | ||
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index 93dc1911363f..90e0e5ff451e 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c | |||
@@ -110,13 +110,15 @@ int xterm_open(int input, int output, int primary, void *d, | |||
110 | 110 | ||
111 | fd = mkstemp(file); | 111 | fd = mkstemp(file); |
112 | if(fd < 0){ | 112 | if(fd < 0){ |
113 | err = -errno; | ||
113 | printk("xterm_open : mkstemp failed, errno = %d\n", errno); | 114 | printk("xterm_open : mkstemp failed, errno = %d\n", errno); |
114 | return(-errno); | 115 | return err; |
115 | } | 116 | } |
116 | 117 | ||
117 | if(unlink(file)){ | 118 | if(unlink(file)){ |
119 | err = -errno; | ||
118 | printk("xterm_open : unlink failed, errno = %d\n", errno); | 120 | printk("xterm_open : unlink failed, errno = %d\n", errno); |
119 | return(-errno); | 121 | return err; |
120 | } | 122 | } |
121 | os_close_file(fd); | 123 | os_close_file(fd); |
122 | 124 | ||
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h index 0aa620970adb..782ac3a3baf9 100644 --- a/arch/um/include/common-offsets.h +++ b/arch/um/include/common-offsets.h | |||
@@ -12,4 +12,6 @@ DEFINE_STR(UM_KERN_WARNING, KERN_WARNING); | |||
12 | DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE); | 12 | DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE); |
13 | DEFINE_STR(UM_KERN_INFO, KERN_INFO); | 13 | DEFINE_STR(UM_KERN_INFO, KERN_INFO); |
14 | DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG); | 14 | DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG); |
15 | DEFINE(HOST_ELF_CLASS, ELF_CLASS); | 15 | DEFINE(UM_ELF_CLASS, ELF_CLASS); |
16 | DEFINE(UM_ELFCLASS32, ELFCLASS32); | ||
17 | DEFINE(UM_ELFCLASS64, ELFCLASS64); | ||
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h index cfa368e045a5..b1b512f47035 100644 --- a/arch/um/include/mconsole.h +++ b/arch/um/include/mconsole.h | |||
@@ -81,6 +81,7 @@ extern void mconsole_stop(struct mc_request *req); | |||
81 | extern void mconsole_go(struct mc_request *req); | 81 | extern void mconsole_go(struct mc_request *req); |
82 | extern void mconsole_log(struct mc_request *req); | 82 | extern void mconsole_log(struct mc_request *req); |
83 | extern void mconsole_proc(struct mc_request *req); | 83 | extern void mconsole_proc(struct mc_request *req); |
84 | extern void mconsole_stack(struct mc_request *req); | ||
84 | 85 | ||
85 | extern int mconsole_get_request(int fd, struct mc_request *req); | 86 | extern int mconsole_get_request(int fd, struct mc_request *req); |
86 | extern int mconsole_notify(char *sock_name, int type, const void *data, | 87 | extern int mconsole_notify(char *sock_name, int type, const void *data, |
diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h index d6404bb64662..9fef4123a65a 100644 --- a/arch/um/include/mem_user.h +++ b/arch/um/include/mem_user.h | |||
@@ -51,7 +51,6 @@ extern unsigned long task_size; | |||
51 | 51 | ||
52 | extern void check_devanon(void); | 52 | extern void check_devanon(void); |
53 | extern int init_mem_user(void); | 53 | extern int init_mem_user(void); |
54 | extern int create_mem_file(unsigned long len); | ||
55 | extern void setup_memory(void *entry); | 54 | extern void setup_memory(void *entry); |
56 | extern unsigned long find_iomem(char *driver, unsigned long *len_out); | 55 | extern unsigned long find_iomem(char *driver, unsigned long *len_out); |
57 | extern int init_maps(unsigned long physmem, unsigned long iomem, | 56 | extern int init_maps(unsigned long physmem, unsigned long iomem, |
@@ -64,20 +63,6 @@ extern unsigned long phys_offset(unsigned long phys); | |||
64 | extern void unmap_physmem(void); | 63 | extern void unmap_physmem(void); |
65 | extern void map_memory(unsigned long virt, unsigned long phys, | 64 | extern void map_memory(unsigned long virt, unsigned long phys, |
66 | unsigned long len, int r, int w, int x); | 65 | unsigned long len, int r, int w, int x); |
67 | extern int protect_memory(unsigned long addr, unsigned long len, | ||
68 | int r, int w, int x, int must_succeed); | ||
69 | extern unsigned long get_kmem_end(void); | 66 | extern unsigned long get_kmem_end(void); |
70 | extern void check_tmpexec(void); | ||
71 | 67 | ||
72 | #endif | 68 | #endif |
73 | |||
74 | /* | ||
75 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
76 | * Emacs will notice this stuff at the end of the file and automatically | ||
77 | * adjust the settings for this buffer only. This must remain at the end | ||
78 | * of the file. | ||
79 | * --------------------------------------------------------------------------- | ||
80 | * Local variables: | ||
81 | * c-file-style: "linux" | ||
82 | * End: | ||
83 | */ | ||
diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 4c362458052c..583329d0a539 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h | |||
@@ -157,6 +157,9 @@ extern int os_lock_file(int fd, int excl); | |||
157 | extern void os_early_checks(void); | 157 | extern void os_early_checks(void); |
158 | extern int can_do_skas(void); | 158 | extern int can_do_skas(void); |
159 | 159 | ||
160 | /* mem.c */ | ||
161 | extern int create_mem_file(unsigned long len); | ||
162 | |||
160 | /* process.c */ | 163 | /* process.c */ |
161 | extern unsigned long os_process_pc(int pid); | 164 | extern unsigned long os_process_pc(int pid); |
162 | extern int os_process_parent(int pid); | 165 | extern int os_process_parent(int pid); |
@@ -181,6 +184,8 @@ extern unsigned long long os_usecs(void); | |||
181 | /* tt.c | 184 | /* tt.c |
182 | * for tt mode only (will be deleted in future...) | 185 | * for tt mode only (will be deleted in future...) |
183 | */ | 186 | */ |
187 | extern int protect_memory(unsigned long addr, unsigned long len, | ||
188 | int r, int w, int x, int must_succeed); | ||
184 | extern void forward_pending_sigio(int target); | 189 | extern void forward_pending_sigio(int target); |
185 | extern int start_fork_tramp(void *arg, unsigned long temp_stack, | 190 | extern int start_fork_tramp(void *arg, unsigned long temp_stack, |
186 | int clone_flags, int (*tramp)(void *)); | 191 | int clone_flags, int (*tramp)(void *)); |
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 614b8ebeb0ed..1a0001b3850c 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | # | 1 | # |
2 | # Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | # Copyright (C) 2002 Jeff Dike (jdike@karaya.com) |
3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
4 | # | 4 | # |
@@ -7,11 +7,11 @@ extra-y := vmlinux.lds | |||
7 | clean-files := | 7 | clean-files := |
8 | 8 | ||
9 | obj-y = config.o exec_kern.o exitcode.o \ | 9 | obj-y = config.o exec_kern.o exitcode.o \ |
10 | helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \ | 10 | helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o physmem.o \ |
11 | physmem.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \ | 11 | process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ |
12 | sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o \ | 12 | signal_kern.o signal_user.o smp.o syscall_kern.o sysrq.o time.o \ |
13 | tempfile.o time.o time_kern.o tlb.o trap_kern.o trap_user.o \ | 13 | time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \ |
14 | uaccess_user.o um_arch.o umid.o user_util.o | 14 | umid.o user_util.o |
15 | 15 | ||
16 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o | 16 | obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o |
17 | obj-$(CONFIG_GPROF) += gprof_syms.o | 17 | obj-$(CONFIG_GPROF) += gprof_syms.o |
@@ -24,8 +24,8 @@ obj-$(CONFIG_MODE_SKAS) += skas/ | |||
24 | 24 | ||
25 | user-objs-$(CONFIG_TTY_LOG) += tty_log.o | 25 | user-objs-$(CONFIG_TTY_LOG) += tty_log.o |
26 | 26 | ||
27 | USER_OBJS := $(user-objs-y) config.o helper.o main.o tempfile.o time.o \ | 27 | USER_OBJS := $(user-objs-y) config.o helper.o main.o time.o tty_log.o umid.o \ |
28 | tty_log.o umid.o user_util.o | 28 | user_util.o |
29 | 29 | ||
30 | include arch/um/scripts/Makefile.rules | 30 | include arch/um/scripts/Makefile.rules |
31 | 31 | ||
diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c index f83e1e8e2392..33fb0bd3b11a 100644 --- a/arch/um/kernel/helper.c +++ b/arch/um/kernel/helper.c | |||
@@ -85,8 +85,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, | |||
85 | data.fd = fds[1]; | 85 | data.fd = fds[1]; |
86 | pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); | 86 | pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); |
87 | if(pid < 0){ | 87 | if(pid < 0){ |
88 | printk("run_helper : clone failed, errno = %d\n", errno); | ||
89 | ret = -errno; | 88 | ret = -errno; |
89 | printk("run_helper : clone failed, errno = %d\n", errno); | ||
90 | goto out_close; | 90 | goto out_close; |
91 | } | 91 | } |
92 | 92 | ||
@@ -122,7 +122,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, | |||
122 | unsigned long *stack_out, int stack_order) | 122 | unsigned long *stack_out, int stack_order) |
123 | { | 123 | { |
124 | unsigned long stack, sp; | 124 | unsigned long stack, sp; |
125 | int pid, status; | 125 | int pid, status, err; |
126 | 126 | ||
127 | stack = alloc_stack(stack_order, um_in_interrupt()); | 127 | stack = alloc_stack(stack_order, um_in_interrupt()); |
128 | if(stack == 0) return(-ENOMEM); | 128 | if(stack == 0) return(-ENOMEM); |
@@ -130,16 +130,18 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, | |||
130 | sp = stack + (page_size() << stack_order) - sizeof(void *); | 130 | sp = stack + (page_size() << stack_order) - sizeof(void *); |
131 | pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); | 131 | pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); |
132 | if(pid < 0){ | 132 | if(pid < 0){ |
133 | err = -errno; | ||
133 | printk("run_helper_thread : clone failed, errno = %d\n", | 134 | printk("run_helper_thread : clone failed, errno = %d\n", |
134 | errno); | 135 | errno); |
135 | return(-errno); | 136 | return err; |
136 | } | 137 | } |
137 | if(stack_out == NULL){ | 138 | if(stack_out == NULL){ |
138 | CATCH_EINTR(pid = waitpid(pid, &status, 0)); | 139 | CATCH_EINTR(pid = waitpid(pid, &status, 0)); |
139 | if(pid < 0){ | 140 | if(pid < 0){ |
141 | err = -errno; | ||
140 | printk("run_helper_thread - wait failed, errno = %d\n", | 142 | printk("run_helper_thread - wait failed, errno = %d\n", |
141 | errno); | 143 | errno); |
142 | pid = -errno; | 144 | pid = err; |
143 | } | 145 | } |
144 | if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) | 146 | if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) |
145 | printk("run_helper_thread - thread returned status " | 147 | printk("run_helper_thread - thread returned status " |
@@ -156,8 +158,8 @@ int helper_wait(int pid) | |||
156 | 158 | ||
157 | CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG)); | 159 | CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG)); |
158 | if(ret < 0){ | 160 | if(ret < 0){ |
161 | ret = -errno; | ||
159 | printk("helper_wait : waitpid failed, errno = %d\n", errno); | 162 | printk("helper_wait : waitpid failed, errno = %d\n", errno); |
160 | return(-errno); | ||
161 | } | 163 | } |
162 | return(ret); | 164 | return(ret); |
163 | } | 165 | } |
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c index cd7c85be0a1b..49ed5ddf0704 100644 --- a/arch/um/kernel/init_task.c +++ b/arch/um/kernel/init_task.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include "asm/pgtable.h" | 13 | #include "asm/pgtable.h" |
14 | #include "user_util.h" | 14 | #include "user_util.h" |
15 | #include "mem_user.h" | 15 | #include "mem_user.h" |
16 | #include "os.h" | ||
16 | 17 | ||
17 | static struct fs_struct init_fs = INIT_FS; | 18 | static struct fs_struct init_fs = INIT_FS; |
18 | struct mm_struct init_mm = INIT_MM(init_mm); | 19 | struct mm_struct init_mm = INIT_MM(init_mm); |
@@ -45,8 +46,8 @@ __attribute__((__section__(".data.init_task"))) = | |||
45 | 46 | ||
46 | void unprotect_stack(unsigned long stack) | 47 | void unprotect_stack(unsigned long stack) |
47 | { | 48 | { |
48 | protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, | 49 | os_protect_memory((void *) stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, |
49 | 1, 1, 0, 1); | 50 | 1, 1, 0); |
50 | } | 51 | } |
51 | 52 | ||
52 | /* | 53 | /* |
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 64fa062cc119..ea008b031a8f 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) | 2 | * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
@@ -19,6 +19,10 @@ | |||
19 | #include "mem_user.h" | 19 | #include "mem_user.h" |
20 | #include "uml_uaccess.h" | 20 | #include "uml_uaccess.h" |
21 | #include "os.h" | 21 | #include "os.h" |
22 | #include "linux/types.h" | ||
23 | #include "linux/string.h" | ||
24 | #include "init.h" | ||
25 | #include "kern_constants.h" | ||
22 | 26 | ||
23 | extern char __binary_start; | 27 | extern char __binary_start; |
24 | 28 | ||
@@ -368,6 +372,16 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) | |||
368 | return pte; | 372 | return pte; |
369 | } | 373 | } |
370 | 374 | ||
375 | struct iomem_region *iomem_regions = NULL; | ||
376 | int iomem_size = 0; | ||
377 | |||
378 | extern int parse_iomem(char *str, int *add) __init; | ||
379 | |||
380 | __uml_setup("iomem=", parse_iomem, | ||
381 | "iomem=<name>,<file>\n" | ||
382 | " Configure <file> as an IO memory region named <name>.\n\n" | ||
383 | ); | ||
384 | |||
371 | /* | 385 | /* |
372 | * Overrides for Emacs so that we follow Linus's tabbing style. | 386 | * Overrides for Emacs so that we follow Linus's tabbing style. |
373 | * Emacs will notice this stuff at the end of the file and automatically | 387 | * Emacs will notice this stuff at the end of the file and automatically |
diff --git a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c deleted file mode 100644 index 4a663fd434bb..000000000000 --- a/arch/um/kernel/mem_user.c +++ /dev/null | |||
@@ -1,273 +0,0 @@ | |||
1 | /* | ||
2 | * arch/um/kernel/mem_user.c | ||
3 | * | ||
4 | * BRIEF MODULE DESCRIPTION | ||
5 | * user side memory routines for supporting IO memory inside user mode linux | ||
6 | * | ||
7 | * Copyright (C) 2001 RidgeRun, Inc. | ||
8 | * Author: RidgeRun, Inc. | ||
9 | * Greg Lonnon glonnon@ridgerun.com or info@ridgerun.com | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
19 | * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
22 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
23 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | * | ||
27 | * You should have received a copy of the GNU General Public License along | ||
28 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
29 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
30 | */ | ||
31 | |||
32 | #include <stdio.h> | ||
33 | #include <stdlib.h> | ||
34 | #include <stddef.h> | ||
35 | #include <stdarg.h> | ||
36 | #include <unistd.h> | ||
37 | #include <errno.h> | ||
38 | #include <string.h> | ||
39 | #include <fcntl.h> | ||
40 | #include <sys/types.h> | ||
41 | #include <sys/mman.h> | ||
42 | #include "kern_util.h" | ||
43 | #include "user.h" | ||
44 | #include "user_util.h" | ||
45 | #include "mem_user.h" | ||
46 | #include "init.h" | ||
47 | #include "os.h" | ||
48 | #include "tempfile.h" | ||
49 | #include "kern_constants.h" | ||
50 | |||
51 | #define TEMPNAME_TEMPLATE "vm_file-XXXXXX" | ||
52 | |||
53 | static int create_tmp_file(unsigned long len) | ||
54 | { | ||
55 | int fd, err; | ||
56 | char zero; | ||
57 | |||
58 | fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); | ||
59 | if(fd < 0) { | ||
60 | os_print_error(fd, "make_tempfile"); | ||
61 | exit(1); | ||
62 | } | ||
63 | |||
64 | err = os_mode_fd(fd, 0777); | ||
65 | if(err < 0){ | ||
66 | os_print_error(err, "os_mode_fd"); | ||
67 | exit(1); | ||
68 | } | ||
69 | err = os_seek_file(fd, len); | ||
70 | if(err < 0){ | ||
71 | os_print_error(err, "os_seek_file"); | ||
72 | exit(1); | ||
73 | } | ||
74 | zero = 0; | ||
75 | err = os_write_file(fd, &zero, 1); | ||
76 | if(err != 1){ | ||
77 | os_print_error(err, "os_write_file"); | ||
78 | exit(1); | ||
79 | } | ||
80 | |||
81 | return(fd); | ||
82 | } | ||
83 | |||
84 | void check_tmpexec(void) | ||
85 | { | ||
86 | void *addr; | ||
87 | int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE); | ||
88 | |||
89 | addr = mmap(NULL, UM_KERN_PAGE_SIZE, | ||
90 | PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); | ||
91 | printf("Checking PROT_EXEC mmap in /tmp..."); | ||
92 | fflush(stdout); | ||
93 | if(addr == MAP_FAILED){ | ||
94 | err = errno; | ||
95 | perror("failed"); | ||
96 | if(err == EPERM) | ||
97 | printf("/tmp must be not mounted noexec\n"); | ||
98 | exit(1); | ||
99 | } | ||
100 | printf("OK\n"); | ||
101 | munmap(addr, UM_KERN_PAGE_SIZE); | ||
102 | |||
103 | os_close_file(fd); | ||
104 | } | ||
105 | |||
106 | static int have_devanon = 0; | ||
107 | |||
108 | void check_devanon(void) | ||
109 | { | ||
110 | int fd; | ||
111 | |||
112 | printk("Checking for /dev/anon on the host..."); | ||
113 | fd = open("/dev/anon", O_RDWR); | ||
114 | if(fd < 0){ | ||
115 | printk("Not available (open failed with errno %d)\n", errno); | ||
116 | return; | ||
117 | } | ||
118 | |||
119 | printk("OK\n"); | ||
120 | have_devanon = 1; | ||
121 | } | ||
122 | |||
123 | static int create_anon_file(unsigned long len) | ||
124 | { | ||
125 | void *addr; | ||
126 | int fd; | ||
127 | |||
128 | fd = open("/dev/anon", O_RDWR); | ||
129 | if(fd < 0) { | ||
130 | os_print_error(fd, "opening /dev/anon"); | ||
131 | exit(1); | ||
132 | } | ||
133 | |||
134 | addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); | ||
135 | if(addr == MAP_FAILED){ | ||
136 | perror("mapping physmem file"); | ||
137 | exit(1); | ||
138 | } | ||
139 | munmap(addr, len); | ||
140 | |||
141 | return(fd); | ||
142 | } | ||
143 | |||
144 | int create_mem_file(unsigned long len) | ||
145 | { | ||
146 | int err, fd; | ||
147 | |||
148 | if(have_devanon) | ||
149 | fd = create_anon_file(len); | ||
150 | else fd = create_tmp_file(len); | ||
151 | |||
152 | err = os_set_exec_close(fd, 1); | ||
153 | if(err < 0) | ||
154 | os_print_error(err, "exec_close"); | ||
155 | return(fd); | ||
156 | } | ||
157 | |||
158 | struct iomem_region *iomem_regions = NULL; | ||
159 | int iomem_size = 0; | ||
160 | |||
161 | static int __init parse_iomem(char *str, int *add) | ||
162 | { | ||
163 | struct iomem_region *new; | ||
164 | struct uml_stat buf; | ||
165 | char *file, *driver; | ||
166 | int fd, err, size; | ||
167 | |||
168 | driver = str; | ||
169 | file = strchr(str,','); | ||
170 | if(file == NULL){ | ||
171 | printf("parse_iomem : failed to parse iomem\n"); | ||
172 | goto out; | ||
173 | } | ||
174 | *file = '\0'; | ||
175 | file++; | ||
176 | fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0); | ||
177 | if(fd < 0){ | ||
178 | os_print_error(fd, "parse_iomem - Couldn't open io file"); | ||
179 | goto out; | ||
180 | } | ||
181 | |||
182 | err = os_stat_fd(fd, &buf); | ||
183 | if(err < 0){ | ||
184 | os_print_error(err, "parse_iomem - cannot stat_fd file"); | ||
185 | goto out_close; | ||
186 | } | ||
187 | |||
188 | new = malloc(sizeof(*new)); | ||
189 | if(new == NULL){ | ||
190 | perror("Couldn't allocate iomem_region struct"); | ||
191 | goto out_close; | ||
192 | } | ||
193 | |||
194 | size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1); | ||
195 | |||
196 | *new = ((struct iomem_region) { .next = iomem_regions, | ||
197 | .driver = driver, | ||
198 | .fd = fd, | ||
199 | .size = size, | ||
200 | .phys = 0, | ||
201 | .virt = 0 }); | ||
202 | iomem_regions = new; | ||
203 | iomem_size += new->size + UM_KERN_PAGE_SIZE; | ||
204 | |||
205 | return(0); | ||
206 | out_close: | ||
207 | os_close_file(fd); | ||
208 | out: | ||
209 | return(1); | ||
210 | } | ||
211 | |||
212 | __uml_setup("iomem=", parse_iomem, | ||
213 | "iomem=<name>,<file>\n" | ||
214 | " Configure <file> as an IO memory region named <name>.\n\n" | ||
215 | ); | ||
216 | |||
217 | int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, | ||
218 | int must_succeed) | ||
219 | { | ||
220 | int err; | ||
221 | |||
222 | err = os_protect_memory((void *) addr, len, r, w, x); | ||
223 | if(err < 0){ | ||
224 | if(must_succeed) | ||
225 | panic("protect failed, err = %d", -err); | ||
226 | else return(err); | ||
227 | } | ||
228 | return(0); | ||
229 | } | ||
230 | |||
231 | #if 0 | ||
232 | /* Debugging facility for dumping stuff out to the host, avoiding the timing | ||
233 | * problems that come with printf and breakpoints. | ||
234 | * Enable in case of emergency. | ||
235 | */ | ||
236 | |||
237 | int logging = 1; | ||
238 | int logging_fd = -1; | ||
239 | |||
240 | int logging_line = 0; | ||
241 | char logging_buf[512]; | ||
242 | |||
243 | void log(char *fmt, ...) | ||
244 | { | ||
245 | va_list ap; | ||
246 | struct timeval tv; | ||
247 | struct openflags flags; | ||
248 | |||
249 | if(logging == 0) return; | ||
250 | if(logging_fd < 0){ | ||
251 | flags = of_create(of_trunc(of_rdwr(OPENFLAGS()))); | ||
252 | logging_fd = os_open_file("log", flags, 0644); | ||
253 | } | ||
254 | gettimeofday(&tv, NULL); | ||
255 | sprintf(logging_buf, "%d\t %u.%u ", logging_line++, tv.tv_sec, | ||
256 | tv.tv_usec); | ||
257 | va_start(ap, fmt); | ||
258 | vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap); | ||
259 | va_end(ap); | ||
260 | write(logging_fd, logging_buf, strlen(logging_buf)); | ||
261 | } | ||
262 | #endif | ||
263 | |||
264 | /* | ||
265 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
266 | * Emacs will notice this stuff at the end of the file and automatically | ||
267 | * adjust the settings for this buffer only. This must remain at the end | ||
268 | * of the file. | ||
269 | * --------------------------------------------------------------------------- | ||
270 | * Local variables: | ||
271 | * c-file-style: "linux" | ||
272 | * End: | ||
273 | */ | ||
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index c23d8a08d0ff..39cf568ccfaf 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c | |||
@@ -113,8 +113,23 @@ void set_current(void *t) | |||
113 | 113 | ||
114 | void *_switch_to(void *prev, void *next, void *last) | 114 | void *_switch_to(void *prev, void *next, void *last) |
115 | { | 115 | { |
116 | return(CHOOSE_MODE(switch_to_tt(prev, next), | 116 | struct task_struct *from = prev; |
117 | switch_to_skas(prev, next))); | 117 | struct task_struct *to= next; |
118 | |||
119 | to->thread.prev_sched = from; | ||
120 | set_current(to); | ||
121 | |||
122 | do { | ||
123 | current->thread.saved_task = NULL ; | ||
124 | CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next); | ||
125 | if(current->thread.saved_task) | ||
126 | show_regs(&(current->thread.regs)); | ||
127 | next= current->thread.saved_task; | ||
128 | prev= current; | ||
129 | } while(current->thread.saved_task); | ||
130 | |||
131 | return(current->thread.prev_sched); | ||
132 | |||
118 | } | 133 | } |
119 | 134 | ||
120 | void interrupt_end(void) | 135 | void interrupt_end(void) |
diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/kernel/skas/include/mode_kern-skas.h index e48490028111..c97a80dfe370 100644 --- a/arch/um/kernel/skas/include/mode_kern-skas.h +++ b/arch/um/kernel/skas/include/mode_kern-skas.h | |||
@@ -11,7 +11,7 @@ | |||
11 | #include "asm/ptrace.h" | 11 | #include "asm/ptrace.h" |
12 | 12 | ||
13 | extern void flush_thread_skas(void); | 13 | extern void flush_thread_skas(void); |
14 | extern void *switch_to_skas(void *prev, void *next); | 14 | extern void switch_to_skas(void *prev, void *next); |
15 | extern void start_thread_skas(struct pt_regs *regs, unsigned long eip, | 15 | extern void start_thread_skas(struct pt_regs *regs, unsigned long eip, |
16 | unsigned long esp); | 16 | unsigned long esp); |
17 | extern int copy_thread_skas(int nr, unsigned long clone_flags, | 17 | extern int copy_thread_skas(int nr, unsigned long clone_flags, |
diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h index 6ee3f3902e68..7da0c2def0ef 100644 --- a/arch/um/kernel/skas/include/uaccess-skas.h +++ b/arch/um/kernel/skas/include/uaccess-skas.h | |||
@@ -18,12 +18,6 @@ | |||
18 | ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ | 18 | ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ |
19 | ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))) | 19 | ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))) |
20 | 20 | ||
21 | static inline int verify_area_skas(int type, const void __user * addr, | ||
22 | unsigned long size) | ||
23 | { | ||
24 | return(access_ok_skas(type, addr, size) ? 0 : -EFAULT); | ||
25 | } | ||
26 | |||
27 | extern int copy_from_user_skas(void *to, const void __user *from, int n); | 21 | extern int copy_from_user_skas(void *to, const void __user *from, int n); |
28 | extern int copy_to_user_skas(void __user *to, const void *from, int n); | 22 | extern int copy_to_user_skas(void __user *to, const void *from, int n); |
29 | extern int strncpy_from_user_skas(char *dst, const char __user *src, int count); | 23 | extern int strncpy_from_user_skas(char *dst, const char __user *src, int count); |
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 3d1b227226e6..efe92e8aa2a9 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include "proc_mm.h" | 24 | #include "proc_mm.h" |
25 | #include "registers.h" | 25 | #include "registers.h" |
26 | 26 | ||
27 | void *switch_to_skas(void *prev, void *next) | 27 | void switch_to_skas(void *prev, void *next) |
28 | { | 28 | { |
29 | struct task_struct *from, *to; | 29 | struct task_struct *from, *to; |
30 | 30 | ||
@@ -35,16 +35,11 @@ void *switch_to_skas(void *prev, void *next) | |||
35 | if(current->pid == 0) | 35 | if(current->pid == 0) |
36 | switch_timers(0); | 36 | switch_timers(0); |
37 | 37 | ||
38 | to->thread.prev_sched = from; | ||
39 | set_current(to); | ||
40 | |||
41 | switch_threads(&from->thread.mode.skas.switch_buf, | 38 | switch_threads(&from->thread.mode.skas.switch_buf, |
42 | to->thread.mode.skas.switch_buf); | 39 | to->thread.mode.skas.switch_buf); |
43 | 40 | ||
44 | if(current->pid == 0) | 41 | if(current->pid == 0) |
45 | switch_timers(1); | 42 | switch_timers(1); |
46 | |||
47 | return(current->thread.prev_sched); | ||
48 | } | 43 | } |
49 | 44 | ||
50 | extern void schedule_tail(struct task_struct *prev); | 45 | extern void schedule_tail(struct task_struct *prev); |
diff --git a/arch/um/kernel/tempfile.c b/arch/um/kernel/tempfile.c deleted file mode 100644 index b1674bc1395d..000000000000 --- a/arch/um/kernel/tempfile.c +++ /dev/null | |||
@@ -1,82 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include <stdio.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <unistd.h> | ||
9 | #include <string.h> | ||
10 | #include <errno.h> | ||
11 | #include <sys/param.h> | ||
12 | #include "init.h" | ||
13 | |||
14 | /* Modified from create_mem_file and start_debugger */ | ||
15 | static char *tempdir = NULL; | ||
16 | |||
17 | static void __init find_tempdir(void) | ||
18 | { | ||
19 | char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; | ||
20 | int i; | ||
21 | char *dir = NULL; | ||
22 | |||
23 | if(tempdir != NULL) return; /* We've already been called */ | ||
24 | for(i = 0; dirs[i]; i++){ | ||
25 | dir = getenv(dirs[i]); | ||
26 | if((dir != NULL) && (*dir != '\0')) | ||
27 | break; | ||
28 | } | ||
29 | if((dir == NULL) || (*dir == '\0')) | ||
30 | dir = "/tmp"; | ||
31 | |||
32 | tempdir = malloc(strlen(dir) + 2); | ||
33 | if(tempdir == NULL){ | ||
34 | fprintf(stderr, "Failed to malloc tempdir, " | ||
35 | "errno = %d\n", errno); | ||
36 | return; | ||
37 | } | ||
38 | strcpy(tempdir, dir); | ||
39 | strcat(tempdir, "/"); | ||
40 | } | ||
41 | |||
42 | int make_tempfile(const char *template, char **out_tempname, int do_unlink) | ||
43 | { | ||
44 | char tempname[MAXPATHLEN]; | ||
45 | int fd; | ||
46 | |||
47 | find_tempdir(); | ||
48 | if (*template != '/') | ||
49 | strcpy(tempname, tempdir); | ||
50 | else | ||
51 | *tempname = 0; | ||
52 | strcat(tempname, template); | ||
53 | fd = mkstemp(tempname); | ||
54 | if(fd < 0){ | ||
55 | fprintf(stderr, "open - cannot create %s: %s\n", tempname, | ||
56 | strerror(errno)); | ||
57 | return -1; | ||
58 | } | ||
59 | if(do_unlink && (unlink(tempname) < 0)){ | ||
60 | perror("unlink"); | ||
61 | return -1; | ||
62 | } | ||
63 | if(out_tempname){ | ||
64 | *out_tempname = strdup(tempname); | ||
65 | if(*out_tempname == NULL){ | ||
66 | perror("strdup"); | ||
67 | return -1; | ||
68 | } | ||
69 | } | ||
70 | return(fd); | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
75 | * Emacs will notice this stuff at the end of the file and automatically | ||
76 | * adjust the settings for this buffer only. This must remain at the end | ||
77 | * of the file. | ||
78 | * --------------------------------------------------------------------------- | ||
79 | * Local variables: | ||
80 | * c-file-style: "linux" | ||
81 | * End: | ||
82 | */ | ||
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index 80ed6188e8a2..0a562c3c0fd8 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c | |||
@@ -307,7 +307,7 @@ int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) | |||
307 | } | 307 | } |
308 | else if(pte_newprot(*pte)){ | 308 | else if(pte_newprot(*pte)){ |
309 | updated = 1; | 309 | updated = 1; |
310 | protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1); | 310 | os_protect_memory((void *) addr, PAGE_SIZE, 1, 1, 1); |
311 | } | 311 | } |
312 | addr += PAGE_SIZE; | 312 | addr += PAGE_SIZE; |
313 | } | 313 | } |
diff --git a/arch/um/kernel/tt/include/mode_kern-tt.h b/arch/um/kernel/tt/include/mode_kern-tt.h index e0ca0e0b2516..2a35b15c5fef 100644 --- a/arch/um/kernel/tt/include/mode_kern-tt.h +++ b/arch/um/kernel/tt/include/mode_kern-tt.h | |||
@@ -11,7 +11,7 @@ | |||
11 | #include "asm/ptrace.h" | 11 | #include "asm/ptrace.h" |
12 | #include "asm/uaccess.h" | 12 | #include "asm/uaccess.h" |
13 | 13 | ||
14 | extern void *switch_to_tt(void *prev, void *next); | 14 | extern void switch_to_tt(void *prev, void *next); |
15 | extern void flush_thread_tt(void); | 15 | extern void flush_thread_tt(void); |
16 | extern void start_thread_tt(struct pt_regs *regs, unsigned long eip, | 16 | extern void start_thread_tt(struct pt_regs *regs, unsigned long eip, |
17 | unsigned long esp); | 17 | unsigned long esp); |
diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/kernel/tt/include/uaccess-tt.h index aa6db384af80..dc2ebfa8c54f 100644 --- a/arch/um/kernel/tt/include/uaccess-tt.h +++ b/arch/um/kernel/tt/include/uaccess-tt.h | |||
@@ -33,12 +33,6 @@ extern unsigned long uml_physmem; | |||
33 | (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ | 33 | (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ |
34 | (under_task_size(addr, size) || is_stack(addr, size)))) | 34 | (under_task_size(addr, size) || is_stack(addr, size)))) |
35 | 35 | ||
36 | static inline int verify_area_tt(int type, const void __user * addr, | ||
37 | unsigned long size) | ||
38 | { | ||
39 | return(access_ok_tt(type, addr, size) ? 0 : -EFAULT); | ||
40 | } | ||
41 | |||
42 | extern unsigned long get_fault_addr(void); | 36 | extern unsigned long get_fault_addr(void); |
43 | 37 | ||
44 | extern int __do_copy_from_user(void *to, const void *from, int n, | 38 | extern int __do_copy_from_user(void *to, const void *from, int n, |
diff --git a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c index 3085267459b1..03e589895388 100644 --- a/arch/um/kernel/tt/mem_user.c +++ b/arch/um/kernel/tt/mem_user.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include "tt.h" | 12 | #include "tt.h" |
13 | #include "mem_user.h" | 13 | #include "mem_user.h" |
14 | #include "user_util.h" | 14 | #include "user_util.h" |
15 | #include "os.h" | ||
15 | 16 | ||
16 | void remap_data(void *segment_start, void *segment_end, int w) | 17 | void remap_data(void *segment_start, void *segment_end, int w) |
17 | { | 18 | { |
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index a189a2b92935..cfaa373a6e77 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c | |||
@@ -23,10 +23,11 @@ | |||
23 | #include "mem_user.h" | 23 | #include "mem_user.h" |
24 | #include "tlb.h" | 24 | #include "tlb.h" |
25 | #include "mode.h" | 25 | #include "mode.h" |
26 | #include "mode_kern.h" | ||
26 | #include "init.h" | 27 | #include "init.h" |
27 | #include "tt.h" | 28 | #include "tt.h" |
28 | 29 | ||
29 | void *switch_to_tt(void *prev, void *next, void *last) | 30 | void switch_to_tt(void *prev, void *next) |
30 | { | 31 | { |
31 | struct task_struct *from, *to, *prev_sched; | 32 | struct task_struct *from, *to, *prev_sched; |
32 | unsigned long flags; | 33 | unsigned long flags; |
@@ -36,8 +37,6 @@ void *switch_to_tt(void *prev, void *next, void *last) | |||
36 | from = prev; | 37 | from = prev; |
37 | to = next; | 38 | to = next; |
38 | 39 | ||
39 | to->thread.prev_sched = from; | ||
40 | |||
41 | cpu = from->thread_info->cpu; | 40 | cpu = from->thread_info->cpu; |
42 | if(cpu == 0) | 41 | if(cpu == 0) |
43 | forward_interrupts(to->thread.mode.tt.extern_pid); | 42 | forward_interrupts(to->thread.mode.tt.extern_pid); |
@@ -53,7 +52,6 @@ void *switch_to_tt(void *prev, void *next, void *last) | |||
53 | forward_pending_sigio(to->thread.mode.tt.extern_pid); | 52 | forward_pending_sigio(to->thread.mode.tt.extern_pid); |
54 | 53 | ||
55 | c = 0; | 54 | c = 0; |
56 | set_current(to); | ||
57 | 55 | ||
58 | err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); | 56 | err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); |
59 | if(err != sizeof(c)) | 57 | if(err != sizeof(c)) |
@@ -85,8 +83,6 @@ void *switch_to_tt(void *prev, void *next, void *last) | |||
85 | 83 | ||
86 | flush_tlb_all(); | 84 | flush_tlb_all(); |
87 | local_irq_restore(flags); | 85 | local_irq_restore(flags); |
88 | |||
89 | return(current->thread.prev_sched); | ||
90 | } | 86 | } |
91 | 87 | ||
92 | void release_thread_tt(struct task_struct *task) | 88 | void release_thread_tt(struct task_struct *task) |
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 09f6f7ce4695..f0a275947d34 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c | |||
@@ -361,11 +361,6 @@ int linux_main(int argc, char **argv) | |||
361 | uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, | 361 | uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, |
362 | &host_task_size, &task_size); | 362 | &host_task_size, &task_size); |
363 | 363 | ||
364 | /* Need to check this early because mmapping happens before the | ||
365 | * kernel is running. | ||
366 | */ | ||
367 | check_tmpexec(); | ||
368 | |||
369 | brk_start = (unsigned long) sbrk(0); | 364 | brk_start = (unsigned long) sbrk(0); |
370 | CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); | 365 | CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); |
371 | /* Increase physical memory size for exec-shield users | 366 | /* Increase physical memory size for exec-shield users |
diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c index 954ff67cc8b3..41d17c71511c 100644 --- a/arch/um/kernel/user_util.c +++ b/arch/um/kernel/user_util.c | |||
@@ -109,18 +109,14 @@ int raw(int fd) | |||
109 | int err; | 109 | int err; |
110 | 110 | ||
111 | CATCH_EINTR(err = tcgetattr(fd, &tt)); | 111 | CATCH_EINTR(err = tcgetattr(fd, &tt)); |
112 | if (err < 0) { | 112 | if(err < 0) |
113 | printk("tcgetattr failed, errno = %d\n", errno); | 113 | return -errno; |
114 | return(-errno); | ||
115 | } | ||
116 | 114 | ||
117 | cfmakeraw(&tt); | 115 | cfmakeraw(&tt); |
118 | 116 | ||
119 | CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); | 117 | CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); |
120 | if (err < 0) { | 118 | if(err < 0) |
121 | printk("tcsetattr failed, errno = %d\n", errno); | 119 | return -errno; |
122 | return(-errno); | ||
123 | } | ||
124 | 120 | ||
125 | /* XXX tcsetattr could have applied only some changes | 121 | /* XXX tcsetattr could have applied only some changes |
126 | * (and cfmakeraw() is a set of changes) */ | 122 | * (and cfmakeraw() is a set of changes) */ |
@@ -132,6 +128,12 @@ void setup_machinename(char *machine_out) | |||
132 | struct utsname host; | 128 | struct utsname host; |
133 | 129 | ||
134 | uname(&host); | 130 | uname(&host); |
131 | #if defined(UML_CONFIG_UML_X86) && !defined(UML_CONFIG_64BIT) | ||
132 | if (!strcmp(host.machine, "x86_64")) { | ||
133 | strcpy(machine_out, "i686"); | ||
134 | return; | ||
135 | } | ||
136 | #endif | ||
135 | strcpy(machine_out, host.machine); | 137 | strcpy(machine_out, host.machine); |
136 | } | 138 | } |
137 | 139 | ||
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 7a1662419c0c..d15ec2af6a22 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile | |||
@@ -3,11 +3,11 @@ | |||
3 | # Licensed under the GPL | 3 | # Licensed under the GPL |
4 | # | 4 | # |
5 | 5 | ||
6 | obj-y = aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \ | 6 | obj-y = aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o time.o \ |
7 | tty.o user_syms.o drivers/ sys-$(SUBARCH)/ | 7 | tt.o tty.o user_syms.o drivers/ sys-$(SUBARCH)/ |
8 | 8 | ||
9 | USER_OBJS := aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \ | 9 | USER_OBJS := aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o \ |
10 | tty.o | 10 | time.o tt.o tty.o |
11 | 11 | ||
12 | elf_aux.o: $(ARCH_DIR)/kernel-offsets.h | 12 | elf_aux.o: $(ARCH_DIR)/kernel-offsets.h |
13 | CFLAGS_elf_aux.o += -I$(objtree)/arch/um | 13 | CFLAGS_elf_aux.o += -I$(objtree)/arch/um |
diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index b04897cd995d..f6e64026f995 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c | |||
@@ -117,6 +117,8 @@ static int do_aio(aio_context_t ctx, struct aio_context *aio) | |||
117 | err = io_submit(ctx, 1, &iocbp); | 117 | err = io_submit(ctx, 1, &iocbp); |
118 | if(err > 0) | 118 | if(err > 0) |
119 | err = 0; | 119 | err = 0; |
120 | else | ||
121 | err = -errno; | ||
120 | 122 | ||
121 | out: | 123 | out: |
122 | return err; | 124 | return err; |
@@ -142,7 +144,8 @@ static int aio_thread(void *arg) | |||
142 | "errno = %d\n", errno); | 144 | "errno = %d\n", errno); |
143 | } | 145 | } |
144 | else { | 146 | else { |
145 | aio = (struct aio_context *) event.data; | 147 | /* This is safe as we've just a pointer here. */ |
148 | aio = (struct aio_context *) (long) event.data; | ||
146 | if(update_aio(aio, event.res)){ | 149 | if(update_aio(aio, event.res)){ |
147 | do_aio(ctx, aio); | 150 | do_aio(ctx, aio); |
148 | continue; | 151 | continue; |
@@ -313,15 +316,16 @@ static int init_aio_26(void) | |||
313 | int err; | 316 | int err; |
314 | 317 | ||
315 | if(io_setup(256, &ctx)){ | 318 | if(io_setup(256, &ctx)){ |
319 | err = -errno; | ||
316 | printk("aio_thread failed to initialize context, err = %d\n", | 320 | printk("aio_thread failed to initialize context, err = %d\n", |
317 | errno); | 321 | errno); |
318 | return -errno; | 322 | return err; |
319 | } | 323 | } |
320 | 324 | ||
321 | err = run_helper_thread(aio_thread, NULL, | 325 | err = run_helper_thread(aio_thread, NULL, |
322 | CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); | 326 | CLONE_FILES | CLONE_VM | SIGCHLD, &stack, 0); |
323 | if(err < 0) | 327 | if(err < 0) |
324 | return -errno; | 328 | return err; |
325 | 329 | ||
326 | aio_pid = err; | 330 | aio_pid = err; |
327 | 331 | ||
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index 4b83c6c3f48d..4ba9b17adf13 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c | |||
@@ -75,7 +75,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, | |||
75 | struct msghdr msg; | 75 | struct msghdr msg; |
76 | struct cmsghdr *cmsg; | 76 | struct cmsghdr *cmsg; |
77 | struct iovec iov; | 77 | struct iovec iov; |
78 | int pid, n; | 78 | int pid, n, err; |
79 | 79 | ||
80 | sprintf(version_buf, "%d", UML_NET_VERSION); | 80 | sprintf(version_buf, "%d", UML_NET_VERSION); |
81 | 81 | ||
@@ -105,9 +105,10 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, | |||
105 | n = recvmsg(me, &msg, 0); | 105 | n = recvmsg(me, &msg, 0); |
106 | *used_out = n; | 106 | *used_out = n; |
107 | if(n < 0){ | 107 | if(n < 0){ |
108 | err = -errno; | ||
108 | printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", | 109 | printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", |
109 | errno); | 110 | errno); |
110 | return(-errno); | 111 | return err; |
111 | } | 112 | } |
112 | CATCH_EINTR(waitpid(pid, NULL, 0)); | 113 | CATCH_EINTR(waitpid(pid, NULL, 0)); |
113 | 114 | ||
@@ -147,9 +148,10 @@ static int tuntap_open(void *data) | |||
147 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; | 148 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; |
148 | strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); | 149 | strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); |
149 | if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ | 150 | if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ |
151 | err = -errno; | ||
150 | printk("TUNSETIFF failed, errno = %d\n", errno); | 152 | printk("TUNSETIFF failed, errno = %d\n", errno); |
151 | os_close_file(pri->fd); | 153 | os_close_file(pri->fd); |
152 | return(-errno); | 154 | return err; |
153 | } | 155 | } |
154 | } | 156 | } |
155 | else { | 157 | else { |
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c index 1399520a8588..ab33cb3c74ec 100644 --- a/arch/um/os-Linux/elf_aux.c +++ b/arch/um/os-Linux/elf_aux.c | |||
@@ -14,7 +14,8 @@ | |||
14 | #include "mem_user.h" | 14 | #include "mem_user.h" |
15 | #include <kernel-offsets.h> | 15 | #include <kernel-offsets.h> |
16 | 16 | ||
17 | #if HOST_ELF_CLASS == ELFCLASS32 | 17 | /* Use the one from the kernel - the host may miss it, if having old headers. */ |
18 | #if UM_ELF_CLASS == UM_ELFCLASS32 | ||
18 | typedef Elf32_auxv_t elf_auxv_t; | 19 | typedef Elf32_auxv_t elf_auxv_t; |
19 | #else | 20 | #else |
20 | typedef Elf64_auxv_t elf_auxv_t; | 21 | typedef Elf64_auxv_t elf_auxv_t; |
@@ -54,7 +55,8 @@ __init void scan_elf_aux( char **envp) | |||
54 | * a_un, so we have to use a_val, which is | 55 | * a_un, so we have to use a_val, which is |
55 | * all that's left. | 56 | * all that's left. |
56 | */ | 57 | */ |
57 | elf_aux_platform = (char *) auxv->a_un.a_val; | 58 | elf_aux_platform = |
59 | (char *) (long) auxv->a_un.a_val; | ||
58 | break; | 60 | break; |
59 | case AT_PAGESZ: | 61 | case AT_PAGESZ: |
60 | page_size = auxv->a_un.a_val; | 62 | page_size = auxv->a_un.a_val; |
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index fd45bb260907..f55773c819e6 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c | |||
@@ -119,15 +119,11 @@ int os_window_size(int fd, int *rows, int *cols) | |||
119 | 119 | ||
120 | int os_new_tty_pgrp(int fd, int pid) | 120 | int os_new_tty_pgrp(int fd, int pid) |
121 | { | 121 | { |
122 | if(ioctl(fd, TIOCSCTTY, 0) < 0){ | 122 | if(ioctl(fd, TIOCSCTTY, 0) < 0) |
123 | printk("TIOCSCTTY failed, errno = %d\n", errno); | 123 | return -errno; |
124 | return(-errno); | ||
125 | } | ||
126 | 124 | ||
127 | if(tcsetpgrp(fd, pid) < 0){ | 125 | if(tcsetpgrp(fd, pid) < 0) |
128 | printk("tcsetpgrp failed, errno = %d\n", errno); | 126 | return -errno; |
129 | return(-errno); | ||
130 | } | ||
131 | 127 | ||
132 | return(0); | 128 | return(0); |
133 | } | 129 | } |
@@ -146,18 +142,12 @@ int os_set_slip(int fd) | |||
146 | int disc, sencap; | 142 | int disc, sencap; |
147 | 143 | ||
148 | disc = N_SLIP; | 144 | disc = N_SLIP; |
149 | if(ioctl(fd, TIOCSETD, &disc) < 0){ | 145 | if(ioctl(fd, TIOCSETD, &disc) < 0) |
150 | printk("Failed to set slip line discipline - " | 146 | return -errno; |
151 | "errno = %d\n", errno); | ||
152 | return(-errno); | ||
153 | } | ||
154 | 147 | ||
155 | sencap = 0; | 148 | sencap = 0; |
156 | if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){ | 149 | if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0) |
157 | printk("Failed to set slip encapsulation - " | 150 | return -errno; |
158 | "errno = %d\n", errno); | ||
159 | return(-errno); | ||
160 | } | ||
161 | 151 | ||
162 | return(0); | 152 | return(0); |
163 | } | 153 | } |
@@ -180,22 +170,15 @@ int os_sigio_async(int master, int slave) | |||
180 | int flags; | 170 | int flags; |
181 | 171 | ||
182 | flags = fcntl(master, F_GETFL); | 172 | flags = fcntl(master, F_GETFL); |
183 | if(flags < 0) { | 173 | if(flags < 0) |
184 | printk("fcntl F_GETFL failed, errno = %d\n", errno); | 174 | return errno; |
185 | return(-errno); | ||
186 | } | ||
187 | 175 | ||
188 | if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || | 176 | if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || |
189 | (fcntl(master, F_SETOWN, os_getpid()) < 0)){ | 177 | (fcntl(master, F_SETOWN, os_getpid()) < 0)) |
190 | printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", | 178 | return -errno; |
191 | errno); | ||
192 | return(-errno); | ||
193 | } | ||
194 | 179 | ||
195 | if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){ | 180 | if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) |
196 | printk("fcntl F_SETFL failed, errno = %d\n", errno); | 181 | return -errno; |
197 | return(-errno); | ||
198 | } | ||
199 | 182 | ||
200 | return(0); | 183 | return(0); |
201 | } | 184 | } |
@@ -255,7 +238,7 @@ int os_file_mode(char *file, struct openflags *mode_out) | |||
255 | 238 | ||
256 | int os_open_file(char *file, struct openflags flags, int mode) | 239 | int os_open_file(char *file, struct openflags flags, int mode) |
257 | { | 240 | { |
258 | int fd, f = 0; | 241 | int fd, err, f = 0; |
259 | 242 | ||
260 | if(flags.r && flags.w) f = O_RDWR; | 243 | if(flags.r && flags.w) f = O_RDWR; |
261 | else if(flags.r) f = O_RDONLY; | 244 | else if(flags.r) f = O_RDONLY; |
@@ -272,8 +255,9 @@ int os_open_file(char *file, struct openflags flags, int mode) | |||
272 | return(-errno); | 255 | return(-errno); |
273 | 256 | ||
274 | if(flags.cl && fcntl(fd, F_SETFD, 1)){ | 257 | if(flags.cl && fcntl(fd, F_SETFD, 1)){ |
258 | err = -errno; | ||
275 | os_close_file(fd); | 259 | os_close_file(fd); |
276 | return(-errno); | 260 | return err; |
277 | } | 261 | } |
278 | 262 | ||
279 | return(fd); | 263 | return(fd); |
@@ -383,9 +367,9 @@ int os_file_size(char *file, unsigned long long *size_out) | |||
383 | return(fd); | 367 | return(fd); |
384 | } | 368 | } |
385 | if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ | 369 | if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ |
370 | err = -errno; | ||
386 | printk("Couldn't get the block size of \"%s\", " | 371 | printk("Couldn't get the block size of \"%s\", " |
387 | "errno = %d\n", file, errno); | 372 | "errno = %d\n", file, errno); |
388 | err = -errno; | ||
389 | os_close_file(fd); | 373 | os_close_file(fd); |
390 | return(err); | 374 | return(err); |
391 | } | 375 | } |
@@ -473,11 +457,14 @@ int os_pipe(int *fds, int stream, int close_on_exec) | |||
473 | 457 | ||
474 | int os_set_fd_async(int fd, int owner) | 458 | int os_set_fd_async(int fd, int owner) |
475 | { | 459 | { |
460 | int err; | ||
461 | |||
476 | /* XXX This should do F_GETFL first */ | 462 | /* XXX This should do F_GETFL first */ |
477 | if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){ | 463 | if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){ |
464 | err = -errno; | ||
478 | printk("os_set_fd_async : failed to set O_ASYNC and " | 465 | printk("os_set_fd_async : failed to set O_ASYNC and " |
479 | "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno); | 466 | "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno); |
480 | return(-errno); | 467 | return err; |
481 | } | 468 | } |
482 | #ifdef notdef | 469 | #ifdef notdef |
483 | if(fcntl(fd, F_SETFD, 1) < 0){ | 470 | if(fcntl(fd, F_SETFD, 1) < 0){ |
@@ -488,10 +475,11 @@ int os_set_fd_async(int fd, int owner) | |||
488 | 475 | ||
489 | if((fcntl(fd, F_SETSIG, SIGIO) < 0) || | 476 | if((fcntl(fd, F_SETSIG, SIGIO) < 0) || |
490 | (fcntl(fd, F_SETOWN, owner) < 0)){ | 477 | (fcntl(fd, F_SETOWN, owner) < 0)){ |
478 | err = -errno; | ||
491 | printk("os_set_fd_async : Failed to fcntl F_SETOWN " | 479 | printk("os_set_fd_async : Failed to fcntl F_SETOWN " |
492 | "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, | 480 | "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd, |
493 | owner, errno); | 481 | owner, errno); |
494 | return(-errno); | 482 | return err; |
495 | } | 483 | } |
496 | 484 | ||
497 | return(0); | 485 | return(0); |
@@ -516,11 +504,9 @@ int os_set_fd_block(int fd, int blocking) | |||
516 | if(blocking) flags &= ~O_NONBLOCK; | 504 | if(blocking) flags &= ~O_NONBLOCK; |
517 | else flags |= O_NONBLOCK; | 505 | else flags |= O_NONBLOCK; |
518 | 506 | ||
519 | if(fcntl(fd, F_SETFL, flags) < 0){ | 507 | if(fcntl(fd, F_SETFL, flags) < 0) |
520 | printk("Failed to change blocking on fd # %d, errno = %d\n", | 508 | return -errno; |
521 | fd, errno); | 509 | |
522 | return(-errno); | ||
523 | } | ||
524 | return(0); | 510 | return(0); |
525 | } | 511 | } |
526 | 512 | ||
@@ -609,11 +595,8 @@ int os_create_unix_socket(char *file, int len, int close_on_exec) | |||
609 | int sock, err; | 595 | int sock, err; |
610 | 596 | ||
611 | sock = socket(PF_UNIX, SOCK_DGRAM, 0); | 597 | sock = socket(PF_UNIX, SOCK_DGRAM, 0); |
612 | if (sock < 0){ | 598 | if(sock < 0) |
613 | printk("create_unix_socket - socket failed, errno = %d\n", | 599 | return -errno; |
614 | errno); | ||
615 | return(-errno); | ||
616 | } | ||
617 | 600 | ||
618 | if(close_on_exec) { | 601 | if(close_on_exec) { |
619 | err = os_set_exec_close(sock, 1); | 602 | err = os_set_exec_close(sock, 1); |
@@ -628,11 +611,8 @@ int os_create_unix_socket(char *file, int len, int close_on_exec) | |||
628 | snprintf(addr.sun_path, len, "%s", file); | 611 | snprintf(addr.sun_path, len, "%s", file); |
629 | 612 | ||
630 | err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); | 613 | err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); |
631 | if (err < 0){ | 614 | if(err < 0) |
632 | printk("create_listening_socket at '%s' - bind failed, " | 615 | return -errno; |
633 | "errno = %d\n", file, errno); | ||
634 | return(-errno); | ||
635 | } | ||
636 | 616 | ||
637 | return(sock); | 617 | return(sock); |
638 | } | 618 | } |
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c new file mode 100644 index 000000000000..8e71edaaf80b --- /dev/null +++ b/arch/um/os-Linux/mem.c | |||
@@ -0,0 +1,161 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <stddef.h> | ||
4 | #include <stdarg.h> | ||
5 | #include <unistd.h> | ||
6 | #include <errno.h> | ||
7 | #include <string.h> | ||
8 | #include <fcntl.h> | ||
9 | #include <sys/types.h> | ||
10 | #include <sys/mman.h> | ||
11 | #include "kern_util.h" | ||
12 | #include "user.h" | ||
13 | #include "user_util.h" | ||
14 | #include "mem_user.h" | ||
15 | #include "init.h" | ||
16 | #include "os.h" | ||
17 | #include "tempfile.h" | ||
18 | #include "kern_constants.h" | ||
19 | |||
20 | #include <sys/param.h> | ||
21 | |||
22 | static char *tempdir = NULL; | ||
23 | |||
24 | static void __init find_tempdir(void) | ||
25 | { | ||
26 | char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; | ||
27 | int i; | ||
28 | char *dir = NULL; | ||
29 | |||
30 | if(tempdir != NULL) return; /* We've already been called */ | ||
31 | for(i = 0; dirs[i]; i++){ | ||
32 | dir = getenv(dirs[i]); | ||
33 | if((dir != NULL) && (*dir != '\0')) | ||
34 | break; | ||
35 | } | ||
36 | if((dir == NULL) || (*dir == '\0')) | ||
37 | dir = "/tmp"; | ||
38 | |||
39 | tempdir = malloc(strlen(dir) + 2); | ||
40 | if(tempdir == NULL){ | ||
41 | fprintf(stderr, "Failed to malloc tempdir, " | ||
42 | "errno = %d\n", errno); | ||
43 | return; | ||
44 | } | ||
45 | strcpy(tempdir, dir); | ||
46 | strcat(tempdir, "/"); | ||
47 | } | ||
48 | |||
49 | /* | ||
50 | * This proc still used in tt-mode | ||
51 | * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger). | ||
52 | * So it isn't 'static' yet. | ||
53 | */ | ||
54 | int make_tempfile(const char *template, char **out_tempname, int do_unlink) | ||
55 | { | ||
56 | char tempname[MAXPATHLEN]; | ||
57 | int fd; | ||
58 | |||
59 | find_tempdir(); | ||
60 | if (*template != '/') | ||
61 | strcpy(tempname, tempdir); | ||
62 | else | ||
63 | *tempname = 0; | ||
64 | strcat(tempname, template); | ||
65 | fd = mkstemp(tempname); | ||
66 | if(fd < 0){ | ||
67 | fprintf(stderr, "open - cannot create %s: %s\n", tempname, | ||
68 | strerror(errno)); | ||
69 | return -1; | ||
70 | } | ||
71 | if(do_unlink && (unlink(tempname) < 0)){ | ||
72 | perror("unlink"); | ||
73 | return -1; | ||
74 | } | ||
75 | if(out_tempname){ | ||
76 | *out_tempname = strdup(tempname); | ||
77 | if(*out_tempname == NULL){ | ||
78 | perror("strdup"); | ||
79 | return -1; | ||
80 | } | ||
81 | } | ||
82 | return(fd); | ||
83 | } | ||
84 | |||
85 | #define TEMPNAME_TEMPLATE "vm_file-XXXXXX" | ||
86 | |||
87 | /* | ||
88 | * This proc is used in start_up.c | ||
89 | * So it isn't 'static'. | ||
90 | */ | ||
91 | int create_tmp_file(unsigned long len) | ||
92 | { | ||
93 | int fd, err; | ||
94 | char zero; | ||
95 | |||
96 | fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); | ||
97 | if(fd < 0) { | ||
98 | exit(1); | ||
99 | } | ||
100 | |||
101 | err = fchmod(fd, 0777); | ||
102 | if(err < 0){ | ||
103 | perror("os_mode_fd"); | ||
104 | exit(1); | ||
105 | } | ||
106 | |||
107 | if (lseek64(fd, len, SEEK_SET) < 0) { | ||
108 | perror("os_seek_file"); | ||
109 | exit(1); | ||
110 | } | ||
111 | |||
112 | zero = 0; | ||
113 | |||
114 | err = os_write_file(fd, &zero, 1); | ||
115 | if(err != 1){ | ||
116 | errno = -err; | ||
117 | perror("os_write_file"); | ||
118 | exit(1); | ||
119 | } | ||
120 | |||
121 | return(fd); | ||
122 | } | ||
123 | |||
124 | static int create_anon_file(unsigned long len) | ||
125 | { | ||
126 | void *addr; | ||
127 | int fd; | ||
128 | |||
129 | fd = open("/dev/anon", O_RDWR); | ||
130 | if(fd < 0) { | ||
131 | perror("opening /dev/anon"); | ||
132 | exit(1); | ||
133 | } | ||
134 | |||
135 | addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); | ||
136 | if(addr == MAP_FAILED){ | ||
137 | perror("mapping physmem file"); | ||
138 | exit(1); | ||
139 | } | ||
140 | munmap(addr, len); | ||
141 | |||
142 | return(fd); | ||
143 | } | ||
144 | |||
145 | extern int have_devanon; | ||
146 | |||
147 | int create_mem_file(unsigned long len) | ||
148 | { | ||
149 | int err, fd; | ||
150 | |||
151 | if(have_devanon) | ||
152 | fd = create_anon_file(len); | ||
153 | else fd = create_tmp_file(len); | ||
154 | |||
155 | err = os_set_exec_close(fd, 1); | ||
156 | if(err < 0){ | ||
157 | errno = -err; | ||
158 | perror("exec_close"); | ||
159 | } | ||
160 | return(fd); | ||
161 | } | ||
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index d32413e4b4ce..d9c52387c4a1 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <unistd.h> | ||
6 | #include <stdio.h> | 7 | #include <stdio.h> |
7 | #include <errno.h> | 8 | #include <errno.h> |
8 | #include <signal.h> | 9 | #include <signal.h> |
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 040cc1472bc7..6af83171ca4e 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c | |||
@@ -4,18 +4,22 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <stdio.h> | 6 | #include <stdio.h> |
7 | #include <stddef.h> | ||
8 | #include <stdarg.h> | ||
9 | #include <stdlib.h> | ||
10 | #include <string.h> | ||
7 | #include <unistd.h> | 11 | #include <unistd.h> |
8 | #include <signal.h> | 12 | #include <signal.h> |
9 | #include <sched.h> | 13 | #include <sched.h> |
14 | #include <fcntl.h> | ||
10 | #include <errno.h> | 15 | #include <errno.h> |
11 | #include <stdarg.h> | ||
12 | #include <stdlib.h> | ||
13 | #include <setjmp.h> | 16 | #include <setjmp.h> |
14 | #include <sys/time.h> | 17 | #include <sys/time.h> |
15 | #include <sys/wait.h> | 18 | #include <sys/wait.h> |
16 | #include <sys/mman.h> | 19 | #include <sys/mman.h> |
17 | #include <asm/unistd.h> | 20 | #include <asm/unistd.h> |
18 | #include <asm/page.h> | 21 | #include <asm/page.h> |
22 | #include <sys/types.h> | ||
19 | #include "user_util.h" | 23 | #include "user_util.h" |
20 | #include "kern_util.h" | 24 | #include "kern_util.h" |
21 | #include "user.h" | 25 | #include "user.h" |
@@ -25,6 +29,7 @@ | |||
25 | #include "sysdep/sigcontext.h" | 29 | #include "sysdep/sigcontext.h" |
26 | #include "irq_user.h" | 30 | #include "irq_user.h" |
27 | #include "ptrace_user.h" | 31 | #include "ptrace_user.h" |
32 | #include "mem_user.h" | ||
28 | #include "time_user.h" | 33 | #include "time_user.h" |
29 | #include "init.h" | 34 | #include "init.h" |
30 | #include "os.h" | 35 | #include "os.h" |
@@ -32,6 +37,8 @@ | |||
32 | #include "choose-mode.h" | 37 | #include "choose-mode.h" |
33 | #include "mode.h" | 38 | #include "mode.h" |
34 | #include "tempfile.h" | 39 | #include "tempfile.h" |
40 | #include "kern_constants.h" | ||
41 | |||
35 | #ifdef UML_CONFIG_MODE_SKAS | 42 | #ifdef UML_CONFIG_MODE_SKAS |
36 | #include "skas.h" | 43 | #include "skas.h" |
37 | #include "skas_ptrace.h" | 44 | #include "skas_ptrace.h" |
@@ -276,9 +283,38 @@ static void __init check_ptrace(void) | |||
276 | check_sysemu(); | 283 | check_sysemu(); |
277 | } | 284 | } |
278 | 285 | ||
286 | extern int create_tmp_file(unsigned long len); | ||
287 | |||
288 | static void check_tmpexec(void) | ||
289 | { | ||
290 | void *addr; | ||
291 | int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE); | ||
292 | |||
293 | addr = mmap(NULL, UM_KERN_PAGE_SIZE, | ||
294 | PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); | ||
295 | printf("Checking PROT_EXEC mmap in /tmp..."); | ||
296 | fflush(stdout); | ||
297 | if(addr == MAP_FAILED){ | ||
298 | err = errno; | ||
299 | perror("failed"); | ||
300 | if(err == EPERM) | ||
301 | printf("/tmp must be not mounted noexec\n"); | ||
302 | exit(1); | ||
303 | } | ||
304 | printf("OK\n"); | ||
305 | munmap(addr, UM_KERN_PAGE_SIZE); | ||
306 | |||
307 | close(fd); | ||
308 | } | ||
309 | |||
279 | void os_early_checks(void) | 310 | void os_early_checks(void) |
280 | { | 311 | { |
281 | check_ptrace(); | 312 | check_ptrace(); |
313 | |||
314 | /* Need to check this early because mmapping happens before the | ||
315 | * kernel is running. | ||
316 | */ | ||
317 | check_tmpexec(); | ||
282 | } | 318 | } |
283 | 319 | ||
284 | static int __init noprocmm_cmd_param(char *str, int* add) | 320 | static int __init noprocmm_cmd_param(char *str, int* add) |
@@ -357,3 +393,72 @@ int can_do_skas(void) | |||
357 | return(0); | 393 | return(0); |
358 | } | 394 | } |
359 | #endif | 395 | #endif |
396 | |||
397 | int have_devanon = 0; | ||
398 | |||
399 | void check_devanon(void) | ||
400 | { | ||
401 | int fd; | ||
402 | |||
403 | printk("Checking for /dev/anon on the host..."); | ||
404 | fd = open("/dev/anon", O_RDWR); | ||
405 | if(fd < 0){ | ||
406 | printk("Not available (open failed with errno %d)\n", errno); | ||
407 | return; | ||
408 | } | ||
409 | |||
410 | printk("OK\n"); | ||
411 | have_devanon = 1; | ||
412 | } | ||
413 | |||
414 | int __init parse_iomem(char *str, int *add) | ||
415 | { | ||
416 | struct iomem_region *new; | ||
417 | struct uml_stat buf; | ||
418 | char *file, *driver; | ||
419 | int fd, err, size; | ||
420 | |||
421 | driver = str; | ||
422 | file = strchr(str,','); | ||
423 | if(file == NULL){ | ||
424 | printf("parse_iomem : failed to parse iomem\n"); | ||
425 | goto out; | ||
426 | } | ||
427 | *file = '\0'; | ||
428 | file++; | ||
429 | fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0); | ||
430 | if(fd < 0){ | ||
431 | os_print_error(fd, "parse_iomem - Couldn't open io file"); | ||
432 | goto out; | ||
433 | } | ||
434 | |||
435 | err = os_stat_fd(fd, &buf); | ||
436 | if(err < 0){ | ||
437 | os_print_error(err, "parse_iomem - cannot stat_fd file"); | ||
438 | goto out_close; | ||
439 | } | ||
440 | |||
441 | new = malloc(sizeof(*new)); | ||
442 | if(new == NULL){ | ||
443 | perror("Couldn't allocate iomem_region struct"); | ||
444 | goto out_close; | ||
445 | } | ||
446 | |||
447 | size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1); | ||
448 | |||
449 | *new = ((struct iomem_region) { .next = iomem_regions, | ||
450 | .driver = driver, | ||
451 | .fd = fd, | ||
452 | .size = size, | ||
453 | .phys = 0, | ||
454 | .virt = 0 }); | ||
455 | iomem_regions = new; | ||
456 | iomem_size += new->size + UM_KERN_PAGE_SIZE; | ||
457 | |||
458 | return(0); | ||
459 | out_close: | ||
460 | os_close_file(fd); | ||
461 | out: | ||
462 | return(1); | ||
463 | } | ||
464 | |||
diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c index 5b047ab8416a..a6db8877931a 100644 --- a/arch/um/os-Linux/tt.c +++ b/arch/um/os-Linux/tt.c | |||
@@ -36,6 +36,20 @@ | |||
36 | #include "mode.h" | 36 | #include "mode.h" |
37 | #include "tempfile.h" | 37 | #include "tempfile.h" |
38 | 38 | ||
39 | int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, | ||
40 | int must_succeed) | ||
41 | { | ||
42 | int err; | ||
43 | |||
44 | err = os_protect_memory((void *) addr, len, r, w, x); | ||
45 | if(err < 0){ | ||
46 | if(must_succeed) | ||
47 | panic("protect failed, err = %d", -err); | ||
48 | else return(err); | ||
49 | } | ||
50 | return(0); | ||
51 | } | ||
52 | |||
39 | /* | 53 | /* |
40 | *------------------------- | 54 | *------------------------- |
41 | * only for tt mode (will be deleted in future...) | 55 | * only for tt mode (will be deleted in future...) |
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index bd3c34aa52e5..36b5c2c13289 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c | |||
@@ -83,6 +83,7 @@ int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) | |||
83 | goto out; | 83 | goto out; |
84 | } | 84 | } |
85 | p = buf; | 85 | p = buf; |
86 | break; | ||
86 | default: | 87 | default: |
87 | res = -ENOSYS; | 88 | res = -ENOSYS; |
88 | goto out; | 89 | goto out; |
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index e63323e03ea9..21afa69a086d 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig | |||
@@ -277,11 +277,6 @@ source "mm/Kconfig" | |||
277 | config HAVE_ARCH_EARLY_PFN_TO_NID | 277 | config HAVE_ARCH_EARLY_PFN_TO_NID |
278 | def_bool y | 278 | def_bool y |
279 | 279 | ||
280 | config HAVE_DEC_LOCK | ||
281 | bool | ||
282 | depends on SMP | ||
283 | default y | ||
284 | |||
285 | config NR_CPUS | 280 | config NR_CPUS |
286 | int "Maximum number of CPUs (2-256)" | 281 | int "Maximum number of CPUs (2-256)" |
287 | range 2 256 | 282 | range 2 256 |
@@ -313,7 +308,7 @@ config HPET_TIMER | |||
313 | present. The HPET provides a stable time base on SMP | 308 | present. The HPET provides a stable time base on SMP |
314 | systems, unlike the TSC, but it is more expensive to access, | 309 | systems, unlike the TSC, but it is more expensive to access, |
315 | as it is off-chip. You can find the HPET spec at | 310 | as it is off-chip. You can find the HPET spec at |
316 | <http://www.intel.com/labs/platcomp/hpet/hpetspec.htm>. | 311 | <http://www.intel.com/hardwaredesign/hpetspec.htm>. |
317 | 312 | ||
318 | config X86_PM_TIMER | 313 | config X86_PM_TIMER |
319 | bool "PM timer" | 314 | bool "PM timer" |
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index c8131f342cfc..d9161e395978 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c | |||
@@ -353,11 +353,6 @@ int setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int exec | |||
353 | mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); | 353 | mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); |
354 | if (!mpnt) | 354 | if (!mpnt) |
355 | return -ENOMEM; | 355 | return -ENOMEM; |
356 | |||
357 | if (security_vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) { | ||
358 | kmem_cache_free(vm_area_cachep, mpnt); | ||
359 | return -ENOMEM; | ||
360 | } | ||
361 | 356 | ||
362 | memset(mpnt, 0, sizeof(*mpnt)); | 357 | memset(mpnt, 0, sizeof(*mpnt)); |
363 | 358 | ||
diff --git a/arch/x86_64/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c index adbc5f8089e9..3a01329473ab 100644 --- a/arch/x86_64/ia32/syscall32.c +++ b/arch/x86_64/ia32/syscall32.c | |||
@@ -52,17 +52,13 @@ int syscall32_setup_pages(struct linux_binprm *bprm, int exstack) | |||
52 | vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); | 52 | vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); |
53 | if (!vma) | 53 | if (!vma) |
54 | return -ENOMEM; | 54 | return -ENOMEM; |
55 | if (security_vm_enough_memory(npages)) { | ||
56 | kmem_cache_free(vm_area_cachep, vma); | ||
57 | return -ENOMEM; | ||
58 | } | ||
59 | 55 | ||
60 | memset(vma, 0, sizeof(struct vm_area_struct)); | 56 | memset(vma, 0, sizeof(struct vm_area_struct)); |
61 | /* Could randomize here */ | 57 | /* Could randomize here */ |
62 | vma->vm_start = VSYSCALL32_BASE; | 58 | vma->vm_start = VSYSCALL32_BASE; |
63 | vma->vm_end = VSYSCALL32_END; | 59 | vma->vm_end = VSYSCALL32_END; |
64 | /* MAYWRITE to allow gdb to COW and set breakpoints */ | 60 | /* MAYWRITE to allow gdb to COW and set breakpoints */ |
65 | vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYEXEC|VM_MAYWRITE; | 61 | vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE; |
66 | vma->vm_flags |= mm->def_flags; | 62 | vma->vm_flags |= mm->def_flags; |
67 | vma->vm_page_prot = protection_map[vma->vm_flags & 7]; | 63 | vma->vm_page_prot = protection_map[vma->vm_flags & 7]; |
68 | vma->vm_ops = &syscall32_vm_ops; | 64 | vma->vm_ops = &syscall32_vm_ops; |
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c index 4e34b0f9d613..ab3f87aaff70 100644 --- a/arch/x86_64/kernel/e820.c +++ b/arch/x86_64/kernel/e820.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/ioport.h> | 17 | #include <linux/ioport.h> |
18 | #include <linux/string.h> | 18 | #include <linux/string.h> |
19 | #include <linux/kexec.h> | 19 | #include <linux/kexec.h> |
20 | #include <linux/module.h> | ||
21 | |||
20 | #include <asm/page.h> | 22 | #include <asm/page.h> |
21 | #include <asm/e820.h> | 23 | #include <asm/e820.h> |
22 | #include <asm/proto.h> | 24 | #include <asm/proto.h> |
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 522944a000ad..c8eee20cd519 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c | |||
@@ -299,15 +299,6 @@ void __init check_ioapic(void) | |||
299 | #endif | 299 | #endif |
300 | /* RED-PEN skip them on mptables too? */ | 300 | /* RED-PEN skip them on mptables too? */ |
301 | return; | 301 | return; |
302 | case PCI_VENDOR_ID_ATI: | ||
303 | /* All timer interrupts on atiixp | ||
304 | are doubled. Disable one. */ | ||
305 | if (disable_timer_pin_1 == 0) { | ||
306 | disable_timer_pin_1 = 1; | ||
307 | printk(KERN_INFO | ||
308 | "ATI board detected. Disabling timer pin 1.\n"); | ||
309 | } | ||
310 | return; | ||
311 | } | 302 | } |
312 | 303 | ||
313 | /* No multi-function device? */ | 304 | /* No multi-function device? */ |
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 351d8d64c2fb..238f73e1a834 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c | |||
@@ -831,11 +831,26 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c) | |||
831 | #endif | 831 | #endif |
832 | } | 832 | } |
833 | 833 | ||
834 | #define HWCR 0xc0010015 | ||
835 | |||
834 | static int __init init_amd(struct cpuinfo_x86 *c) | 836 | static int __init init_amd(struct cpuinfo_x86 *c) |
835 | { | 837 | { |
836 | int r; | 838 | int r; |
837 | int level; | 839 | int level; |
838 | 840 | ||
841 | #ifdef CONFIG_SMP | ||
842 | unsigned long value; | ||
843 | |||
844 | // Disable TLB flush filter by setting HWCR.FFDIS: | ||
845 | // bit 6 of msr C001_0015 | ||
846 | // | ||
847 | // Errata 63 for SH-B3 steppings | ||
848 | // Errata 122 for all(?) steppings | ||
849 | rdmsrl(HWCR, value); | ||
850 | value |= 1 << 6; | ||
851 | wrmsrl(HWCR, value); | ||
852 | #endif | ||
853 | |||
839 | /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; | 854 | /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; |
840 | 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ | 855 | 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ |
841 | clear_bit(0*32+31, &c->x86_capability); | 856 | clear_bit(0*32+31, &c->x86_capability); |
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c index 68ec03070e5a..fd99ddd009bc 100644 --- a/arch/x86_64/kernel/x8664_ksyms.c +++ b/arch/x86_64/kernel/x8664_ksyms.c | |||
@@ -178,10 +178,6 @@ EXPORT_SYMBOL(rwsem_down_write_failed_thunk); | |||
178 | 178 | ||
179 | EXPORT_SYMBOL(empty_zero_page); | 179 | EXPORT_SYMBOL(empty_zero_page); |
180 | 180 | ||
181 | #ifdef CONFIG_HAVE_DEC_LOCK | ||
182 | EXPORT_SYMBOL(_atomic_dec_and_lock); | ||
183 | #endif | ||
184 | |||
185 | EXPORT_SYMBOL(die_chain); | 181 | EXPORT_SYMBOL(die_chain); |
186 | EXPORT_SYMBOL(register_die_notifier); | 182 | EXPORT_SYMBOL(register_die_notifier); |
187 | 183 | ||
diff --git a/arch/x86_64/lib/Makefile b/arch/x86_64/lib/Makefile index 6b26a1c1e9ff..bba5db6cebd6 100644 --- a/arch/x86_64/lib/Makefile +++ b/arch/x86_64/lib/Makefile | |||
@@ -10,5 +10,3 @@ lib-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \ | |||
10 | usercopy.o getuser.o putuser.o \ | 10 | usercopy.o getuser.o putuser.o \ |
11 | thunk.o clear_page.o copy_page.o bitstr.o bitops.o | 11 | thunk.o clear_page.o copy_page.o bitstr.o bitops.o |
12 | lib-y += memcpy.o memmove.o memset.o copy_user.o | 12 | lib-y += memcpy.o memmove.o memset.o copy_user.o |
13 | |||
14 | lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o | ||
diff --git a/arch/x86_64/lib/dec_and_lock.c b/arch/x86_64/lib/dec_and_lock.c deleted file mode 100644 index ab43394dc775..000000000000 --- a/arch/x86_64/lib/dec_and_lock.c +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /* | ||
2 | * x86 version of "atomic_dec_and_lock()" using | ||
3 | * the atomic "cmpxchg" instruction. | ||
4 | * | ||
5 | * (For CPU's lacking cmpxchg, we use the slow | ||
6 | * generic version, and this one never even gets | ||
7 | * compiled). | ||
8 | */ | ||
9 | |||
10 | #include <linux/spinlock.h> | ||
11 | #include <asm/atomic.h> | ||
12 | |||
13 | int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) | ||
14 | { | ||
15 | int counter; | ||
16 | int newcount; | ||
17 | |||
18 | repeat: | ||
19 | counter = atomic_read(atomic); | ||
20 | newcount = counter-1; | ||
21 | |||
22 | if (!newcount) | ||
23 | goto slow_path; | ||
24 | |||
25 | asm volatile("lock; cmpxchgl %1,%2" | ||
26 | :"=a" (newcount) | ||
27 | :"r" (newcount), "m" (atomic->counter), "0" (counter)); | ||
28 | |||
29 | /* If the above failed, "eax" will have changed */ | ||
30 | if (newcount != counter) | ||
31 | goto repeat; | ||
32 | return 0; | ||
33 | |||
34 | slow_path: | ||
35 | spin_lock(lock); | ||
36 | if (atomic_dec_and_test(atomic)) | ||
37 | return 1; | ||
38 | spin_unlock(lock); | ||
39 | return 0; | ||
40 | } | ||
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 2b6257bec4c3..7e841aa2a4aa 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig | |||
@@ -26,10 +26,6 @@ config RWSEM_XCHGADD_ALGORITHM | |||
26 | bool | 26 | bool |
27 | default y | 27 | default y |
28 | 28 | ||
29 | config HAVE_DEC_LOCK | ||
30 | bool | ||
31 | default y | ||
32 | |||
33 | config GENERIC_HARDIRQS | 29 | config GENERIC_HARDIRQS |
34 | bool | 30 | bool |
35 | default y | 31 | default y |
diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c index 141b4c237a50..2b850e5860a0 100644 --- a/drivers/acorn/char/pcf8583.c +++ b/drivers/acorn/char/pcf8583.c | |||
@@ -23,12 +23,13 @@ static struct i2c_driver pcf8583_driver; | |||
23 | 23 | ||
24 | static unsigned short ignore[] = { I2C_CLIENT_END }; | 24 | static unsigned short ignore[] = { I2C_CLIENT_END }; |
25 | static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END }; | 25 | static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END }; |
26 | static unsigned short *forces[] = { NULL }; | ||
26 | 27 | ||
27 | static struct i2c_client_address_data addr_data = { | 28 | static struct i2c_client_address_data addr_data = { |
28 | .normal_i2c = normal_addr, | 29 | .normal_i2c = normal_addr, |
29 | .probe = ignore, | 30 | .probe = ignore, |
30 | .ignore = ignore, | 31 | .ignore = ignore, |
31 | .force = ignore, | 32 | .forces = forces, |
32 | }; | 33 | }; |
33 | 34 | ||
34 | #define DAT(x) ((unsigned int)(x->dev.driver_data)) | 35 | #define DAT(x) ((unsigned int)(x->dev.driver_data)) |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index c56f995aadad..486b6e1c7dfb 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -483,9 +483,6 @@ static int cciss_open(struct inode *inode, struct file *filep) | |||
483 | printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name); | 483 | printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name); |
484 | #endif /* CCISS_DEBUG */ | 484 | #endif /* CCISS_DEBUG */ |
485 | 485 | ||
486 | if (host->busy_initializing) | ||
487 | return -EBUSY; | ||
488 | |||
489 | if (host->busy_initializing || drv->busy_configuring) | 486 | if (host->busy_initializing || drv->busy_configuring) |
490 | return -EBUSY; | 487 | return -EBUSY; |
491 | /* | 488 | /* |
@@ -2991,6 +2988,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
2991 | hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); | 2988 | hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); |
2992 | 2989 | ||
2993 | cciss_procinit(i); | 2990 | cciss_procinit(i); |
2991 | hba[i]->busy_initializing = 0; | ||
2994 | 2992 | ||
2995 | for(j=0; j < NWD; j++) { /* mfm */ | 2993 | for(j=0; j < NWD; j++) { /* mfm */ |
2996 | drive_info_struct *drv = &(hba[i]->drv[j]); | 2994 | drive_info_struct *drv = &(hba[i]->drv[j]); |
@@ -3033,7 +3031,6 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3033 | add_disk(disk); | 3031 | add_disk(disk); |
3034 | } | 3032 | } |
3035 | 3033 | ||
3036 | hba[i]->busy_initializing = 0; | ||
3037 | return(1); | 3034 | return(1); |
3038 | 3035 | ||
3039 | clean4: | 3036 | clean4: |
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 483d71b10cf9..baedac522945 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c | |||
@@ -2373,44 +2373,6 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector) | |||
2373 | 2373 | ||
2374 | EXPORT_SYMBOL(blkdev_issue_flush); | 2374 | EXPORT_SYMBOL(blkdev_issue_flush); |
2375 | 2375 | ||
2376 | /** | ||
2377 | * blkdev_scsi_issue_flush_fn - issue flush for SCSI devices | ||
2378 | * @q: device queue | ||
2379 | * @disk: gendisk | ||
2380 | * @error_sector: error offset | ||
2381 | * | ||
2382 | * Description: | ||
2383 | * Devices understanding the SCSI command set, can use this function as | ||
2384 | * a helper for issuing a cache flush. Note: driver is required to store | ||
2385 | * the error offset (in case of error flushing) in ->sector of struct | ||
2386 | * request. | ||
2387 | */ | ||
2388 | int blkdev_scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, | ||
2389 | sector_t *error_sector) | ||
2390 | { | ||
2391 | struct request *rq = blk_get_request(q, WRITE, __GFP_WAIT); | ||
2392 | int ret; | ||
2393 | |||
2394 | rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER; | ||
2395 | rq->sector = 0; | ||
2396 | memset(rq->cmd, 0, sizeof(rq->cmd)); | ||
2397 | rq->cmd[0] = 0x35; | ||
2398 | rq->cmd_len = 12; | ||
2399 | rq->data = NULL; | ||
2400 | rq->data_len = 0; | ||
2401 | rq->timeout = 60 * HZ; | ||
2402 | |||
2403 | ret = blk_execute_rq(q, disk, rq, 0); | ||
2404 | |||
2405 | if (ret && error_sector) | ||
2406 | *error_sector = rq->sector; | ||
2407 | |||
2408 | blk_put_request(rq); | ||
2409 | return ret; | ||
2410 | } | ||
2411 | |||
2412 | EXPORT_SYMBOL(blkdev_scsi_issue_flush_fn); | ||
2413 | |||
2414 | static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) | 2376 | static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io) |
2415 | { | 2377 | { |
2416 | int rw = rq_data_dir(rq); | 2378 | int rw = rq_data_dir(rq); |
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index 711d2f314ac3..94af920465b5 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c | |||
@@ -750,6 +750,14 @@ static int pf_ready(void) | |||
750 | 750 | ||
751 | static struct request_queue *pf_queue; | 751 | static struct request_queue *pf_queue; |
752 | 752 | ||
753 | static void pf_end_request(int uptodate) | ||
754 | { | ||
755 | if (pf_req) { | ||
756 | end_request(pf_req, uptodate); | ||
757 | pf_req = NULL; | ||
758 | } | ||
759 | } | ||
760 | |||
753 | static void do_pf_request(request_queue_t * q) | 761 | static void do_pf_request(request_queue_t * q) |
754 | { | 762 | { |
755 | if (pf_busy) | 763 | if (pf_busy) |
@@ -765,7 +773,7 @@ repeat: | |||
765 | pf_count = pf_req->current_nr_sectors; | 773 | pf_count = pf_req->current_nr_sectors; |
766 | 774 | ||
767 | if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) { | 775 | if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) { |
768 | end_request(pf_req, 0); | 776 | pf_end_request(0); |
769 | goto repeat; | 777 | goto repeat; |
770 | } | 778 | } |
771 | 779 | ||
@@ -780,7 +788,7 @@ repeat: | |||
780 | pi_do_claimed(pf_current->pi, do_pf_write); | 788 | pi_do_claimed(pf_current->pi, do_pf_write); |
781 | else { | 789 | else { |
782 | pf_busy = 0; | 790 | pf_busy = 0; |
783 | end_request(pf_req, 0); | 791 | pf_end_request(0); |
784 | goto repeat; | 792 | goto repeat; |
785 | } | 793 | } |
786 | } | 794 | } |
@@ -798,9 +806,11 @@ static int pf_next_buf(void) | |||
798 | if (!pf_count) | 806 | if (!pf_count) |
799 | return 1; | 807 | return 1; |
800 | spin_lock_irqsave(&pf_spin_lock, saved_flags); | 808 | spin_lock_irqsave(&pf_spin_lock, saved_flags); |
801 | end_request(pf_req, 1); | 809 | pf_end_request(1); |
802 | pf_count = pf_req->current_nr_sectors; | 810 | if (pf_req) { |
803 | pf_buf = pf_req->buffer; | 811 | pf_count = pf_req->current_nr_sectors; |
812 | pf_buf = pf_req->buffer; | ||
813 | } | ||
804 | spin_unlock_irqrestore(&pf_spin_lock, saved_flags); | 814 | spin_unlock_irqrestore(&pf_spin_lock, saved_flags); |
805 | return 1; | 815 | return 1; |
806 | } | 816 | } |
@@ -810,7 +820,7 @@ static inline void next_request(int success) | |||
810 | unsigned long saved_flags; | 820 | unsigned long saved_flags; |
811 | 821 | ||
812 | spin_lock_irqsave(&pf_spin_lock, saved_flags); | 822 | spin_lock_irqsave(&pf_spin_lock, saved_flags); |
813 | end_request(pf_req, success); | 823 | pf_end_request(success); |
814 | pf_busy = 0; | 824 | pf_busy = 0; |
815 | do_pf_request(pf_queue); | 825 | do_pf_request(pf_queue); |
816 | spin_unlock_irqrestore(&pf_spin_lock, saved_flags); | 826 | spin_unlock_irqrestore(&pf_spin_lock, saved_flags); |
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index 856c2278e9d0..079ec344eb47 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c | |||
@@ -168,6 +168,7 @@ static int verify_command(struct file *file, unsigned char *cmd) | |||
168 | safe_for_write(WRITE_VERIFY_12), | 168 | safe_for_write(WRITE_VERIFY_12), |
169 | safe_for_write(WRITE_16), | 169 | safe_for_write(WRITE_16), |
170 | safe_for_write(WRITE_LONG), | 170 | safe_for_write(WRITE_LONG), |
171 | safe_for_write(WRITE_LONG_2), | ||
171 | safe_for_write(ERASE), | 172 | safe_for_write(ERASE), |
172 | safe_for_write(GPCMD_MODE_SELECT_10), | 173 | safe_for_write(GPCMD_MODE_SELECT_10), |
173 | safe_for_write(MODE_SELECT), | 174 | safe_for_write(MODE_SELECT), |
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 99762b6c19ae..de5d6d212674 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c | |||
@@ -252,7 +252,7 @@ hp_zx1_configure (void) | |||
252 | readl(hp->ioc_regs+HP_ZX1_PDIR_BASE); | 252 | readl(hp->ioc_regs+HP_ZX1_PDIR_BASE); |
253 | writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG); | 253 | writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG); |
254 | readl(hp->ioc_regs+HP_ZX1_TCNFG); | 254 | readl(hp->ioc_regs+HP_ZX1_TCNFG); |
255 | writel(~(HP_ZX1_IOVA_SIZE-1), hp->ioc_regs+HP_ZX1_IMASK); | 255 | writel((unsigned int)(~(HP_ZX1_IOVA_SIZE-1)), hp->ioc_regs+HP_ZX1_IMASK); |
256 | readl(hp->ioc_regs+HP_ZX1_IMASK); | 256 | readl(hp->ioc_regs+HP_ZX1_IMASK); |
257 | writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE); | 257 | writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE); |
258 | readl(hp->ioc_regs+HP_ZX1_IBASE); | 258 | readl(hp->ioc_regs+HP_ZX1_IBASE); |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 58d3738a2b7f..407708a001e4 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -534,7 +534,7 @@ static void shutdown(struct channel *ch) | |||
534 | 534 | ||
535 | unsigned long flags; | 535 | unsigned long flags; |
536 | struct tty_struct *tty; | 536 | struct tty_struct *tty; |
537 | struct board_chan *bc; | 537 | struct board_chan __iomem *bc; |
538 | 538 | ||
539 | if (!(ch->asyncflags & ASYNC_INITIALIZED)) | 539 | if (!(ch->asyncflags & ASYNC_INITIALIZED)) |
540 | return; | 540 | return; |
@@ -618,7 +618,7 @@ static int pc_write(struct tty_struct * tty, | |||
618 | struct channel *ch; | 618 | struct channel *ch; |
619 | unsigned long flags; | 619 | unsigned long flags; |
620 | int remain; | 620 | int remain; |
621 | struct board_chan *bc; | 621 | struct board_chan __iomem *bc; |
622 | 622 | ||
623 | /* ---------------------------------------------------------------- | 623 | /* ---------------------------------------------------------------- |
624 | pc_write is primarily called directly by the kernel routine | 624 | pc_write is primarily called directly by the kernel routine |
@@ -685,7 +685,7 @@ static int pc_write(struct tty_struct * tty, | |||
685 | ------------------------------------------------------------------- */ | 685 | ------------------------------------------------------------------- */ |
686 | 686 | ||
687 | dataLen = min(bytesAvailable, dataLen); | 687 | dataLen = min(bytesAvailable, dataLen); |
688 | memcpy(ch->txptr + head, buf, dataLen); | 688 | memcpy_toio(ch->txptr + head, buf, dataLen); |
689 | buf += dataLen; | 689 | buf += dataLen; |
690 | head += dataLen; | 690 | head += dataLen; |
691 | amountCopied += dataLen; | 691 | amountCopied += dataLen; |
@@ -726,7 +726,7 @@ static int pc_write_room(struct tty_struct *tty) | |||
726 | struct channel *ch; | 726 | struct channel *ch; |
727 | unsigned long flags; | 727 | unsigned long flags; |
728 | unsigned int head, tail; | 728 | unsigned int head, tail; |
729 | struct board_chan *bc; | 729 | struct board_chan __iomem *bc; |
730 | 730 | ||
731 | remain = 0; | 731 | remain = 0; |
732 | 732 | ||
@@ -773,7 +773,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty) | |||
773 | int remain; | 773 | int remain; |
774 | unsigned long flags; | 774 | unsigned long flags; |
775 | struct channel *ch; | 775 | struct channel *ch; |
776 | struct board_chan *bc; | 776 | struct board_chan __iomem *bc; |
777 | 777 | ||
778 | /* --------------------------------------------------------- | 778 | /* --------------------------------------------------------- |
779 | verifyChannel returns the channel from the tty struct | 779 | verifyChannel returns the channel from the tty struct |
@@ -830,7 +830,7 @@ static void pc_flush_buffer(struct tty_struct *tty) | |||
830 | unsigned int tail; | 830 | unsigned int tail; |
831 | unsigned long flags; | 831 | unsigned long flags; |
832 | struct channel *ch; | 832 | struct channel *ch; |
833 | struct board_chan *bc; | 833 | struct board_chan __iomem *bc; |
834 | /* --------------------------------------------------------- | 834 | /* --------------------------------------------------------- |
835 | verifyChannel returns the channel from the tty struct | 835 | verifyChannel returns the channel from the tty struct |
836 | if it is valid. This serves as a sanity check. | 836 | if it is valid. This serves as a sanity check. |
@@ -976,7 +976,7 @@ static int pc_open(struct tty_struct *tty, struct file * filp) | |||
976 | struct channel *ch; | 976 | struct channel *ch; |
977 | unsigned long flags; | 977 | unsigned long flags; |
978 | int line, retval, boardnum; | 978 | int line, retval, boardnum; |
979 | struct board_chan *bc; | 979 | struct board_chan __iomem *bc; |
980 | unsigned int head; | 980 | unsigned int head; |
981 | 981 | ||
982 | line = tty->index; | 982 | line = tty->index; |
@@ -1041,7 +1041,7 @@ static int pc_open(struct tty_struct *tty, struct file * filp) | |||
1041 | ch->statusflags = 0; | 1041 | ch->statusflags = 0; |
1042 | 1042 | ||
1043 | /* Save boards current modem status */ | 1043 | /* Save boards current modem status */ |
1044 | ch->imodem = bc->mstat; | 1044 | ch->imodem = readb(&bc->mstat); |
1045 | 1045 | ||
1046 | /* ---------------------------------------------------------------- | 1046 | /* ---------------------------------------------------------------- |
1047 | Set receive head and tail ptrs to each other. This indicates | 1047 | Set receive head and tail ptrs to each other. This indicates |
@@ -1399,10 +1399,10 @@ static void post_fep_init(unsigned int crd) | |||
1399 | { /* Begin post_fep_init */ | 1399 | { /* Begin post_fep_init */ |
1400 | 1400 | ||
1401 | int i; | 1401 | int i; |
1402 | unsigned char *memaddr; | 1402 | void __iomem *memaddr; |
1403 | struct global_data *gd; | 1403 | struct global_data __iomem *gd; |
1404 | struct board_info *bd; | 1404 | struct board_info *bd; |
1405 | struct board_chan *bc; | 1405 | struct board_chan __iomem *bc; |
1406 | struct channel *ch; | 1406 | struct channel *ch; |
1407 | int shrinkmem = 0, lowwater ; | 1407 | int shrinkmem = 0, lowwater ; |
1408 | 1408 | ||
@@ -1461,7 +1461,7 @@ static void post_fep_init(unsigned int crd) | |||
1461 | 8 and 64 of these structures. | 1461 | 8 and 64 of these structures. |
1462 | -------------------------------------------------------------------- */ | 1462 | -------------------------------------------------------------------- */ |
1463 | 1463 | ||
1464 | bc = (struct board_chan *)(memaddr + CHANSTRUCT); | 1464 | bc = memaddr + CHANSTRUCT; |
1465 | 1465 | ||
1466 | /* ------------------------------------------------------------------- | 1466 | /* ------------------------------------------------------------------- |
1467 | The below assignment will set gd to point at the BEGINING of | 1467 | The below assignment will set gd to point at the BEGINING of |
@@ -1470,7 +1470,7 @@ static void post_fep_init(unsigned int crd) | |||
1470 | pointer begins at 0xd10. | 1470 | pointer begins at 0xd10. |
1471 | ---------------------------------------------------------------------- */ | 1471 | ---------------------------------------------------------------------- */ |
1472 | 1472 | ||
1473 | gd = (struct global_data *)(memaddr + GLOBAL); | 1473 | gd = memaddr + GLOBAL; |
1474 | 1474 | ||
1475 | /* -------------------------------------------------------------------- | 1475 | /* -------------------------------------------------------------------- |
1476 | XEPORTS (address 0xc22) points at the number of channels the | 1476 | XEPORTS (address 0xc22) points at the number of channels the |
@@ -1493,6 +1493,7 @@ static void post_fep_init(unsigned int crd) | |||
1493 | 1493 | ||
1494 | for (i = 0; i < bd->numports; i++, ch++, bc++) { /* Begin for each port */ | 1494 | for (i = 0; i < bd->numports; i++, ch++, bc++) { /* Begin for each port */ |
1495 | unsigned long flags; | 1495 | unsigned long flags; |
1496 | u16 tseg, rseg; | ||
1496 | 1497 | ||
1497 | ch->brdchan = bc; | 1498 | ch->brdchan = bc; |
1498 | ch->mailbox = gd; | 1499 | ch->mailbox = gd; |
@@ -1553,50 +1554,53 @@ static void post_fep_init(unsigned int crd) | |||
1553 | shrinkmem = 0; | 1554 | shrinkmem = 0; |
1554 | } | 1555 | } |
1555 | 1556 | ||
1557 | tseg = readw(&bc->tseg); | ||
1558 | rseg = readw(&bc->rseg); | ||
1559 | |||
1556 | switch (bd->type) { | 1560 | switch (bd->type) { |
1557 | 1561 | ||
1558 | case PCIXEM: | 1562 | case PCIXEM: |
1559 | case PCIXRJ: | 1563 | case PCIXRJ: |
1560 | case PCIXR: | 1564 | case PCIXR: |
1561 | /* Cover all the 2MEG cards */ | 1565 | /* Cover all the 2MEG cards */ |
1562 | ch->txptr = memaddr + (((bc->tseg) << 4) & 0x1fffff); | 1566 | ch->txptr = memaddr + ((tseg << 4) & 0x1fffff); |
1563 | ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x1fffff); | 1567 | ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff); |
1564 | ch->txwin = FEPWIN | ((bc->tseg) >> 11); | 1568 | ch->txwin = FEPWIN | (tseg >> 11); |
1565 | ch->rxwin = FEPWIN | ((bc->rseg) >> 11); | 1569 | ch->rxwin = FEPWIN | (rseg >> 11); |
1566 | break; | 1570 | break; |
1567 | 1571 | ||
1568 | case PCXEM: | 1572 | case PCXEM: |
1569 | case EISAXEM: | 1573 | case EISAXEM: |
1570 | /* Cover all the 32K windowed cards */ | 1574 | /* Cover all the 32K windowed cards */ |
1571 | /* Mask equal to window size - 1 */ | 1575 | /* Mask equal to window size - 1 */ |
1572 | ch->txptr = memaddr + (((bc->tseg) << 4) & 0x7fff); | 1576 | ch->txptr = memaddr + ((tseg << 4) & 0x7fff); |
1573 | ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x7fff); | 1577 | ch->rxptr = memaddr + ((rseg << 4) & 0x7fff); |
1574 | ch->txwin = FEPWIN | ((bc->tseg) >> 11); | 1578 | ch->txwin = FEPWIN | (tseg >> 11); |
1575 | ch->rxwin = FEPWIN | ((bc->rseg) >> 11); | 1579 | ch->rxwin = FEPWIN | (rseg >> 11); |
1576 | break; | 1580 | break; |
1577 | 1581 | ||
1578 | case PCXEVE: | 1582 | case PCXEVE: |
1579 | case PCXE: | 1583 | case PCXE: |
1580 | ch->txptr = memaddr + (((bc->tseg - bd->memory_seg) << 4) & 0x1fff); | 1584 | ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff); |
1581 | ch->txwin = FEPWIN | ((bc->tseg - bd->memory_seg) >> 9); | 1585 | ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9); |
1582 | ch->rxptr = memaddr + (((bc->rseg - bd->memory_seg) << 4) & 0x1fff); | 1586 | ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff); |
1583 | ch->rxwin = FEPWIN | ((bc->rseg - bd->memory_seg) >>9 ); | 1587 | ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >>9 ); |
1584 | break; | 1588 | break; |
1585 | 1589 | ||
1586 | case PCXI: | 1590 | case PCXI: |
1587 | case PC64XE: | 1591 | case PC64XE: |
1588 | ch->txptr = memaddr + ((bc->tseg - bd->memory_seg) << 4); | 1592 | ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4); |
1589 | ch->rxptr = memaddr + ((bc->rseg - bd->memory_seg) << 4); | 1593 | ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4); |
1590 | ch->txwin = ch->rxwin = 0; | 1594 | ch->txwin = ch->rxwin = 0; |
1591 | break; | 1595 | break; |
1592 | 1596 | ||
1593 | } /* End switch bd->type */ | 1597 | } /* End switch bd->type */ |
1594 | 1598 | ||
1595 | ch->txbufhead = 0; | 1599 | ch->txbufhead = 0; |
1596 | ch->txbufsize = bc->tmax + 1; | 1600 | ch->txbufsize = readw(&bc->tmax) + 1; |
1597 | 1601 | ||
1598 | ch->rxbufhead = 0; | 1602 | ch->rxbufhead = 0; |
1599 | ch->rxbufsize = bc->rmax + 1; | 1603 | ch->rxbufsize = readw(&bc->rmax) + 1; |
1600 | 1604 | ||
1601 | lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2); | 1605 | lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2); |
1602 | 1606 | ||
@@ -1718,11 +1722,11 @@ static void epcapoll(unsigned long ignored) | |||
1718 | static void doevent(int crd) | 1722 | static void doevent(int crd) |
1719 | { /* Begin doevent */ | 1723 | { /* Begin doevent */ |
1720 | 1724 | ||
1721 | void *eventbuf; | 1725 | void __iomem *eventbuf; |
1722 | struct channel *ch, *chan0; | 1726 | struct channel *ch, *chan0; |
1723 | static struct tty_struct *tty; | 1727 | static struct tty_struct *tty; |
1724 | struct board_info *bd; | 1728 | struct board_info *bd; |
1725 | struct board_chan *bc; | 1729 | struct board_chan __iomem *bc; |
1726 | unsigned int tail, head; | 1730 | unsigned int tail, head; |
1727 | int event, channel; | 1731 | int event, channel; |
1728 | int mstat, lstat; | 1732 | int mstat, lstat; |
@@ -1817,7 +1821,7 @@ static void doevent(int crd) | |||
1817 | static void fepcmd(struct channel *ch, int cmd, int word_or_byte, | 1821 | static void fepcmd(struct channel *ch, int cmd, int word_or_byte, |
1818 | int byte2, int ncmds, int bytecmd) | 1822 | int byte2, int ncmds, int bytecmd) |
1819 | { /* Begin fepcmd */ | 1823 | { /* Begin fepcmd */ |
1820 | unchar *memaddr; | 1824 | unchar __iomem *memaddr; |
1821 | unsigned int head, cmdTail, cmdStart, cmdMax; | 1825 | unsigned int head, cmdTail, cmdStart, cmdMax; |
1822 | long count; | 1826 | long count; |
1823 | int n; | 1827 | int n; |
@@ -2000,7 +2004,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) | |||
2000 | 2004 | ||
2001 | unsigned int cmdHead; | 2005 | unsigned int cmdHead; |
2002 | struct termios *ts; | 2006 | struct termios *ts; |
2003 | struct board_chan *bc; | 2007 | struct board_chan __iomem *bc; |
2004 | unsigned mval, hflow, cflag, iflag; | 2008 | unsigned mval, hflow, cflag, iflag; |
2005 | 2009 | ||
2006 | bc = ch->brdchan; | 2010 | bc = ch->brdchan; |
@@ -2010,7 +2014,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) | |||
2010 | ts = tty->termios; | 2014 | ts = tty->termios; |
2011 | if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */ | 2015 | if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */ |
2012 | cmdHead = readw(&bc->rin); | 2016 | cmdHead = readw(&bc->rin); |
2013 | bc->rout = cmdHead; | 2017 | writew(cmdHead, &bc->rout); |
2014 | cmdHead = readw(&bc->tin); | 2018 | cmdHead = readw(&bc->tin); |
2015 | /* Changing baud in mid-stream transmission can be wonderful */ | 2019 | /* Changing baud in mid-stream transmission can be wonderful */ |
2016 | /* --------------------------------------------------------------- | 2020 | /* --------------------------------------------------------------- |
@@ -2116,7 +2120,7 @@ static void receive_data(struct channel *ch) | |||
2116 | unchar *rptr; | 2120 | unchar *rptr; |
2117 | struct termios *ts = NULL; | 2121 | struct termios *ts = NULL; |
2118 | struct tty_struct *tty; | 2122 | struct tty_struct *tty; |
2119 | struct board_chan *bc; | 2123 | struct board_chan __iomem *bc; |
2120 | int dataToRead, wrapgap, bytesAvailable; | 2124 | int dataToRead, wrapgap, bytesAvailable; |
2121 | unsigned int tail, head; | 2125 | unsigned int tail, head; |
2122 | unsigned int wrapmask; | 2126 | unsigned int wrapmask; |
@@ -2154,7 +2158,7 @@ static void receive_data(struct channel *ch) | |||
2154 | --------------------------------------------------------------------- */ | 2158 | --------------------------------------------------------------------- */ |
2155 | 2159 | ||
2156 | if (!tty || !ts || !(ts->c_cflag & CREAD)) { | 2160 | if (!tty || !ts || !(ts->c_cflag & CREAD)) { |
2157 | bc->rout = head; | 2161 | writew(head, &bc->rout); |
2158 | return; | 2162 | return; |
2159 | } | 2163 | } |
2160 | 2164 | ||
@@ -2270,7 +2274,7 @@ static int info_ioctl(struct tty_struct *tty, struct file * file, | |||
2270 | static int pc_tiocmget(struct tty_struct *tty, struct file *file) | 2274 | static int pc_tiocmget(struct tty_struct *tty, struct file *file) |
2271 | { | 2275 | { |
2272 | struct channel *ch = (struct channel *) tty->driver_data; | 2276 | struct channel *ch = (struct channel *) tty->driver_data; |
2273 | struct board_chan *bc; | 2277 | struct board_chan __iomem *bc; |
2274 | unsigned int mstat, mflag = 0; | 2278 | unsigned int mstat, mflag = 0; |
2275 | unsigned long flags; | 2279 | unsigned long flags; |
2276 | 2280 | ||
@@ -2351,7 +2355,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, | |||
2351 | unsigned long flags; | 2355 | unsigned long flags; |
2352 | unsigned int mflag, mstat; | 2356 | unsigned int mflag, mstat; |
2353 | unsigned char startc, stopc; | 2357 | unsigned char startc, stopc; |
2354 | struct board_chan *bc; | 2358 | struct board_chan __iomem *bc; |
2355 | struct channel *ch = (struct channel *) tty->driver_data; | 2359 | struct channel *ch = (struct channel *) tty->driver_data; |
2356 | void __user *argp = (void __user *)arg; | 2360 | void __user *argp = (void __user *)arg; |
2357 | 2361 | ||
@@ -2633,7 +2637,7 @@ static void pc_start(struct tty_struct *tty) | |||
2633 | spin_lock_irqsave(&epca_lock, flags); | 2637 | spin_lock_irqsave(&epca_lock, flags); |
2634 | /* Just in case output was resumed because of a change in Digi-flow */ | 2638 | /* Just in case output was resumed because of a change in Digi-flow */ |
2635 | if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */ | 2639 | if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */ |
2636 | struct board_chan *bc; | 2640 | struct board_chan __iomem *bc; |
2637 | globalwinon(ch); | 2641 | globalwinon(ch); |
2638 | bc = ch->brdchan; | 2642 | bc = ch->brdchan; |
2639 | if (ch->statusflags & LOWWAIT) | 2643 | if (ch->statusflags & LOWWAIT) |
@@ -2727,7 +2731,7 @@ void digi_send_break(struct channel *ch, int msec) | |||
2727 | static void setup_empty_event(struct tty_struct *tty, struct channel *ch) | 2731 | static void setup_empty_event(struct tty_struct *tty, struct channel *ch) |
2728 | { /* Begin setup_empty_event */ | 2732 | { /* Begin setup_empty_event */ |
2729 | 2733 | ||
2730 | struct board_chan *bc = ch->brdchan; | 2734 | struct board_chan __iomem *bc = ch->brdchan; |
2731 | 2735 | ||
2732 | globalwinon(ch); | 2736 | globalwinon(ch); |
2733 | ch->statusflags |= EMPTYWAIT; | 2737 | ch->statusflags |= EMPTYWAIT; |
diff --git a/drivers/char/epca.h b/drivers/char/epca.h index 20eeb5a70e1a..456d6c8f94a8 100644 --- a/drivers/char/epca.h +++ b/drivers/char/epca.h | |||
@@ -128,17 +128,17 @@ struct channel | |||
128 | unsigned long c_cflag; | 128 | unsigned long c_cflag; |
129 | unsigned long c_lflag; | 129 | unsigned long c_lflag; |
130 | unsigned long c_oflag; | 130 | unsigned long c_oflag; |
131 | unsigned char *txptr; | 131 | unsigned char __iomem *txptr; |
132 | unsigned char *rxptr; | 132 | unsigned char __iomem *rxptr; |
133 | unsigned char *tmp_buf; | 133 | unsigned char *tmp_buf; |
134 | struct board_info *board; | 134 | struct board_info *board; |
135 | struct board_chan *brdchan; | 135 | struct board_chan __iomem *brdchan; |
136 | struct digi_struct digiext; | 136 | struct digi_struct digiext; |
137 | struct tty_struct *tty; | 137 | struct tty_struct *tty; |
138 | wait_queue_head_t open_wait; | 138 | wait_queue_head_t open_wait; |
139 | wait_queue_head_t close_wait; | 139 | wait_queue_head_t close_wait; |
140 | struct work_struct tqueue; | 140 | struct work_struct tqueue; |
141 | struct global_data *mailbox; | 141 | struct global_data __iomem *mailbox; |
142 | }; | 142 | }; |
143 | 143 | ||
144 | struct board_info | 144 | struct board_info |
@@ -149,8 +149,8 @@ struct board_info | |||
149 | unsigned short numports; | 149 | unsigned short numports; |
150 | unsigned long port; | 150 | unsigned long port; |
151 | unsigned long membase; | 151 | unsigned long membase; |
152 | unsigned char __iomem *re_map_port; | 152 | void __iomem *re_map_port; |
153 | unsigned char *re_map_membase; | 153 | void __iomem *re_map_membase; |
154 | unsigned long memory_seg; | 154 | unsigned long memory_seg; |
155 | void ( * memwinon ) (struct board_info *, unsigned int) ; | 155 | void ( * memwinon ) (struct board_info *, unsigned int) ; |
156 | void ( * memwinoff ) (struct board_info *, unsigned int) ; | 156 | void ( * memwinoff ) (struct board_info *, unsigned int) ; |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index cddb789902db..f92177634677 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -839,9 +839,6 @@ int __init hvc_init(void) | |||
839 | hvc_driver->flags = TTY_DRIVER_REAL_RAW; | 839 | hvc_driver->flags = TTY_DRIVER_REAL_RAW; |
840 | tty_set_operations(hvc_driver, &hvc_ops); | 840 | tty_set_operations(hvc_driver, &hvc_ops); |
841 | 841 | ||
842 | if (tty_register_driver(hvc_driver)) | ||
843 | panic("Couldn't register hvc console driver\n"); | ||
844 | |||
845 | /* Always start the kthread because there can be hotplug vty adapters | 842 | /* Always start the kthread because there can be hotplug vty adapters |
846 | * added later. */ | 843 | * added later. */ |
847 | hvc_task = kthread_run(khvcd, NULL, "khvcd"); | 844 | hvc_task = kthread_run(khvcd, NULL, "khvcd"); |
@@ -851,6 +848,9 @@ int __init hvc_init(void) | |||
851 | return -EIO; | 848 | return -EIO; |
852 | } | 849 | } |
853 | 850 | ||
851 | if (tty_register_driver(hvc_driver)) | ||
852 | panic("Couldn't register hvc console driver\n"); | ||
853 | |||
854 | return 0; | 854 | return 0; |
855 | } | 855 | } |
856 | module_init(hvc_init); | 856 | module_init(hvc_init); |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 1e33cb032e07..e91268e86833 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -810,13 +810,14 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) | |||
810 | * from the top and bottom of cursor position | 810 | * from the top and bottom of cursor position |
811 | */ | 811 | */ |
812 | old_origin += (vc->vc_y - new_rows/2) * old_row_size; | 812 | old_origin += (vc->vc_y - new_rows/2) * old_row_size; |
813 | end = old_origin + new_screen_size; | 813 | end = old_origin + (old_row_size * new_rows); |
814 | } | 814 | } |
815 | } else | 815 | } else |
816 | /* | 816 | /* |
817 | * Cursor near the top, copy contents from the top of buffer | 817 | * Cursor near the top, copy contents from the top of buffer |
818 | */ | 818 | */ |
819 | end = (old_rows > new_rows) ? old_origin + new_screen_size : | 819 | end = (old_rows > new_rows) ? old_origin + |
820 | (old_row_size * new_rows) : | ||
820 | vc->vc_scr_end; | 821 | vc->vc_scr_end; |
821 | 822 | ||
822 | update_attr(vc); | 823 | update_attr(vc); |
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c index c694eee1fb24..75ca84ed4adf 100644 --- a/drivers/char/watchdog/mpcore_wdt.c +++ b/drivers/char/watchdog/mpcore_wdt.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/device.h> | 32 | #include <linux/device.h> |
33 | |||
34 | #include <asm/hardware/arm_twd.h> | ||
33 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
34 | 36 | ||
35 | struct mpcore_wdt { | 37 | struct mpcore_wdt { |
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index 3b865f34a095..b66782398258 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c | |||
@@ -50,7 +50,7 @@ | |||
50 | MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); | 50 | MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); |
51 | MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); | 51 | MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); |
52 | MODULE_LICENSE("GPL"); | 52 | MODULE_LICENSE("GPL"); |
53 | MODULE_VERSION("1.0"); | 53 | MODULE_VERSION("2.0"); |
54 | 54 | ||
55 | #define BIOS_SCAN_LIMIT 0xffffffff | 55 | #define BIOS_SCAN_LIMIT 0xffffffff |
56 | #define MAX_IMAGE_LENGTH 16 | 56 | #define MAX_IMAGE_LENGTH 16 |
@@ -65,10 +65,11 @@ static struct _rbu_data { | |||
65 | unsigned long packet_write_count; | 65 | unsigned long packet_write_count; |
66 | unsigned long num_packets; | 66 | unsigned long num_packets; |
67 | unsigned long packetsize; | 67 | unsigned long packetsize; |
68 | int entry_created; | ||
68 | } rbu_data; | 69 | } rbu_data; |
69 | 70 | ||
70 | static char image_type[MAX_IMAGE_LENGTH] = "mono"; | 71 | static char image_type[MAX_IMAGE_LENGTH + 1] = "mono"; |
71 | module_param_string(image_type, image_type, sizeof(image_type), 0); | 72 | module_param_string(image_type, image_type, sizeof (image_type), 0); |
72 | MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet"); | 73 | MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet"); |
73 | 74 | ||
74 | struct packet_data { | 75 | struct packet_data { |
@@ -114,7 +115,7 @@ static int fill_last_packet(void *data, size_t length) | |||
114 | 115 | ||
115 | if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) { | 116 | if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) { |
116 | pr_debug("dell_rbu:%s: packet size data " | 117 | pr_debug("dell_rbu:%s: packet size data " |
117 | "overrun\n", __FUNCTION__); | 118 | "overrun\n", __FUNCTION__); |
118 | return -EINVAL; | 119 | return -EINVAL; |
119 | } | 120 | } |
120 | 121 | ||
@@ -146,12 +147,14 @@ static int create_packet(size_t length) | |||
146 | pr_debug("create_packet: packetsize not specified\n"); | 147 | pr_debug("create_packet: packetsize not specified\n"); |
147 | return -EINVAL; | 148 | return -EINVAL; |
148 | } | 149 | } |
150 | spin_unlock(&rbu_data.lock); | ||
151 | newpacket = kmalloc(sizeof (struct packet_data), GFP_KERNEL); | ||
152 | spin_lock(&rbu_data.lock); | ||
149 | 153 | ||
150 | newpacket = kmalloc(sizeof(struct packet_data), GFP_KERNEL); | ||
151 | if (!newpacket) { | 154 | if (!newpacket) { |
152 | printk(KERN_WARNING | 155 | printk(KERN_WARNING |
153 | "dell_rbu:%s: failed to allocate new " | 156 | "dell_rbu:%s: failed to allocate new " |
154 | "packet\n", __FUNCTION__); | 157 | "packet\n", __FUNCTION__); |
155 | return -ENOMEM; | 158 | return -ENOMEM; |
156 | } | 159 | } |
157 | 160 | ||
@@ -160,15 +163,17 @@ static int create_packet(size_t length) | |||
160 | * there is no upper limit on memory | 163 | * there is no upper limit on memory |
161 | * address for packetized mechanism | 164 | * address for packetized mechanism |
162 | */ | 165 | */ |
163 | newpacket->data = (unsigned char *)__get_free_pages(GFP_KERNEL, | 166 | spin_unlock(&rbu_data.lock); |
164 | ordernum); | 167 | newpacket->data = (unsigned char *) __get_free_pages(GFP_KERNEL, |
168 | ordernum); | ||
169 | spin_lock(&rbu_data.lock); | ||
165 | 170 | ||
166 | pr_debug("create_packet: newpacket %p\n", newpacket->data); | 171 | pr_debug("create_packet: newpacket %p\n", newpacket->data); |
167 | 172 | ||
168 | if (!newpacket->data) { | 173 | if (!newpacket->data) { |
169 | printk(KERN_WARNING | 174 | printk(KERN_WARNING |
170 | "dell_rbu:%s: failed to allocate new " | 175 | "dell_rbu:%s: failed to allocate new " |
171 | "packet\n", __FUNCTION__); | 176 | "packet\n", __FUNCTION__); |
172 | kfree(newpacket); | 177 | kfree(newpacket); |
173 | return -ENOMEM; | 178 | return -ENOMEM; |
174 | } | 179 | } |
@@ -204,9 +209,8 @@ static int packetize_data(void *data, size_t length) | |||
204 | return rc; | 209 | return rc; |
205 | } | 210 | } |
206 | 211 | ||
207 | static int | 212 | static int do_packet_read(char *data, struct list_head *ptemp_list, |
208 | do_packet_read(char *data, struct list_head *ptemp_list, | 213 | int length, int bytes_read, int *list_read_count) |
209 | int length, int bytes_read, int *list_read_count) | ||
210 | { | 214 | { |
211 | void *ptemp_buf; | 215 | void *ptemp_buf; |
212 | struct packet_data *newpacket = NULL; | 216 | struct packet_data *newpacket = NULL; |
@@ -239,7 +243,7 @@ do_packet_read(char *data, struct list_head *ptemp_list, | |||
239 | return bytes_copied; | 243 | return bytes_copied; |
240 | } | 244 | } |
241 | 245 | ||
242 | static int packet_read_list(char *data, size_t * pread_length) | 246 | static int packet_read_list(char *data, size_t *pread_length) |
243 | { | 247 | { |
244 | struct list_head *ptemp_list; | 248 | struct list_head *ptemp_list; |
245 | int temp_count = 0; | 249 | int temp_count = 0; |
@@ -258,8 +262,7 @@ static int packet_read_list(char *data, size_t * pread_length) | |||
258 | ptemp_list = (&packet_data_head.list)->next; | 262 | ptemp_list = (&packet_data_head.list)->next; |
259 | while (!list_empty(ptemp_list)) { | 263 | while (!list_empty(ptemp_list)) { |
260 | bytes_copied = do_packet_read(pdest, ptemp_list, | 264 | bytes_copied = do_packet_read(pdest, ptemp_list, |
261 | remaining_bytes, bytes_read, | 265 | remaining_bytes, bytes_read, &temp_count); |
262 | &temp_count); | ||
263 | remaining_bytes -= bytes_copied; | 266 | remaining_bytes -= bytes_copied; |
264 | bytes_read += bytes_copied; | 267 | bytes_read += bytes_copied; |
265 | pdest += bytes_copied; | 268 | pdest += bytes_copied; |
@@ -287,7 +290,7 @@ static void packet_empty_list(void) | |||
287 | ptemp_list = (&packet_data_head.list)->next; | 290 | ptemp_list = (&packet_data_head.list)->next; |
288 | while (!list_empty(ptemp_list)) { | 291 | while (!list_empty(ptemp_list)) { |
289 | newpacket = | 292 | newpacket = |
290 | list_entry(ptemp_list, struct packet_data, list); | 293 | list_entry(ptemp_list, struct packet_data, list); |
291 | pnext_list = ptemp_list->next; | 294 | pnext_list = ptemp_list->next; |
292 | list_del(ptemp_list); | 295 | list_del(ptemp_list); |
293 | ptemp_list = pnext_list; | 296 | ptemp_list = pnext_list; |
@@ -296,8 +299,8 @@ static void packet_empty_list(void) | |||
296 | * to make sure there are no stale RBU packets left in memory | 299 | * to make sure there are no stale RBU packets left in memory |
297 | */ | 300 | */ |
298 | memset(newpacket->data, 0, rbu_data.packetsize); | 301 | memset(newpacket->data, 0, rbu_data.packetsize); |
299 | free_pages((unsigned long)newpacket->data, | 302 | free_pages((unsigned long) newpacket->data, |
300 | newpacket->ordernum); | 303 | newpacket->ordernum); |
301 | kfree(newpacket); | 304 | kfree(newpacket); |
302 | } | 305 | } |
303 | rbu_data.packet_write_count = 0; | 306 | rbu_data.packet_write_count = 0; |
@@ -319,14 +322,13 @@ static void img_update_free(void) | |||
319 | * BIOS image copied in memory. | 322 | * BIOS image copied in memory. |
320 | */ | 323 | */ |
321 | memset(rbu_data.image_update_buffer, 0, | 324 | memset(rbu_data.image_update_buffer, 0, |
322 | rbu_data.image_update_buffer_size); | 325 | rbu_data.image_update_buffer_size); |
323 | if (rbu_data.dma_alloc == 1) | 326 | if (rbu_data.dma_alloc == 1) |
324 | dma_free_coherent(NULL, rbu_data.bios_image_size, | 327 | dma_free_coherent(NULL, rbu_data.bios_image_size, |
325 | rbu_data.image_update_buffer, | 328 | rbu_data.image_update_buffer, dell_rbu_dmaaddr); |
326 | dell_rbu_dmaaddr); | ||
327 | else | 329 | else |
328 | free_pages((unsigned long)rbu_data.image_update_buffer, | 330 | free_pages((unsigned long) rbu_data.image_update_buffer, |
329 | rbu_data.image_update_ordernum); | 331 | rbu_data.image_update_ordernum); |
330 | 332 | ||
331 | /* | 333 | /* |
332 | * Re-initialize the rbu_data variables after a free | 334 | * Re-initialize the rbu_data variables after a free |
@@ -366,7 +368,7 @@ static int img_update_realloc(unsigned long size) | |||
366 | */ | 368 | */ |
367 | if ((size != 0) && (rbu_data.image_update_buffer == NULL)) { | 369 | if ((size != 0) && (rbu_data.image_update_buffer == NULL)) { |
368 | printk(KERN_ERR "dell_rbu:%s: corruption " | 370 | printk(KERN_ERR "dell_rbu:%s: corruption " |
369 | "check failed\n", __FUNCTION__); | 371 | "check failed\n", __FUNCTION__); |
370 | return -EINVAL; | 372 | return -EINVAL; |
371 | } | 373 | } |
372 | /* | 374 | /* |
@@ -385,17 +387,16 @@ static int img_update_realloc(unsigned long size) | |||
385 | 387 | ||
386 | ordernum = get_order(size); | 388 | ordernum = get_order(size); |
387 | image_update_buffer = | 389 | image_update_buffer = |
388 | (unsigned char *)__get_free_pages(GFP_KERNEL, ordernum); | 390 | (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum); |
389 | 391 | ||
390 | img_buf_phys_addr = | 392 | img_buf_phys_addr = |
391 | (unsigned long)virt_to_phys(image_update_buffer); | 393 | (unsigned long) virt_to_phys(image_update_buffer); |
392 | 394 | ||
393 | if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { | 395 | if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { |
394 | free_pages((unsigned long)image_update_buffer, ordernum); | 396 | free_pages((unsigned long) image_update_buffer, ordernum); |
395 | ordernum = -1; | 397 | ordernum = -1; |
396 | image_update_buffer = dma_alloc_coherent(NULL, size, | 398 | image_update_buffer = dma_alloc_coherent(NULL, size, |
397 | &dell_rbu_dmaaddr, | 399 | &dell_rbu_dmaaddr, GFP_KERNEL); |
398 | GFP_KERNEL); | ||
399 | dma_alloc = 1; | 400 | dma_alloc = 1; |
400 | } | 401 | } |
401 | 402 | ||
@@ -405,13 +406,13 @@ static int img_update_realloc(unsigned long size) | |||
405 | rbu_data.image_update_buffer = image_update_buffer; | 406 | rbu_data.image_update_buffer = image_update_buffer; |
406 | rbu_data.image_update_buffer_size = size; | 407 | rbu_data.image_update_buffer_size = size; |
407 | rbu_data.bios_image_size = | 408 | rbu_data.bios_image_size = |
408 | rbu_data.image_update_buffer_size; | 409 | rbu_data.image_update_buffer_size; |
409 | rbu_data.image_update_ordernum = ordernum; | 410 | rbu_data.image_update_ordernum = ordernum; |
410 | rbu_data.dma_alloc = dma_alloc; | 411 | rbu_data.dma_alloc = dma_alloc; |
411 | rc = 0; | 412 | rc = 0; |
412 | } else { | 413 | } else { |
413 | pr_debug("Not enough memory for image update:" | 414 | pr_debug("Not enough memory for image update:" |
414 | "size = %ld\n", size); | 415 | "size = %ld\n", size); |
415 | rc = -ENOMEM; | 416 | rc = -ENOMEM; |
416 | } | 417 | } |
417 | 418 | ||
@@ -438,7 +439,7 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) | |||
438 | if (pos > imagesize) { | 439 | if (pos > imagesize) { |
439 | retval = 0; | 440 | retval = 0; |
440 | printk(KERN_WARNING "dell_rbu:read_packet_data: " | 441 | printk(KERN_WARNING "dell_rbu:read_packet_data: " |
441 | "data underrun\n"); | 442 | "data underrun\n"); |
442 | goto read_rbu_data_exit; | 443 | goto read_rbu_data_exit; |
443 | } | 444 | } |
444 | 445 | ||
@@ -468,11 +469,11 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) | |||
468 | 469 | ||
469 | /* check to see if we have something to return */ | 470 | /* check to see if we have something to return */ |
470 | if ((rbu_data.image_update_buffer == NULL) || | 471 | if ((rbu_data.image_update_buffer == NULL) || |
471 | (rbu_data.bios_image_size == 0)) { | 472 | (rbu_data.bios_image_size == 0)) { |
472 | pr_debug("read_rbu_data_mono: image_update_buffer %p ," | 473 | pr_debug("read_rbu_data_mono: image_update_buffer %p ," |
473 | "bios_image_size %lu\n", | 474 | "bios_image_size %lu\n", |
474 | rbu_data.image_update_buffer, | 475 | rbu_data.image_update_buffer, |
475 | rbu_data.bios_image_size); | 476 | rbu_data.bios_image_size); |
476 | ret_count = -ENOMEM; | 477 | ret_count = -ENOMEM; |
477 | goto read_rbu_data_exit; | 478 | goto read_rbu_data_exit; |
478 | } | 479 | } |
@@ -497,8 +498,8 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) | |||
497 | return ret_count; | 498 | return ret_count; |
498 | } | 499 | } |
499 | 500 | ||
500 | static ssize_t | 501 | static ssize_t read_rbu_data(struct kobject *kobj, char *buffer, |
501 | read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count) | 502 | loff_t pos, size_t count) |
502 | { | 503 | { |
503 | ssize_t ret_count = 0; | 504 | ssize_t ret_count = 0; |
504 | 505 | ||
@@ -515,62 +516,20 @@ read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count) | |||
515 | return ret_count; | 516 | return ret_count; |
516 | } | 517 | } |
517 | 518 | ||
518 | static ssize_t | ||
519 | read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, | ||
520 | size_t count) | ||
521 | { | ||
522 | int size = 0; | ||
523 | if (!pos) | ||
524 | size = sprintf(buffer, "%s\n", image_type); | ||
525 | return size; | ||
526 | } | ||
527 | |||
528 | static ssize_t | ||
529 | write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, | ||
530 | size_t count) | ||
531 | { | ||
532 | int rc = count; | ||
533 | spin_lock(&rbu_data.lock); | ||
534 | |||
535 | if (strlen(buffer) < MAX_IMAGE_LENGTH) | ||
536 | sscanf(buffer, "%s", image_type); | ||
537 | else | ||
538 | printk(KERN_WARNING "dell_rbu: image_type is invalid" | ||
539 | "max chars = %d, \n incoming str--%s-- \n", | ||
540 | MAX_IMAGE_LENGTH, buffer); | ||
541 | |||
542 | /* we must free all previous allocations */ | ||
543 | packet_empty_list(); | ||
544 | img_update_free(); | ||
545 | |||
546 | spin_unlock(&rbu_data.lock); | ||
547 | return rc; | ||
548 | |||
549 | } | ||
550 | |||
551 | static struct bin_attribute rbu_data_attr = { | ||
552 | .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444}, | ||
553 | .read = read_rbu_data, | ||
554 | }; | ||
555 | |||
556 | static struct bin_attribute rbu_image_type_attr = { | ||
557 | .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644}, | ||
558 | .read = read_rbu_image_type, | ||
559 | .write = write_rbu_image_type, | ||
560 | }; | ||
561 | |||
562 | static void callbackfn_rbu(const struct firmware *fw, void *context) | 519 | static void callbackfn_rbu(const struct firmware *fw, void *context) |
563 | { | 520 | { |
564 | int rc = 0; | 521 | int rc = 0; |
565 | 522 | ||
566 | if (!fw || !fw->size) | 523 | if (!fw || !fw->size) { |
524 | rbu_data.entry_created = 0; | ||
567 | return; | 525 | return; |
526 | } | ||
568 | 527 | ||
569 | spin_lock(&rbu_data.lock); | 528 | spin_lock(&rbu_data.lock); |
570 | if (!strcmp(image_type, "mono")) { | 529 | if (!strcmp(image_type, "mono")) { |
571 | if (!img_update_realloc(fw->size)) | 530 | if (!img_update_realloc(fw->size)) |
572 | memcpy(rbu_data.image_update_buffer, | 531 | memcpy(rbu_data.image_update_buffer, |
573 | fw->data, fw->size); | 532 | fw->data, fw->size); |
574 | } else if (!strcmp(image_type, "packet")) { | 533 | } else if (!strcmp(image_type, "packet")) { |
575 | if (!rbu_data.packetsize) | 534 | if (!rbu_data.packetsize) |
576 | rbu_data.packetsize = fw->size; | 535 | rbu_data.packetsize = fw->size; |
@@ -584,14 +543,103 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) | |||
584 | spin_unlock(&rbu_data.lock); | 543 | spin_unlock(&rbu_data.lock); |
585 | 544 | ||
586 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | 545 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, |
587 | "dell_rbu", &rbu_device->dev, | 546 | "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); |
588 | &context, callbackfn_rbu); | ||
589 | if (rc) | 547 | if (rc) |
590 | printk(KERN_ERR | 548 | printk(KERN_ERR |
591 | "dell_rbu:%s request_firmware_nowait failed" | 549 | "dell_rbu:%s request_firmware_nowait failed" |
592 | " %d\n", __FUNCTION__, rc); | 550 | " %d\n", __FUNCTION__, rc); |
551 | else | ||
552 | rbu_data.entry_created = 1; | ||
553 | } | ||
554 | |||
555 | static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, | ||
556 | loff_t pos, size_t count) | ||
557 | { | ||
558 | int size = 0; | ||
559 | if (!pos) | ||
560 | size = sprintf(buffer, "%s\n", image_type); | ||
561 | return size; | ||
562 | } | ||
563 | |||
564 | static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, | ||
565 | loff_t pos, size_t count) | ||
566 | { | ||
567 | int rc = count; | ||
568 | int req_firm_rc = 0; | ||
569 | int i; | ||
570 | spin_lock(&rbu_data.lock); | ||
571 | /* | ||
572 | * Find the first newline or space | ||
573 | */ | ||
574 | for (i = 0; i < count; ++i) | ||
575 | if (buffer[i] == '\n' || buffer[i] == ' ') { | ||
576 | buffer[i] = '\0'; | ||
577 | break; | ||
578 | } | ||
579 | if (i == count) | ||
580 | buffer[count] = '\0'; | ||
581 | |||
582 | if (strstr(buffer, "mono")) | ||
583 | strcpy(image_type, "mono"); | ||
584 | else if (strstr(buffer, "packet")) | ||
585 | strcpy(image_type, "packet"); | ||
586 | else if (strstr(buffer, "init")) { | ||
587 | /* | ||
588 | * If due to the user error the driver gets in a bad | ||
589 | * state where even though it is loaded , the | ||
590 | * /sys/class/firmware/dell_rbu entries are missing. | ||
591 | * to cover this situation the user can recreate entries | ||
592 | * by writing init to image_type. | ||
593 | */ | ||
594 | if (!rbu_data.entry_created) { | ||
595 | spin_unlock(&rbu_data.lock); | ||
596 | req_firm_rc = request_firmware_nowait(THIS_MODULE, | ||
597 | FW_ACTION_NOHOTPLUG, "dell_rbu", | ||
598 | &rbu_device->dev, &context, | ||
599 | callbackfn_rbu); | ||
600 | if (req_firm_rc) { | ||
601 | printk(KERN_ERR | ||
602 | "dell_rbu:%s request_firmware_nowait" | ||
603 | " failed %d\n", __FUNCTION__, rc); | ||
604 | rc = -EIO; | ||
605 | } else | ||
606 | rbu_data.entry_created = 1; | ||
607 | |||
608 | spin_lock(&rbu_data.lock); | ||
609 | } | ||
610 | } else { | ||
611 | printk(KERN_WARNING "dell_rbu: image_type is invalid\n"); | ||
612 | spin_unlock(&rbu_data.lock); | ||
613 | return -EINVAL; | ||
614 | } | ||
615 | |||
616 | /* we must free all previous allocations */ | ||
617 | packet_empty_list(); | ||
618 | img_update_free(); | ||
619 | spin_unlock(&rbu_data.lock); | ||
620 | |||
621 | return rc; | ||
593 | } | 622 | } |
594 | 623 | ||
624 | static struct bin_attribute rbu_data_attr = { | ||
625 | .attr = { | ||
626 | .name = "data", | ||
627 | .owner = THIS_MODULE, | ||
628 | .mode = 0444, | ||
629 | }, | ||
630 | .read = read_rbu_data, | ||
631 | }; | ||
632 | |||
633 | static struct bin_attribute rbu_image_type_attr = { | ||
634 | .attr = { | ||
635 | .name = "image_type", | ||
636 | .owner = THIS_MODULE, | ||
637 | .mode = 0644, | ||
638 | }, | ||
639 | .read = read_rbu_image_type, | ||
640 | .write = write_rbu_image_type, | ||
641 | }; | ||
642 | |||
595 | static int __init dcdrbu_init(void) | 643 | static int __init dcdrbu_init(void) |
596 | { | 644 | { |
597 | int rc = 0; | 645 | int rc = 0; |
@@ -599,11 +647,11 @@ static int __init dcdrbu_init(void) | |||
599 | 647 | ||
600 | init_packet_head(); | 648 | init_packet_head(); |
601 | rbu_device = | 649 | rbu_device = |
602 | platform_device_register_simple("dell_rbu", -1, NULL, 0); | 650 | platform_device_register_simple("dell_rbu", -1, NULL, 0); |
603 | if (!rbu_device) { | 651 | if (!rbu_device) { |
604 | printk(KERN_ERR | 652 | printk(KERN_ERR |
605 | "dell_rbu:%s:platform_device_register_simple " | 653 | "dell_rbu:%s:platform_device_register_simple " |
606 | "failed\n", __FUNCTION__); | 654 | "failed\n", __FUNCTION__); |
607 | return -EIO; | 655 | return -EIO; |
608 | } | 656 | } |
609 | 657 | ||
@@ -611,11 +659,12 @@ static int __init dcdrbu_init(void) | |||
611 | sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); | 659 | sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); |
612 | 660 | ||
613 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | 661 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, |
614 | "dell_rbu", &rbu_device->dev, | 662 | "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); |
615 | &context, callbackfn_rbu); | ||
616 | if (rc) | 663 | if (rc) |
617 | printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait" | 664 | printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait" |
618 | " failed %d\n", __FUNCTION__, rc); | 665 | " failed %d\n", __FUNCTION__, rc); |
666 | else | ||
667 | rbu_data.entry_created = 1; | ||
619 | 668 | ||
620 | return rc; | 669 | return rc; |
621 | 670 | ||
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index eaebfc14c933..4c56411f3993 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c | |||
@@ -5,10 +5,10 @@ | |||
5 | * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com> | 5 | * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com> |
6 | * | 6 | * |
7 | * The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad | 7 | * The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad |
8 | * T41, T42, T43, R51, and X40, at least. It provides a basic two-axis | 8 | * T41, T42, T43, R50, R50p, R51, and X40, at least. It provides a basic |
9 | * accelerometer and other data, such as the device's temperature. | 9 | * two-axis accelerometer and other data, such as the device's temperature. |
10 | * | 10 | * |
11 | * Based on the document by Mark A. Smith available at | 11 | * This driver is based on the document by Mark A. Smith available at |
12 | * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial | 12 | * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial |
13 | * and error. | 13 | * and error. |
14 | * | 14 | * |
@@ -36,12 +36,7 @@ | |||
36 | #include <asm/io.h> | 36 | #include <asm/io.h> |
37 | 37 | ||
38 | #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ | 38 | #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ |
39 | #define HDAPS_NR_PORTS 0x30 /* 0x1600 - 0x162f */ | 39 | #define HDAPS_NR_PORTS 0x30 /* number of ports: 0x1600 - 0x162f */ |
40 | |||
41 | #define STATE_FRESH 0x50 /* accelerometer data is fresh */ | ||
42 | |||
43 | #define REFRESH_ASYNC 0x00 /* do asynchronous refresh */ | ||
44 | #define REFRESH_SYNC 0x01 /* do synchronous refresh */ | ||
45 | 40 | ||
46 | #define HDAPS_PORT_STATE 0x1611 /* device state */ | 41 | #define HDAPS_PORT_STATE 0x1611 /* device state */ |
47 | #define HDAPS_PORT_YPOS 0x1612 /* y-axis position */ | 42 | #define HDAPS_PORT_YPOS 0x1612 /* y-axis position */ |
@@ -53,7 +48,7 @@ | |||
53 | #define HDAPS_PORT_UNKNOWN 0x161c /* what is this? */ | 48 | #define HDAPS_PORT_UNKNOWN 0x161c /* what is this? */ |
54 | #define HDAPS_PORT_KMACT 0x161d /* keyboard or mouse activity */ | 49 | #define HDAPS_PORT_KMACT 0x161d /* keyboard or mouse activity */ |
55 | 50 | ||
56 | #define HDAPS_READ_MASK 0xff /* some reads have the low 8 bits set */ | 51 | #define STATE_FRESH 0x50 /* accelerometer data is fresh */ |
57 | 52 | ||
58 | #define KEYBD_MASK 0x20 /* set if keyboard activity */ | 53 | #define KEYBD_MASK 0x20 /* set if keyboard activity */ |
59 | #define MOUSE_MASK 0x40 /* set if mouse activity */ | 54 | #define MOUSE_MASK 0x40 /* set if mouse activity */ |
@@ -63,12 +58,11 @@ | |||
63 | #define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */ | 58 | #define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */ |
64 | #define INIT_WAIT_MSECS 200 /* ... in 200ms increments */ | 59 | #define INIT_WAIT_MSECS 200 /* ... in 200ms increments */ |
65 | 60 | ||
66 | static struct platform_device *pdev; | 61 | #define HDAPS_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */ |
67 | static struct input_dev hdaps_idev; | 62 | #define HDAPS_INPUT_FUZZ 4 /* input event threshold */ |
63 | |||
68 | static struct timer_list hdaps_timer; | 64 | static struct timer_list hdaps_timer; |
69 | static unsigned int hdaps_mousedev_threshold = 4; | 65 | static struct platform_device *pdev; |
70 | static unsigned long hdaps_poll_ms = 50; | ||
71 | static unsigned int hdaps_mousedev; | ||
72 | static unsigned int hdaps_invert; | 66 | static unsigned int hdaps_invert; |
73 | static u8 km_activity; | 67 | static u8 km_activity; |
74 | static int rest_x; | 68 | static int rest_x; |
@@ -81,14 +75,14 @@ static DECLARE_MUTEX(hdaps_sem); | |||
81 | */ | 75 | */ |
82 | static inline u8 __get_latch(u16 port) | 76 | static inline u8 __get_latch(u16 port) |
83 | { | 77 | { |
84 | return inb(port) & HDAPS_READ_MASK; | 78 | return inb(port) & 0xff; |
85 | } | 79 | } |
86 | 80 | ||
87 | /* | 81 | /* |
88 | * __check_latch - Check a port latch for a given value. Callers must hold | 82 | * __check_latch - Check a port latch for a given value. Returns zero if the |
89 | * hdaps_sem. Returns zero if the port contains the given value. | 83 | * port contains the given value. Callers must hold hdaps_sem. |
90 | */ | 84 | */ |
91 | static inline unsigned int __check_latch(u16 port, u8 val) | 85 | static inline int __check_latch(u16 port, u8 val) |
92 | { | 86 | { |
93 | if (__get_latch(port) == val) | 87 | if (__get_latch(port) == val) |
94 | return 0; | 88 | return 0; |
@@ -99,7 +93,7 @@ static inline unsigned int __check_latch(u16 port, u8 val) | |||
99 | * __wait_latch - Wait up to 100us for a port latch to get a certain value, | 93 | * __wait_latch - Wait up to 100us for a port latch to get a certain value, |
100 | * returning zero if the value is obtained. Callers must hold hdaps_sem. | 94 | * returning zero if the value is obtained. Callers must hold hdaps_sem. |
101 | */ | 95 | */ |
102 | static unsigned int __wait_latch(u16 port, u8 val) | 96 | static int __wait_latch(u16 port, u8 val) |
103 | { | 97 | { |
104 | unsigned int i; | 98 | unsigned int i; |
105 | 99 | ||
@@ -109,59 +103,42 @@ static unsigned int __wait_latch(u16 port, u8 val) | |||
109 | udelay(5); | 103 | udelay(5); |
110 | } | 104 | } |
111 | 105 | ||
112 | return -EINVAL; | 106 | return -EIO; |
113 | } | 107 | } |
114 | 108 | ||
115 | /* | 109 | /* |
116 | * __device_refresh - Request a refresh from the accelerometer. | 110 | * __device_refresh - request a refresh from the accelerometer. Does not wait |
117 | * | 111 | * for refresh to complete. Callers must hold hdaps_sem. |
118 | * If sync is REFRESH_SYNC, we perform a synchronous refresh and will wait. | ||
119 | * Returns zero if successful and nonzero on error. | ||
120 | * | ||
121 | * If sync is REFRESH_ASYNC, we merely kick off a new refresh if the device is | ||
122 | * not up-to-date. Always returns zero. | ||
123 | * | ||
124 | * Callers must hold hdaps_sem. | ||
125 | */ | 112 | */ |
126 | static int __device_refresh(unsigned int sync) | 113 | static void __device_refresh(void) |
127 | { | 114 | { |
128 | u8 state; | 115 | udelay(200); |
129 | 116 | if (inb(0x1604) != STATE_FRESH) { | |
130 | udelay(100); | 117 | outb(0x11, 0x1610); |
131 | 118 | outb(0x01, 0x161f); | |
132 | state = inb(0x1604); | 119 | } |
133 | if (state == STATE_FRESH) | 120 | } |
134 | return 0; | ||
135 | |||
136 | outb(0x11, 0x1610); | ||
137 | outb(0x01, 0x161f); | ||
138 | if (sync == REFRESH_ASYNC) | ||
139 | return 0; | ||
140 | 121 | ||
122 | /* | ||
123 | * __device_refresh_sync - request a synchronous refresh from the | ||
124 | * accelerometer. We wait for the refresh to complete. Returns zero if | ||
125 | * successful and nonzero on error. Callers must hold hdaps_sem. | ||
126 | */ | ||
127 | static int __device_refresh_sync(void) | ||
128 | { | ||
129 | __device_refresh(); | ||
141 | return __wait_latch(0x1604, STATE_FRESH); | 130 | return __wait_latch(0x1604, STATE_FRESH); |
142 | } | 131 | } |
143 | 132 | ||
144 | /* | 133 | /* |
145 | * __device_complete - Indicate to the accelerometer that we are done reading | 134 | * __device_complete - indicate to the accelerometer that we are done reading |
146 | * data, and then initiate an async refresh. Callers must hold hdaps_sem. | 135 | * data, and then initiate an async refresh. Callers must hold hdaps_sem. |
147 | */ | 136 | */ |
148 | static inline void __device_complete(void) | 137 | static inline void __device_complete(void) |
149 | { | 138 | { |
150 | inb(0x161f); | 139 | inb(0x161f); |
151 | inb(0x1604); | 140 | inb(0x1604); |
152 | __device_refresh(REFRESH_ASYNC); | 141 | __device_refresh(); |
153 | } | ||
154 | |||
155 | static int __hdaps_readb_one(unsigned int port, u8 *val) | ||
156 | { | ||
157 | /* do a sync refresh -- we need to be sure that we read fresh data */ | ||
158 | if (__device_refresh(REFRESH_SYNC)) | ||
159 | return -EIO; | ||
160 | |||
161 | *val = inb(port); | ||
162 | __device_complete(); | ||
163 | |||
164 | return 0; | ||
165 | } | 142 | } |
166 | 143 | ||
167 | /* | 144 | /* |
@@ -174,17 +151,26 @@ static int hdaps_readb_one(unsigned int port, u8 *val) | |||
174 | int ret; | 151 | int ret; |
175 | 152 | ||
176 | down(&hdaps_sem); | 153 | down(&hdaps_sem); |
177 | ret = __hdaps_readb_one(port, val); | ||
178 | up(&hdaps_sem); | ||
179 | 154 | ||
155 | /* do a sync refresh -- we need to be sure that we read fresh data */ | ||
156 | ret = __device_refresh_sync(); | ||
157 | if (ret) | ||
158 | goto out; | ||
159 | |||
160 | *val = inb(port); | ||
161 | __device_complete(); | ||
162 | |||
163 | out: | ||
164 | up(&hdaps_sem); | ||
180 | return ret; | 165 | return ret; |
181 | } | 166 | } |
182 | 167 | ||
168 | /* __hdaps_read_pair - internal lockless helper for hdaps_read_pair(). */ | ||
183 | static int __hdaps_read_pair(unsigned int port1, unsigned int port2, | 169 | static int __hdaps_read_pair(unsigned int port1, unsigned int port2, |
184 | int *x, int *y) | 170 | int *x, int *y) |
185 | { | 171 | { |
186 | /* do a sync refresh -- we need to be sure that we read fresh data */ | 172 | /* do a sync refresh -- we need to be sure that we read fresh data */ |
187 | if (__device_refresh(REFRESH_SYNC)) | 173 | if (__device_refresh_sync()) |
188 | return -EIO; | 174 | return -EIO; |
189 | 175 | ||
190 | *y = inw(port2); | 176 | *y = inw(port2); |
@@ -217,11 +203,13 @@ static int hdaps_read_pair(unsigned int port1, unsigned int port2, | |||
217 | return ret; | 203 | return ret; |
218 | } | 204 | } |
219 | 205 | ||
220 | /* initialize the accelerometer */ | 206 | /* |
207 | * hdaps_device_init - initialize the accelerometer. Returns zero on success | ||
208 | * and negative error code on failure. Can sleep. | ||
209 | */ | ||
221 | static int hdaps_device_init(void) | 210 | static int hdaps_device_init(void) |
222 | { | 211 | { |
223 | unsigned int total_msecs = INIT_TIMEOUT_MSECS; | 212 | int total, ret = -ENXIO; |
224 | int ret = -ENXIO; | ||
225 | 213 | ||
226 | down(&hdaps_sem); | 214 | down(&hdaps_sem); |
227 | 215 | ||
@@ -231,8 +219,10 @@ static int hdaps_device_init(void) | |||
231 | goto out; | 219 | goto out; |
232 | 220 | ||
233 | /* | 221 | /* |
234 | * The 0x03 value appears to only work on some thinkpads, such as the | 222 | * Most ThinkPads return 0x01. |
235 | * T42p. Others return 0x01. | 223 | * |
224 | * Others--namely the R50p, T41p, and T42p--return 0x03. These laptops | ||
225 | * have "inverted" axises. | ||
236 | * | 226 | * |
237 | * The 0x02 value occurs when the chip has been previously initialized. | 227 | * The 0x02 value occurs when the chip has been previously initialized. |
238 | */ | 228 | */ |
@@ -267,24 +257,23 @@ static int hdaps_device_init(void) | |||
267 | outb(0x01, 0x161f); | 257 | outb(0x01, 0x161f); |
268 | if (__wait_latch(0x161f, 0x00)) | 258 | if (__wait_latch(0x161f, 0x00)) |
269 | goto out; | 259 | goto out; |
270 | if (__device_refresh(REFRESH_SYNC)) | 260 | if (__device_refresh_sync()) |
271 | goto out; | 261 | goto out; |
272 | if (__wait_latch(0x1611, 0x00)) | 262 | if (__wait_latch(0x1611, 0x00)) |
273 | goto out; | 263 | goto out; |
274 | 264 | ||
275 | /* we have done our dance, now let's wait for the applause */ | 265 | /* we have done our dance, now let's wait for the applause */ |
276 | while (total_msecs > 0) { | 266 | for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) { |
277 | u8 ignored; | 267 | int x, y; |
278 | 268 | ||
279 | /* a read of the device helps push it into action */ | 269 | /* a read of the device helps push it into action */ |
280 | __hdaps_readb_one(HDAPS_PORT_UNKNOWN, &ignored); | 270 | __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y); |
281 | if (!__wait_latch(0x1611, 0x02)) { | 271 | if (!__wait_latch(0x1611, 0x02)) { |
282 | ret = 0; | 272 | ret = 0; |
283 | break; | 273 | break; |
284 | } | 274 | } |
285 | 275 | ||
286 | msleep(INIT_WAIT_MSECS); | 276 | msleep(INIT_WAIT_MSECS); |
287 | total_msecs -= INIT_WAIT_MSECS; | ||
288 | } | 277 | } |
289 | 278 | ||
290 | out: | 279 | out: |
@@ -293,96 +282,6 @@ out: | |||
293 | } | 282 | } |
294 | 283 | ||
295 | 284 | ||
296 | /* Input class stuff */ | ||
297 | |||
298 | /* | ||
299 | * hdaps_calibrate - Zero out our "resting" values. Callers must hold hdaps_sem. | ||
300 | */ | ||
301 | static void hdaps_calibrate(void) | ||
302 | { | ||
303 | int x, y; | ||
304 | |||
305 | if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) | ||
306 | return; | ||
307 | |||
308 | rest_x = x; | ||
309 | rest_y = y; | ||
310 | } | ||
311 | |||
312 | static void hdaps_mousedev_poll(unsigned long unused) | ||
313 | { | ||
314 | int x, y; | ||
315 | |||
316 | /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ | ||
317 | if (down_trylock(&hdaps_sem)) { | ||
318 | mod_timer(&hdaps_timer,jiffies+msecs_to_jiffies(hdaps_poll_ms)); | ||
319 | return; | ||
320 | } | ||
321 | |||
322 | if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) | ||
323 | goto out; | ||
324 | |||
325 | x -= rest_x; | ||
326 | y -= rest_y; | ||
327 | if (abs(x) > hdaps_mousedev_threshold) | ||
328 | input_report_rel(&hdaps_idev, REL_X, x); | ||
329 | if (abs(y) > hdaps_mousedev_threshold) | ||
330 | input_report_rel(&hdaps_idev, REL_Y, y); | ||
331 | input_sync(&hdaps_idev); | ||
332 | |||
333 | mod_timer(&hdaps_timer, jiffies + msecs_to_jiffies(hdaps_poll_ms)); | ||
334 | |||
335 | out: | ||
336 | up(&hdaps_sem); | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | * hdaps_mousedev_enable - enable the input class device. Can sleep. | ||
341 | */ | ||
342 | static void hdaps_mousedev_enable(void) | ||
343 | { | ||
344 | down(&hdaps_sem); | ||
345 | |||
346 | /* calibrate the device before enabling */ | ||
347 | hdaps_calibrate(); | ||
348 | |||
349 | /* initialize the input class */ | ||
350 | init_input_dev(&hdaps_idev); | ||
351 | hdaps_idev.dev = &pdev->dev; | ||
352 | hdaps_idev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
353 | hdaps_idev.relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
354 | hdaps_idev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT); | ||
355 | input_register_device(&hdaps_idev); | ||
356 | |||
357 | /* start up our timer */ | ||
358 | init_timer(&hdaps_timer); | ||
359 | hdaps_timer.function = hdaps_mousedev_poll; | ||
360 | hdaps_timer.expires = jiffies + msecs_to_jiffies(hdaps_poll_ms); | ||
361 | add_timer(&hdaps_timer); | ||
362 | |||
363 | hdaps_mousedev = 1; | ||
364 | |||
365 | up(&hdaps_sem); | ||
366 | |||
367 | printk(KERN_INFO "hdaps: input device enabled.\n"); | ||
368 | } | ||
369 | |||
370 | /* | ||
371 | * hdaps_mousedev_disable - disable the input class device. Caller must hold | ||
372 | * hdaps_sem. | ||
373 | */ | ||
374 | static void hdaps_mousedev_disable(void) | ||
375 | { | ||
376 | down(&hdaps_sem); | ||
377 | if (hdaps_mousedev) { | ||
378 | hdaps_mousedev = 0; | ||
379 | del_timer_sync(&hdaps_timer); | ||
380 | input_unregister_device(&hdaps_idev); | ||
381 | } | ||
382 | up(&hdaps_sem); | ||
383 | } | ||
384 | |||
385 | |||
386 | /* Device model stuff */ | 285 | /* Device model stuff */ |
387 | 286 | ||
388 | static int hdaps_probe(struct device *dev) | 287 | static int hdaps_probe(struct device *dev) |
@@ -412,6 +311,49 @@ static struct device_driver hdaps_driver = { | |||
412 | .resume = hdaps_resume | 311 | .resume = hdaps_resume |
413 | }; | 312 | }; |
414 | 313 | ||
314 | /* Input class stuff */ | ||
315 | |||
316 | static struct input_dev hdaps_idev = { | ||
317 | .name = "hdaps", | ||
318 | .evbit = { BIT(EV_ABS) }, | ||
319 | .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, | ||
320 | .absmin = { [ABS_X] = -256, [ABS_Y] = -256 }, | ||
321 | .absmax = { [ABS_X] = 256, [ABS_Y] = 256 }, | ||
322 | .absfuzz = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ }, | ||
323 | .absflat = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ }, | ||
324 | }; | ||
325 | |||
326 | /* | ||
327 | * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem. | ||
328 | */ | ||
329 | static void hdaps_calibrate(void) | ||
330 | { | ||
331 | __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y); | ||
332 | } | ||
333 | |||
334 | static void hdaps_mousedev_poll(unsigned long unused) | ||
335 | { | ||
336 | int x, y; | ||
337 | |||
338 | /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ | ||
339 | if (down_trylock(&hdaps_sem)) { | ||
340 | mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD); | ||
341 | return; | ||
342 | } | ||
343 | |||
344 | if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) | ||
345 | goto out; | ||
346 | |||
347 | input_report_abs(&hdaps_idev, ABS_X, x - rest_x); | ||
348 | input_report_abs(&hdaps_idev, ABS_Y, y - rest_y); | ||
349 | input_sync(&hdaps_idev); | ||
350 | |||
351 | mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD); | ||
352 | |||
353 | out: | ||
354 | up(&hdaps_sem); | ||
355 | } | ||
356 | |||
415 | 357 | ||
416 | /* Sysfs Files */ | 358 | /* Sysfs Files */ |
417 | 359 | ||
@@ -517,69 +459,6 @@ static ssize_t hdaps_invert_store(struct device *dev, | |||
517 | return count; | 459 | return count; |
518 | } | 460 | } |
519 | 461 | ||
520 | static ssize_t hdaps_mousedev_show(struct device *dev, | ||
521 | struct device_attribute *attr, char *buf) | ||
522 | { | ||
523 | return sprintf(buf, "%d\n", hdaps_mousedev); | ||
524 | } | ||
525 | |||
526 | static ssize_t hdaps_mousedev_store(struct device *dev, | ||
527 | struct device_attribute *attr, | ||
528 | const char *buf, size_t count) | ||
529 | { | ||
530 | int enable; | ||
531 | |||
532 | if (sscanf(buf, "%d", &enable) != 1) | ||
533 | return -EINVAL; | ||
534 | |||
535 | if (enable == 1) | ||
536 | hdaps_mousedev_enable(); | ||
537 | else if (enable == 0) | ||
538 | hdaps_mousedev_disable(); | ||
539 | else | ||
540 | return -EINVAL; | ||
541 | |||
542 | return count; | ||
543 | } | ||
544 | |||
545 | static ssize_t hdaps_poll_show(struct device *dev, | ||
546 | struct device_attribute *attr, char *buf) | ||
547 | { | ||
548 | return sprintf(buf, "%lu\n", hdaps_poll_ms); | ||
549 | } | ||
550 | |||
551 | static ssize_t hdaps_poll_store(struct device *dev, | ||
552 | struct device_attribute *attr, | ||
553 | const char *buf, size_t count) | ||
554 | { | ||
555 | unsigned int poll; | ||
556 | |||
557 | if (sscanf(buf, "%u", &poll) != 1 || poll == 0) | ||
558 | return -EINVAL; | ||
559 | hdaps_poll_ms = poll; | ||
560 | |||
561 | return count; | ||
562 | } | ||
563 | |||
564 | static ssize_t hdaps_threshold_show(struct device *dev, | ||
565 | struct device_attribute *attr, char *buf) | ||
566 | { | ||
567 | return sprintf(buf, "%u\n", hdaps_mousedev_threshold); | ||
568 | } | ||
569 | |||
570 | static ssize_t hdaps_threshold_store(struct device *dev, | ||
571 | struct device_attribute *attr, | ||
572 | const char *buf, size_t count) | ||
573 | { | ||
574 | unsigned int threshold; | ||
575 | |||
576 | if (sscanf(buf, "%u", &threshold) != 1 || threshold == 0) | ||
577 | return -EINVAL; | ||
578 | hdaps_mousedev_threshold = threshold; | ||
579 | |||
580 | return count; | ||
581 | } | ||
582 | |||
583 | static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL); | 462 | static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL); |
584 | static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL); | 463 | static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL); |
585 | static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL); | 464 | static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL); |
@@ -588,10 +467,6 @@ static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL); | |||
588 | static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL); | 467 | static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL); |
589 | static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store); | 468 | static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store); |
590 | static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store); | 469 | static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store); |
591 | static DEVICE_ATTR(mousedev, 0644, hdaps_mousedev_show, hdaps_mousedev_store); | ||
592 | static DEVICE_ATTR(mousedev_poll_ms, 0644, hdaps_poll_show, hdaps_poll_store); | ||
593 | static DEVICE_ATTR(mousedev_threshold, 0644, hdaps_threshold_show, | ||
594 | hdaps_threshold_store); | ||
595 | 470 | ||
596 | static struct attribute *hdaps_attributes[] = { | 471 | static struct attribute *hdaps_attributes[] = { |
597 | &dev_attr_position.attr, | 472 | &dev_attr_position.attr, |
@@ -601,9 +476,6 @@ static struct attribute *hdaps_attributes[] = { | |||
601 | &dev_attr_keyboard_activity.attr, | 476 | &dev_attr_keyboard_activity.attr, |
602 | &dev_attr_mouse_activity.attr, | 477 | &dev_attr_mouse_activity.attr, |
603 | &dev_attr_calibrate.attr, | 478 | &dev_attr_calibrate.attr, |
604 | &dev_attr_mousedev.attr, | ||
605 | &dev_attr_mousedev_threshold.attr, | ||
606 | &dev_attr_mousedev_poll_ms.attr, | ||
607 | &dev_attr_invert.attr, | 479 | &dev_attr_invert.attr, |
608 | NULL, | 480 | NULL, |
609 | }; | 481 | }; |
@@ -619,7 +491,7 @@ static struct attribute_group hdaps_attribute_group = { | |||
619 | * XXX: We should be able to return nonzero and halt the detection process. | 491 | * XXX: We should be able to return nonzero and halt the detection process. |
620 | * But there is a bug in dmi_check_system() where a nonzero return from the | 492 | * But there is a bug in dmi_check_system() where a nonzero return from the |
621 | * first match will result in a return of failure from dmi_check_system(). | 493 | * first match will result in a return of failure from dmi_check_system(). |
622 | * I fixed this; the patch is in 2.6-mm. Once in Linus's tree we can make | 494 | * I fixed this; the patch is 2.6-git. Once in a released tree, we can make |
623 | * hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1. | 495 | * hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1. |
624 | */ | 496 | */ |
625 | static int hdaps_dmi_match(struct dmi_system_id *id) | 497 | static int hdaps_dmi_match(struct dmi_system_id *id) |
@@ -668,6 +540,7 @@ static int __init hdaps_init(void) | |||
668 | HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"), | 540 | HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"), |
669 | HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"), | 541 | HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"), |
670 | HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"), | 542 | HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"), |
543 | HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"), | ||
671 | { .ident = NULL } | 544 | { .ident = NULL } |
672 | }; | 545 | }; |
673 | 546 | ||
@@ -696,8 +569,18 @@ static int __init hdaps_init(void) | |||
696 | if (ret) | 569 | if (ret) |
697 | goto out_device; | 570 | goto out_device; |
698 | 571 | ||
699 | if (hdaps_mousedev) | 572 | /* initial calibrate for the input device */ |
700 | hdaps_mousedev_enable(); | 573 | hdaps_calibrate(); |
574 | |||
575 | /* initialize the input class */ | ||
576 | hdaps_idev.dev = &pdev->dev; | ||
577 | input_register_device(&hdaps_idev); | ||
578 | |||
579 | /* start up our timer for the input device */ | ||
580 | init_timer(&hdaps_timer); | ||
581 | hdaps_timer.function = hdaps_mousedev_poll; | ||
582 | hdaps_timer.expires = jiffies + HDAPS_POLL_PERIOD; | ||
583 | add_timer(&hdaps_timer); | ||
701 | 584 | ||
702 | printk(KERN_INFO "hdaps: driver successfully loaded.\n"); | 585 | printk(KERN_INFO "hdaps: driver successfully loaded.\n"); |
703 | return 0; | 586 | return 0; |
@@ -715,8 +598,8 @@ out: | |||
715 | 598 | ||
716 | static void __exit hdaps_exit(void) | 599 | static void __exit hdaps_exit(void) |
717 | { | 600 | { |
718 | hdaps_mousedev_disable(); | 601 | del_timer_sync(&hdaps_timer); |
719 | 602 | input_unregister_device(&hdaps_idev); | |
720 | sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); | 603 | sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); |
721 | platform_device_unregister(pdev); | 604 | platform_device_unregister(pdev); |
722 | driver_unregister(&hdaps_driver); | 605 | driver_unregister(&hdaps_driver); |
@@ -728,9 +611,6 @@ static void __exit hdaps_exit(void) | |||
728 | module_init(hdaps_init); | 611 | module_init(hdaps_init); |
729 | module_exit(hdaps_exit); | 612 | module_exit(hdaps_exit); |
730 | 613 | ||
731 | module_param_named(mousedev, hdaps_mousedev, bool, 0); | ||
732 | MODULE_PARM_DESC(mousedev, "enable the input class device"); | ||
733 | |||
734 | module_param_named(invert, hdaps_invert, bool, 0); | 614 | module_param_named(invert, hdaps_invert, bool, 0); |
735 | MODULE_PARM_DESC(invert, "invert data along each axis"); | 615 | MODULE_PARM_DESC(invert, "invert data along each axis"); |
736 | 616 | ||
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index fdf53ce04248..44b595d90a4a 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -914,19 +914,23 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num | |||
914 | return ret; | 914 | return ret; |
915 | } | 915 | } |
916 | 916 | ||
917 | static u32 i2c_pxa_functionality(struct i2c_adapter *adap) | ||
918 | { | ||
919 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
920 | } | ||
921 | |||
917 | static struct i2c_algorithm i2c_pxa_algorithm = { | 922 | static struct i2c_algorithm i2c_pxa_algorithm = { |
918 | .name = "PXA-I2C-Algorithm", | ||
919 | .id = I2C_ALGO_PXA, | ||
920 | .master_xfer = i2c_pxa_xfer, | 923 | .master_xfer = i2c_pxa_xfer, |
924 | .functionality = i2c_pxa_functionality, | ||
921 | }; | 925 | }; |
922 | 926 | ||
923 | static struct pxa_i2c i2c_pxa = { | 927 | static struct pxa_i2c i2c_pxa = { |
924 | .lock = SPIN_LOCK_UNLOCKED, | 928 | .lock = SPIN_LOCK_UNLOCKED, |
925 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER(i2c_pxa.wait), | 929 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER(i2c_pxa.wait), |
926 | .adap = { | 930 | .adap = { |
927 | .name = "pxa2xx-i2c", | 931 | .owner = THIS_MODULE, |
928 | .id = I2C_ALGO_PXA, | ||
929 | .algo = &i2c_pxa_algorithm, | 932 | .algo = &i2c_pxa_algorithm, |
933 | .name = "pxa2xx-i2c", | ||
930 | .retries = 5, | 934 | .retries = 5, |
931 | }, | 935 | }, |
932 | }; | 936 | }; |
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index d04f62ab5de1..ace8edad6e96 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c | |||
@@ -500,6 +500,7 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long | |||
500 | } | 500 | } |
501 | 501 | ||
502 | rq.special = args; | 502 | rq.special = args; |
503 | args->rq = &rq; | ||
503 | return ide_do_drive_cmd(drive, &rq, ide_wait); | 504 | return ide_do_drive_cmd(drive, &rq, ide_wait); |
504 | } | 505 | } |
505 | 506 | ||
diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c index 2bd8b1cc57c4..e23836d0e21b 100644 --- a/drivers/infiniband/core/mad_rmpp.c +++ b/drivers/infiniband/core/mad_rmpp.c | |||
@@ -412,8 +412,8 @@ static inline int get_mad_len(struct mad_rmpp_recv *rmpp_recv) | |||
412 | 412 | ||
413 | hdr_size = data_offset(rmpp_mad->mad_hdr.mgmt_class); | 413 | hdr_size = data_offset(rmpp_mad->mad_hdr.mgmt_class); |
414 | data_size = sizeof(struct ib_rmpp_mad) - hdr_size; | 414 | data_size = sizeof(struct ib_rmpp_mad) - hdr_size; |
415 | pad = data_size - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); | 415 | pad = IB_MGMT_RMPP_DATA - be32_to_cpu(rmpp_mad->rmpp_hdr.paylen_newwin); |
416 | if (pad > data_size || pad < 0) | 416 | if (pad > IB_MGMT_RMPP_DATA || pad < 0) |
417 | pad = 0; | 417 | pad = 0; |
418 | 418 | ||
419 | return hdr_size + rmpp_recv->seg_num * data_size - pad; | 419 | return hdr_size + rmpp_recv->seg_num * data_size - pad; |
@@ -583,6 +583,7 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) | |||
583 | { | 583 | { |
584 | struct ib_rmpp_mad *rmpp_mad; | 584 | struct ib_rmpp_mad *rmpp_mad; |
585 | int timeout; | 585 | int timeout; |
586 | u32 paylen; | ||
586 | 587 | ||
587 | rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr; | 588 | rmpp_mad = (struct ib_rmpp_mad *)mad_send_wr->send_wr.wr.ud.mad_hdr; |
588 | ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE); | 589 | ib_set_rmpp_flags(&rmpp_mad->rmpp_hdr, IB_MGMT_RMPP_FLAG_ACTIVE); |
@@ -590,11 +591,9 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) | |||
590 | 591 | ||
591 | if (mad_send_wr->seg_num == 1) { | 592 | if (mad_send_wr->seg_num == 1) { |
592 | rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST; | 593 | rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST; |
593 | rmpp_mad->rmpp_hdr.paylen_newwin = | 594 | paylen = mad_send_wr->total_seg * IB_MGMT_RMPP_DATA - |
594 | cpu_to_be32(mad_send_wr->total_seg * | 595 | mad_send_wr->pad; |
595 | (sizeof(struct ib_rmpp_mad) - | 596 | rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen); |
596 | offsetof(struct ib_rmpp_mad, data)) - | ||
597 | mad_send_wr->pad); | ||
598 | mad_send_wr->sg_list[0].length = sizeof(struct ib_rmpp_mad); | 597 | mad_send_wr->sg_list[0].length = sizeof(struct ib_rmpp_mad); |
599 | } else { | 598 | } else { |
600 | mad_send_wr->send_wr.num_sge = 2; | 599 | mad_send_wr->send_wr.num_sge = 2; |
@@ -608,10 +607,8 @@ static int send_next_seg(struct ib_mad_send_wr_private *mad_send_wr) | |||
608 | 607 | ||
609 | if (mad_send_wr->seg_num == mad_send_wr->total_seg) { | 608 | if (mad_send_wr->seg_num == mad_send_wr->total_seg) { |
610 | rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST; | 609 | rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST; |
611 | rmpp_mad->rmpp_hdr.paylen_newwin = | 610 | paylen = IB_MGMT_RMPP_DATA - mad_send_wr->pad; |
612 | cpu_to_be32(sizeof(struct ib_rmpp_mad) - | 611 | rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen); |
613 | offsetof(struct ib_rmpp_mad, data) - | ||
614 | mad_send_wr->pad); | ||
615 | } | 612 | } |
616 | 613 | ||
617 | /* 2 seconds for an ACK until we can find the packet lifetime */ | 614 | /* 2 seconds for an ACK until we can find the packet lifetime */ |
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 7c2f03057ddb..a64d6b4dcc16 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c | |||
@@ -334,10 +334,11 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, | |||
334 | ret = -EINVAL; | 334 | ret = -EINVAL; |
335 | goto err_ah; | 335 | goto err_ah; |
336 | } | 336 | } |
337 | /* Validate that management class can support RMPP */ | 337 | |
338 | /* Validate that the management class can support RMPP */ | ||
338 | if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) { | 339 | if (rmpp_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_ADM) { |
339 | hdr_len = offsetof(struct ib_sa_mad, data); | 340 | hdr_len = offsetof(struct ib_sa_mad, data); |
340 | data_len = length; | 341 | data_len = length - hdr_len; |
341 | } else if ((rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && | 342 | } else if ((rmpp_mad->mad_hdr.mgmt_class >= IB_MGMT_CLASS_VENDOR_RANGE2_START) && |
342 | (rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) { | 343 | (rmpp_mad->mad_hdr.mgmt_class <= IB_MGMT_CLASS_VENDOR_RANGE2_END)) { |
343 | hdr_len = offsetof(struct ib_vendor_mad, data); | 344 | hdr_len = offsetof(struct ib_vendor_mad, data); |
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index 18f0981eb0c1..78152a8ad17d 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c | |||
@@ -476,12 +476,8 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, | |||
476 | int i; | 476 | int i; |
477 | u8 status; | 477 | u8 status; |
478 | 478 | ||
479 | /* Make sure EQ size is aligned to a power of 2 size. */ | 479 | eq->dev = dev; |
480 | for (i = 1; i < nent; i <<= 1) | 480 | eq->nent = roundup_pow_of_two(max(nent, 2)); |
481 | ; /* nothing */ | ||
482 | nent = i; | ||
483 | |||
484 | eq->dev = dev; | ||
485 | 481 | ||
486 | eq->page_list = kmalloc(npages * sizeof *eq->page_list, | 482 | eq->page_list = kmalloc(npages * sizeof *eq->page_list, |
487 | GFP_KERNEL); | 483 | GFP_KERNEL); |
@@ -512,7 +508,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, | |||
512 | memset(eq->page_list[i].buf, 0, PAGE_SIZE); | 508 | memset(eq->page_list[i].buf, 0, PAGE_SIZE); |
513 | } | 509 | } |
514 | 510 | ||
515 | for (i = 0; i < nent; ++i) | 511 | for (i = 0; i < eq->nent; ++i) |
516 | set_eqe_hw(get_eqe(eq, i)); | 512 | set_eqe_hw(get_eqe(eq, i)); |
517 | 513 | ||
518 | eq->eqn = mthca_alloc(&dev->eq_table.alloc); | 514 | eq->eqn = mthca_alloc(&dev->eq_table.alloc); |
@@ -528,8 +524,6 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, | |||
528 | if (err) | 524 | if (err) |
529 | goto err_out_free_eq; | 525 | goto err_out_free_eq; |
530 | 526 | ||
531 | eq->nent = nent; | ||
532 | |||
533 | memset(eq_context, 0, sizeof *eq_context); | 527 | memset(eq_context, 0, sizeof *eq_context); |
534 | eq_context->flags = cpu_to_be32(MTHCA_EQ_STATUS_OK | | 528 | eq_context->flags = cpu_to_be32(MTHCA_EQ_STATUS_OK | |
535 | MTHCA_EQ_OWNER_HW | | 529 | MTHCA_EQ_OWNER_HW | |
@@ -538,7 +532,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, | |||
538 | if (mthca_is_memfree(dev)) | 532 | if (mthca_is_memfree(dev)) |
539 | eq_context->flags |= cpu_to_be32(MTHCA_EQ_STATE_ARBEL); | 533 | eq_context->flags |= cpu_to_be32(MTHCA_EQ_STATE_ARBEL); |
540 | 534 | ||
541 | eq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24); | 535 | eq_context->logsize_usrpage = cpu_to_be32((ffs(eq->nent) - 1) << 24); |
542 | if (mthca_is_memfree(dev)) { | 536 | if (mthca_is_memfree(dev)) { |
543 | eq_context->arbel_pd = cpu_to_be32(dev->driver_pd.pd_num); | 537 | eq_context->arbel_pd = cpu_to_be32(dev->driver_pd.pd_num); |
544 | } else { | 538 | } else { |
@@ -569,7 +563,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, | |||
569 | dev->eq_table.arm_mask |= eq->eqn_mask; | 563 | dev->eq_table.arm_mask |= eq->eqn_mask; |
570 | 564 | ||
571 | mthca_dbg(dev, "Allocated EQ %d with %d entries\n", | 565 | mthca_dbg(dev, "Allocated EQ %d with %d entries\n", |
572 | eq->eqn, nent); | 566 | eq->eqn, eq->nent); |
573 | 567 | ||
574 | return err; | 568 | return err; |
575 | 569 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index bcef06bf15e7..5fa00669f9b8 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c | |||
@@ -227,7 +227,6 @@ static void mthca_wq_init(struct mthca_wq *wq) | |||
227 | wq->last_comp = wq->max - 1; | 227 | wq->last_comp = wq->max - 1; |
228 | wq->head = 0; | 228 | wq->head = 0; |
229 | wq->tail = 0; | 229 | wq->tail = 0; |
230 | wq->last = NULL; | ||
231 | } | 230 | } |
232 | 231 | ||
233 | void mthca_qp_event(struct mthca_dev *dev, u32 qpn, | 232 | void mthca_qp_event(struct mthca_dev *dev, u32 qpn, |
@@ -687,7 +686,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
687 | } | 686 | } |
688 | 687 | ||
689 | if (attr_mask & IB_QP_TIMEOUT) { | 688 | if (attr_mask & IB_QP_TIMEOUT) { |
690 | qp_context->pri_path.ackto = attr->timeout; | 689 | qp_context->pri_path.ackto = attr->timeout << 3; |
691 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ACK_TIMEOUT); | 690 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ACK_TIMEOUT); |
692 | } | 691 | } |
693 | 692 | ||
@@ -1103,6 +1102,9 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev, | |||
1103 | } | 1102 | } |
1104 | } | 1103 | } |
1105 | 1104 | ||
1105 | qp->sq.last = get_send_wqe(qp, qp->sq.max - 1); | ||
1106 | qp->rq.last = get_recv_wqe(qp, qp->rq.max - 1); | ||
1107 | |||
1106 | return 0; | 1108 | return 0; |
1107 | } | 1109 | } |
1108 | 1110 | ||
@@ -1583,15 +1585,13 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
1583 | goto out; | 1585 | goto out; |
1584 | } | 1586 | } |
1585 | 1587 | ||
1586 | if (prev_wqe) { | 1588 | ((struct mthca_next_seg *) prev_wqe)->nda_op = |
1587 | ((struct mthca_next_seg *) prev_wqe)->nda_op = | 1589 | cpu_to_be32(((ind << qp->sq.wqe_shift) + |
1588 | cpu_to_be32(((ind << qp->sq.wqe_shift) + | 1590 | qp->send_wqe_offset) | |
1589 | qp->send_wqe_offset) | | 1591 | mthca_opcode[wr->opcode]); |
1590 | mthca_opcode[wr->opcode]); | 1592 | wmb(); |
1591 | wmb(); | 1593 | ((struct mthca_next_seg *) prev_wqe)->ee_nds = |
1592 | ((struct mthca_next_seg *) prev_wqe)->ee_nds = | 1594 | cpu_to_be32((size0 ? 0 : MTHCA_NEXT_DBD) | size); |
1593 | cpu_to_be32((size0 ? 0 : MTHCA_NEXT_DBD) | size); | ||
1594 | } | ||
1595 | 1595 | ||
1596 | if (!size0) { | 1596 | if (!size0) { |
1597 | size0 = size; | 1597 | size0 = size; |
@@ -1688,13 +1688,11 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, | |||
1688 | 1688 | ||
1689 | qp->wrid[ind] = wr->wr_id; | 1689 | qp->wrid[ind] = wr->wr_id; |
1690 | 1690 | ||
1691 | if (likely(prev_wqe)) { | 1691 | ((struct mthca_next_seg *) prev_wqe)->nda_op = |
1692 | ((struct mthca_next_seg *) prev_wqe)->nda_op = | 1692 | cpu_to_be32((ind << qp->rq.wqe_shift) | 1); |
1693 | cpu_to_be32((ind << qp->rq.wqe_shift) | 1); | 1693 | wmb(); |
1694 | wmb(); | 1694 | ((struct mthca_next_seg *) prev_wqe)->ee_nds = |
1695 | ((struct mthca_next_seg *) prev_wqe)->ee_nds = | 1695 | cpu_to_be32(MTHCA_NEXT_DBD | size); |
1696 | cpu_to_be32(MTHCA_NEXT_DBD | size); | ||
1697 | } | ||
1698 | 1696 | ||
1699 | if (!size0) | 1697 | if (!size0) |
1700 | size0 = size; | 1698 | size0 = size; |
@@ -1905,15 +1903,13 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, | |||
1905 | goto out; | 1903 | goto out; |
1906 | } | 1904 | } |
1907 | 1905 | ||
1908 | if (likely(prev_wqe)) { | 1906 | ((struct mthca_next_seg *) prev_wqe)->nda_op = |
1909 | ((struct mthca_next_seg *) prev_wqe)->nda_op = | 1907 | cpu_to_be32(((ind << qp->sq.wqe_shift) + |
1910 | cpu_to_be32(((ind << qp->sq.wqe_shift) + | 1908 | qp->send_wqe_offset) | |
1911 | qp->send_wqe_offset) | | 1909 | mthca_opcode[wr->opcode]); |
1912 | mthca_opcode[wr->opcode]); | 1910 | wmb(); |
1913 | wmb(); | 1911 | ((struct mthca_next_seg *) prev_wqe)->ee_nds = |
1914 | ((struct mthca_next_seg *) prev_wqe)->ee_nds = | 1912 | cpu_to_be32(MTHCA_NEXT_DBD | size); |
1915 | cpu_to_be32(MTHCA_NEXT_DBD | size); | ||
1916 | } | ||
1917 | 1913 | ||
1918 | if (!size0) { | 1914 | if (!size0) { |
1919 | size0 = size; | 1915 | size0 = size; |
@@ -2127,5 +2123,6 @@ void __devexit mthca_cleanup_qp_table(struct mthca_dev *dev) | |||
2127 | for (i = 0; i < 2; ++i) | 2123 | for (i = 0; i < 2; ++i) |
2128 | mthca_CONF_SPECIAL_QP(dev, i, 0, &status); | 2124 | mthca_CONF_SPECIAL_QP(dev, i, 0, &status); |
2129 | 2125 | ||
2126 | mthca_array_cleanup(&dev->qp_table.qp, dev->limits.num_qps); | ||
2130 | mthca_alloc_cleanup(&dev->qp_table.alloc); | 2127 | mthca_alloc_cleanup(&dev->qp_table.alloc); |
2131 | } | 2128 | } |
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 75cd2d84ef12..18998d48c53e 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c | |||
@@ -172,6 +172,8 @@ static int mthca_alloc_srq_buf(struct mthca_dev *dev, struct mthca_pd *pd, | |||
172 | scatter->lkey = cpu_to_be32(MTHCA_INVAL_LKEY); | 172 | scatter->lkey = cpu_to_be32(MTHCA_INVAL_LKEY); |
173 | } | 173 | } |
174 | 174 | ||
175 | srq->last = get_wqe(srq, srq->max - 1); | ||
176 | |||
175 | return 0; | 177 | return 0; |
176 | } | 178 | } |
177 | 179 | ||
@@ -189,7 +191,6 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, | |||
189 | 191 | ||
190 | srq->max = attr->max_wr; | 192 | srq->max = attr->max_wr; |
191 | srq->max_gs = attr->max_sge; | 193 | srq->max_gs = attr->max_sge; |
192 | srq->last = NULL; | ||
193 | srq->counter = 0; | 194 | srq->counter = 0; |
194 | 195 | ||
195 | if (mthca_is_memfree(dev)) | 196 | if (mthca_is_memfree(dev)) |
@@ -409,7 +410,7 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, | |||
409 | mthca_err(dev, "SRQ %06x full\n", srq->srqn); | 410 | mthca_err(dev, "SRQ %06x full\n", srq->srqn); |
410 | err = -ENOMEM; | 411 | err = -ENOMEM; |
411 | *bad_wr = wr; | 412 | *bad_wr = wr; |
412 | return nreq; | 413 | break; |
413 | } | 414 | } |
414 | 415 | ||
415 | wqe = get_wqe(srq, ind); | 416 | wqe = get_wqe(srq, ind); |
@@ -427,7 +428,7 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, | |||
427 | err = -EINVAL; | 428 | err = -EINVAL; |
428 | *bad_wr = wr; | 429 | *bad_wr = wr; |
429 | srq->last = prev_wqe; | 430 | srq->last = prev_wqe; |
430 | return nreq; | 431 | break; |
431 | } | 432 | } |
432 | 433 | ||
433 | for (i = 0; i < wr->num_sge; ++i) { | 434 | for (i = 0; i < wr->num_sge; ++i) { |
@@ -446,20 +447,16 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, | |||
446 | ((struct mthca_data_seg *) wqe)->addr = 0; | 447 | ((struct mthca_data_seg *) wqe)->addr = 0; |
447 | } | 448 | } |
448 | 449 | ||
449 | if (likely(prev_wqe)) { | 450 | ((struct mthca_next_seg *) prev_wqe)->nda_op = |
450 | ((struct mthca_next_seg *) prev_wqe)->nda_op = | 451 | cpu_to_be32((ind << srq->wqe_shift) | 1); |
451 | cpu_to_be32((ind << srq->wqe_shift) | 1); | 452 | wmb(); |
452 | wmb(); | 453 | ((struct mthca_next_seg *) prev_wqe)->ee_nds = |
453 | ((struct mthca_next_seg *) prev_wqe)->ee_nds = | 454 | cpu_to_be32(MTHCA_NEXT_DBD); |
454 | cpu_to_be32(MTHCA_NEXT_DBD); | ||
455 | } | ||
456 | 455 | ||
457 | srq->wrid[ind] = wr->wr_id; | 456 | srq->wrid[ind] = wr->wr_id; |
458 | srq->first_free = next_ind; | 457 | srq->first_free = next_ind; |
459 | } | 458 | } |
460 | 459 | ||
461 | return nreq; | ||
462 | |||
463 | if (likely(nreq)) { | 460 | if (likely(nreq)) { |
464 | __be32 doorbell[2]; | 461 | __be32 doorbell[2]; |
465 | 462 | ||
@@ -503,7 +500,7 @@ int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, | |||
503 | mthca_err(dev, "SRQ %06x full\n", srq->srqn); | 500 | mthca_err(dev, "SRQ %06x full\n", srq->srqn); |
504 | err = -ENOMEM; | 501 | err = -ENOMEM; |
505 | *bad_wr = wr; | 502 | *bad_wr = wr; |
506 | return nreq; | 503 | break; |
507 | } | 504 | } |
508 | 505 | ||
509 | wqe = get_wqe(srq, ind); | 506 | wqe = get_wqe(srq, ind); |
@@ -519,7 +516,7 @@ int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, | |||
519 | if (unlikely(wr->num_sge > srq->max_gs)) { | 516 | if (unlikely(wr->num_sge > srq->max_gs)) { |
520 | err = -EINVAL; | 517 | err = -EINVAL; |
521 | *bad_wr = wr; | 518 | *bad_wr = wr; |
522 | return nreq; | 519 | break; |
523 | } | 520 | } |
524 | 521 | ||
525 | for (i = 0; i < wr->num_sge; ++i) { | 522 | for (i = 0; i < wr->num_sge; ++i) { |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index bea960b8191f..4ea1c1ca85bc 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
@@ -257,7 +257,7 @@ void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid, | |||
257 | 257 | ||
258 | void ipoib_mcast_restart_task(void *dev_ptr); | 258 | void ipoib_mcast_restart_task(void *dev_ptr); |
259 | int ipoib_mcast_start_thread(struct net_device *dev); | 259 | int ipoib_mcast_start_thread(struct net_device *dev); |
260 | int ipoib_mcast_stop_thread(struct net_device *dev); | 260 | int ipoib_mcast_stop_thread(struct net_device *dev, int flush); |
261 | 261 | ||
262 | void ipoib_mcast_dev_down(struct net_device *dev); | 262 | void ipoib_mcast_dev_down(struct net_device *dev); |
263 | void ipoib_mcast_dev_flush(struct net_device *dev); | 263 | void ipoib_mcast_dev_flush(struct net_device *dev); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index ef0e3894863c..f7440096b5ed 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
@@ -432,7 +432,7 @@ int ipoib_ib_dev_down(struct net_device *dev) | |||
432 | flush_workqueue(ipoib_workqueue); | 432 | flush_workqueue(ipoib_workqueue); |
433 | } | 433 | } |
434 | 434 | ||
435 | ipoib_mcast_stop_thread(dev); | 435 | ipoib_mcast_stop_thread(dev, 1); |
436 | 436 | ||
437 | /* | 437 | /* |
438 | * Flush the multicast groups first so we stop any multicast joins. The | 438 | * Flush the multicast groups first so we stop any multicast joins. The |
@@ -599,7 +599,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) | |||
599 | 599 | ||
600 | ipoib_dbg(priv, "cleaning up ib_dev\n"); | 600 | ipoib_dbg(priv, "cleaning up ib_dev\n"); |
601 | 601 | ||
602 | ipoib_mcast_stop_thread(dev); | 602 | ipoib_mcast_stop_thread(dev, 1); |
603 | 603 | ||
604 | /* Delete the broadcast address and the local address */ | 604 | /* Delete the broadcast address and the local address */ |
605 | ipoib_mcast_dev_down(dev); | 605 | ipoib_mcast_dev_down(dev); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 49d120d2b92c..704f48e0b6a7 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -1005,6 +1005,7 @@ debug_failed: | |||
1005 | 1005 | ||
1006 | register_failed: | 1006 | register_failed: |
1007 | ib_unregister_event_handler(&priv->event_handler); | 1007 | ib_unregister_event_handler(&priv->event_handler); |
1008 | flush_scheduled_work(); | ||
1008 | 1009 | ||
1009 | event_failed: | 1010 | event_failed: |
1010 | ipoib_dev_cleanup(priv->dev); | 1011 | ipoib_dev_cleanup(priv->dev); |
@@ -1057,6 +1058,7 @@ static void ipoib_remove_one(struct ib_device *device) | |||
1057 | 1058 | ||
1058 | list_for_each_entry_safe(priv, tmp, dev_list, list) { | 1059 | list_for_each_entry_safe(priv, tmp, dev_list, list) { |
1059 | ib_unregister_event_handler(&priv->event_handler); | 1060 | ib_unregister_event_handler(&priv->event_handler); |
1061 | flush_scheduled_work(); | ||
1060 | 1062 | ||
1061 | unregister_netdev(priv->dev); | 1063 | unregister_netdev(priv->dev); |
1062 | ipoib_dev_cleanup(priv->dev); | 1064 | ipoib_dev_cleanup(priv->dev); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index aca7aea18a69..36ce29836bf2 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
@@ -145,7 +145,7 @@ static struct ipoib_mcast *ipoib_mcast_alloc(struct net_device *dev, | |||
145 | 145 | ||
146 | mcast->dev = dev; | 146 | mcast->dev = dev; |
147 | mcast->created = jiffies; | 147 | mcast->created = jiffies; |
148 | mcast->backoff = HZ; | 148 | mcast->backoff = 1; |
149 | mcast->logcount = 0; | 149 | mcast->logcount = 0; |
150 | 150 | ||
151 | INIT_LIST_HEAD(&mcast->list); | 151 | INIT_LIST_HEAD(&mcast->list); |
@@ -396,7 +396,7 @@ static void ipoib_mcast_join_complete(int status, | |||
396 | IPOIB_GID_ARG(mcast->mcmember.mgid), status); | 396 | IPOIB_GID_ARG(mcast->mcmember.mgid), status); |
397 | 397 | ||
398 | if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) { | 398 | if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) { |
399 | mcast->backoff = HZ; | 399 | mcast->backoff = 1; |
400 | down(&mcast_mutex); | 400 | down(&mcast_mutex); |
401 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | 401 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) |
402 | queue_work(ipoib_workqueue, &priv->mcast_task); | 402 | queue_work(ipoib_workqueue, &priv->mcast_task); |
@@ -496,7 +496,7 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, | |||
496 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | 496 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) |
497 | queue_delayed_work(ipoib_workqueue, | 497 | queue_delayed_work(ipoib_workqueue, |
498 | &priv->mcast_task, | 498 | &priv->mcast_task, |
499 | mcast->backoff); | 499 | mcast->backoff * HZ); |
500 | up(&mcast_mutex); | 500 | up(&mcast_mutex); |
501 | } else | 501 | } else |
502 | mcast->query_id = ret; | 502 | mcast->query_id = ret; |
@@ -598,7 +598,7 @@ int ipoib_mcast_start_thread(struct net_device *dev) | |||
598 | return 0; | 598 | return 0; |
599 | } | 599 | } |
600 | 600 | ||
601 | int ipoib_mcast_stop_thread(struct net_device *dev) | 601 | int ipoib_mcast_stop_thread(struct net_device *dev, int flush) |
602 | { | 602 | { |
603 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 603 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
604 | struct ipoib_mcast *mcast; | 604 | struct ipoib_mcast *mcast; |
@@ -610,7 +610,8 @@ int ipoib_mcast_stop_thread(struct net_device *dev) | |||
610 | cancel_delayed_work(&priv->mcast_task); | 610 | cancel_delayed_work(&priv->mcast_task); |
611 | up(&mcast_mutex); | 611 | up(&mcast_mutex); |
612 | 612 | ||
613 | flush_workqueue(ipoib_workqueue); | 613 | if (flush) |
614 | flush_workqueue(ipoib_workqueue); | ||
614 | 615 | ||
615 | if (priv->broadcast && priv->broadcast->query) { | 616 | if (priv->broadcast && priv->broadcast->query) { |
616 | ib_sa_cancel_query(priv->broadcast->query_id, priv->broadcast->query); | 617 | ib_sa_cancel_query(priv->broadcast->query_id, priv->broadcast->query); |
@@ -832,7 +833,7 @@ void ipoib_mcast_restart_task(void *dev_ptr) | |||
832 | 833 | ||
833 | ipoib_dbg_mcast(priv, "restarting multicast task\n"); | 834 | ipoib_dbg_mcast(priv, "restarting multicast task\n"); |
834 | 835 | ||
835 | ipoib_mcast_stop_thread(dev); | 836 | ipoib_mcast_stop_thread(dev, 0); |
836 | 837 | ||
837 | spin_lock_irqsave(&priv->lock, flags); | 838 | spin_lock_irqsave(&priv->lock, flags); |
838 | 839 | ||
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 8337b0f26cc4..4866fc32d8d9 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c | |||
@@ -61,6 +61,7 @@ static const PCI_ENTRY id_list[] = | |||
61 | {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"}, | 61 | {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"}, |
62 | {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"}, | 62 | {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"}, |
63 | {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"}, | 63 | {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"}, |
64 | {PCI_VENDOR_ID_SITECOM, PCI_DEVICE_ID_SITECOM_DC105V2, "Sitecom Europe", "DC-105 ISDN PCI"}, | ||
64 | {0, 0, NULL, NULL}, | 65 | {0, 0, NULL, NULL}, |
65 | }; | 66 | }; |
66 | 67 | ||
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index c6b5bf7d2aca..dc334aab433e 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c | |||
@@ -611,7 +611,7 @@ static int sedlbauer_event(event_t event, int priority, | |||
611 | } /* sedlbauer_event */ | 611 | } /* sedlbauer_event */ |
612 | 612 | ||
613 | static struct pcmcia_device_id sedlbauer_ids[] = { | 613 | static struct pcmcia_device_id sedlbauer_ids[] = { |
614 | PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", "speed star II", "V 3.1", "(c) 93 - 98 cb ", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a, 0x50d4149c), | 614 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "speed star II", "V 3.1", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a), |
615 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90), | 615 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90), |
616 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce), | 616 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce), |
617 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (C) 93-94 VK", 0x81fb79f5, 0xe4e9bc12, 0x8db143fe), | 617 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (C) 93-94 VK", 0x81fb79f5, 0xe4e9bc12, 0x8db143fe), |
diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h index 0fda5c89429b..9ffaae7c657a 100644 --- a/drivers/isdn/hisax/st5481.h +++ b/drivers/isdn/hisax/st5481.h | |||
@@ -466,10 +466,10 @@ void st5481_stop(struct st5481_adapter *adapter); | |||
466 | #define __debug_variable st5481_debug | 466 | #define __debug_variable st5481_debug |
467 | #include "hisax_debug.h" | 467 | #include "hisax_debug.h" |
468 | 468 | ||
469 | #ifdef CONFIG_HISAX_DEBUG | ||
470 | |||
471 | extern int st5481_debug; | 469 | extern int st5481_debug; |
472 | 470 | ||
471 | #ifdef CONFIG_HISAX_DEBUG | ||
472 | |||
473 | #define DBG_ISO_PACKET(level,urb) \ | 473 | #define DBG_ISO_PACKET(level,urb) \ |
474 | if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb) | 474 | if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb) |
475 | 475 | ||
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c index 2fcd093921d8..0a2536d62402 100644 --- a/drivers/isdn/hisax/st5481_b.c +++ b/drivers/isdn/hisax/st5481_b.c | |||
@@ -172,14 +172,18 @@ static void usb_b_out_complete(struct urb *urb, struct pt_regs *regs) | |||
172 | test_and_clear_bit(buf_nr, &b_out->busy); | 172 | test_and_clear_bit(buf_nr, &b_out->busy); |
173 | 173 | ||
174 | if (unlikely(urb->status < 0)) { | 174 | if (unlikely(urb->status < 0)) { |
175 | if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { | 175 | switch (urb->status) { |
176 | WARN("urb status %d",urb->status); | 176 | case -ENOENT: |
177 | if (b_out->busy == 0) { | 177 | case -ESHUTDOWN: |
178 | st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL); | 178 | case -ECONNRESET: |
179 | } | 179 | DBG(4,"urb killed status %d", urb->status); |
180 | } else { | 180 | return; // Give up |
181 | DBG(1,"urb killed"); | 181 | default: |
182 | return; // Give up | 182 | WARN("urb status %d",urb->status); |
183 | if (b_out->busy == 0) { | ||
184 | st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL); | ||
185 | } | ||
186 | break; | ||
183 | } | 187 | } |
184 | } | 188 | } |
185 | 189 | ||
@@ -205,7 +209,9 @@ static void st5481B_mode(struct st5481_bcs *bcs, int mode) | |||
205 | bcs->mode = mode; | 209 | bcs->mode = mode; |
206 | 210 | ||
207 | // Cancel all USB transfers on this B channel | 211 | // Cancel all USB transfers on this B channel |
212 | b_out->urb[0]->transfer_flags |= URB_ASYNC_UNLINK; | ||
208 | usb_unlink_urb(b_out->urb[0]); | 213 | usb_unlink_urb(b_out->urb[0]); |
214 | b_out->urb[1]->transfer_flags |= URB_ASYNC_UNLINK; | ||
209 | usb_unlink_urb(b_out->urb[1]); | 215 | usb_unlink_urb(b_out->urb[1]); |
210 | b_out->busy = 0; | 216 | b_out->busy = 0; |
211 | 217 | ||
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c index 071b1d31999f..941f7022ada1 100644 --- a/drivers/isdn/hisax/st5481_d.c +++ b/drivers/isdn/hisax/st5481_d.c | |||
@@ -382,16 +382,20 @@ static void usb_d_out_complete(struct urb *urb, struct pt_regs *regs) | |||
382 | test_and_clear_bit(buf_nr, &d_out->busy); | 382 | test_and_clear_bit(buf_nr, &d_out->busy); |
383 | 383 | ||
384 | if (unlikely(urb->status < 0)) { | 384 | if (unlikely(urb->status < 0)) { |
385 | if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { | 385 | switch (urb->status) { |
386 | WARN("urb status %d",urb->status); | 386 | case -ENOENT: |
387 | if (d_out->busy == 0) { | 387 | case -ESHUTDOWN: |
388 | st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter); | 388 | case -ECONNRESET: |
389 | } | 389 | DBG(1,"urb killed status %d", urb->status); |
390 | return; | 390 | break; |
391 | } else { | 391 | default: |
392 | DBG(1,"urb killed"); | 392 | WARN("urb status %d",urb->status); |
393 | return; // Give up | 393 | if (d_out->busy == 0) { |
394 | st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter); | ||
395 | } | ||
396 | break; | ||
394 | } | 397 | } |
398 | return; // Give up | ||
395 | } | 399 | } |
396 | 400 | ||
397 | FsmEvent(&adapter->d_out.fsm, EV_DOUT_COMPLETE, (void *) buf_nr); | 401 | FsmEvent(&adapter->d_out.fsm, EV_DOUT_COMPLETE, (void *) buf_nr); |
@@ -709,14 +713,14 @@ int st5481_setup_d(struct st5481_adapter *adapter) | |||
709 | 713 | ||
710 | adapter->l1m.fsm = &l1fsm; | 714 | adapter->l1m.fsm = &l1fsm; |
711 | adapter->l1m.state = ST_L1_F3; | 715 | adapter->l1m.state = ST_L1_F3; |
712 | adapter->l1m.debug = 1; | 716 | adapter->l1m.debug = st5481_debug & 0x100; |
713 | adapter->l1m.userdata = adapter; | 717 | adapter->l1m.userdata = adapter; |
714 | adapter->l1m.printdebug = l1m_debug; | 718 | adapter->l1m.printdebug = l1m_debug; |
715 | FsmInitTimer(&adapter->l1m, &adapter->timer); | 719 | FsmInitTimer(&adapter->l1m, &adapter->timer); |
716 | 720 | ||
717 | adapter->d_out.fsm.fsm = &dout_fsm; | 721 | adapter->d_out.fsm.fsm = &dout_fsm; |
718 | adapter->d_out.fsm.state = ST_DOUT_NONE; | 722 | adapter->d_out.fsm.state = ST_DOUT_NONE; |
719 | adapter->d_out.fsm.debug = 1; | 723 | adapter->d_out.fsm.debug = st5481_debug & 0x100; |
720 | adapter->d_out.fsm.userdata = adapter; | 724 | adapter->d_out.fsm.userdata = adapter; |
721 | adapter->d_out.fsm.printdebug = dout_debug; | 725 | adapter->d_out.fsm.printdebug = dout_debug; |
722 | 726 | ||
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c index 7aa810d5d333..2cf5d1a6df6c 100644 --- a/drivers/isdn/hisax/st5481_init.c +++ b/drivers/isdn/hisax/st5481_init.c | |||
@@ -43,10 +43,10 @@ static int number_of_leds = 2; /* 2 LEDs on the adpater default */ | |||
43 | module_param(number_of_leds, int, 0); | 43 | module_param(number_of_leds, int, 0); |
44 | 44 | ||
45 | #ifdef CONFIG_HISAX_DEBUG | 45 | #ifdef CONFIG_HISAX_DEBUG |
46 | static int debug = 0x1; | 46 | static int debug = 0; |
47 | module_param(debug, int, 0); | 47 | module_param(debug, int, 0); |
48 | int st5481_debug; | ||
49 | #endif | 48 | #endif |
49 | int st5481_debug; | ||
50 | 50 | ||
51 | static LIST_HEAD(adapter_list); | 51 | static LIST_HEAD(adapter_list); |
52 | 52 | ||
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c index ab62223297a5..ffd5b2d45552 100644 --- a/drivers/isdn/hisax/st5481_usb.c +++ b/drivers/isdn/hisax/st5481_usb.c | |||
@@ -132,11 +132,15 @@ static void usb_ctrl_complete(struct urb *urb, struct pt_regs *regs) | |||
132 | struct ctrl_msg *ctrl_msg; | 132 | struct ctrl_msg *ctrl_msg; |
133 | 133 | ||
134 | if (unlikely(urb->status < 0)) { | 134 | if (unlikely(urb->status < 0)) { |
135 | if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { | 135 | switch (urb->status) { |
136 | WARN("urb status %d",urb->status); | 136 | case -ENOENT: |
137 | } else { | 137 | case -ESHUTDOWN: |
138 | DBG(1,"urb killed"); | 138 | case -ECONNRESET: |
139 | return; // Give up | 139 | DBG(1,"urb killed status %d", urb->status); |
140 | return; // Give up | ||
141 | default: | ||
142 | WARN("urb status %d",urb->status); | ||
143 | break; | ||
140 | } | 144 | } |
141 | } | 145 | } |
142 | 146 | ||
@@ -184,22 +188,22 @@ static void usb_int_complete(struct urb *urb, struct pt_regs *regs) | |||
184 | int status; | 188 | int status; |
185 | 189 | ||
186 | switch (urb->status) { | 190 | switch (urb->status) { |
187 | case 0: | 191 | case 0: |
188 | /* success */ | 192 | /* success */ |
189 | break; | 193 | break; |
190 | case -ECONNRESET: | 194 | case -ECONNRESET: |
191 | case -ENOENT: | 195 | case -ENOENT: |
192 | case -ESHUTDOWN: | 196 | case -ESHUTDOWN: |
193 | /* this urb is terminated, clean up */ | 197 | /* this urb is terminated, clean up */ |
194 | DBG(1, "urb shutting down with status: %d", urb->status); | 198 | DBG(2, "urb shutting down with status: %d", urb->status); |
195 | return; | 199 | return; |
196 | default: | 200 | default: |
197 | WARN("nonzero urb status received: %d", urb->status); | 201 | WARN("nonzero urb status received: %d", urb->status); |
198 | goto exit; | 202 | goto exit; |
199 | } | 203 | } |
200 | 204 | ||
201 | 205 | ||
202 | DBG_PACKET(1, data, INT_PKT_SIZE); | 206 | DBG_PACKET(2, data, INT_PKT_SIZE); |
203 | 207 | ||
204 | if (urb->actual_length == 0) { | 208 | if (urb->actual_length == 0) { |
205 | goto exit; | 209 | goto exit; |
@@ -250,7 +254,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter) | |||
250 | struct urb *urb; | 254 | struct urb *urb; |
251 | u8 *buf; | 255 | u8 *buf; |
252 | 256 | ||
253 | DBG(1,""); | 257 | DBG(2,""); |
254 | 258 | ||
255 | if ((status = usb_reset_configuration (dev)) < 0) { | 259 | if ((status = usb_reset_configuration (dev)) < 0) { |
256 | WARN("reset_configuration failed,status=%d",status); | 260 | WARN("reset_configuration failed,status=%d",status); |
@@ -330,15 +334,17 @@ void st5481_release_usb(struct st5481_adapter *adapter) | |||
330 | DBG(1,""); | 334 | DBG(1,""); |
331 | 335 | ||
332 | // Stop and free Control and Interrupt URBs | 336 | // Stop and free Control and Interrupt URBs |
333 | usb_unlink_urb(ctrl->urb); | 337 | usb_kill_urb(ctrl->urb); |
334 | if (ctrl->urb->transfer_buffer) | 338 | if (ctrl->urb->transfer_buffer) |
335 | kfree(ctrl->urb->transfer_buffer); | 339 | kfree(ctrl->urb->transfer_buffer); |
336 | usb_free_urb(ctrl->urb); | 340 | usb_free_urb(ctrl->urb); |
341 | ctrl->urb = NULL; | ||
337 | 342 | ||
338 | usb_unlink_urb(intr->urb); | 343 | usb_kill_urb(intr->urb); |
339 | if (intr->urb->transfer_buffer) | 344 | if (intr->urb->transfer_buffer) |
340 | kfree(intr->urb->transfer_buffer); | 345 | kfree(intr->urb->transfer_buffer); |
341 | usb_free_urb(intr->urb); | 346 | usb_free_urb(intr->urb); |
347 | ctrl->urb = NULL; | ||
342 | } | 348 | } |
343 | 349 | ||
344 | /* | 350 | /* |
@@ -406,6 +412,7 @@ fill_isoc_urb(struct urb *urb, struct usb_device *dev, | |||
406 | spin_lock_init(&urb->lock); | 412 | spin_lock_init(&urb->lock); |
407 | urb->dev=dev; | 413 | urb->dev=dev; |
408 | urb->pipe=pipe; | 414 | urb->pipe=pipe; |
415 | urb->interval = 1; | ||
409 | urb->transfer_buffer=buf; | 416 | urb->transfer_buffer=buf; |
410 | urb->number_of_packets = num_packets; | 417 | urb->number_of_packets = num_packets; |
411 | urb->transfer_buffer_length=num_packets*packet_size; | 418 | urb->transfer_buffer_length=num_packets*packet_size; |
@@ -452,7 +459,9 @@ st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev, | |||
452 | if (urb[j]) { | 459 | if (urb[j]) { |
453 | if (urb[j]->transfer_buffer) | 460 | if (urb[j]->transfer_buffer) |
454 | kfree(urb[j]->transfer_buffer); | 461 | kfree(urb[j]->transfer_buffer); |
462 | urb[j]->transfer_buffer = NULL; | ||
455 | usb_free_urb(urb[j]); | 463 | usb_free_urb(urb[j]); |
464 | urb[j] = NULL; | ||
456 | } | 465 | } |
457 | } | 466 | } |
458 | return retval; | 467 | return retval; |
@@ -463,10 +472,11 @@ void st5481_release_isocpipes(struct urb* urb[2]) | |||
463 | int j; | 472 | int j; |
464 | 473 | ||
465 | for (j = 0; j < 2; j++) { | 474 | for (j = 0; j < 2; j++) { |
466 | usb_unlink_urb(urb[j]); | 475 | usb_kill_urb(urb[j]); |
467 | if (urb[j]->transfer_buffer) | 476 | if (urb[j]->transfer_buffer) |
468 | kfree(urb[j]->transfer_buffer); | 477 | kfree(urb[j]->transfer_buffer); |
469 | usb_free_urb(urb[j]); | 478 | usb_free_urb(urb[j]); |
479 | urb[j] = NULL; | ||
470 | } | 480 | } |
471 | } | 481 | } |
472 | 482 | ||
@@ -485,11 +495,15 @@ static void usb_in_complete(struct urb *urb, struct pt_regs *regs) | |||
485 | int len, count, status; | 495 | int len, count, status; |
486 | 496 | ||
487 | if (unlikely(urb->status < 0)) { | 497 | if (unlikely(urb->status < 0)) { |
488 | if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { | 498 | switch (urb->status) { |
489 | WARN("urb status %d",urb->status); | 499 | case -ENOENT: |
490 | } else { | 500 | case -ESHUTDOWN: |
491 | DBG(1,"urb killed"); | 501 | case -ECONNRESET: |
492 | return; // Give up | 502 | DBG(1,"urb killed status %d", urb->status); |
503 | return; // Give up | ||
504 | default: | ||
505 | WARN("urb status %d",urb->status); | ||
506 | break; | ||
493 | } | 507 | } |
494 | } | 508 | } |
495 | 509 | ||
@@ -631,7 +645,9 @@ void st5481_in_mode(struct st5481_in *in, int mode) | |||
631 | 645 | ||
632 | in->mode = mode; | 646 | in->mode = mode; |
633 | 647 | ||
648 | in->urb[0]->transfer_flags |= URB_ASYNC_UNLINK; | ||
634 | usb_unlink_urb(in->urb[0]); | 649 | usb_unlink_urb(in->urb[0]); |
650 | in->urb[1]->transfer_flags |= URB_ASYNC_UNLINK; | ||
635 | usb_unlink_urb(in->urb[1]); | 651 | usb_unlink_urb(in->urb[1]); |
636 | 652 | ||
637 | if (in->mode != L1_MODE_NULL) { | 653 | if (in->mode != L1_MODE_NULL) { |
diff --git a/drivers/md/raid6.h b/drivers/md/raid6.h index f80ee6350edf..31cbee71365f 100644 --- a/drivers/md/raid6.h +++ b/drivers/md/raid6.h | |||
@@ -69,9 +69,13 @@ extern const char raid6_empty_zero_page[PAGE_SIZE]; | |||
69 | #define __init | 69 | #define __init |
70 | #define __exit | 70 | #define __exit |
71 | #define __attribute_const__ __attribute__((const)) | 71 | #define __attribute_const__ __attribute__((const)) |
72 | #define noinline __attribute__((noinline)) | ||
72 | 73 | ||
73 | #define preempt_enable() | 74 | #define preempt_enable() |
74 | #define preempt_disable() | 75 | #define preempt_disable() |
76 | #define cpu_has_feature(x) 1 | ||
77 | #define enable_kernel_altivec() | ||
78 | #define disable_kernel_altivec() | ||
75 | 79 | ||
76 | #endif /* __KERNEL__ */ | 80 | #endif /* __KERNEL__ */ |
77 | 81 | ||
diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c index acf386fc4b4f..51c63c0cf1c9 100644 --- a/drivers/md/raid6algos.c +++ b/drivers/md/raid6algos.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include "raid6.h" | 19 | #include "raid6.h" |
20 | #ifndef __KERNEL__ | 20 | #ifndef __KERNEL__ |
21 | #include <sys/mman.h> | 21 | #include <sys/mman.h> |
22 | #include <stdio.h> | ||
22 | #endif | 23 | #endif |
23 | 24 | ||
24 | struct raid6_calls raid6_call; | 25 | struct raid6_calls raid6_call; |
diff --git a/drivers/md/raid6altivec.uc b/drivers/md/raid6altivec.uc index 1de8f030eee0..b9afd35b8812 100644 --- a/drivers/md/raid6altivec.uc +++ b/drivers/md/raid6altivec.uc | |||
@@ -27,16 +27,20 @@ | |||
27 | #ifdef CONFIG_ALTIVEC | 27 | #ifdef CONFIG_ALTIVEC |
28 | 28 | ||
29 | #include <altivec.h> | 29 | #include <altivec.h> |
30 | #include <asm/system.h> | 30 | #ifdef __KERNEL__ |
31 | #include <asm/cputable.h> | 31 | # include <asm/system.h> |
32 | # include <asm/cputable.h> | ||
33 | #endif | ||
32 | 34 | ||
33 | /* | 35 | /* |
34 | * This is the C data type to use | 36 | * This is the C data type to use. We use a vector of |
37 | * signed char so vec_cmpgt() will generate the right | ||
38 | * instruction. | ||
35 | */ | 39 | */ |
36 | 40 | ||
37 | typedef vector unsigned char unative_t; | 41 | typedef vector signed char unative_t; |
38 | 42 | ||
39 | #define NBYTES(x) ((vector unsigned char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}) | 43 | #define NBYTES(x) ((vector signed char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}) |
40 | #define NSIZE sizeof(unative_t) | 44 | #define NSIZE sizeof(unative_t) |
41 | 45 | ||
42 | /* | 46 | /* |
@@ -108,7 +112,11 @@ int raid6_have_altivec(void); | |||
108 | int raid6_have_altivec(void) | 112 | int raid6_have_altivec(void) |
109 | { | 113 | { |
110 | /* This assumes either all CPUs have Altivec or none does */ | 114 | /* This assumes either all CPUs have Altivec or none does */ |
115 | # ifdef __KERNEL__ | ||
111 | return cpu_has_feature(CPU_FTR_ALTIVEC); | 116 | return cpu_has_feature(CPU_FTR_ALTIVEC); |
117 | # else | ||
118 | return 1; | ||
119 | # endif | ||
112 | } | 120 | } |
113 | #endif | 121 | #endif |
114 | 122 | ||
diff --git a/drivers/md/raid6test/Makefile b/drivers/md/raid6test/Makefile index 557806728609..78e0396adf2a 100644 --- a/drivers/md/raid6test/Makefile +++ b/drivers/md/raid6test/Makefile | |||
@@ -8,6 +8,8 @@ OPTFLAGS = -O2 # Adjust as desired | |||
8 | CFLAGS = -I.. -g $(OPTFLAGS) | 8 | CFLAGS = -I.. -g $(OPTFLAGS) |
9 | LD = ld | 9 | LD = ld |
10 | PERL = perl | 10 | PERL = perl |
11 | AR = ar | ||
12 | RANLIB = ranlib | ||
11 | 13 | ||
12 | .c.o: | 14 | .c.o: |
13 | $(CC) $(CFLAGS) -c -o $@ $< | 15 | $(CC) $(CFLAGS) -c -o $@ $< |
@@ -18,18 +20,33 @@ PERL = perl | |||
18 | %.uc: ../%.uc | 20 | %.uc: ../%.uc |
19 | cp -f $< $@ | 21 | cp -f $< $@ |
20 | 22 | ||
21 | all: raid6.o raid6test | 23 | all: raid6.a raid6test |
22 | 24 | ||
23 | raid6.o: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \ | 25 | raid6.a: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \ |
24 | raid6int32.o \ | 26 | raid6int32.o \ |
25 | raid6mmx.o raid6sse1.o raid6sse2.o \ | 27 | raid6mmx.o raid6sse1.o raid6sse2.o \ |
28 | raid6altivec1.o raid6altivec2.o raid6altivec4.o raid6altivec8.o \ | ||
26 | raid6recov.o raid6algos.o \ | 29 | raid6recov.o raid6algos.o \ |
27 | raid6tables.o | 30 | raid6tables.o |
28 | $(LD) -r -o $@ $^ | 31 | rm -f $@ |
32 | $(AR) cq $@ $^ | ||
33 | $(RANLIB) $@ | ||
29 | 34 | ||
30 | raid6test: raid6.o test.c | 35 | raid6test: test.c raid6.a |
31 | $(CC) $(CFLAGS) -o raid6test $^ | 36 | $(CC) $(CFLAGS) -o raid6test $^ |
32 | 37 | ||
38 | raid6altivec1.c: raid6altivec.uc ../unroll.pl | ||
39 | $(PERL) ../unroll.pl 1 < raid6altivec.uc > $@ | ||
40 | |||
41 | raid6altivec2.c: raid6altivec.uc ../unroll.pl | ||
42 | $(PERL) ../unroll.pl 2 < raid6altivec.uc > $@ | ||
43 | |||
44 | raid6altivec4.c: raid6altivec.uc ../unroll.pl | ||
45 | $(PERL) ../unroll.pl 4 < raid6altivec.uc > $@ | ||
46 | |||
47 | raid6altivec8.c: raid6altivec.uc ../unroll.pl | ||
48 | $(PERL) ../unroll.pl 8 < raid6altivec.uc > $@ | ||
49 | |||
33 | raid6int1.c: raid6int.uc ../unroll.pl | 50 | raid6int1.c: raid6int.uc ../unroll.pl |
34 | $(PERL) ../unroll.pl 1 < raid6int.uc > $@ | 51 | $(PERL) ../unroll.pl 1 < raid6int.uc > $@ |
35 | 52 | ||
@@ -52,7 +69,7 @@ raid6tables.c: mktables | |||
52 | ./mktables > raid6tables.c | 69 | ./mktables > raid6tables.c |
53 | 70 | ||
54 | clean: | 71 | clean: |
55 | rm -f *.o mktables mktables.c raid6int.uc raid6*.c raid6test | 72 | rm -f *.o *.a mktables mktables.c raid6int.uc raid6*.c raid6test |
56 | 73 | ||
57 | spotless: clean | 74 | spotless: clean |
58 | rm -f *~ | 75 | rm -f *~ |
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index 33f209a39cb6..1883d22cffeb 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig | |||
@@ -35,6 +35,23 @@ config FUSION_FC | |||
35 | LSIFC929X | 35 | LSIFC929X |
36 | LSIFC929XL | 36 | LSIFC929XL |
37 | 37 | ||
38 | config FUSION_SAS | ||
39 | tristate "Fusion MPT ScsiHost drivers for SAS" | ||
40 | depends on PCI && SCSI | ||
41 | select FUSION | ||
42 | select SCSI_SAS_ATTRS | ||
43 | ---help--- | ||
44 | SCSI HOST support for a SAS host adapters. | ||
45 | |||
46 | List of supported controllers: | ||
47 | |||
48 | LSISAS1064 | ||
49 | LSISAS1066 | ||
50 | LSISAS1068 | ||
51 | LSISAS1064E | ||
52 | LSISAS1066E | ||
53 | LSISAS1068E | ||
54 | |||
38 | config FUSION_MAX_SGE | 55 | config FUSION_MAX_SGE |
39 | int "Maximum number of scatter gather entries (16 - 128)" | 56 | int "Maximum number of scatter gather entries (16 - 128)" |
40 | depends on FUSION | 57 | depends on FUSION |
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile index 1d2f9db813c1..8a2e2657f4c2 100644 --- a/drivers/message/fusion/Makefile +++ b/drivers/message/fusion/Makefile | |||
@@ -34,5 +34,6 @@ | |||
34 | 34 | ||
35 | obj-$(CONFIG_FUSION_SPI) += mptbase.o mptscsih.o mptspi.o | 35 | obj-$(CONFIG_FUSION_SPI) += mptbase.o mptscsih.o mptspi.o |
36 | obj-$(CONFIG_FUSION_FC) += mptbase.o mptscsih.o mptfc.o | 36 | obj-$(CONFIG_FUSION_FC) += mptbase.o mptscsih.o mptfc.o |
37 | obj-$(CONFIG_FUSION_SAS) += mptbase.o mptscsih.o mptsas.o | ||
37 | obj-$(CONFIG_FUSION_CTL) += mptctl.o | 38 | obj-$(CONFIG_FUSION_CTL) += mptctl.o |
38 | obj-$(CONFIG_FUSION_LAN) += mptlan.o | 39 | obj-$(CONFIG_FUSION_LAN) += mptlan.o |
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index f517d0692d5f..790a2932ded9 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -135,13 +135,12 @@ static void mpt_adapter_dispose(MPT_ADAPTER *ioc); | |||
135 | 135 | ||
136 | static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc); | 136 | static void MptDisplayIocCapabilities(MPT_ADAPTER *ioc); |
137 | static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag); | 137 | static int MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag); |
138 | //static u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked); | ||
139 | static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason); | 138 | static int GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason); |
140 | static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag); | 139 | static int GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag); |
141 | static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag); | 140 | static int SendIocInit(MPT_ADAPTER *ioc, int sleepFlag); |
142 | static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag); | 141 | static int SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag); |
143 | static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag); | 142 | static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag); |
144 | static int mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag); | 143 | static int mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag); |
145 | static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag); | 144 | static int mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag); |
146 | static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag); | 145 | static int KickStart(MPT_ADAPTER *ioc, int ignore, int sleepFlag); |
147 | static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag); | 146 | static int SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag); |
@@ -152,6 +151,7 @@ static int WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag); | |||
152 | static int GetLanConfigPages(MPT_ADAPTER *ioc); | 151 | static int GetLanConfigPages(MPT_ADAPTER *ioc); |
153 | static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); | 152 | static int GetFcPortPage0(MPT_ADAPTER *ioc, int portnum); |
154 | static int GetIoUnitPage2(MPT_ADAPTER *ioc); | 153 | static int GetIoUnitPage2(MPT_ADAPTER *ioc); |
154 | int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); | ||
155 | static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum); | 155 | static int mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum); |
156 | static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); | 156 | static int mpt_readScsiDevicePageHeaders(MPT_ADAPTER *ioc, int portnum); |
157 | static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); | 157 | static void mpt_read_ioc_pg_1(MPT_ADAPTER *ioc); |
@@ -159,6 +159,8 @@ static void mpt_read_ioc_pg_4(MPT_ADAPTER *ioc); | |||
159 | static void mpt_timer_expired(unsigned long data); | 159 | static void mpt_timer_expired(unsigned long data); |
160 | static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch); | 160 | static int SendEventNotification(MPT_ADAPTER *ioc, u8 EvSwitch); |
161 | static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); | 161 | static int SendEventAck(MPT_ADAPTER *ioc, EventNotificationReply_t *evnp); |
162 | static int mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag); | ||
163 | static int mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init); | ||
162 | 164 | ||
163 | #ifdef CONFIG_PROC_FS | 165 | #ifdef CONFIG_PROC_FS |
164 | static int procmpt_summary_read(char *buf, char **start, off_t offset, | 166 | static int procmpt_summary_read(char *buf, char **start, off_t offset, |
@@ -175,6 +177,7 @@ static int ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t * | |||
175 | static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); | 177 | static void mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf); |
176 | static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); | 178 | static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info); |
177 | static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info); | 179 | static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info); |
180 | static void mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info); | ||
178 | 181 | ||
179 | /* module entry point */ | 182 | /* module entry point */ |
180 | static int __init fusion_init (void); | 183 | static int __init fusion_init (void); |
@@ -206,6 +209,144 @@ pci_enable_io_access(struct pci_dev *pdev) | |||
206 | pci_write_config_word(pdev, PCI_COMMAND, command_reg); | 209 | pci_write_config_word(pdev, PCI_COMMAND, command_reg); |
207 | } | 210 | } |
208 | 211 | ||
212 | /* | ||
213 | * Process turbo (context) reply... | ||
214 | */ | ||
215 | static void | ||
216 | mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa) | ||
217 | { | ||
218 | MPT_FRAME_HDR *mf = NULL; | ||
219 | MPT_FRAME_HDR *mr = NULL; | ||
220 | int req_idx = 0; | ||
221 | int cb_idx; | ||
222 | |||
223 | dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", | ||
224 | ioc->name, pa)); | ||
225 | |||
226 | switch (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT) { | ||
227 | case MPI_CONTEXT_REPLY_TYPE_SCSI_INIT: | ||
228 | req_idx = pa & 0x0000FFFF; | ||
229 | cb_idx = (pa & 0x00FF0000) >> 16; | ||
230 | mf = MPT_INDEX_2_MFPTR(ioc, req_idx); | ||
231 | break; | ||
232 | case MPI_CONTEXT_REPLY_TYPE_LAN: | ||
233 | cb_idx = mpt_lan_index; | ||
234 | /* | ||
235 | * Blind set of mf to NULL here was fatal | ||
236 | * after lan_reply says "freeme" | ||
237 | * Fix sort of combined with an optimization here; | ||
238 | * added explicit check for case where lan_reply | ||
239 | * was just returning 1 and doing nothing else. | ||
240 | * For this case skip the callback, but set up | ||
241 | * proper mf value first here:-) | ||
242 | */ | ||
243 | if ((pa & 0x58000000) == 0x58000000) { | ||
244 | req_idx = pa & 0x0000FFFF; | ||
245 | mf = MPT_INDEX_2_MFPTR(ioc, req_idx); | ||
246 | mpt_free_msg_frame(ioc, mf); | ||
247 | mb(); | ||
248 | return; | ||
249 | break; | ||
250 | } | ||
251 | mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); | ||
252 | break; | ||
253 | case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET: | ||
254 | cb_idx = mpt_stm_index; | ||
255 | mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); | ||
256 | break; | ||
257 | default: | ||
258 | cb_idx = 0; | ||
259 | BUG(); | ||
260 | } | ||
261 | |||
262 | /* Check for (valid) IO callback! */ | ||
263 | if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || | ||
264 | MptCallbacks[cb_idx] == NULL) { | ||
265 | printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n", | ||
266 | __FUNCTION__, ioc->name, cb_idx); | ||
267 | goto out; | ||
268 | } | ||
269 | |||
270 | if (MptCallbacks[cb_idx](ioc, mf, mr)) | ||
271 | mpt_free_msg_frame(ioc, mf); | ||
272 | out: | ||
273 | mb(); | ||
274 | } | ||
275 | |||
276 | static void | ||
277 | mpt_reply(MPT_ADAPTER *ioc, u32 pa) | ||
278 | { | ||
279 | MPT_FRAME_HDR *mf; | ||
280 | MPT_FRAME_HDR *mr; | ||
281 | int req_idx; | ||
282 | int cb_idx; | ||
283 | int freeme; | ||
284 | |||
285 | u32 reply_dma_low; | ||
286 | u16 ioc_stat; | ||
287 | |||
288 | /* non-TURBO reply! Hmmm, something may be up... | ||
289 | * Newest turbo reply mechanism; get address | ||
290 | * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)! | ||
291 | */ | ||
292 | |||
293 | /* Map DMA address of reply header to cpu address. | ||
294 | * pa is 32 bits - but the dma address may be 32 or 64 bits | ||
295 | * get offset based only only the low addresses | ||
296 | */ | ||
297 | |||
298 | reply_dma_low = (pa <<= 1); | ||
299 | mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames + | ||
300 | (reply_dma_low - ioc->reply_frames_low_dma)); | ||
301 | |||
302 | req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx); | ||
303 | cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx; | ||
304 | mf = MPT_INDEX_2_MFPTR(ioc, req_idx); | ||
305 | |||
306 | dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n", | ||
307 | ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function)); | ||
308 | DBG_DUMP_REPLY_FRAME(mr) | ||
309 | |||
310 | /* Check/log IOC log info | ||
311 | */ | ||
312 | ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus); | ||
313 | if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { | ||
314 | u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); | ||
315 | if (ioc->bus_type == FC) | ||
316 | mpt_fc_log_info(ioc, log_info); | ||
317 | else if (ioc->bus_type == SCSI) | ||
318 | mpt_sp_log_info(ioc, log_info); | ||
319 | else if (ioc->bus_type == SAS) | ||
320 | mpt_sas_log_info(ioc, log_info); | ||
321 | } | ||
322 | if (ioc_stat & MPI_IOCSTATUS_MASK) { | ||
323 | if (ioc->bus_type == SCSI && | ||
324 | cb_idx != mpt_stm_index && | ||
325 | cb_idx != mpt_lan_index) | ||
326 | mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf); | ||
327 | } | ||
328 | |||
329 | |||
330 | /* Check for (valid) IO callback! */ | ||
331 | if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || | ||
332 | MptCallbacks[cb_idx] == NULL) { | ||
333 | printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n", | ||
334 | __FUNCTION__, ioc->name, cb_idx); | ||
335 | freeme = 0; | ||
336 | goto out; | ||
337 | } | ||
338 | |||
339 | freeme = MptCallbacks[cb_idx](ioc, mf, mr); | ||
340 | |||
341 | out: | ||
342 | /* Flush (non-TURBO) reply with a WRITE! */ | ||
343 | CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa); | ||
344 | |||
345 | if (freeme) | ||
346 | mpt_free_msg_frame(ioc, mf); | ||
347 | mb(); | ||
348 | } | ||
349 | |||
209 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 350 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
210 | /* | 351 | /* |
211 | * mpt_interrupt - MPT adapter (IOC) specific interrupt handler. | 352 | * mpt_interrupt - MPT adapter (IOC) specific interrupt handler. |
@@ -227,164 +368,21 @@ pci_enable_io_access(struct pci_dev *pdev) | |||
227 | static irqreturn_t | 368 | static irqreturn_t |
228 | mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) | 369 | mpt_interrupt(int irq, void *bus_id, struct pt_regs *r) |
229 | { | 370 | { |
230 | MPT_ADAPTER *ioc; | 371 | MPT_ADAPTER *ioc = bus_id; |
231 | MPT_FRAME_HDR *mf; | 372 | u32 pa; |
232 | MPT_FRAME_HDR *mr; | ||
233 | u32 pa; | ||
234 | int req_idx; | ||
235 | int cb_idx; | ||
236 | int type; | ||
237 | int freeme; | ||
238 | |||
239 | ioc = (MPT_ADAPTER *)bus_id; | ||
240 | 373 | ||
241 | /* | 374 | /* |
242 | * Drain the reply FIFO! | 375 | * Drain the reply FIFO! |
243 | * | ||
244 | * NOTES: I've seen up to 10 replies processed in this loop, so far... | ||
245 | * Update: I've seen up to 9182 replies processed in this loop! ?? | ||
246 | * Update: Limit ourselves to processing max of N replies | ||
247 | * (bottom of loop). | ||
248 | */ | 376 | */ |
249 | while (1) { | 377 | while (1) { |
250 | 378 | pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo); | |
251 | if ((pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo)) == 0xFFFFFFFF) | 379 | if (pa == 0xFFFFFFFF) |
252 | return IRQ_HANDLED; | 380 | return IRQ_HANDLED; |
253 | 381 | else if (pa & MPI_ADDRESS_REPLY_A_BIT) | |
254 | cb_idx = 0; | 382 | mpt_reply(ioc, pa); |
255 | freeme = 0; | 383 | else |
256 | 384 | mpt_turbo_reply(ioc, pa); | |
257 | /* | 385 | } |
258 | * Check for non-TURBO reply! | ||
259 | */ | ||
260 | if (pa & MPI_ADDRESS_REPLY_A_BIT) { | ||
261 | u32 reply_dma_low; | ||
262 | u16 ioc_stat; | ||
263 | |||
264 | /* non-TURBO reply! Hmmm, something may be up... | ||
265 | * Newest turbo reply mechanism; get address | ||
266 | * via left shift 1 (get rid of MPI_ADDRESS_REPLY_A_BIT)! | ||
267 | */ | ||
268 | |||
269 | /* Map DMA address of reply header to cpu address. | ||
270 | * pa is 32 bits - but the dma address may be 32 or 64 bits | ||
271 | * get offset based only only the low addresses | ||
272 | */ | ||
273 | reply_dma_low = (pa = (pa << 1)); | ||
274 | mr = (MPT_FRAME_HDR *)((u8 *)ioc->reply_frames + | ||
275 | (reply_dma_low - ioc->reply_frames_low_dma)); | ||
276 | |||
277 | req_idx = le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx); | ||
278 | cb_idx = mr->u.frame.hwhdr.msgctxu.fld.cb_idx; | ||
279 | mf = MPT_INDEX_2_MFPTR(ioc, req_idx); | ||
280 | |||
281 | dmfprintk((MYIOC_s_INFO_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n", | ||
282 | ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function)); | ||
283 | DBG_DUMP_REPLY_FRAME(mr) | ||
284 | |||
285 | /* Check/log IOC log info | ||
286 | */ | ||
287 | ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus); | ||
288 | if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { | ||
289 | u32 log_info = le32_to_cpu(mr->u.reply.IOCLogInfo); | ||
290 | if (ioc->bus_type == FC) | ||
291 | mpt_fc_log_info(ioc, log_info); | ||
292 | else if (ioc->bus_type == SCSI) | ||
293 | mpt_sp_log_info(ioc, log_info); | ||
294 | } | ||
295 | if (ioc_stat & MPI_IOCSTATUS_MASK) { | ||
296 | if (ioc->bus_type == SCSI) | ||
297 | mpt_sp_ioc_info(ioc, (u32)ioc_stat, mf); | ||
298 | } | ||
299 | } else { | ||
300 | /* | ||
301 | * Process turbo (context) reply... | ||
302 | */ | ||
303 | dmfprintk((MYIOC_s_INFO_FMT "Got TURBO reply req_idx=%08x\n", ioc->name, pa)); | ||
304 | type = (pa >> MPI_CONTEXT_REPLY_TYPE_SHIFT); | ||
305 | if (type == MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET) { | ||
306 | cb_idx = mpt_stm_index; | ||
307 | mf = NULL; | ||
308 | mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); | ||
309 | } else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) { | ||
310 | cb_idx = mpt_lan_index; | ||
311 | /* Blind set of mf to NULL here was fatal | ||
312 | * after lan_reply says "freeme" | ||
313 | * Fix sort of combined with an optimization here; | ||
314 | * added explicit check for case where lan_reply | ||
315 | * was just returning 1 and doing nothing else. | ||
316 | * For this case skip the callback, but set up | ||
317 | * proper mf value first here:-) | ||
318 | */ | ||
319 | if ((pa & 0x58000000) == 0x58000000) { | ||
320 | req_idx = pa & 0x0000FFFF; | ||
321 | mf = MPT_INDEX_2_MFPTR(ioc, req_idx); | ||
322 | freeme = 1; | ||
323 | /* | ||
324 | * IMPORTANT! Invalidate the callback! | ||
325 | */ | ||
326 | cb_idx = 0; | ||
327 | } else { | ||
328 | mf = NULL; | ||
329 | } | ||
330 | mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); | ||
331 | } else { | ||
332 | req_idx = pa & 0x0000FFFF; | ||
333 | cb_idx = (pa & 0x00FF0000) >> 16; | ||
334 | mf = MPT_INDEX_2_MFPTR(ioc, req_idx); | ||
335 | mr = NULL; | ||
336 | } | ||
337 | pa = 0; /* No reply flush! */ | ||
338 | } | ||
339 | |||
340 | #ifdef MPT_DEBUG_IRQ | ||
341 | if (ioc->bus_type == SCSI) { | ||
342 | /* Verify mf, mr are reasonable. | ||
343 | */ | ||
344 | if ((mf) && ((mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth)) | ||
345 | || (mf < ioc->req_frames)) ) { | ||
346 | printk(MYIOC_s_WARN_FMT | ||
347 | "mpt_interrupt: Invalid mf (%p)!\n", ioc->name, (void *)mf); | ||
348 | cb_idx = 0; | ||
349 | pa = 0; | ||
350 | freeme = 0; | ||
351 | } | ||
352 | if ((pa) && (mr) && ((mr >= MPT_INDEX_2_RFPTR(ioc, ioc->req_depth)) | ||
353 | || (mr < ioc->reply_frames)) ) { | ||
354 | printk(MYIOC_s_WARN_FMT | ||
355 | "mpt_interrupt: Invalid rf (%p)!\n", ioc->name, (void *)mr); | ||
356 | cb_idx = 0; | ||
357 | pa = 0; | ||
358 | freeme = 0; | ||
359 | } | ||
360 | if (cb_idx > (MPT_MAX_PROTOCOL_DRIVERS-1)) { | ||
361 | printk(MYIOC_s_WARN_FMT | ||
362 | "mpt_interrupt: Invalid cb_idx (%d)!\n", ioc->name, cb_idx); | ||
363 | cb_idx = 0; | ||
364 | pa = 0; | ||
365 | freeme = 0; | ||
366 | } | ||
367 | } | ||
368 | #endif | ||
369 | |||
370 | /* Check for (valid) IO callback! */ | ||
371 | if (cb_idx) { | ||
372 | /* Do the callback! */ | ||
373 | freeme = (*(MptCallbacks[cb_idx]))(ioc, mf, mr); | ||
374 | } | ||
375 | |||
376 | if (pa) { | ||
377 | /* Flush (non-TURBO) reply with a WRITE! */ | ||
378 | CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa); | ||
379 | } | ||
380 | |||
381 | if (freeme) { | ||
382 | /* Put Request back on FreeQ! */ | ||
383 | mpt_free_msg_frame(ioc, mf); | ||
384 | } | ||
385 | |||
386 | mb(); | ||
387 | } /* drain reply FIFO */ | ||
388 | 386 | ||
389 | return IRQ_HANDLED; | 387 | return IRQ_HANDLED; |
390 | } | 388 | } |
@@ -509,6 +507,14 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) | |||
509 | pCfg->wait_done = 1; | 507 | pCfg->wait_done = 1; |
510 | wake_up(&mpt_waitq); | 508 | wake_up(&mpt_waitq); |
511 | } | 509 | } |
510 | } else if (func == MPI_FUNCTION_SAS_IO_UNIT_CONTROL) { | ||
511 | /* we should be always getting a reply frame */ | ||
512 | memcpy(ioc->persist_reply_frame, reply, | ||
513 | min(MPT_DEFAULT_FRAME_SIZE, | ||
514 | 4*reply->u.reply.MsgLength)); | ||
515 | del_timer(&ioc->persist_timer); | ||
516 | ioc->persist_wait_done = 1; | ||
517 | wake_up(&mpt_waitq); | ||
512 | } else { | 518 | } else { |
513 | printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n", | 519 | printk(MYIOC_s_ERR_FMT "Unexpected msg function (=%02Xh) reply received!\n", |
514 | ioc->name, func); | 520 | ioc->name, func); |
@@ -750,6 +756,7 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) | |||
750 | mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR, | 756 | mf = list_entry(ioc->FreeQ.next, MPT_FRAME_HDR, |
751 | u.frame.linkage.list); | 757 | u.frame.linkage.list); |
752 | list_del(&mf->u.frame.linkage.list); | 758 | list_del(&mf->u.frame.linkage.list); |
759 | mf->u.frame.linkage.arg1 = 0; | ||
753 | mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ | 760 | mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ |
754 | req_offset = (u8 *)mf - (u8 *)ioc->req_frames; | 761 | req_offset = (u8 *)mf - (u8 *)ioc->req_frames; |
755 | /* u16! */ | 762 | /* u16! */ |
@@ -845,6 +852,7 @@ mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) | |||
845 | 852 | ||
846 | /* Put Request back on FreeQ! */ | 853 | /* Put Request back on FreeQ! */ |
847 | spin_lock_irqsave(&ioc->FreeQlock, flags); | 854 | spin_lock_irqsave(&ioc->FreeQlock, flags); |
855 | mf->u.frame.linkage.arg1 = 0xdeadbeaf; /* signature to know if this mf is freed */ | ||
848 | list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); | 856 | list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ); |
849 | #ifdef MFCNT | 857 | #ifdef MFCNT |
850 | ioc->mfcnt--; | 858 | ioc->mfcnt--; |
@@ -971,12 +979,123 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, | |||
971 | 979 | ||
972 | /* Make sure there are no doorbells */ | 980 | /* Make sure there are no doorbells */ |
973 | CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); | 981 | CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); |
974 | 982 | ||
975 | return r; | 983 | return r; |
976 | } | 984 | } |
977 | 985 | ||
978 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 986 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
979 | /** | 987 | /** |
988 | * mpt_host_page_access_control - provides mechanism for the host | ||
989 | * driver to control the IOC's Host Page Buffer access. | ||
990 | * @ioc: Pointer to MPT adapter structure | ||
991 | * @access_control_value: define bits below | ||
992 | * | ||
993 | * Access Control Value - bits[15:12] | ||
994 | * 0h Reserved | ||
995 | * 1h Enable Access { MPI_DB_HPBAC_ENABLE_ACCESS } | ||
996 | * 2h Disable Access { MPI_DB_HPBAC_DISABLE_ACCESS } | ||
997 | * 3h Free Buffer { MPI_DB_HPBAC_FREE_BUFFER } | ||
998 | * | ||
999 | * Returns 0 for success, non-zero for failure. | ||
1000 | */ | ||
1001 | |||
1002 | static int | ||
1003 | mpt_host_page_access_control(MPT_ADAPTER *ioc, u8 access_control_value, int sleepFlag) | ||
1004 | { | ||
1005 | int r = 0; | ||
1006 | |||
1007 | /* return if in use */ | ||
1008 | if (CHIPREG_READ32(&ioc->chip->Doorbell) | ||
1009 | & MPI_DOORBELL_ACTIVE) | ||
1010 | return -1; | ||
1011 | |||
1012 | CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); | ||
1013 | |||
1014 | CHIPREG_WRITE32(&ioc->chip->Doorbell, | ||
1015 | ((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL | ||
1016 | <<MPI_DOORBELL_FUNCTION_SHIFT) | | ||
1017 | (access_control_value<<12))); | ||
1018 | |||
1019 | /* Wait for IOC to clear Doorbell Status bit */ | ||
1020 | if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) { | ||
1021 | return -2; | ||
1022 | }else | ||
1023 | return 0; | ||
1024 | } | ||
1025 | |||
1026 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
1027 | /** | ||
1028 | * mpt_host_page_alloc - allocate system memory for the fw | ||
1029 | * If we already allocated memory in past, then resend the same pointer. | ||
1030 | * ioc@: Pointer to pointer to IOC adapter | ||
1031 | * ioc_init@: Pointer to ioc init config page | ||
1032 | * | ||
1033 | * Returns 0 for success, non-zero for failure. | ||
1034 | */ | ||
1035 | static int | ||
1036 | mpt_host_page_alloc(MPT_ADAPTER *ioc, pIOCInit_t ioc_init) | ||
1037 | { | ||
1038 | char *psge; | ||
1039 | int flags_length; | ||
1040 | u32 host_page_buffer_sz=0; | ||
1041 | |||
1042 | if(!ioc->HostPageBuffer) { | ||
1043 | |||
1044 | host_page_buffer_sz = | ||
1045 | le32_to_cpu(ioc->facts.HostPageBufferSGE.FlagsLength) & 0xFFFFFF; | ||
1046 | |||
1047 | if(!host_page_buffer_sz) | ||
1048 | return 0; /* fw doesn't need any host buffers */ | ||
1049 | |||
1050 | /* spin till we get enough memory */ | ||
1051 | while(host_page_buffer_sz > 0) { | ||
1052 | |||
1053 | if((ioc->HostPageBuffer = pci_alloc_consistent( | ||
1054 | ioc->pcidev, | ||
1055 | host_page_buffer_sz, | ||
1056 | &ioc->HostPageBuffer_dma)) != NULL) { | ||
1057 | |||
1058 | dinitprintk((MYIOC_s_INFO_FMT | ||
1059 | "host_page_buffer @ %p, dma @ %x, sz=%d bytes\n", | ||
1060 | ioc->name, | ||
1061 | ioc->HostPageBuffer, | ||
1062 | ioc->HostPageBuffer_dma, | ||
1063 | host_page_buffer_sz)); | ||
1064 | ioc->alloc_total += host_page_buffer_sz; | ||
1065 | ioc->HostPageBuffer_sz = host_page_buffer_sz; | ||
1066 | break; | ||
1067 | } | ||
1068 | |||
1069 | host_page_buffer_sz -= (4*1024); | ||
1070 | } | ||
1071 | } | ||
1072 | |||
1073 | if(!ioc->HostPageBuffer) { | ||
1074 | printk(MYIOC_s_ERR_FMT | ||
1075 | "Failed to alloc memory for host_page_buffer!\n", | ||
1076 | ioc->name); | ||
1077 | return -999; | ||
1078 | } | ||
1079 | |||
1080 | psge = (char *)&ioc_init->HostPageBufferSGE; | ||
1081 | flags_length = MPI_SGE_FLAGS_SIMPLE_ELEMENT | | ||
1082 | MPI_SGE_FLAGS_SYSTEM_ADDRESS | | ||
1083 | MPI_SGE_FLAGS_32_BIT_ADDRESSING | | ||
1084 | MPI_SGE_FLAGS_HOST_TO_IOC | | ||
1085 | MPI_SGE_FLAGS_END_OF_BUFFER; | ||
1086 | if (sizeof(dma_addr_t) == sizeof(u64)) { | ||
1087 | flags_length |= MPI_SGE_FLAGS_64_BIT_ADDRESSING; | ||
1088 | } | ||
1089 | flags_length = flags_length << MPI_SGE_FLAGS_SHIFT; | ||
1090 | flags_length |= ioc->HostPageBuffer_sz; | ||
1091 | mpt_add_sge(psge, flags_length, ioc->HostPageBuffer_dma); | ||
1092 | ioc->facts.HostPageBufferSGE = ioc_init->HostPageBufferSGE; | ||
1093 | |||
1094 | return 0; | ||
1095 | } | ||
1096 | |||
1097 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
1098 | /** | ||
980 | * mpt_verify_adapter - Given a unique IOC identifier, set pointer to | 1099 | * mpt_verify_adapter - Given a unique IOC identifier, set pointer to |
981 | * the associated MPT adapter structure. | 1100 | * the associated MPT adapter structure. |
982 | * @iocid: IOC unique identifier (integer) | 1101 | * @iocid: IOC unique identifier (integer) |
@@ -1084,7 +1203,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1084 | 1203 | ||
1085 | /* Initilize SCSI Config Data structure | 1204 | /* Initilize SCSI Config Data structure |
1086 | */ | 1205 | */ |
1087 | memset(&ioc->spi_data, 0, sizeof(ScsiCfgData)); | 1206 | memset(&ioc->spi_data, 0, sizeof(SpiCfgData)); |
1088 | 1207 | ||
1089 | /* Initialize the running configQ head. | 1208 | /* Initialize the running configQ head. |
1090 | */ | 1209 | */ |
@@ -1213,6 +1332,33 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1213 | ioc->prod_name = "LSI53C1035"; | 1332 | ioc->prod_name = "LSI53C1035"; |
1214 | ioc->bus_type = SCSI; | 1333 | ioc->bus_type = SCSI; |
1215 | } | 1334 | } |
1335 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064) { | ||
1336 | ioc->prod_name = "LSISAS1064"; | ||
1337 | ioc->bus_type = SAS; | ||
1338 | ioc->errata_flag_1064 = 1; | ||
1339 | } | ||
1340 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066) { | ||
1341 | ioc->prod_name = "LSISAS1066"; | ||
1342 | ioc->bus_type = SAS; | ||
1343 | ioc->errata_flag_1064 = 1; | ||
1344 | } | ||
1345 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068) { | ||
1346 | ioc->prod_name = "LSISAS1068"; | ||
1347 | ioc->bus_type = SAS; | ||
1348 | ioc->errata_flag_1064 = 1; | ||
1349 | } | ||
1350 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1064E) { | ||
1351 | ioc->prod_name = "LSISAS1064E"; | ||
1352 | ioc->bus_type = SAS; | ||
1353 | } | ||
1354 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1066E) { | ||
1355 | ioc->prod_name = "LSISAS1066E"; | ||
1356 | ioc->bus_type = SAS; | ||
1357 | } | ||
1358 | else if (pdev->device == MPI_MANUFACTPAGE_DEVID_SAS1068E) { | ||
1359 | ioc->prod_name = "LSISAS1068E"; | ||
1360 | ioc->bus_type = SAS; | ||
1361 | } | ||
1216 | 1362 | ||
1217 | if (ioc->errata_flag_1064) | 1363 | if (ioc->errata_flag_1064) |
1218 | pci_disable_io_access(pdev); | 1364 | pci_disable_io_access(pdev); |
@@ -1604,8 +1750,23 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
1604 | */ | 1750 | */ |
1605 | if (ret == 0) { | 1751 | if (ret == 0) { |
1606 | rc = mpt_do_upload(ioc, sleepFlag); | 1752 | rc = mpt_do_upload(ioc, sleepFlag); |
1607 | if (rc != 0) | 1753 | if (rc == 0) { |
1754 | if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) { | ||
1755 | /* | ||
1756 | * Maintain only one pointer to FW memory | ||
1757 | * so there will not be two attempt to | ||
1758 | * downloadboot onboard dual function | ||
1759 | * chips (mpt_adapter_disable, | ||
1760 | * mpt_diag_reset) | ||
1761 | */ | ||
1762 | ioc->cached_fw = NULL; | ||
1763 | ddlprintk((MYIOC_s_INFO_FMT ": mpt_upload: alt_%s has cached_fw=%p \n", | ||
1764 | ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw)); | ||
1765 | } | ||
1766 | } else { | ||
1608 | printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); | 1767 | printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); |
1768 | ret = -5; | ||
1769 | } | ||
1609 | } | 1770 | } |
1610 | } | 1771 | } |
1611 | } | 1772 | } |
@@ -1640,7 +1801,22 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) | |||
1640 | * and we try GetLanConfigPages again... | 1801 | * and we try GetLanConfigPages again... |
1641 | */ | 1802 | */ |
1642 | if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { | 1803 | if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) { |
1643 | if (ioc->bus_type == FC) { | 1804 | if (ioc->bus_type == SAS) { |
1805 | |||
1806 | /* clear persistency table */ | ||
1807 | if(ioc->facts.IOCExceptions & | ||
1808 | MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL) { | ||
1809 | ret = mptbase_sas_persist_operation(ioc, | ||
1810 | MPI_SAS_OP_CLEAR_NOT_PRESENT); | ||
1811 | if(ret != 0) | ||
1812 | return -1; | ||
1813 | } | ||
1814 | |||
1815 | /* Find IM volumes | ||
1816 | */ | ||
1817 | mpt_findImVolumes(ioc); | ||
1818 | |||
1819 | } else if (ioc->bus_type == FC) { | ||
1644 | /* | 1820 | /* |
1645 | * Pre-fetch FC port WWN and stuff... | 1821 | * Pre-fetch FC port WWN and stuff... |
1646 | * (FCPortPage0_t stuff) | 1822 | * (FCPortPage0_t stuff) |
@@ -1783,7 +1959,7 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) | |||
1783 | 1959 | ||
1784 | if (ioc->cached_fw != NULL) { | 1960 | if (ioc->cached_fw != NULL) { |
1785 | ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n")); | 1961 | ddlprintk((KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n")); |
1786 | if ((ret = mpt_downloadboot(ioc, NO_SLEEP)) < 0) { | 1962 | if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) { |
1787 | printk(KERN_WARNING MYNAM | 1963 | printk(KERN_WARNING MYNAM |
1788 | ": firmware downloadboot failure (%d)!\n", ret); | 1964 | ": firmware downloadboot failure (%d)!\n", ret); |
1789 | } | 1965 | } |
@@ -1831,9 +2007,9 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) | |||
1831 | } | 2007 | } |
1832 | 2008 | ||
1833 | kfree(ioc->spi_data.nvram); | 2009 | kfree(ioc->spi_data.nvram); |
1834 | kfree(ioc->spi_data.pIocPg3); | 2010 | kfree(ioc->raid_data.pIocPg3); |
1835 | ioc->spi_data.nvram = NULL; | 2011 | ioc->spi_data.nvram = NULL; |
1836 | ioc->spi_data.pIocPg3 = NULL; | 2012 | ioc->raid_data.pIocPg3 = NULL; |
1837 | 2013 | ||
1838 | if (ioc->spi_data.pIocPg4 != NULL) { | 2014 | if (ioc->spi_data.pIocPg4 != NULL) { |
1839 | sz = ioc->spi_data.IocPg4Sz; | 2015 | sz = ioc->spi_data.IocPg4Sz; |
@@ -1852,6 +2028,23 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) | |||
1852 | 2028 | ||
1853 | kfree(ioc->ChainToChain); | 2029 | kfree(ioc->ChainToChain); |
1854 | ioc->ChainToChain = NULL; | 2030 | ioc->ChainToChain = NULL; |
2031 | |||
2032 | if (ioc->HostPageBuffer != NULL) { | ||
2033 | if((ret = mpt_host_page_access_control(ioc, | ||
2034 | MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) { | ||
2035 | printk(KERN_ERR MYNAM | ||
2036 | ": %s: host page buffers free failed (%d)!\n", | ||
2037 | __FUNCTION__, ret); | ||
2038 | } | ||
2039 | dexitprintk((KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n", | ||
2040 | ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz)); | ||
2041 | pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz, | ||
2042 | ioc->HostPageBuffer, | ||
2043 | ioc->HostPageBuffer_dma); | ||
2044 | ioc->HostPageBuffer = NULL; | ||
2045 | ioc->HostPageBuffer_sz = 0; | ||
2046 | ioc->alloc_total -= ioc->HostPageBuffer_sz; | ||
2047 | } | ||
1855 | } | 2048 | } |
1856 | 2049 | ||
1857 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2050 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -2034,7 +2227,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) | |||
2034 | * Loop here waiting for IOC to come READY. | 2227 | * Loop here waiting for IOC to come READY. |
2035 | */ | 2228 | */ |
2036 | ii = 0; | 2229 | ii = 0; |
2037 | cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 15; /* 15 seconds */ | 2230 | cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 5; /* 5 seconds */ |
2038 | 2231 | ||
2039 | while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) { | 2232 | while ((ioc_state = mpt_GetIocState(ioc, 1)) != MPI_IOC_STATE_READY) { |
2040 | if (ioc_state == MPI_IOC_STATE_OPERATIONAL) { | 2233 | if (ioc_state == MPI_IOC_STATE_OPERATIONAL) { |
@@ -2212,6 +2405,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) | |||
2212 | le32_to_cpu(facts->CurrentSenseBufferHighAddr); | 2405 | le32_to_cpu(facts->CurrentSenseBufferHighAddr); |
2213 | facts->CurReplyFrameSize = | 2406 | facts->CurReplyFrameSize = |
2214 | le16_to_cpu(facts->CurReplyFrameSize); | 2407 | le16_to_cpu(facts->CurReplyFrameSize); |
2408 | facts->IOCCapabilities = le32_to_cpu(facts->IOCCapabilities); | ||
2215 | 2409 | ||
2216 | /* | 2410 | /* |
2217 | * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx | 2411 | * Handle NEW (!) IOCFactsReply fields in MPI-1.01.xx |
@@ -2383,13 +2577,25 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) | |||
2383 | ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n", | 2577 | ddlprintk((MYIOC_s_INFO_FMT "upload_fw %d facts.Flags=%x\n", |
2384 | ioc->name, ioc->upload_fw, ioc->facts.Flags)); | 2578 | ioc->name, ioc->upload_fw, ioc->facts.Flags)); |
2385 | 2579 | ||
2386 | if (ioc->bus_type == FC) | 2580 | if(ioc->bus_type == SAS) |
2581 | ioc_init.MaxDevices = ioc->facts.MaxDevices; | ||
2582 | else if(ioc->bus_type == FC) | ||
2387 | ioc_init.MaxDevices = MPT_MAX_FC_DEVICES; | 2583 | ioc_init.MaxDevices = MPT_MAX_FC_DEVICES; |
2388 | else | 2584 | else |
2389 | ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES; | 2585 | ioc_init.MaxDevices = MPT_MAX_SCSI_DEVICES; |
2390 | |||
2391 | ioc_init.MaxBuses = MPT_MAX_BUS; | 2586 | ioc_init.MaxBuses = MPT_MAX_BUS; |
2392 | 2587 | dinitprintk((MYIOC_s_INFO_FMT "facts.MsgVersion=%x\n", | |
2588 | ioc->name, ioc->facts.MsgVersion)); | ||
2589 | if (ioc->facts.MsgVersion >= MPI_VERSION_01_05) { | ||
2590 | // set MsgVersion and HeaderVersion host driver was built with | ||
2591 | ioc_init.MsgVersion = cpu_to_le16(MPI_VERSION); | ||
2592 | ioc_init.HeaderVersion = cpu_to_le16(MPI_HEADER_VERSION); | ||
2593 | |||
2594 | if (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT) { | ||
2595 | ioc_init.HostPageBufferSGE = ioc->facts.HostPageBufferSGE; | ||
2596 | } else if(mpt_host_page_alloc(ioc, &ioc_init)) | ||
2597 | return -99; | ||
2598 | } | ||
2393 | ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */ | 2599 | ioc_init.ReplyFrameSize = cpu_to_le16(ioc->reply_sz); /* in BYTES */ |
2394 | 2600 | ||
2395 | if (sizeof(dma_addr_t) == sizeof(u64)) { | 2601 | if (sizeof(dma_addr_t) == sizeof(u64)) { |
@@ -2403,17 +2609,21 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) | |||
2403 | ioc_init.HostMfaHighAddr = cpu_to_le32(0); | 2609 | ioc_init.HostMfaHighAddr = cpu_to_le32(0); |
2404 | ioc_init.SenseBufferHighAddr = cpu_to_le32(0); | 2610 | ioc_init.SenseBufferHighAddr = cpu_to_le32(0); |
2405 | } | 2611 | } |
2406 | 2612 | ||
2407 | ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr; | 2613 | ioc->facts.CurrentHostMfaHighAddr = ioc_init.HostMfaHighAddr; |
2408 | ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr; | 2614 | ioc->facts.CurrentSenseBufferHighAddr = ioc_init.SenseBufferHighAddr; |
2615 | ioc->facts.MaxDevices = ioc_init.MaxDevices; | ||
2616 | ioc->facts.MaxBuses = ioc_init.MaxBuses; | ||
2409 | 2617 | ||
2410 | dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n", | 2618 | dhsprintk((MYIOC_s_INFO_FMT "Sending IOCInit (req @ %p)\n", |
2411 | ioc->name, &ioc_init)); | 2619 | ioc->name, &ioc_init)); |
2412 | 2620 | ||
2413 | r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init, | 2621 | r = mpt_handshake_req_reply_wait(ioc, sizeof(IOCInit_t), (u32*)&ioc_init, |
2414 | sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag); | 2622 | sizeof(MPIDefaultReply_t), (u16*)&init_reply, 10 /*seconds*/, sleepFlag); |
2415 | if (r != 0) | 2623 | if (r != 0) { |
2624 | printk(MYIOC_s_ERR_FMT "Sending IOCInit failed(%d)!\n",ioc->name, r); | ||
2416 | return r; | 2625 | return r; |
2626 | } | ||
2417 | 2627 | ||
2418 | /* No need to byte swap the multibyte fields in the reply | 2628 | /* No need to byte swap the multibyte fields in the reply |
2419 | * since we don't even look at it's contents. | 2629 | * since we don't even look at it's contents. |
@@ -2472,7 +2682,7 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) | |||
2472 | { | 2682 | { |
2473 | PortEnable_t port_enable; | 2683 | PortEnable_t port_enable; |
2474 | MPIDefaultReply_t reply_buf; | 2684 | MPIDefaultReply_t reply_buf; |
2475 | int ii; | 2685 | int rc; |
2476 | int req_sz; | 2686 | int req_sz; |
2477 | int reply_sz; | 2687 | int reply_sz; |
2478 | 2688 | ||
@@ -2494,22 +2704,15 @@ SendPortEnable(MPT_ADAPTER *ioc, int portnum, int sleepFlag) | |||
2494 | 2704 | ||
2495 | /* RAID FW may take a long time to enable | 2705 | /* RAID FW may take a long time to enable |
2496 | */ | 2706 | */ |
2497 | if (ioc->bus_type == FC) { | 2707 | if ( (ioc->facts.ProductID & MPI_FW_HEADER_PID_PROD_MASK) |
2498 | ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, | 2708 | > MPI_FW_HEADER_PID_PROD_TARGET_SCSI ) { |
2499 | reply_sz, (u16*)&reply_buf, 65 /*seconds*/, sleepFlag); | 2709 | rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, |
2500 | } else { | ||
2501 | ii = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, | ||
2502 | reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag); | 2710 | reply_sz, (u16*)&reply_buf, 300 /*seconds*/, sleepFlag); |
2711 | } else { | ||
2712 | rc = mpt_handshake_req_reply_wait(ioc, req_sz, (u32*)&port_enable, | ||
2713 | reply_sz, (u16*)&reply_buf, 30 /*seconds*/, sleepFlag); | ||
2503 | } | 2714 | } |
2504 | 2715 | return rc; | |
2505 | if (ii != 0) | ||
2506 | return ii; | ||
2507 | |||
2508 | /* We do not even look at the reply, so we need not | ||
2509 | * swap the multi-byte fields. | ||
2510 | */ | ||
2511 | |||
2512 | return 0; | ||
2513 | } | 2716 | } |
2514 | 2717 | ||
2515 | /* | 2718 | /* |
@@ -2666,9 +2869,8 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) | |||
2666 | * <0 for fw upload failure. | 2869 | * <0 for fw upload failure. |
2667 | */ | 2870 | */ |
2668 | static int | 2871 | static int |
2669 | mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) | 2872 | mpt_downloadboot(MPT_ADAPTER *ioc, MpiFwHeader_t *pFwHeader, int sleepFlag) |
2670 | { | 2873 | { |
2671 | MpiFwHeader_t *pFwHeader; | ||
2672 | MpiExtImageHeader_t *pExtImage; | 2874 | MpiExtImageHeader_t *pExtImage; |
2673 | u32 fwSize; | 2875 | u32 fwSize; |
2674 | u32 diag0val; | 2876 | u32 diag0val; |
@@ -2679,18 +2881,8 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) | |||
2679 | u32 load_addr; | 2881 | u32 load_addr; |
2680 | u32 ioc_state=0; | 2882 | u32 ioc_state=0; |
2681 | 2883 | ||
2682 | ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x, ioc FW Ptr %p\n", | 2884 | ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n", |
2683 | ioc->name, ioc->facts.FWImageSize, ioc->cached_fw)); | 2885 | ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader)); |
2684 | |||
2685 | if ( ioc->facts.FWImageSize == 0 ) | ||
2686 | return -1; | ||
2687 | |||
2688 | if (ioc->cached_fw == NULL) | ||
2689 | return -2; | ||
2690 | |||
2691 | /* prevent a second downloadboot and memory free with alt_ioc */ | ||
2692 | if (ioc->alt_ioc && ioc->alt_ioc->cached_fw) | ||
2693 | ioc->alt_ioc->cached_fw = NULL; | ||
2694 | 2886 | ||
2695 | CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); | 2887 | CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); |
2696 | CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); | 2888 | CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE); |
@@ -2718,16 +2910,17 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) | |||
2718 | ioc->name, count)); | 2910 | ioc->name, count)); |
2719 | break; | 2911 | break; |
2720 | } | 2912 | } |
2721 | /* wait 1 sec */ | 2913 | /* wait .1 sec */ |
2722 | if (sleepFlag == CAN_SLEEP) { | 2914 | if (sleepFlag == CAN_SLEEP) { |
2723 | msleep_interruptible (1000); | 2915 | msleep_interruptible (100); |
2724 | } else { | 2916 | } else { |
2725 | mdelay (1000); | 2917 | mdelay (100); |
2726 | } | 2918 | } |
2727 | } | 2919 | } |
2728 | 2920 | ||
2729 | if ( count == 30 ) { | 2921 | if ( count == 30 ) { |
2730 | ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! Unable to RESET_ADAPTER diag0val=%x\n", | 2922 | ddlprintk((MYIOC_s_INFO_FMT "downloadboot failed! " |
2923 | "Unable to get MPI_DIAG_DRWE mode, diag0val=%x\n", | ||
2731 | ioc->name, diag0val)); | 2924 | ioc->name, diag0val)); |
2732 | return -3; | 2925 | return -3; |
2733 | } | 2926 | } |
@@ -2742,7 +2935,6 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) | |||
2742 | /* Set the DiagRwEn and Disable ARM bits */ | 2935 | /* Set the DiagRwEn and Disable ARM bits */ |
2743 | CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM)); | 2936 | CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM)); |
2744 | 2937 | ||
2745 | pFwHeader = (MpiFwHeader_t *) ioc->cached_fw; | ||
2746 | fwSize = (pFwHeader->ImageSize + 3)/4; | 2938 | fwSize = (pFwHeader->ImageSize + 3)/4; |
2747 | ptrFw = (u32 *) pFwHeader; | 2939 | ptrFw = (u32 *) pFwHeader; |
2748 | 2940 | ||
@@ -2792,19 +2984,38 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) | |||
2792 | /* Clear the internal flash bad bit - autoincrementing register, | 2984 | /* Clear the internal flash bad bit - autoincrementing register, |
2793 | * so must do two writes. | 2985 | * so must do two writes. |
2794 | */ | 2986 | */ |
2795 | CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); | 2987 | if (ioc->bus_type == SCSI) { |
2796 | diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData); | 2988 | /* |
2797 | diagRwData |= 0x4000000; | 2989 | * 1030 and 1035 H/W errata, workaround to access |
2798 | CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); | 2990 | * the ClearFlashBadSignatureBit |
2799 | CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData); | 2991 | */ |
2992 | CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); | ||
2993 | diagRwData = CHIPREG_PIO_READ32(&ioc->pio_chip->DiagRwData); | ||
2994 | diagRwData |= 0x40000000; | ||
2995 | CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000); | ||
2996 | CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData); | ||
2997 | |||
2998 | } else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ { | ||
2999 | diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); | ||
3000 | CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | | ||
3001 | MPI_DIAG_CLEAR_FLASH_BAD_SIG); | ||
3002 | |||
3003 | /* wait 1 msec */ | ||
3004 | if (sleepFlag == CAN_SLEEP) { | ||
3005 | msleep_interruptible (1); | ||
3006 | } else { | ||
3007 | mdelay (1); | ||
3008 | } | ||
3009 | } | ||
2800 | 3010 | ||
2801 | if (ioc->errata_flag_1064) | 3011 | if (ioc->errata_flag_1064) |
2802 | pci_disable_io_access(ioc->pcidev); | 3012 | pci_disable_io_access(ioc->pcidev); |
2803 | 3013 | ||
2804 | diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); | 3014 | diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic); |
2805 | ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n", | 3015 | ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, " |
3016 | "turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n", | ||
2806 | ioc->name, diag0val)); | 3017 | ioc->name, diag0val)); |
2807 | diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM); | 3018 | diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE); |
2808 | ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n", | 3019 | ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n", |
2809 | ioc->name, diag0val)); | 3020 | ioc->name, diag0val)); |
2810 | CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); | 3021 | CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val); |
@@ -2812,10 +3023,23 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag) | |||
2812 | /* Write 0xFF to reset the sequencer */ | 3023 | /* Write 0xFF to reset the sequencer */ |
2813 | CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); | 3024 | CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF); |
2814 | 3025 | ||
3026 | if (ioc->bus_type == SAS) { | ||
3027 | ioc_state = mpt_GetIocState(ioc, 0); | ||
3028 | if ( (GetIocFacts(ioc, sleepFlag, | ||
3029 | MPT_HOSTEVENT_IOC_BRINGUP)) != 0 ) { | ||
3030 | ddlprintk((MYIOC_s_INFO_FMT "GetIocFacts failed: IocState=%x\n", | ||
3031 | ioc->name, ioc_state)); | ||
3032 | return -EFAULT; | ||
3033 | } | ||
3034 | } | ||
3035 | |||
2815 | for (count=0; count<HZ*20; count++) { | 3036 | for (count=0; count<HZ*20; count++) { |
2816 | if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) { | 3037 | if ((ioc_state = mpt_GetIocState(ioc, 0)) & MPI_IOC_STATE_READY) { |
2817 | ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n", | 3038 | ddlprintk((MYIOC_s_INFO_FMT "downloadboot successful! (count=%d) IocState=%x\n", |
2818 | ioc->name, count, ioc_state)); | 3039 | ioc->name, count, ioc_state)); |
3040 | if (ioc->bus_type == SAS) { | ||
3041 | return 0; | ||
3042 | } | ||
2819 | if ((SendIocInit(ioc, sleepFlag)) != 0) { | 3043 | if ((SendIocInit(ioc, sleepFlag)) != 0) { |
2820 | ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n", | 3044 | ddlprintk((MYIOC_s_INFO_FMT "downloadboot: SendIocInit failed\n", |
2821 | ioc->name)); | 3045 | ioc->name)); |
@@ -3049,12 +3273,13 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) | |||
3049 | 3273 | ||
3050 | /* wait 1 sec */ | 3274 | /* wait 1 sec */ |
3051 | if (sleepFlag == CAN_SLEEP) { | 3275 | if (sleepFlag == CAN_SLEEP) { |
3052 | ssleep(1); | 3276 | msleep_interruptible (1000); |
3053 | } else { | 3277 | } else { |
3054 | mdelay (1000); | 3278 | mdelay (1000); |
3055 | } | 3279 | } |
3056 | } | 3280 | } |
3057 | if ((count = mpt_downloadboot(ioc, sleepFlag)) < 0) { | 3281 | if ((count = mpt_downloadboot(ioc, |
3282 | (MpiFwHeader_t *)ioc->cached_fw, sleepFlag)) < 0) { | ||
3058 | printk(KERN_WARNING MYNAM | 3283 | printk(KERN_WARNING MYNAM |
3059 | ": firmware downloadboot failure (%d)!\n", count); | 3284 | ": firmware downloadboot failure (%d)!\n", count); |
3060 | } | 3285 | } |
@@ -3637,7 +3862,7 @@ WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag) | |||
3637 | int count = 0; | 3862 | int count = 0; |
3638 | u32 intstat=0; | 3863 | u32 intstat=0; |
3639 | 3864 | ||
3640 | cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong; | 3865 | cntdn = 1000 * howlong; |
3641 | 3866 | ||
3642 | if (sleepFlag == CAN_SLEEP) { | 3867 | if (sleepFlag == CAN_SLEEP) { |
3643 | while (--cntdn) { | 3868 | while (--cntdn) { |
@@ -3687,7 +3912,7 @@ WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag) | |||
3687 | int count = 0; | 3912 | int count = 0; |
3688 | u32 intstat=0; | 3913 | u32 intstat=0; |
3689 | 3914 | ||
3690 | cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * howlong; | 3915 | cntdn = 1000 * howlong; |
3691 | if (sleepFlag == CAN_SLEEP) { | 3916 | if (sleepFlag == CAN_SLEEP) { |
3692 | while (--cntdn) { | 3917 | while (--cntdn) { |
3693 | intstat = CHIPREG_READ32(&ioc->chip->IntStatus); | 3918 | intstat = CHIPREG_READ32(&ioc->chip->IntStatus); |
@@ -4001,6 +4226,85 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) | |||
4001 | 4226 | ||
4002 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 4227 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
4003 | /* | 4228 | /* |
4229 | * mptbase_sas_persist_operation - Perform operation on SAS Persitent Table | ||
4230 | * @ioc: Pointer to MPT_ADAPTER structure | ||
4231 | * @sas_address: 64bit SAS Address for operation. | ||
4232 | * @target_id: specified target for operation | ||
4233 | * @bus: specified bus for operation | ||
4234 | * @persist_opcode: see below | ||
4235 | * | ||
4236 | * MPI_SAS_OP_CLEAR_NOT_PRESENT - Free all persist TargetID mappings for | ||
4237 | * devices not currently present. | ||
4238 | * MPI_SAS_OP_CLEAR_ALL_PERSISTENT - Clear al persist TargetID mappings | ||
4239 | * | ||
4240 | * NOTE: Don't use not this function during interrupt time. | ||
4241 | * | ||
4242 | * Returns: 0 for success, non-zero error | ||
4243 | */ | ||
4244 | |||
4245 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
4246 | int | ||
4247 | mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode) | ||
4248 | { | ||
4249 | SasIoUnitControlRequest_t *sasIoUnitCntrReq; | ||
4250 | SasIoUnitControlReply_t *sasIoUnitCntrReply; | ||
4251 | MPT_FRAME_HDR *mf = NULL; | ||
4252 | MPIHeader_t *mpi_hdr; | ||
4253 | |||
4254 | |||
4255 | /* insure garbage is not sent to fw */ | ||
4256 | switch(persist_opcode) { | ||
4257 | |||
4258 | case MPI_SAS_OP_CLEAR_NOT_PRESENT: | ||
4259 | case MPI_SAS_OP_CLEAR_ALL_PERSISTENT: | ||
4260 | break; | ||
4261 | |||
4262 | default: | ||
4263 | return -1; | ||
4264 | break; | ||
4265 | } | ||
4266 | |||
4267 | printk("%s: persist_opcode=%x\n",__FUNCTION__, persist_opcode); | ||
4268 | |||
4269 | /* Get a MF for this command. | ||
4270 | */ | ||
4271 | if ((mf = mpt_get_msg_frame(mpt_base_index, ioc)) == NULL) { | ||
4272 | printk("%s: no msg frames!\n",__FUNCTION__); | ||
4273 | return -1; | ||
4274 | } | ||
4275 | |||
4276 | mpi_hdr = (MPIHeader_t *) mf; | ||
4277 | sasIoUnitCntrReq = (SasIoUnitControlRequest_t *)mf; | ||
4278 | memset(sasIoUnitCntrReq,0,sizeof(SasIoUnitControlRequest_t)); | ||
4279 | sasIoUnitCntrReq->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL; | ||
4280 | sasIoUnitCntrReq->MsgContext = mpi_hdr->MsgContext; | ||
4281 | sasIoUnitCntrReq->Operation = persist_opcode; | ||
4282 | |||
4283 | init_timer(&ioc->persist_timer); | ||
4284 | ioc->persist_timer.data = (unsigned long) ioc; | ||
4285 | ioc->persist_timer.function = mpt_timer_expired; | ||
4286 | ioc->persist_timer.expires = jiffies + HZ*10 /* 10 sec */; | ||
4287 | ioc->persist_wait_done=0; | ||
4288 | add_timer(&ioc->persist_timer); | ||
4289 | mpt_put_msg_frame(mpt_base_index, ioc, mf); | ||
4290 | wait_event(mpt_waitq, ioc->persist_wait_done); | ||
4291 | |||
4292 | sasIoUnitCntrReply = | ||
4293 | (SasIoUnitControlReply_t *)ioc->persist_reply_frame; | ||
4294 | if (le16_to_cpu(sasIoUnitCntrReply->IOCStatus) != MPI_IOCSTATUS_SUCCESS) { | ||
4295 | printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", | ||
4296 | __FUNCTION__, | ||
4297 | sasIoUnitCntrReply->IOCStatus, | ||
4298 | sasIoUnitCntrReply->IOCLogInfo); | ||
4299 | return -1; | ||
4300 | } | ||
4301 | |||
4302 | printk("%s: success\n",__FUNCTION__); | ||
4303 | return 0; | ||
4304 | } | ||
4305 | |||
4306 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
4307 | /* | ||
4004 | * GetIoUnitPage2 - Retrieve BIOS version and boot order information. | 4308 | * GetIoUnitPage2 - Retrieve BIOS version and boot order information. |
4005 | * @ioc: Pointer to MPT_ADAPTER structure | 4309 | * @ioc: Pointer to MPT_ADAPTER structure |
4006 | * | 4310 | * |
@@ -4340,10 +4644,10 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) | |||
4340 | if (mpt_config(ioc, &cfg) != 0) | 4644 | if (mpt_config(ioc, &cfg) != 0) |
4341 | goto done_and_free; | 4645 | goto done_and_free; |
4342 | 4646 | ||
4343 | if ( (mem = (u8 *)ioc->spi_data.pIocPg2) == NULL ) { | 4647 | if ( (mem = (u8 *)ioc->raid_data.pIocPg2) == NULL ) { |
4344 | mem = kmalloc(iocpage2sz, GFP_ATOMIC); | 4648 | mem = kmalloc(iocpage2sz, GFP_ATOMIC); |
4345 | if (mem) { | 4649 | if (mem) { |
4346 | ioc->spi_data.pIocPg2 = (IOCPage2_t *) mem; | 4650 | ioc->raid_data.pIocPg2 = (IOCPage2_t *) mem; |
4347 | } else { | 4651 | } else { |
4348 | goto done_and_free; | 4652 | goto done_and_free; |
4349 | } | 4653 | } |
@@ -4360,7 +4664,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) | |||
4360 | /* At least 1 RAID Volume | 4664 | /* At least 1 RAID Volume |
4361 | */ | 4665 | */ |
4362 | pIocRv = pIoc2->RaidVolume; | 4666 | pIocRv = pIoc2->RaidVolume; |
4363 | ioc->spi_data.isRaid = 0; | 4667 | ioc->raid_data.isRaid = 0; |
4364 | for (jj = 0; jj < nVols; jj++, pIocRv++) { | 4668 | for (jj = 0; jj < nVols; jj++, pIocRv++) { |
4365 | vid = pIocRv->VolumeID; | 4669 | vid = pIocRv->VolumeID; |
4366 | vbus = pIocRv->VolumeBus; | 4670 | vbus = pIocRv->VolumeBus; |
@@ -4369,7 +4673,7 @@ mpt_findImVolumes(MPT_ADAPTER *ioc) | |||
4369 | /* find the match | 4673 | /* find the match |
4370 | */ | 4674 | */ |
4371 | if (vbus == 0) { | 4675 | if (vbus == 0) { |
4372 | ioc->spi_data.isRaid |= (1 << vid); | 4676 | ioc->raid_data.isRaid |= (1 << vid); |
4373 | } else { | 4677 | } else { |
4374 | /* Error! Always bus 0 | 4678 | /* Error! Always bus 0 |
4375 | */ | 4679 | */ |
@@ -4404,8 +4708,8 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) | |||
4404 | 4708 | ||
4405 | /* Free the old page | 4709 | /* Free the old page |
4406 | */ | 4710 | */ |
4407 | kfree(ioc->spi_data.pIocPg3); | 4711 | kfree(ioc->raid_data.pIocPg3); |
4408 | ioc->spi_data.pIocPg3 = NULL; | 4712 | ioc->raid_data.pIocPg3 = NULL; |
4409 | 4713 | ||
4410 | /* There is at least one physical disk. | 4714 | /* There is at least one physical disk. |
4411 | * Read and save IOC Page 3 | 4715 | * Read and save IOC Page 3 |
@@ -4442,7 +4746,7 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc) | |||
4442 | mem = kmalloc(iocpage3sz, GFP_ATOMIC); | 4746 | mem = kmalloc(iocpage3sz, GFP_ATOMIC); |
4443 | if (mem) { | 4747 | if (mem) { |
4444 | memcpy(mem, (u8 *)pIoc3, iocpage3sz); | 4748 | memcpy(mem, (u8 *)pIoc3, iocpage3sz); |
4445 | ioc->spi_data.pIocPg3 = (IOCPage3_t *) mem; | 4749 | ioc->raid_data.pIocPg3 = (IOCPage3_t *) mem; |
4446 | } | 4750 | } |
4447 | } | 4751 | } |
4448 | 4752 | ||
@@ -5366,8 +5670,8 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) | |||
5366 | } | 5670 | } |
5367 | 5671 | ||
5368 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 5672 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
5369 | static char * | 5673 | static void |
5370 | EventDescriptionStr(u8 event, u32 evData0) | 5674 | EventDescriptionStr(u8 event, u32 evData0, char *evStr) |
5371 | { | 5675 | { |
5372 | char *ds; | 5676 | char *ds; |
5373 | 5677 | ||
@@ -5420,8 +5724,95 @@ EventDescriptionStr(u8 event, u32 evData0) | |||
5420 | ds = "Events(OFF) Change"; | 5724 | ds = "Events(OFF) Change"; |
5421 | break; | 5725 | break; |
5422 | case MPI_EVENT_INTEGRATED_RAID: | 5726 | case MPI_EVENT_INTEGRATED_RAID: |
5423 | ds = "Integrated Raid"; | 5727 | { |
5728 | u8 ReasonCode = (u8)(evData0 >> 16); | ||
5729 | switch (ReasonCode) { | ||
5730 | case MPI_EVENT_RAID_RC_VOLUME_CREATED : | ||
5731 | ds = "Integrated Raid: Volume Created"; | ||
5732 | break; | ||
5733 | case MPI_EVENT_RAID_RC_VOLUME_DELETED : | ||
5734 | ds = "Integrated Raid: Volume Deleted"; | ||
5735 | break; | ||
5736 | case MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED : | ||
5737 | ds = "Integrated Raid: Volume Settings Changed"; | ||
5738 | break; | ||
5739 | case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED : | ||
5740 | ds = "Integrated Raid: Volume Status Changed"; | ||
5741 | break; | ||
5742 | case MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED : | ||
5743 | ds = "Integrated Raid: Volume Physdisk Changed"; | ||
5744 | break; | ||
5745 | case MPI_EVENT_RAID_RC_PHYSDISK_CREATED : | ||
5746 | ds = "Integrated Raid: Physdisk Created"; | ||
5747 | break; | ||
5748 | case MPI_EVENT_RAID_RC_PHYSDISK_DELETED : | ||
5749 | ds = "Integrated Raid: Physdisk Deleted"; | ||
5750 | break; | ||
5751 | case MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED : | ||
5752 | ds = "Integrated Raid: Physdisk Settings Changed"; | ||
5753 | break; | ||
5754 | case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED : | ||
5755 | ds = "Integrated Raid: Physdisk Status Changed"; | ||
5756 | break; | ||
5757 | case MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED : | ||
5758 | ds = "Integrated Raid: Domain Validation Needed"; | ||
5759 | break; | ||
5760 | case MPI_EVENT_RAID_RC_SMART_DATA : | ||
5761 | ds = "Integrated Raid; Smart Data"; | ||
5762 | break; | ||
5763 | case MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED : | ||
5764 | ds = "Integrated Raid: Replace Action Started"; | ||
5765 | break; | ||
5766 | default: | ||
5767 | ds = "Integrated Raid"; | ||
5768 | break; | ||
5769 | } | ||
5770 | break; | ||
5771 | } | ||
5772 | case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE: | ||
5773 | ds = "SCSI Device Status Change"; | ||
5774 | break; | ||
5775 | case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: | ||
5776 | { | ||
5777 | u8 ReasonCode = (u8)(evData0 >> 16); | ||
5778 | switch (ReasonCode) { | ||
5779 | case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: | ||
5780 | ds = "SAS Device Status Change: Added"; | ||
5781 | break; | ||
5782 | case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING: | ||
5783 | ds = "SAS Device Status Change: Deleted"; | ||
5784 | break; | ||
5785 | case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA: | ||
5786 | ds = "SAS Device Status Change: SMART Data"; | ||
5787 | break; | ||
5788 | case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED: | ||
5789 | ds = "SAS Device Status Change: No Persistancy Added"; | ||
5790 | break; | ||
5791 | default: | ||
5792 | ds = "SAS Device Status Change: Unknown"; | ||
5793 | break; | ||
5794 | } | ||
5795 | break; | ||
5796 | } | ||
5797 | case MPI_EVENT_ON_BUS_TIMER_EXPIRED: | ||
5798 | ds = "Bus Timer Expired"; | ||
5799 | break; | ||
5800 | case MPI_EVENT_QUEUE_FULL: | ||
5801 | ds = "Queue Full"; | ||
5802 | break; | ||
5803 | case MPI_EVENT_SAS_SES: | ||
5804 | ds = "SAS SES Event"; | ||
5805 | break; | ||
5806 | case MPI_EVENT_PERSISTENT_TABLE_FULL: | ||
5807 | ds = "Persistent Table Full"; | ||
5808 | break; | ||
5809 | case MPI_EVENT_SAS_PHY_LINK_STATUS: | ||
5810 | ds = "SAS PHY Link Status"; | ||
5811 | break; | ||
5812 | case MPI_EVENT_SAS_DISCOVERY_ERROR: | ||
5813 | ds = "SAS Discovery Error"; | ||
5424 | break; | 5814 | break; |
5815 | |||
5425 | /* | 5816 | /* |
5426 | * MPT base "custom" events may be added here... | 5817 | * MPT base "custom" events may be added here... |
5427 | */ | 5818 | */ |
@@ -5429,7 +5820,7 @@ EventDescriptionStr(u8 event, u32 evData0) | |||
5429 | ds = "Unknown"; | 5820 | ds = "Unknown"; |
5430 | break; | 5821 | break; |
5431 | } | 5822 | } |
5432 | return ds; | 5823 | strcpy(evStr,ds); |
5433 | } | 5824 | } |
5434 | 5825 | ||
5435 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 5826 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -5451,7 +5842,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply | |||
5451 | int ii; | 5842 | int ii; |
5452 | int r = 0; | 5843 | int r = 0; |
5453 | int handlers = 0; | 5844 | int handlers = 0; |
5454 | char *evStr; | 5845 | char evStr[100]; |
5455 | u8 event; | 5846 | u8 event; |
5456 | 5847 | ||
5457 | /* | 5848 | /* |
@@ -5464,7 +5855,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply | |||
5464 | evData0 = le32_to_cpu(pEventReply->Data[0]); | 5855 | evData0 = le32_to_cpu(pEventReply->Data[0]); |
5465 | } | 5856 | } |
5466 | 5857 | ||
5467 | evStr = EventDescriptionStr(event, evData0); | 5858 | EventDescriptionStr(event, evData0, evStr); |
5468 | devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n", | 5859 | devtprintk((MYIOC_s_INFO_FMT "MPT event (%s=%02Xh) detected!\n", |
5469 | ioc->name, | 5860 | ioc->name, |
5470 | evStr, | 5861 | evStr, |
@@ -5481,20 +5872,6 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply | |||
5481 | * Do general / base driver event processing | 5872 | * Do general / base driver event processing |
5482 | */ | 5873 | */ |
5483 | switch(event) { | 5874 | switch(event) { |
5484 | case MPI_EVENT_NONE: /* 00 */ | ||
5485 | case MPI_EVENT_LOG_DATA: /* 01 */ | ||
5486 | case MPI_EVENT_STATE_CHANGE: /* 02 */ | ||
5487 | case MPI_EVENT_UNIT_ATTENTION: /* 03 */ | ||
5488 | case MPI_EVENT_IOC_BUS_RESET: /* 04 */ | ||
5489 | case MPI_EVENT_EXT_BUS_RESET: /* 05 */ | ||
5490 | case MPI_EVENT_RESCAN: /* 06 */ | ||
5491 | case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */ | ||
5492 | case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */ | ||
5493 | case MPI_EVENT_LOGOUT: /* 09 */ | ||
5494 | case MPI_EVENT_INTEGRATED_RAID: /* 0B */ | ||
5495 | case MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE: /* 0C */ | ||
5496 | default: | ||
5497 | break; | ||
5498 | case MPI_EVENT_EVENT_CHANGE: /* 0A */ | 5875 | case MPI_EVENT_EVENT_CHANGE: /* 0A */ |
5499 | if (evDataLen) { | 5876 | if (evDataLen) { |
5500 | u8 evState = evData0 & 0xFF; | 5877 | u8 evState = evData0 & 0xFF; |
@@ -5507,6 +5884,8 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply | |||
5507 | } | 5884 | } |
5508 | } | 5885 | } |
5509 | break; | 5886 | break; |
5887 | default: | ||
5888 | break; | ||
5510 | } | 5889 | } |
5511 | 5890 | ||
5512 | /* | 5891 | /* |
@@ -5653,6 +6032,111 @@ mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info) | |||
5653 | printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc); | 6032 | printk(MYIOC_s_INFO_FMT "LogInfo(0x%08x): F/W: %s\n", ioc->name, log_info, desc); |
5654 | } | 6033 | } |
5655 | 6034 | ||
6035 | /* strings for sas loginfo */ | ||
6036 | static char *originator_str[] = { | ||
6037 | "IOP", /* 00h */ | ||
6038 | "PL", /* 01h */ | ||
6039 | "IR" /* 02h */ | ||
6040 | }; | ||
6041 | static char *iop_code_str[] = { | ||
6042 | NULL, /* 00h */ | ||
6043 | "Invalid SAS Address", /* 01h */ | ||
6044 | NULL, /* 02h */ | ||
6045 | "Invalid Page", /* 03h */ | ||
6046 | NULL, /* 04h */ | ||
6047 | "Task Terminated" /* 05h */ | ||
6048 | }; | ||
6049 | static char *pl_code_str[] = { | ||
6050 | NULL, /* 00h */ | ||
6051 | "Open Failure", /* 01h */ | ||
6052 | "Invalid Scatter Gather List", /* 02h */ | ||
6053 | "Wrong Relative Offset or Frame Length", /* 03h */ | ||
6054 | "Frame Transfer Error", /* 04h */ | ||
6055 | "Transmit Frame Connected Low", /* 05h */ | ||
6056 | "SATA Non-NCQ RW Error Bit Set", /* 06h */ | ||
6057 | "SATA Read Log Receive Data Error", /* 07h */ | ||
6058 | "SATA NCQ Fail All Commands After Error", /* 08h */ | ||
6059 | "SATA Error in Receive Set Device Bit FIS", /* 09h */ | ||
6060 | "Receive Frame Invalid Message", /* 0Ah */ | ||
6061 | "Receive Context Message Valid Error", /* 0Bh */ | ||
6062 | "Receive Frame Current Frame Error", /* 0Ch */ | ||
6063 | "SATA Link Down", /* 0Dh */ | ||
6064 | "Discovery SATA Init W IOS", /* 0Eh */ | ||
6065 | "Config Invalid Page", /* 0Fh */ | ||
6066 | "Discovery SATA Init Timeout", /* 10h */ | ||
6067 | "Reset", /* 11h */ | ||
6068 | "Abort", /* 12h */ | ||
6069 | "IO Not Yet Executed", /* 13h */ | ||
6070 | "IO Executed", /* 14h */ | ||
6071 | NULL, /* 15h */ | ||
6072 | NULL, /* 16h */ | ||
6073 | NULL, /* 17h */ | ||
6074 | NULL, /* 18h */ | ||
6075 | NULL, /* 19h */ | ||
6076 | NULL, /* 1Ah */ | ||
6077 | NULL, /* 1Bh */ | ||
6078 | NULL, /* 1Ch */ | ||
6079 | NULL, /* 1Dh */ | ||
6080 | NULL, /* 1Eh */ | ||
6081 | NULL, /* 1Fh */ | ||
6082 | "Enclosure Management" /* 20h */ | ||
6083 | }; | ||
6084 | |||
6085 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
6086 | /* | ||
6087 | * mpt_sas_log_info - Log information returned from SAS IOC. | ||
6088 | * @ioc: Pointer to MPT_ADAPTER structure | ||
6089 | * @log_info: U32 LogInfo reply word from the IOC | ||
6090 | * | ||
6091 | * Refer to lsi/mpi_log_sas.h. | ||
6092 | */ | ||
6093 | static void | ||
6094 | mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info) | ||
6095 | { | ||
6096 | union loginfo_type { | ||
6097 | u32 loginfo; | ||
6098 | struct { | ||
6099 | u32 subcode:16; | ||
6100 | u32 code:8; | ||
6101 | u32 originator:4; | ||
6102 | u32 bus_type:4; | ||
6103 | }dw; | ||
6104 | }; | ||
6105 | union loginfo_type sas_loginfo; | ||
6106 | char *code_desc = NULL; | ||
6107 | |||
6108 | sas_loginfo.loginfo = log_info; | ||
6109 | if ((sas_loginfo.dw.bus_type != 3 /*SAS*/) && | ||
6110 | (sas_loginfo.dw.originator < sizeof(originator_str)/sizeof(char*))) | ||
6111 | return; | ||
6112 | if ((sas_loginfo.dw.originator == 0 /*IOP*/) && | ||
6113 | (sas_loginfo.dw.code < sizeof(iop_code_str)/sizeof(char*))) { | ||
6114 | code_desc = iop_code_str[sas_loginfo.dw.code]; | ||
6115 | }else if ((sas_loginfo.dw.originator == 1 /*PL*/) && | ||
6116 | (sas_loginfo.dw.code < sizeof(pl_code_str)/sizeof(char*) )) { | ||
6117 | code_desc = pl_code_str[sas_loginfo.dw.code]; | ||
6118 | } | ||
6119 | |||
6120 | if (code_desc != NULL) | ||
6121 | printk(MYIOC_s_INFO_FMT | ||
6122 | "LogInfo(0x%08x): Originator={%s}, Code={%s}," | ||
6123 | " SubCode(0x%04x)\n", | ||
6124 | ioc->name, | ||
6125 | log_info, | ||
6126 | originator_str[sas_loginfo.dw.originator], | ||
6127 | code_desc, | ||
6128 | sas_loginfo.dw.subcode); | ||
6129 | else | ||
6130 | printk(MYIOC_s_INFO_FMT | ||
6131 | "LogInfo(0x%08x): Originator={%s}, Code=(0x%02x)," | ||
6132 | " SubCode(0x%04x)\n", | ||
6133 | ioc->name, | ||
6134 | log_info, | ||
6135 | originator_str[sas_loginfo.dw.originator], | ||
6136 | sas_loginfo.dw.code, | ||
6137 | sas_loginfo.dw.subcode); | ||
6138 | } | ||
6139 | |||
5656 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6140 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
5657 | /* | 6141 | /* |
5658 | * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC. | 6142 | * mpt_sp_ioc_info - IOC information returned from SCSI Parallel IOC. |
@@ -5814,6 +6298,7 @@ EXPORT_SYMBOL(mpt_findImVolumes); | |||
5814 | EXPORT_SYMBOL(mpt_read_ioc_pg_3); | 6298 | EXPORT_SYMBOL(mpt_read_ioc_pg_3); |
5815 | EXPORT_SYMBOL(mpt_alloc_fw_memory); | 6299 | EXPORT_SYMBOL(mpt_alloc_fw_memory); |
5816 | EXPORT_SYMBOL(mpt_free_fw_memory); | 6300 | EXPORT_SYMBOL(mpt_free_fw_memory); |
6301 | EXPORT_SYMBOL(mptbase_sas_persist_operation); | ||
5817 | 6302 | ||
5818 | 6303 | ||
5819 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6304 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index f4827d923731..75105277e22f 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h | |||
@@ -65,6 +65,7 @@ | |||
65 | #include "lsi/mpi_fc.h" /* Fibre Channel (lowlevel) support */ | 65 | #include "lsi/mpi_fc.h" /* Fibre Channel (lowlevel) support */ |
66 | #include "lsi/mpi_targ.h" /* SCSI/FCP Target protcol support */ | 66 | #include "lsi/mpi_targ.h" /* SCSI/FCP Target protcol support */ |
67 | #include "lsi/mpi_tool.h" /* Tools support */ | 67 | #include "lsi/mpi_tool.h" /* Tools support */ |
68 | #include "lsi/mpi_sas.h" /* SAS support */ | ||
68 | 69 | ||
69 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 70 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
70 | 71 | ||
@@ -76,8 +77,8 @@ | |||
76 | #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR | 77 | #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR |
77 | #endif | 78 | #endif |
78 | 79 | ||
79 | #define MPT_LINUX_VERSION_COMMON "3.03.02" | 80 | #define MPT_LINUX_VERSION_COMMON "3.03.03" |
80 | #define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.02" | 81 | #define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.03" |
81 | #define WHAT_MAGIC_STRING "@" "(" "#" ")" | 82 | #define WHAT_MAGIC_STRING "@" "(" "#" ")" |
82 | 83 | ||
83 | #define show_mptmod_ver(s,ver) \ | 84 | #define show_mptmod_ver(s,ver) \ |
@@ -423,7 +424,7 @@ typedef struct _MPT_IOCTL { | |||
423 | /* | 424 | /* |
424 | * Event Structure and define | 425 | * Event Structure and define |
425 | */ | 426 | */ |
426 | #define MPTCTL_EVENT_LOG_SIZE (0x0000000A) | 427 | #define MPTCTL_EVENT_LOG_SIZE (0x000000032) |
427 | typedef struct _mpt_ioctl_events { | 428 | typedef struct _mpt_ioctl_events { |
428 | u32 event; /* Specified by define above */ | 429 | u32 event; /* Specified by define above */ |
429 | u32 eventContext; /* Index or counter */ | 430 | u32 eventContext; /* Index or counter */ |
@@ -451,16 +452,13 @@ typedef struct _mpt_ioctl_events { | |||
451 | #define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */ | 452 | #define MPT_SCSICFG_ALL_IDS 0x02 /* WriteSDP1 to all IDS */ |
452 | /* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */ | 453 | /* #define MPT_SCSICFG_BLK_NEGO 0x10 WriteSDP1 with WDTR and SDTR disabled */ |
453 | 454 | ||
454 | typedef struct _ScsiCfgData { | 455 | typedef struct _SpiCfgData { |
455 | u32 PortFlags; | 456 | u32 PortFlags; |
456 | int *nvram; /* table of device NVRAM values */ | 457 | int *nvram; /* table of device NVRAM values */ |
457 | IOCPage2_t *pIocPg2; /* table of Raid Volumes */ | ||
458 | IOCPage3_t *pIocPg3; /* table of physical disks */ | ||
459 | IOCPage4_t *pIocPg4; /* SEP devices addressing */ | 458 | IOCPage4_t *pIocPg4; /* SEP devices addressing */ |
460 | dma_addr_t IocPg4_dma; /* Phys Addr of IOCPage4 data */ | 459 | dma_addr_t IocPg4_dma; /* Phys Addr of IOCPage4 data */ |
461 | int IocPg4Sz; /* IOCPage4 size */ | 460 | int IocPg4Sz; /* IOCPage4 size */ |
462 | u8 dvStatus[MPT_MAX_SCSI_DEVICES]; | 461 | u8 dvStatus[MPT_MAX_SCSI_DEVICES]; |
463 | int isRaid; /* bit field, 1 if RAID */ | ||
464 | u8 minSyncFactor; /* 0xFF if async */ | 462 | u8 minSyncFactor; /* 0xFF if async */ |
465 | u8 maxSyncOffset; /* 0 if async */ | 463 | u8 maxSyncOffset; /* 0 if async */ |
466 | u8 maxBusWidth; /* 0 if narrow, 1 if wide */ | 464 | u8 maxBusWidth; /* 0 if narrow, 1 if wide */ |
@@ -472,10 +470,28 @@ typedef struct _ScsiCfgData { | |||
472 | u8 dvScheduled; /* 1 if scheduled */ | 470 | u8 dvScheduled; /* 1 if scheduled */ |
473 | u8 forceDv; /* 1 to force DV scheduling */ | 471 | u8 forceDv; /* 1 to force DV scheduling */ |
474 | u8 noQas; /* Disable QAS for this adapter */ | 472 | u8 noQas; /* Disable QAS for this adapter */ |
475 | u8 Saf_Te; /* 1 to force all Processors as SAF-TE if Inquiry data length is too short to check for SAF-TE */ | 473 | u8 Saf_Te; /* 1 to force all Processors as |
474 | * SAF-TE if Inquiry data length | ||
475 | * is too short to check for SAF-TE | ||
476 | */ | ||
476 | u8 mpt_dv; /* command line option: enhanced=1, basic=0 */ | 477 | u8 mpt_dv; /* command line option: enhanced=1, basic=0 */ |
478 | u8 bus_reset; /* 1 to allow bus reset */ | ||
477 | u8 rsvd[1]; | 479 | u8 rsvd[1]; |
478 | } ScsiCfgData; | 480 | }SpiCfgData; |
481 | |||
482 | typedef struct _SasCfgData { | ||
483 | u8 ptClear; /* 1 to automatically clear the | ||
484 | * persistent table. | ||
485 | * 0 to disable | ||
486 | * automatic clearing. | ||
487 | */ | ||
488 | }SasCfgData; | ||
489 | |||
490 | typedef struct _RaidCfgData { | ||
491 | IOCPage2_t *pIocPg2; /* table of Raid Volumes */ | ||
492 | IOCPage3_t *pIocPg3; /* table of physical disks */ | ||
493 | int isRaid; /* bit field, 1 if RAID */ | ||
494 | }RaidCfgData; | ||
479 | 495 | ||
480 | /* | 496 | /* |
481 | * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS | 497 | * Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS |
@@ -530,11 +546,16 @@ typedef struct _MPT_ADAPTER | |||
530 | u8 *sense_buf_pool; | 546 | u8 *sense_buf_pool; |
531 | dma_addr_t sense_buf_pool_dma; | 547 | dma_addr_t sense_buf_pool_dma; |
532 | u32 sense_buf_low_dma; | 548 | u32 sense_buf_low_dma; |
549 | u8 *HostPageBuffer; /* SAS - host page buffer support */ | ||
550 | u32 HostPageBuffer_sz; | ||
551 | dma_addr_t HostPageBuffer_dma; | ||
533 | int mtrr_reg; | 552 | int mtrr_reg; |
534 | struct pci_dev *pcidev; /* struct pci_dev pointer */ | 553 | struct pci_dev *pcidev; /* struct pci_dev pointer */ |
535 | u8 __iomem *memmap; /* mmap address */ | 554 | u8 __iomem *memmap; /* mmap address */ |
536 | struct Scsi_Host *sh; /* Scsi Host pointer */ | 555 | struct Scsi_Host *sh; /* Scsi Host pointer */ |
537 | ScsiCfgData spi_data; /* Scsi config. data */ | 556 | SpiCfgData spi_data; /* Scsi config. data */ |
557 | RaidCfgData raid_data; /* Raid config. data */ | ||
558 | SasCfgData sas_data; /* Sas config. data */ | ||
538 | MPT_IOCTL *ioctl; /* ioctl data pointer */ | 559 | MPT_IOCTL *ioctl; /* ioctl data pointer */ |
539 | struct proc_dir_entry *ioc_dentry; | 560 | struct proc_dir_entry *ioc_dentry; |
540 | struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */ | 561 | struct _MPT_ADAPTER *alt_ioc; /* ptr to 929 bound adapter port */ |
@@ -554,31 +575,35 @@ typedef struct _MPT_ADAPTER | |||
554 | #else | 575 | #else |
555 | u32 mfcnt; | 576 | u32 mfcnt; |
556 | #endif | 577 | #endif |
557 | u32 NB_for_64_byte_frame; | 578 | u32 NB_for_64_byte_frame; |
558 | u32 hs_req[MPT_MAX_FRAME_SIZE/sizeof(u32)]; | 579 | u32 hs_req[MPT_MAX_FRAME_SIZE/sizeof(u32)]; |
559 | u16 hs_reply[MPT_MAX_FRAME_SIZE/sizeof(u16)]; | 580 | u16 hs_reply[MPT_MAX_FRAME_SIZE/sizeof(u16)]; |
560 | IOCFactsReply_t facts; | 581 | IOCFactsReply_t facts; |
561 | PortFactsReply_t pfacts[2]; | 582 | PortFactsReply_t pfacts[2]; |
562 | FCPortPage0_t fc_port_page0[2]; | 583 | FCPortPage0_t fc_port_page0[2]; |
584 | struct timer_list persist_timer; /* persist table timer */ | ||
585 | int persist_wait_done; /* persist completion flag */ | ||
586 | u8 persist_reply_frame[MPT_DEFAULT_FRAME_SIZE]; /* persist reply */ | ||
563 | LANPage0_t lan_cnfg_page0; | 587 | LANPage0_t lan_cnfg_page0; |
564 | LANPage1_t lan_cnfg_page1; | 588 | LANPage1_t lan_cnfg_page1; |
565 | /* | 589 | /* |
566 | * Description: errata_flag_1064 | 590 | * Description: errata_flag_1064 |
567 | * If a PCIX read occurs within 1 or 2 cycles after the chip receives | 591 | * If a PCIX read occurs within 1 or 2 cycles after the chip receives |
568 | * a split completion for a read data, an internal address pointer incorrectly | 592 | * a split completion for a read data, an internal address pointer incorrectly |
569 | * increments by 32 bytes | 593 | * increments by 32 bytes |
570 | */ | 594 | */ |
571 | int errata_flag_1064; | 595 | int errata_flag_1064; |
572 | u8 FirstWhoInit; | 596 | u8 FirstWhoInit; |
573 | u8 upload_fw; /* If set, do a fw upload */ | 597 | u8 upload_fw; /* If set, do a fw upload */ |
574 | u8 reload_fw; /* Force a FW Reload on next reset */ | 598 | u8 reload_fw; /* Force a FW Reload on next reset */ |
575 | u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */ | 599 | u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */ |
576 | u8 pad1[4]; | 600 | u8 pad1[4]; |
577 | int DoneCtx; | 601 | int DoneCtx; |
578 | int TaskCtx; | 602 | int TaskCtx; |
579 | int InternalCtx; | 603 | int InternalCtx; |
580 | struct list_head list; | 604 | struct list_head list; |
581 | struct net_device *netdev; | 605 | struct net_device *netdev; |
606 | struct list_head sas_topology; | ||
582 | } MPT_ADAPTER; | 607 | } MPT_ADAPTER; |
583 | 608 | ||
584 | /* | 609 | /* |
@@ -964,6 +989,7 @@ extern void mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size); | |||
964 | extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); | 989 | extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); |
965 | extern int mpt_findImVolumes(MPT_ADAPTER *ioc); | 990 | extern int mpt_findImVolumes(MPT_ADAPTER *ioc); |
966 | extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); | 991 | extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); |
992 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); | ||
967 | 993 | ||
968 | /* | 994 | /* |
969 | * Public data decl's... | 995 | * Public data decl's... |
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 7577c2417e2e..cb2d59d5f5af 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c | |||
@@ -1326,7 +1326,7 @@ mptctl_gettargetinfo (unsigned long arg) | |||
1326 | */ | 1326 | */ |
1327 | if (hd && hd->Targets) { | 1327 | if (hd && hd->Targets) { |
1328 | mpt_findImVolumes(ioc); | 1328 | mpt_findImVolumes(ioc); |
1329 | pIoc2 = ioc->spi_data.pIocPg2; | 1329 | pIoc2 = ioc->raid_data.pIocPg2; |
1330 | for ( id = 0; id <= max_id; ) { | 1330 | for ( id = 0; id <= max_id; ) { |
1331 | if ( pIoc2 && pIoc2->NumActiveVolumes ) { | 1331 | if ( pIoc2 && pIoc2->NumActiveVolumes ) { |
1332 | if ( id == pIoc2->RaidVolume[0].VolumeID ) { | 1332 | if ( id == pIoc2->RaidVolume[0].VolumeID ) { |
@@ -1348,7 +1348,7 @@ mptctl_gettargetinfo (unsigned long arg) | |||
1348 | --maxWordsLeft; | 1348 | --maxWordsLeft; |
1349 | goto next_id; | 1349 | goto next_id; |
1350 | } else { | 1350 | } else { |
1351 | pIoc3 = ioc->spi_data.pIocPg3; | 1351 | pIoc3 = ioc->raid_data.pIocPg3; |
1352 | for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) { | 1352 | for ( jj = 0; jj < pIoc3->NumPhysDisks; jj++ ) { |
1353 | if ( pIoc3->PhysDisk[jj].PhysDiskID == id ) | 1353 | if ( pIoc3->PhysDisk[jj].PhysDiskID == id ) |
1354 | goto next_id; | 1354 | goto next_id; |
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 13771abea13f..a628be9bbbad 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c | |||
@@ -189,7 +189,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
189 | printk(MYIOC_s_WARN_FMT | 189 | printk(MYIOC_s_WARN_FMT |
190 | "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", | 190 | "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", |
191 | ioc->name, ioc); | 191 | ioc->name, ioc); |
192 | return -ENODEV; | 192 | return 0; |
193 | } | 193 | } |
194 | 194 | ||
195 | sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST)); | 195 | sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST)); |
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 52794be5a95c..ed3c891e388f 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c | |||
@@ -312,7 +312,12 @@ static int | |||
312 | mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | 312 | mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) |
313 | { | 313 | { |
314 | struct net_device *dev = ioc->netdev; | 314 | struct net_device *dev = ioc->netdev; |
315 | struct mpt_lan_priv *priv = netdev_priv(dev); | 315 | struct mpt_lan_priv *priv; |
316 | |||
317 | if (dev == NULL) | ||
318 | return(1); | ||
319 | else | ||
320 | priv = netdev_priv(dev); | ||
316 | 321 | ||
317 | dlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to LAN driver!\n", | 322 | dlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to LAN driver!\n", |
318 | reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( | 323 | reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( |
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c new file mode 100644 index 000000000000..429820e48c69 --- /dev/null +++ b/drivers/message/fusion/mptsas.c | |||
@@ -0,0 +1,1235 @@ | |||
1 | /* | ||
2 | * linux/drivers/message/fusion/mptsas.c | ||
3 | * For use with LSI Logic PCI chip/adapter(s) | ||
4 | * running LSI Logic Fusion MPT (Message Passing Technology) firmware. | ||
5 | * | ||
6 | * Copyright (c) 1999-2005 LSI Logic Corporation | ||
7 | * (mailto:mpt_linux_developer@lsil.com) | ||
8 | * Copyright (c) 2005 Dell | ||
9 | */ | ||
10 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
11 | /* | ||
12 | This program is free software; you can redistribute it and/or modify | ||
13 | it under the terms of the GNU General Public License as published by | ||
14 | the Free Software Foundation; version 2 of the License. | ||
15 | |||
16 | This program is distributed in the hope that it will be useful, | ||
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | GNU General Public License for more details. | ||
20 | |||
21 | NO WARRANTY | ||
22 | THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR | ||
23 | CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT | ||
24 | LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, | ||
25 | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is | ||
26 | solely responsible for determining the appropriateness of using and | ||
27 | distributing the Program and assumes all risks associated with its | ||
28 | exercise of rights under this Agreement, including but not limited to | ||
29 | the risks and costs of program errors, damage to or loss of data, | ||
30 | programs or equipment, and unavailability or interruption of operations. | ||
31 | |||
32 | DISCLAIMER OF LIABILITY | ||
33 | NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY | ||
34 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
35 | DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND | ||
36 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | ||
37 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | ||
38 | USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED | ||
39 | HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES | ||
40 | |||
41 | You should have received a copy of the GNU General Public License | ||
42 | along with this program; if not, write to the Free Software | ||
43 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
44 | */ | ||
45 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
46 | |||
47 | #include <linux/module.h> | ||
48 | #include <linux/kernel.h> | ||
49 | #include <linux/init.h> | ||
50 | #include <linux/errno.h> | ||
51 | #include <linux/sched.h> | ||
52 | #include <linux/workqueue.h> | ||
53 | |||
54 | #include <scsi/scsi_cmnd.h> | ||
55 | #include <scsi/scsi_device.h> | ||
56 | #include <scsi/scsi_host.h> | ||
57 | #include <scsi/scsi_transport_sas.h> | ||
58 | |||
59 | #include "mptbase.h" | ||
60 | #include "mptscsih.h" | ||
61 | |||
62 | |||
63 | #define my_NAME "Fusion MPT SAS Host driver" | ||
64 | #define my_VERSION MPT_LINUX_VERSION_COMMON | ||
65 | #define MYNAM "mptsas" | ||
66 | |||
67 | MODULE_AUTHOR(MODULEAUTHOR); | ||
68 | MODULE_DESCRIPTION(my_NAME); | ||
69 | MODULE_LICENSE("GPL"); | ||
70 | |||
71 | static int mpt_pq_filter; | ||
72 | module_param(mpt_pq_filter, int, 0); | ||
73 | MODULE_PARM_DESC(mpt_pq_filter, | ||
74 | "Enable peripheral qualifier filter: enable=1 " | ||
75 | "(default=0)"); | ||
76 | |||
77 | static int mpt_pt_clear; | ||
78 | module_param(mpt_pt_clear, int, 0); | ||
79 | MODULE_PARM_DESC(mpt_pt_clear, | ||
80 | "Clear persistency table: enable=1 " | ||
81 | "(default=MPTSCSIH_PT_CLEAR=0)"); | ||
82 | |||
83 | static int mptsasDoneCtx = -1; | ||
84 | static int mptsasTaskCtx = -1; | ||
85 | static int mptsasInternalCtx = -1; /* Used only for internal commands */ | ||
86 | |||
87 | |||
88 | /* | ||
89 | * SAS topology structures | ||
90 | * | ||
91 | * The MPT Fusion firmware interface spreads information about the | ||
92 | * SAS topology over many manufacture pages, thus we need some data | ||
93 | * structure to collect it and process it for the SAS transport class. | ||
94 | */ | ||
95 | |||
96 | struct mptsas_devinfo { | ||
97 | u16 handle; /* unique id to address this device */ | ||
98 | u8 phy_id; /* phy number of parent device */ | ||
99 | u8 port_id; /* sas physical port this device | ||
100 | is assoc'd with */ | ||
101 | u8 target; /* logical target id of this device */ | ||
102 | u8 bus; /* logical bus number of this device */ | ||
103 | u64 sas_address; /* WWN of this device, | ||
104 | SATA is assigned by HBA,expander */ | ||
105 | u32 device_info; /* bitfield detailed info about this device */ | ||
106 | }; | ||
107 | |||
108 | struct mptsas_phyinfo { | ||
109 | u8 phy_id; /* phy index */ | ||
110 | u8 port_id; /* port number this phy is part of */ | ||
111 | u8 negotiated_link_rate; /* nego'd link rate for this phy */ | ||
112 | u8 hw_link_rate; /* hardware max/min phys link rate */ | ||
113 | u8 programmed_link_rate; /* programmed max/min phy link rate */ | ||
114 | struct mptsas_devinfo identify; /* point to phy device info */ | ||
115 | struct mptsas_devinfo attached; /* point to attached device info */ | ||
116 | struct sas_rphy *rphy; | ||
117 | }; | ||
118 | |||
119 | struct mptsas_portinfo { | ||
120 | struct list_head list; | ||
121 | u16 handle; /* unique id to address this */ | ||
122 | u8 num_phys; /* number of phys */ | ||
123 | struct mptsas_phyinfo *phy_info; | ||
124 | }; | ||
125 | |||
126 | /* | ||
127 | * This is pretty ugly. We will be able to seriously clean it up | ||
128 | * once the DV code in mptscsih goes away and we can properly | ||
129 | * implement ->target_alloc. | ||
130 | */ | ||
131 | static int | ||
132 | mptsas_slave_alloc(struct scsi_device *device) | ||
133 | { | ||
134 | struct Scsi_Host *host = device->host; | ||
135 | MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; | ||
136 | struct sas_rphy *rphy; | ||
137 | struct mptsas_portinfo *p; | ||
138 | VirtDevice *vdev; | ||
139 | uint target = device->id; | ||
140 | int i; | ||
141 | |||
142 | if ((vdev = hd->Targets[target]) != NULL) | ||
143 | goto out; | ||
144 | |||
145 | vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL); | ||
146 | if (!vdev) { | ||
147 | printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", | ||
148 | hd->ioc->name, sizeof(VirtDevice)); | ||
149 | return -ENOMEM; | ||
150 | } | ||
151 | |||
152 | memset(vdev, 0, sizeof(VirtDevice)); | ||
153 | vdev->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY; | ||
154 | vdev->ioc_id = hd->ioc->id; | ||
155 | |||
156 | rphy = dev_to_rphy(device->sdev_target->dev.parent); | ||
157 | list_for_each_entry(p, &hd->ioc->sas_topology, list) { | ||
158 | for (i = 0; i < p->num_phys; i++) { | ||
159 | if (p->phy_info[i].attached.sas_address == | ||
160 | rphy->identify.sas_address) { | ||
161 | vdev->target_id = | ||
162 | p->phy_info[i].attached.target; | ||
163 | vdev->bus_id = p->phy_info[i].attached.bus; | ||
164 | hd->Targets[device->id] = vdev; | ||
165 | goto out; | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | |||
170 | printk("No matching SAS device found!!\n"); | ||
171 | kfree(vdev); | ||
172 | return -ENODEV; | ||
173 | |||
174 | out: | ||
175 | vdev->num_luns++; | ||
176 | device->hostdata = vdev; | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static struct scsi_host_template mptsas_driver_template = { | ||
181 | .proc_name = "mptsas", | ||
182 | .proc_info = mptscsih_proc_info, | ||
183 | .name = "MPT SPI Host", | ||
184 | .info = mptscsih_info, | ||
185 | .queuecommand = mptscsih_qcmd, | ||
186 | .slave_alloc = mptsas_slave_alloc, | ||
187 | .slave_configure = mptscsih_slave_configure, | ||
188 | .slave_destroy = mptscsih_slave_destroy, | ||
189 | .change_queue_depth = mptscsih_change_queue_depth, | ||
190 | .eh_abort_handler = mptscsih_abort, | ||
191 | .eh_device_reset_handler = mptscsih_dev_reset, | ||
192 | .eh_bus_reset_handler = mptscsih_bus_reset, | ||
193 | .eh_host_reset_handler = mptscsih_host_reset, | ||
194 | .bios_param = mptscsih_bios_param, | ||
195 | .can_queue = MPT_FC_CAN_QUEUE, | ||
196 | .this_id = -1, | ||
197 | .sg_tablesize = MPT_SCSI_SG_DEPTH, | ||
198 | .max_sectors = 8192, | ||
199 | .cmd_per_lun = 7, | ||
200 | .use_clustering = ENABLE_CLUSTERING, | ||
201 | }; | ||
202 | |||
203 | static struct sas_function_template mptsas_transport_functions = { | ||
204 | }; | ||
205 | |||
206 | static struct scsi_transport_template *mptsas_transport_template; | ||
207 | |||
208 | #ifdef SASDEBUG | ||
209 | static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) | ||
210 | { | ||
211 | printk("---- IO UNIT PAGE 0 ------------\n"); | ||
212 | printk("Handle=0x%X\n", | ||
213 | le16_to_cpu(phy_data->AttachedDeviceHandle)); | ||
214 | printk("Controller Handle=0x%X\n", | ||
215 | le16_to_cpu(phy_data->ControllerDevHandle)); | ||
216 | printk("Port=0x%X\n", phy_data->Port); | ||
217 | printk("Port Flags=0x%X\n", phy_data->PortFlags); | ||
218 | printk("PHY Flags=0x%X\n", phy_data->PhyFlags); | ||
219 | printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate); | ||
220 | printk("Controller PHY Device Info=0x%X\n", | ||
221 | le32_to_cpu(phy_data->ControllerPhyDeviceInfo)); | ||
222 | printk("DiscoveryStatus=0x%X\n", | ||
223 | le32_to_cpu(phy_data->DiscoveryStatus)); | ||
224 | printk("\n"); | ||
225 | } | ||
226 | |||
227 | static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0) | ||
228 | { | ||
229 | __le64 sas_address; | ||
230 | |||
231 | memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64)); | ||
232 | |||
233 | printk("---- SAS PHY PAGE 0 ------------\n"); | ||
234 | printk("Attached Device Handle=0x%X\n", | ||
235 | le16_to_cpu(pg0->AttachedDevHandle)); | ||
236 | printk("SAS Address=0x%llX\n", | ||
237 | (unsigned long long)le64_to_cpu(sas_address)); | ||
238 | printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier); | ||
239 | printk("Attached Device Info=0x%X\n", | ||
240 | le32_to_cpu(pg0->AttachedDeviceInfo)); | ||
241 | printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate); | ||
242 | printk("Change Count=0x%X\n", pg0->ChangeCount); | ||
243 | printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo)); | ||
244 | printk("\n"); | ||
245 | } | ||
246 | |||
247 | static void mptsas_print_device_pg0(SasDevicePage0_t *pg0) | ||
248 | { | ||
249 | __le64 sas_address; | ||
250 | |||
251 | memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64)); | ||
252 | |||
253 | printk("---- SAS DEVICE PAGE 0 ---------\n"); | ||
254 | printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle)); | ||
255 | printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle)); | ||
256 | printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot)); | ||
257 | printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address)); | ||
258 | printk("Target ID=0x%X\n", pg0->TargetID); | ||
259 | printk("Bus=0x%X\n", pg0->Bus); | ||
260 | printk("PhyNum=0x%X\n", pg0->PhyNum); | ||
261 | printk("AccessStatus=0x%X\n", le16_to_cpu(pg0->AccessStatus)); | ||
262 | printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo)); | ||
263 | printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags)); | ||
264 | printk("Physical Port=0x%X\n", pg0->PhysicalPort); | ||
265 | printk("\n"); | ||
266 | } | ||
267 | |||
268 | static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1) | ||
269 | { | ||
270 | printk("---- SAS EXPANDER PAGE 1 ------------\n"); | ||
271 | |||
272 | printk("Physical Port=0x%X\n", pg1->PhysicalPort); | ||
273 | printk("PHY Identifier=0x%X\n", pg1->Phy); | ||
274 | printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate); | ||
275 | printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate); | ||
276 | printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate); | ||
277 | printk("Owner Device Handle=0x%X\n", | ||
278 | le16_to_cpu(pg1->OwnerDevHandle)); | ||
279 | printk("Attached Device Handle=0x%X\n", | ||
280 | le16_to_cpu(pg1->AttachedDevHandle)); | ||
281 | } | ||
282 | #else | ||
283 | #define mptsas_print_phy_data(phy_data) do { } while (0) | ||
284 | #define mptsas_print_phy_pg0(pg0) do { } while (0) | ||
285 | #define mptsas_print_device_pg0(pg0) do { } while (0) | ||
286 | #define mptsas_print_expander_pg1(pg1) do { } while (0) | ||
287 | #endif | ||
288 | |||
289 | static int | ||
290 | mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) | ||
291 | { | ||
292 | ConfigExtendedPageHeader_t hdr; | ||
293 | CONFIGPARMS cfg; | ||
294 | SasIOUnitPage0_t *buffer; | ||
295 | dma_addr_t dma_handle; | ||
296 | int error, i; | ||
297 | |||
298 | hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION; | ||
299 | hdr.ExtPageLength = 0; | ||
300 | hdr.PageNumber = 0; | ||
301 | hdr.Reserved1 = 0; | ||
302 | hdr.Reserved2 = 0; | ||
303 | hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; | ||
304 | hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; | ||
305 | |||
306 | cfg.cfghdr.ehdr = &hdr; | ||
307 | cfg.physAddr = -1; | ||
308 | cfg.pageAddr = 0; | ||
309 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
310 | cfg.dir = 0; /* read */ | ||
311 | cfg.timeout = 10; | ||
312 | |||
313 | error = mpt_config(ioc, &cfg); | ||
314 | if (error) | ||
315 | goto out; | ||
316 | if (!hdr.ExtPageLength) { | ||
317 | error = -ENXIO; | ||
318 | goto out; | ||
319 | } | ||
320 | |||
321 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
322 | &dma_handle); | ||
323 | if (!buffer) { | ||
324 | error = -ENOMEM; | ||
325 | goto out; | ||
326 | } | ||
327 | |||
328 | cfg.physAddr = dma_handle; | ||
329 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
330 | |||
331 | error = mpt_config(ioc, &cfg); | ||
332 | if (error) | ||
333 | goto out_free_consistent; | ||
334 | |||
335 | port_info->num_phys = buffer->NumPhys; | ||
336 | port_info->phy_info = kcalloc(port_info->num_phys, | ||
337 | sizeof(struct mptsas_phyinfo),GFP_KERNEL); | ||
338 | if (!port_info->phy_info) { | ||
339 | error = -ENOMEM; | ||
340 | goto out_free_consistent; | ||
341 | } | ||
342 | |||
343 | for (i = 0; i < port_info->num_phys; i++) { | ||
344 | mptsas_print_phy_data(&buffer->PhyData[i]); | ||
345 | port_info->phy_info[i].phy_id = i; | ||
346 | port_info->phy_info[i].port_id = | ||
347 | buffer->PhyData[i].Port; | ||
348 | port_info->phy_info[i].negotiated_link_rate = | ||
349 | buffer->PhyData[i].NegotiatedLinkRate; | ||
350 | } | ||
351 | |||
352 | out_free_consistent: | ||
353 | pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
354 | buffer, dma_handle); | ||
355 | out: | ||
356 | return error; | ||
357 | } | ||
358 | |||
359 | static int | ||
360 | mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, | ||
361 | u32 form, u32 form_specific) | ||
362 | { | ||
363 | ConfigExtendedPageHeader_t hdr; | ||
364 | CONFIGPARMS cfg; | ||
365 | SasPhyPage0_t *buffer; | ||
366 | dma_addr_t dma_handle; | ||
367 | int error; | ||
368 | |||
369 | hdr.PageVersion = MPI_SASPHY0_PAGEVERSION; | ||
370 | hdr.ExtPageLength = 0; | ||
371 | hdr.PageNumber = 0; | ||
372 | hdr.Reserved1 = 0; | ||
373 | hdr.Reserved2 = 0; | ||
374 | hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; | ||
375 | hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY; | ||
376 | |||
377 | cfg.cfghdr.ehdr = &hdr; | ||
378 | cfg.dir = 0; /* read */ | ||
379 | cfg.timeout = 10; | ||
380 | |||
381 | /* Get Phy Pg 0 for each Phy. */ | ||
382 | cfg.physAddr = -1; | ||
383 | cfg.pageAddr = form + form_specific; | ||
384 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
385 | |||
386 | error = mpt_config(ioc, &cfg); | ||
387 | if (error) | ||
388 | goto out; | ||
389 | |||
390 | if (!hdr.ExtPageLength) { | ||
391 | error = -ENXIO; | ||
392 | goto out; | ||
393 | } | ||
394 | |||
395 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
396 | &dma_handle); | ||
397 | if (!buffer) { | ||
398 | error = -ENOMEM; | ||
399 | goto out; | ||
400 | } | ||
401 | |||
402 | cfg.physAddr = dma_handle; | ||
403 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
404 | |||
405 | error = mpt_config(ioc, &cfg); | ||
406 | if (error) | ||
407 | goto out_free_consistent; | ||
408 | |||
409 | mptsas_print_phy_pg0(buffer); | ||
410 | |||
411 | phy_info->hw_link_rate = buffer->HwLinkRate; | ||
412 | phy_info->programmed_link_rate = buffer->ProgrammedLinkRate; | ||
413 | phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle); | ||
414 | phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle); | ||
415 | |||
416 | out_free_consistent: | ||
417 | pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
418 | buffer, dma_handle); | ||
419 | out: | ||
420 | return error; | ||
421 | } | ||
422 | |||
423 | static int | ||
424 | mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info, | ||
425 | u32 form, u32 form_specific) | ||
426 | { | ||
427 | ConfigExtendedPageHeader_t hdr; | ||
428 | CONFIGPARMS cfg; | ||
429 | SasDevicePage0_t *buffer; | ||
430 | dma_addr_t dma_handle; | ||
431 | __le64 sas_address; | ||
432 | int error; | ||
433 | |||
434 | hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION; | ||
435 | hdr.ExtPageLength = 0; | ||
436 | hdr.PageNumber = 0; | ||
437 | hdr.Reserved1 = 0; | ||
438 | hdr.Reserved2 = 0; | ||
439 | hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; | ||
440 | hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE; | ||
441 | |||
442 | cfg.cfghdr.ehdr = &hdr; | ||
443 | cfg.pageAddr = form + form_specific; | ||
444 | cfg.physAddr = -1; | ||
445 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
446 | cfg.dir = 0; /* read */ | ||
447 | cfg.timeout = 10; | ||
448 | |||
449 | error = mpt_config(ioc, &cfg); | ||
450 | if (error) | ||
451 | goto out; | ||
452 | if (!hdr.ExtPageLength) { | ||
453 | error = -ENXIO; | ||
454 | goto out; | ||
455 | } | ||
456 | |||
457 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
458 | &dma_handle); | ||
459 | if (!buffer) { | ||
460 | error = -ENOMEM; | ||
461 | goto out; | ||
462 | } | ||
463 | |||
464 | cfg.physAddr = dma_handle; | ||
465 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
466 | |||
467 | error = mpt_config(ioc, &cfg); | ||
468 | if (error) | ||
469 | goto out_free_consistent; | ||
470 | |||
471 | mptsas_print_device_pg0(buffer); | ||
472 | |||
473 | device_info->handle = le16_to_cpu(buffer->DevHandle); | ||
474 | device_info->phy_id = buffer->PhyNum; | ||
475 | device_info->port_id = buffer->PhysicalPort; | ||
476 | device_info->target = buffer->TargetID; | ||
477 | device_info->bus = buffer->Bus; | ||
478 | memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64)); | ||
479 | device_info->sas_address = le64_to_cpu(sas_address); | ||
480 | device_info->device_info = | ||
481 | le32_to_cpu(buffer->DeviceInfo); | ||
482 | |||
483 | out_free_consistent: | ||
484 | pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
485 | buffer, dma_handle); | ||
486 | out: | ||
487 | return error; | ||
488 | } | ||
489 | |||
490 | static int | ||
491 | mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info, | ||
492 | u32 form, u32 form_specific) | ||
493 | { | ||
494 | ConfigExtendedPageHeader_t hdr; | ||
495 | CONFIGPARMS cfg; | ||
496 | SasExpanderPage0_t *buffer; | ||
497 | dma_addr_t dma_handle; | ||
498 | int error; | ||
499 | |||
500 | hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION; | ||
501 | hdr.ExtPageLength = 0; | ||
502 | hdr.PageNumber = 0; | ||
503 | hdr.Reserved1 = 0; | ||
504 | hdr.Reserved2 = 0; | ||
505 | hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; | ||
506 | hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER; | ||
507 | |||
508 | cfg.cfghdr.ehdr = &hdr; | ||
509 | cfg.physAddr = -1; | ||
510 | cfg.pageAddr = form + form_specific; | ||
511 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
512 | cfg.dir = 0; /* read */ | ||
513 | cfg.timeout = 10; | ||
514 | |||
515 | error = mpt_config(ioc, &cfg); | ||
516 | if (error) | ||
517 | goto out; | ||
518 | |||
519 | if (!hdr.ExtPageLength) { | ||
520 | error = -ENXIO; | ||
521 | goto out; | ||
522 | } | ||
523 | |||
524 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
525 | &dma_handle); | ||
526 | if (!buffer) { | ||
527 | error = -ENOMEM; | ||
528 | goto out; | ||
529 | } | ||
530 | |||
531 | cfg.physAddr = dma_handle; | ||
532 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
533 | |||
534 | error = mpt_config(ioc, &cfg); | ||
535 | if (error) | ||
536 | goto out_free_consistent; | ||
537 | |||
538 | /* save config data */ | ||
539 | port_info->num_phys = buffer->NumPhys; | ||
540 | port_info->handle = le16_to_cpu(buffer->DevHandle); | ||
541 | port_info->phy_info = kcalloc(port_info->num_phys, | ||
542 | sizeof(struct mptsas_phyinfo),GFP_KERNEL); | ||
543 | if (!port_info->phy_info) { | ||
544 | error = -ENOMEM; | ||
545 | goto out_free_consistent; | ||
546 | } | ||
547 | |||
548 | out_free_consistent: | ||
549 | pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
550 | buffer, dma_handle); | ||
551 | out: | ||
552 | return error; | ||
553 | } | ||
554 | |||
555 | static int | ||
556 | mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, | ||
557 | u32 form, u32 form_specific) | ||
558 | { | ||
559 | ConfigExtendedPageHeader_t hdr; | ||
560 | CONFIGPARMS cfg; | ||
561 | SasExpanderPage1_t *buffer; | ||
562 | dma_addr_t dma_handle; | ||
563 | int error; | ||
564 | |||
565 | hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION; | ||
566 | hdr.ExtPageLength = 0; | ||
567 | hdr.PageNumber = 1; | ||
568 | hdr.Reserved1 = 0; | ||
569 | hdr.Reserved2 = 0; | ||
570 | hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED; | ||
571 | hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER; | ||
572 | |||
573 | cfg.cfghdr.ehdr = &hdr; | ||
574 | cfg.physAddr = -1; | ||
575 | cfg.pageAddr = form + form_specific; | ||
576 | cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER; | ||
577 | cfg.dir = 0; /* read */ | ||
578 | cfg.timeout = 10; | ||
579 | |||
580 | error = mpt_config(ioc, &cfg); | ||
581 | if (error) | ||
582 | goto out; | ||
583 | |||
584 | if (!hdr.ExtPageLength) { | ||
585 | error = -ENXIO; | ||
586 | goto out; | ||
587 | } | ||
588 | |||
589 | buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
590 | &dma_handle); | ||
591 | if (!buffer) { | ||
592 | error = -ENOMEM; | ||
593 | goto out; | ||
594 | } | ||
595 | |||
596 | cfg.physAddr = dma_handle; | ||
597 | cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; | ||
598 | |||
599 | error = mpt_config(ioc, &cfg); | ||
600 | if (error) | ||
601 | goto out_free_consistent; | ||
602 | |||
603 | |||
604 | mptsas_print_expander_pg1(buffer); | ||
605 | |||
606 | /* save config data */ | ||
607 | phy_info->phy_id = buffer->Phy; | ||
608 | phy_info->port_id = buffer->PhysicalPort; | ||
609 | phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate; | ||
610 | phy_info->programmed_link_rate = buffer->ProgrammedLinkRate; | ||
611 | phy_info->hw_link_rate = buffer->HwLinkRate; | ||
612 | phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle); | ||
613 | phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle); | ||
614 | |||
615 | |||
616 | out_free_consistent: | ||
617 | pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4, | ||
618 | buffer, dma_handle); | ||
619 | out: | ||
620 | return error; | ||
621 | } | ||
622 | |||
623 | static void | ||
624 | mptsas_parse_device_info(struct sas_identify *identify, | ||
625 | struct mptsas_devinfo *device_info) | ||
626 | { | ||
627 | u16 protocols; | ||
628 | |||
629 | identify->sas_address = device_info->sas_address; | ||
630 | identify->phy_identifier = device_info->phy_id; | ||
631 | |||
632 | /* | ||
633 | * Fill in Phy Initiator Port Protocol. | ||
634 | * Bits 6:3, more than one bit can be set, fall through cases. | ||
635 | */ | ||
636 | protocols = device_info->device_info & 0x78; | ||
637 | identify->initiator_port_protocols = 0; | ||
638 | if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR) | ||
639 | identify->initiator_port_protocols |= SAS_PROTOCOL_SSP; | ||
640 | if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR) | ||
641 | identify->initiator_port_protocols |= SAS_PROTOCOL_STP; | ||
642 | if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR) | ||
643 | identify->initiator_port_protocols |= SAS_PROTOCOL_SMP; | ||
644 | if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST) | ||
645 | identify->initiator_port_protocols |= SAS_PROTOCOL_SATA; | ||
646 | |||
647 | /* | ||
648 | * Fill in Phy Target Port Protocol. | ||
649 | * Bits 10:7, more than one bit can be set, fall through cases. | ||
650 | */ | ||
651 | protocols = device_info->device_info & 0x780; | ||
652 | identify->target_port_protocols = 0; | ||
653 | if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET) | ||
654 | identify->target_port_protocols |= SAS_PROTOCOL_SSP; | ||
655 | if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET) | ||
656 | identify->target_port_protocols |= SAS_PROTOCOL_STP; | ||
657 | if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET) | ||
658 | identify->target_port_protocols |= SAS_PROTOCOL_SMP; | ||
659 | if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE) | ||
660 | identify->target_port_protocols |= SAS_PROTOCOL_SATA; | ||
661 | |||
662 | /* | ||
663 | * Fill in Attached device type. | ||
664 | */ | ||
665 | switch (device_info->device_info & | ||
666 | MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) { | ||
667 | case MPI_SAS_DEVICE_INFO_NO_DEVICE: | ||
668 | identify->device_type = SAS_PHY_UNUSED; | ||
669 | break; | ||
670 | case MPI_SAS_DEVICE_INFO_END_DEVICE: | ||
671 | identify->device_type = SAS_END_DEVICE; | ||
672 | break; | ||
673 | case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER: | ||
674 | identify->device_type = SAS_EDGE_EXPANDER_DEVICE; | ||
675 | break; | ||
676 | case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER: | ||
677 | identify->device_type = SAS_FANOUT_EXPANDER_DEVICE; | ||
678 | break; | ||
679 | } | ||
680 | } | ||
681 | |||
682 | static int mptsas_probe_one_phy(struct device *dev, | ||
683 | struct mptsas_phyinfo *phy_info, int index) | ||
684 | { | ||
685 | struct sas_phy *port; | ||
686 | int error; | ||
687 | |||
688 | port = sas_phy_alloc(dev, index); | ||
689 | if (!port) | ||
690 | return -ENOMEM; | ||
691 | |||
692 | port->port_identifier = phy_info->port_id; | ||
693 | mptsas_parse_device_info(&port->identify, &phy_info->identify); | ||
694 | |||
695 | /* | ||
696 | * Set Negotiated link rate. | ||
697 | */ | ||
698 | switch (phy_info->negotiated_link_rate) { | ||
699 | case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED: | ||
700 | port->negotiated_linkrate = SAS_PHY_DISABLED; | ||
701 | break; | ||
702 | case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION: | ||
703 | port->negotiated_linkrate = SAS_LINK_RATE_FAILED; | ||
704 | break; | ||
705 | case MPI_SAS_IOUNIT0_RATE_1_5: | ||
706 | port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS; | ||
707 | break; | ||
708 | case MPI_SAS_IOUNIT0_RATE_3_0: | ||
709 | port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS; | ||
710 | break; | ||
711 | case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE: | ||
712 | case MPI_SAS_IOUNIT0_RATE_UNKNOWN: | ||
713 | default: | ||
714 | port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN; | ||
715 | break; | ||
716 | } | ||
717 | |||
718 | /* | ||
719 | * Set Max hardware link rate. | ||
720 | */ | ||
721 | switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { | ||
722 | case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5: | ||
723 | port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; | ||
724 | break; | ||
725 | case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: | ||
726 | port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; | ||
727 | break; | ||
728 | default: | ||
729 | break; | ||
730 | } | ||
731 | |||
732 | /* | ||
733 | * Set Max programmed link rate. | ||
734 | */ | ||
735 | switch (phy_info->programmed_link_rate & | ||
736 | MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) { | ||
737 | case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5: | ||
738 | port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS; | ||
739 | break; | ||
740 | case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0: | ||
741 | port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS; | ||
742 | break; | ||
743 | default: | ||
744 | break; | ||
745 | } | ||
746 | |||
747 | /* | ||
748 | * Set Min hardware link rate. | ||
749 | */ | ||
750 | switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) { | ||
751 | case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5: | ||
752 | port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; | ||
753 | break; | ||
754 | case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: | ||
755 | port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS; | ||
756 | break; | ||
757 | default: | ||
758 | break; | ||
759 | } | ||
760 | |||
761 | /* | ||
762 | * Set Min programmed link rate. | ||
763 | */ | ||
764 | switch (phy_info->programmed_link_rate & | ||
765 | MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) { | ||
766 | case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5: | ||
767 | port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS; | ||
768 | break; | ||
769 | case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0: | ||
770 | port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS; | ||
771 | break; | ||
772 | default: | ||
773 | break; | ||
774 | } | ||
775 | |||
776 | error = sas_phy_add(port); | ||
777 | if (error) { | ||
778 | sas_phy_free(port); | ||
779 | return error; | ||
780 | } | ||
781 | |||
782 | if (phy_info->attached.handle) { | ||
783 | struct sas_rphy *rphy; | ||
784 | |||
785 | rphy = sas_rphy_alloc(port); | ||
786 | if (!rphy) | ||
787 | return 0; /* non-fatal: an rphy can be added later */ | ||
788 | |||
789 | mptsas_parse_device_info(&rphy->identify, &phy_info->attached); | ||
790 | error = sas_rphy_add(rphy); | ||
791 | if (error) { | ||
792 | sas_rphy_free(rphy); | ||
793 | return error; | ||
794 | } | ||
795 | |||
796 | phy_info->rphy = rphy; | ||
797 | } | ||
798 | |||
799 | return 0; | ||
800 | } | ||
801 | |||
802 | static int | ||
803 | mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index) | ||
804 | { | ||
805 | struct mptsas_portinfo *port_info; | ||
806 | u32 handle = 0xFFFF; | ||
807 | int error = -ENOMEM, i; | ||
808 | |||
809 | port_info = kmalloc(sizeof(*port_info), GFP_KERNEL); | ||
810 | if (!port_info) | ||
811 | goto out; | ||
812 | memset(port_info, 0, sizeof(*port_info)); | ||
813 | |||
814 | error = mptsas_sas_io_unit_pg0(ioc, port_info); | ||
815 | if (error) | ||
816 | goto out_free_port_info; | ||
817 | |||
818 | list_add_tail(&port_info->list, &ioc->sas_topology); | ||
819 | |||
820 | for (i = 0; i < port_info->num_phys; i++) { | ||
821 | mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i], | ||
822 | (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER << | ||
823 | MPI_SAS_PHY_PGAD_FORM_SHIFT), i); | ||
824 | |||
825 | mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify, | ||
826 | (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE << | ||
827 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle); | ||
828 | handle = port_info->phy_info[i].identify.handle; | ||
829 | |||
830 | if (port_info->phy_info[i].attached.handle) { | ||
831 | mptsas_sas_device_pg0(ioc, | ||
832 | &port_info->phy_info[i].attached, | ||
833 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << | ||
834 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | ||
835 | port_info->phy_info[i].attached.handle); | ||
836 | } | ||
837 | |||
838 | mptsas_probe_one_phy(&ioc->sh->shost_gendev, | ||
839 | &port_info->phy_info[i], *index); | ||
840 | (*index)++; | ||
841 | } | ||
842 | |||
843 | return 0; | ||
844 | |||
845 | out_free_port_info: | ||
846 | kfree(port_info); | ||
847 | out: | ||
848 | return error; | ||
849 | } | ||
850 | |||
851 | static int | ||
852 | mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index) | ||
853 | { | ||
854 | struct mptsas_portinfo *port_info, *p; | ||
855 | int error = -ENOMEM, i, j; | ||
856 | |||
857 | port_info = kmalloc(sizeof(*port_info), GFP_KERNEL); | ||
858 | if (!port_info) | ||
859 | goto out; | ||
860 | memset(port_info, 0, sizeof(*port_info)); | ||
861 | |||
862 | error = mptsas_sas_expander_pg0(ioc, port_info, | ||
863 | (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE << | ||
864 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle); | ||
865 | if (error) | ||
866 | goto out_free_port_info; | ||
867 | |||
868 | *handle = port_info->handle; | ||
869 | |||
870 | list_add_tail(&port_info->list, &ioc->sas_topology); | ||
871 | for (i = 0; i < port_info->num_phys; i++) { | ||
872 | struct device *parent; | ||
873 | |||
874 | mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i], | ||
875 | (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM << | ||
876 | MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle); | ||
877 | |||
878 | if (port_info->phy_info[i].identify.handle) { | ||
879 | mptsas_sas_device_pg0(ioc, | ||
880 | &port_info->phy_info[i].identify, | ||
881 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << | ||
882 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | ||
883 | port_info->phy_info[i].identify.handle); | ||
884 | } | ||
885 | |||
886 | if (port_info->phy_info[i].attached.handle) { | ||
887 | mptsas_sas_device_pg0(ioc, | ||
888 | &port_info->phy_info[i].attached, | ||
889 | (MPI_SAS_DEVICE_PGAD_FORM_HANDLE << | ||
890 | MPI_SAS_DEVICE_PGAD_FORM_SHIFT), | ||
891 | port_info->phy_info[i].attached.handle); | ||
892 | } | ||
893 | |||
894 | /* | ||
895 | * If we find a parent port handle this expander is | ||
896 | * attached to another expander, else it hangs of the | ||
897 | * HBA phys. | ||
898 | */ | ||
899 | parent = &ioc->sh->shost_gendev; | ||
900 | list_for_each_entry(p, &ioc->sas_topology, list) { | ||
901 | for (j = 0; j < p->num_phys; j++) { | ||
902 | if (port_info->phy_info[i].identify.handle == | ||
903 | p->phy_info[j].attached.handle) | ||
904 | parent = &p->phy_info[j].rphy->dev; | ||
905 | } | ||
906 | } | ||
907 | |||
908 | mptsas_probe_one_phy(parent, &port_info->phy_info[i], *index); | ||
909 | (*index)++; | ||
910 | } | ||
911 | |||
912 | return 0; | ||
913 | |||
914 | out_free_port_info: | ||
915 | kfree(port_info); | ||
916 | out: | ||
917 | return error; | ||
918 | } | ||
919 | |||
920 | static void | ||
921 | mptsas_scan_sas_topology(MPT_ADAPTER *ioc) | ||
922 | { | ||
923 | u32 handle = 0xFFFF; | ||
924 | int index = 0; | ||
925 | |||
926 | mptsas_probe_hba_phys(ioc, &index); | ||
927 | while (!mptsas_probe_expander_phys(ioc, &handle, &index)) | ||
928 | ; | ||
929 | } | ||
930 | |||
931 | static int | ||
932 | mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
933 | { | ||
934 | struct Scsi_Host *sh; | ||
935 | MPT_SCSI_HOST *hd; | ||
936 | MPT_ADAPTER *ioc; | ||
937 | unsigned long flags; | ||
938 | int sz, ii; | ||
939 | int numSGE = 0; | ||
940 | int scale; | ||
941 | int ioc_cap; | ||
942 | u8 *mem; | ||
943 | int error=0; | ||
944 | int r; | ||
945 | |||
946 | r = mpt_attach(pdev,id); | ||
947 | if (r) | ||
948 | return r; | ||
949 | |||
950 | ioc = pci_get_drvdata(pdev); | ||
951 | ioc->DoneCtx = mptsasDoneCtx; | ||
952 | ioc->TaskCtx = mptsasTaskCtx; | ||
953 | ioc->InternalCtx = mptsasInternalCtx; | ||
954 | |||
955 | /* Added sanity check on readiness of the MPT adapter. | ||
956 | */ | ||
957 | if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) { | ||
958 | printk(MYIOC_s_WARN_FMT | ||
959 | "Skipping because it's not operational!\n", | ||
960 | ioc->name); | ||
961 | return -ENODEV; | ||
962 | } | ||
963 | |||
964 | if (!ioc->active) { | ||
965 | printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n", | ||
966 | ioc->name); | ||
967 | return -ENODEV; | ||
968 | } | ||
969 | |||
970 | /* Sanity check - ensure at least 1 port is INITIATOR capable | ||
971 | */ | ||
972 | ioc_cap = 0; | ||
973 | for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) { | ||
974 | if (ioc->pfacts[ii].ProtocolFlags & | ||
975 | MPI_PORTFACTS_PROTOCOL_INITIATOR) | ||
976 | ioc_cap++; | ||
977 | } | ||
978 | |||
979 | if (!ioc_cap) { | ||
980 | printk(MYIOC_s_WARN_FMT | ||
981 | "Skipping ioc=%p because SCSI Initiator mode " | ||
982 | "is NOT enabled!\n", ioc->name, ioc); | ||
983 | return 0; | ||
984 | } | ||
985 | |||
986 | sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST)); | ||
987 | if (!sh) { | ||
988 | printk(MYIOC_s_WARN_FMT | ||
989 | "Unable to register controller with SCSI subsystem\n", | ||
990 | ioc->name); | ||
991 | return -1; | ||
992 | } | ||
993 | |||
994 | spin_lock_irqsave(&ioc->FreeQlock, flags); | ||
995 | |||
996 | /* Attach the SCSI Host to the IOC structure | ||
997 | */ | ||
998 | ioc->sh = sh; | ||
999 | |||
1000 | sh->io_port = 0; | ||
1001 | sh->n_io_port = 0; | ||
1002 | sh->irq = 0; | ||
1003 | |||
1004 | /* set 16 byte cdb's */ | ||
1005 | sh->max_cmd_len = 16; | ||
1006 | |||
1007 | sh->max_id = ioc->pfacts->MaxDevices + 1; | ||
1008 | |||
1009 | sh->transportt = mptsas_transport_template; | ||
1010 | |||
1011 | sh->max_lun = MPT_LAST_LUN + 1; | ||
1012 | sh->max_channel = 0; | ||
1013 | sh->this_id = ioc->pfacts[0].PortSCSIID; | ||
1014 | |||
1015 | /* Required entry. | ||
1016 | */ | ||
1017 | sh->unique_id = ioc->id; | ||
1018 | |||
1019 | INIT_LIST_HEAD(&ioc->sas_topology); | ||
1020 | |||
1021 | /* Verify that we won't exceed the maximum | ||
1022 | * number of chain buffers | ||
1023 | * We can optimize: ZZ = req_sz/sizeof(SGE) | ||
1024 | * For 32bit SGE's: | ||
1025 | * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ | ||
1026 | * + (req_sz - 64)/sizeof(SGE) | ||
1027 | * A slightly different algorithm is required for | ||
1028 | * 64bit SGEs. | ||
1029 | */ | ||
1030 | scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32)); | ||
1031 | if (sizeof(dma_addr_t) == sizeof(u64)) { | ||
1032 | numSGE = (scale - 1) * | ||
1033 | (ioc->facts.MaxChainDepth-1) + scale + | ||
1034 | (ioc->req_sz - 60) / (sizeof(dma_addr_t) + | ||
1035 | sizeof(u32)); | ||
1036 | } else { | ||
1037 | numSGE = 1 + (scale - 1) * | ||
1038 | (ioc->facts.MaxChainDepth-1) + scale + | ||
1039 | (ioc->req_sz - 64) / (sizeof(dma_addr_t) + | ||
1040 | sizeof(u32)); | ||
1041 | } | ||
1042 | |||
1043 | if (numSGE < sh->sg_tablesize) { | ||
1044 | /* Reset this value */ | ||
1045 | dprintk((MYIOC_s_INFO_FMT | ||
1046 | "Resetting sg_tablesize to %d from %d\n", | ||
1047 | ioc->name, numSGE, sh->sg_tablesize)); | ||
1048 | sh->sg_tablesize = numSGE; | ||
1049 | } | ||
1050 | |||
1051 | spin_unlock_irqrestore(&ioc->FreeQlock, flags); | ||
1052 | |||
1053 | hd = (MPT_SCSI_HOST *) sh->hostdata; | ||
1054 | hd->ioc = ioc; | ||
1055 | |||
1056 | /* SCSI needs scsi_cmnd lookup table! | ||
1057 | * (with size equal to req_depth*PtrSz!) | ||
1058 | */ | ||
1059 | sz = ioc->req_depth * sizeof(void *); | ||
1060 | mem = kmalloc(sz, GFP_ATOMIC); | ||
1061 | if (mem == NULL) { | ||
1062 | error = -ENOMEM; | ||
1063 | goto mptsas_probe_failed; | ||
1064 | } | ||
1065 | |||
1066 | memset(mem, 0, sz); | ||
1067 | hd->ScsiLookup = (struct scsi_cmnd **) mem; | ||
1068 | |||
1069 | dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n", | ||
1070 | ioc->name, hd->ScsiLookup, sz)); | ||
1071 | |||
1072 | /* Allocate memory for the device structures. | ||
1073 | * A non-Null pointer at an offset | ||
1074 | * indicates a device exists. | ||
1075 | * max_id = 1 + maximum id (hosts.h) | ||
1076 | */ | ||
1077 | sz = sh->max_id * sizeof(void *); | ||
1078 | mem = kmalloc(sz, GFP_ATOMIC); | ||
1079 | if (mem == NULL) { | ||
1080 | error = -ENOMEM; | ||
1081 | goto mptsas_probe_failed; | ||
1082 | } | ||
1083 | |||
1084 | memset(mem, 0, sz); | ||
1085 | hd->Targets = (VirtDevice **) mem; | ||
1086 | |||
1087 | dprintk((KERN_INFO | ||
1088 | " Targets @ %p, sz=%d\n", hd->Targets, sz)); | ||
1089 | |||
1090 | /* Clear the TM flags | ||
1091 | */ | ||
1092 | hd->tmPending = 0; | ||
1093 | hd->tmState = TM_STATE_NONE; | ||
1094 | hd->resetPending = 0; | ||
1095 | hd->abortSCpnt = NULL; | ||
1096 | |||
1097 | /* Clear the pointer used to store | ||
1098 | * single-threaded commands, i.e., those | ||
1099 | * issued during a bus scan, dv and | ||
1100 | * configuration pages. | ||
1101 | */ | ||
1102 | hd->cmdPtr = NULL; | ||
1103 | |||
1104 | /* Initialize this SCSI Hosts' timers | ||
1105 | * To use, set the timer expires field | ||
1106 | * and add_timer | ||
1107 | */ | ||
1108 | init_timer(&hd->timer); | ||
1109 | hd->timer.data = (unsigned long) hd; | ||
1110 | hd->timer.function = mptscsih_timer_expired; | ||
1111 | |||
1112 | hd->mpt_pq_filter = mpt_pq_filter; | ||
1113 | ioc->sas_data.ptClear = mpt_pt_clear; | ||
1114 | |||
1115 | if (ioc->sas_data.ptClear==1) { | ||
1116 | mptbase_sas_persist_operation( | ||
1117 | ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT); | ||
1118 | } | ||
1119 | |||
1120 | ddvprintk((MYIOC_s_INFO_FMT | ||
1121 | "mpt_pq_filter %x mpt_pq_filter %x\n", | ||
1122 | ioc->name, | ||
1123 | mpt_pq_filter, | ||
1124 | mpt_pq_filter)); | ||
1125 | |||
1126 | init_waitqueue_head(&hd->scandv_waitq); | ||
1127 | hd->scandv_wait_done = 0; | ||
1128 | hd->last_queue_full = 0; | ||
1129 | |||
1130 | error = scsi_add_host(sh, &ioc->pcidev->dev); | ||
1131 | if (error) { | ||
1132 | dprintk((KERN_ERR MYNAM | ||
1133 | "scsi_add_host failed\n")); | ||
1134 | goto mptsas_probe_failed; | ||
1135 | } | ||
1136 | |||
1137 | mptsas_scan_sas_topology(ioc); | ||
1138 | |||
1139 | return 0; | ||
1140 | |||
1141 | mptsas_probe_failed: | ||
1142 | |||
1143 | mptscsih_remove(pdev); | ||
1144 | return error; | ||
1145 | } | ||
1146 | |||
1147 | static void __devexit mptsas_remove(struct pci_dev *pdev) | ||
1148 | { | ||
1149 | MPT_ADAPTER *ioc = pci_get_drvdata(pdev); | ||
1150 | struct mptsas_portinfo *p, *n; | ||
1151 | |||
1152 | sas_remove_host(ioc->sh); | ||
1153 | |||
1154 | list_for_each_entry_safe(p, n, &ioc->sas_topology, list) { | ||
1155 | list_del(&p->list); | ||
1156 | kfree(p); | ||
1157 | } | ||
1158 | |||
1159 | mptscsih_remove(pdev); | ||
1160 | } | ||
1161 | |||
1162 | static struct pci_device_id mptsas_pci_table[] = { | ||
1163 | { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064, | ||
1164 | PCI_ANY_ID, PCI_ANY_ID }, | ||
1165 | { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066, | ||
1166 | PCI_ANY_ID, PCI_ANY_ID }, | ||
1167 | { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068, | ||
1168 | PCI_ANY_ID, PCI_ANY_ID }, | ||
1169 | { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E, | ||
1170 | PCI_ANY_ID, PCI_ANY_ID }, | ||
1171 | { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E, | ||
1172 | PCI_ANY_ID, PCI_ANY_ID }, | ||
1173 | { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E, | ||
1174 | PCI_ANY_ID, PCI_ANY_ID }, | ||
1175 | {0} /* Terminating entry */ | ||
1176 | }; | ||
1177 | MODULE_DEVICE_TABLE(pci, mptsas_pci_table); | ||
1178 | |||
1179 | |||
1180 | static struct pci_driver mptsas_driver = { | ||
1181 | .name = "mptsas", | ||
1182 | .id_table = mptsas_pci_table, | ||
1183 | .probe = mptsas_probe, | ||
1184 | .remove = __devexit_p(mptsas_remove), | ||
1185 | .shutdown = mptscsih_shutdown, | ||
1186 | #ifdef CONFIG_PM | ||
1187 | .suspend = mptscsih_suspend, | ||
1188 | .resume = mptscsih_resume, | ||
1189 | #endif | ||
1190 | }; | ||
1191 | |||
1192 | static int __init | ||
1193 | mptsas_init(void) | ||
1194 | { | ||
1195 | show_mptmod_ver(my_NAME, my_VERSION); | ||
1196 | |||
1197 | mptsas_transport_template = | ||
1198 | sas_attach_transport(&mptsas_transport_functions); | ||
1199 | if (!mptsas_transport_template) | ||
1200 | return -ENODEV; | ||
1201 | |||
1202 | mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER); | ||
1203 | mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER); | ||
1204 | mptsasInternalCtx = | ||
1205 | mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER); | ||
1206 | |||
1207 | if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) { | ||
1208 | devtprintk((KERN_INFO MYNAM | ||
1209 | ": Registered for IOC event notifications\n")); | ||
1210 | } | ||
1211 | |||
1212 | if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) { | ||
1213 | dprintk((KERN_INFO MYNAM | ||
1214 | ": Registered for IOC reset notifications\n")); | ||
1215 | } | ||
1216 | |||
1217 | return pci_register_driver(&mptsas_driver); | ||
1218 | } | ||
1219 | |||
1220 | static void __exit | ||
1221 | mptsas_exit(void) | ||
1222 | { | ||
1223 | pci_unregister_driver(&mptsas_driver); | ||
1224 | sas_release_transport(mptsas_transport_template); | ||
1225 | |||
1226 | mpt_reset_deregister(mptsasDoneCtx); | ||
1227 | mpt_event_deregister(mptsasDoneCtx); | ||
1228 | |||
1229 | mpt_deregister(mptsasInternalCtx); | ||
1230 | mpt_deregister(mptsasTaskCtx); | ||
1231 | mpt_deregister(mptsasDoneCtx); | ||
1232 | } | ||
1233 | |||
1234 | module_init(mptsas_init); | ||
1235 | module_exit(mptsas_exit); | ||
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 4a003dc5fde8..5cb07eb224d7 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #include <scsi/scsi_device.h> | 62 | #include <scsi/scsi_device.h> |
63 | #include <scsi/scsi_host.h> | 63 | #include <scsi/scsi_host.h> |
64 | #include <scsi/scsi_tcq.h> | 64 | #include <scsi/scsi_tcq.h> |
65 | #include <scsi/scsi_dbg.h> | ||
65 | 66 | ||
66 | #include "mptbase.h" | 67 | #include "mptbase.h" |
67 | #include "mptscsih.h" | 68 | #include "mptscsih.h" |
@@ -93,8 +94,9 @@ typedef struct _BIG_SENSE_BUF { | |||
93 | 94 | ||
94 | #define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */ | 95 | #define MPT_ICFLAG_BUF_CAP 0x01 /* ReadBuffer Read Capacity format */ |
95 | #define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */ | 96 | #define MPT_ICFLAG_ECHO 0x02 /* ReadBuffer Echo buffer format */ |
96 | #define MPT_ICFLAG_PHYS_DISK 0x04 /* Any SCSI IO but do Phys Disk Format */ | 97 | #define MPT_ICFLAG_EBOS 0x04 /* ReadBuffer Echo buffer has EBOS */ |
97 | #define MPT_ICFLAG_TAGGED_CMD 0x08 /* Do tagged IO */ | 98 | #define MPT_ICFLAG_PHYS_DISK 0x08 /* Any SCSI IO but do Phys Disk Format */ |
99 | #define MPT_ICFLAG_TAGGED_CMD 0x10 /* Do tagged IO */ | ||
98 | #define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */ | 100 | #define MPT_ICFLAG_DID_RESET 0x20 /* Bus Reset occurred with this command */ |
99 | #define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */ | 101 | #define MPT_ICFLAG_RESERVED 0x40 /* Reserved has been issued */ |
100 | 102 | ||
@@ -159,6 +161,8 @@ int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR | |||
159 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); | 161 | static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd); |
160 | static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum); | 162 | static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum); |
161 | 163 | ||
164 | static struct work_struct mptscsih_persistTask; | ||
165 | |||
162 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | 166 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION |
163 | static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); | 167 | static int mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io); |
164 | static void mptscsih_domainValidation(void *hd); | 168 | static void mptscsih_domainValidation(void *hd); |
@@ -167,6 +171,7 @@ static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id); | |||
167 | static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target); | 171 | static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target); |
168 | static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage); | 172 | static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage); |
169 | static void mptscsih_fillbuf(char *buffer, int size, int index, int width); | 173 | static void mptscsih_fillbuf(char *buffer, int size, int index, int width); |
174 | static void mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id); | ||
170 | #endif | 175 | #endif |
171 | 176 | ||
172 | void mptscsih_remove(struct pci_dev *); | 177 | void mptscsih_remove(struct pci_dev *); |
@@ -606,11 +611,24 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
606 | xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); | 611 | xfer_cnt = le32_to_cpu(pScsiReply->TransferCount); |
607 | sc->resid = sc->request_bufflen - xfer_cnt; | 612 | sc->resid = sc->request_bufflen - xfer_cnt; |
608 | 613 | ||
614 | /* | ||
615 | * if we get a data underrun indication, yet no data was | ||
616 | * transferred and the SCSI status indicates that the | ||
617 | * command was never started, change the data underrun | ||
618 | * to success | ||
619 | */ | ||
620 | if (status == MPI_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 && | ||
621 | (scsi_status == MPI_SCSI_STATUS_BUSY || | ||
622 | scsi_status == MPI_SCSI_STATUS_RESERVATION_CONFLICT || | ||
623 | scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)) { | ||
624 | status = MPI_IOCSTATUS_SUCCESS; | ||
625 | } | ||
626 | |||
609 | dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n" | 627 | dreplyprintk((KERN_NOTICE "Reply ha=%d id=%d lun=%d:\n" |
610 | "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n" | 628 | "IOCStatus=%04xh SCSIState=%02xh SCSIStatus=%02xh\n" |
611 | "resid=%d bufflen=%d xfer_cnt=%d\n", | 629 | "resid=%d bufflen=%d xfer_cnt=%d\n", |
612 | ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], | 630 | ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], |
613 | status, scsi_state, scsi_status, sc->resid, | 631 | status, scsi_state, scsi_status, sc->resid, |
614 | sc->request_bufflen, xfer_cnt)); | 632 | sc->request_bufflen, xfer_cnt)); |
615 | 633 | ||
616 | if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) | 634 | if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) |
@@ -619,8 +637,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
619 | /* | 637 | /* |
620 | * Look for + dump FCP ResponseInfo[]! | 638 | * Look for + dump FCP ResponseInfo[]! |
621 | */ | 639 | */ |
622 | if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID) { | 640 | if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID && |
623 | printk(KERN_NOTICE " FCP_ResponseInfo=%08xh\n", | 641 | pScsiReply->ResponseInfo) { |
642 | printk(KERN_NOTICE "ha=%d id=%d lun=%d: " | ||
643 | "FCP_ResponseInfo=%08xh\n", | ||
644 | ioc->id, pScsiReq->TargetID, pScsiReq->LUN[1], | ||
624 | le32_to_cpu(pScsiReply->ResponseInfo)); | 645 | le32_to_cpu(pScsiReply->ResponseInfo)); |
625 | } | 646 | } |
626 | 647 | ||
@@ -661,23 +682,13 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
661 | break; | 682 | break; |
662 | 683 | ||
663 | case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ | 684 | case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: /* 0x0049 */ |
664 | if ( xfer_cnt >= sc->underflow ) { | 685 | sc->resid = sc->request_bufflen - xfer_cnt; |
665 | /* Sufficient data transfer occurred */ | 686 | if((xfer_cnt==0)||(sc->underflow > xfer_cnt)) |
687 | sc->result=DID_SOFT_ERROR << 16; | ||
688 | else /* Sufficient data transfer occurred */ | ||
666 | sc->result = (DID_OK << 16) | scsi_status; | 689 | sc->result = (DID_OK << 16) | scsi_status; |
667 | } else if ( xfer_cnt == 0 ) { | 690 | dreplyprintk((KERN_NOTICE |
668 | /* A CRC Error causes this condition; retry */ | 691 | "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->device->id)); |
669 | sc->result = (DRIVER_SENSE << 24) | (DID_OK << 16) | | ||
670 | (CHECK_CONDITION << 1); | ||
671 | sc->sense_buffer[0] = 0x70; | ||
672 | sc->sense_buffer[2] = NO_SENSE; | ||
673 | sc->sense_buffer[12] = 0; | ||
674 | sc->sense_buffer[13] = 0; | ||
675 | } else { | ||
676 | sc->result = DID_SOFT_ERROR << 16; | ||
677 | } | ||
678 | dreplyprintk((KERN_NOTICE | ||
679 | "RESIDUAL_MISMATCH: result=%x on id=%d\n", | ||
680 | sc->result, sc->device->id)); | ||
681 | break; | 692 | break; |
682 | 693 | ||
683 | case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ | 694 | case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ |
@@ -692,7 +703,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
692 | ; | 703 | ; |
693 | } else { | 704 | } else { |
694 | if (xfer_cnt < sc->underflow) { | 705 | if (xfer_cnt < sc->underflow) { |
695 | sc->result = DID_SOFT_ERROR << 16; | 706 | if (scsi_status == SAM_STAT_BUSY) |
707 | sc->result = SAM_STAT_BUSY; | ||
708 | else | ||
709 | sc->result = DID_SOFT_ERROR << 16; | ||
696 | } | 710 | } |
697 | if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) { | 711 | if (scsi_state & (MPI_SCSI_STATE_AUTOSENSE_FAILED | MPI_SCSI_STATE_NO_SCSI_STATUS)) { |
698 | /* What to do? | 712 | /* What to do? |
@@ -717,8 +731,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) | |||
717 | 731 | ||
718 | case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ | 732 | case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ |
719 | case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ | 733 | case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ |
720 | scsi_status = pScsiReply->SCSIStatus; | 734 | if (scsi_status == MPI_SCSI_STATUS_BUSY) |
721 | sc->result = (DID_OK << 16) | scsi_status; | 735 | sc->result = (DID_BUS_BUSY << 16) | scsi_status; |
736 | else | ||
737 | sc->result = (DID_OK << 16) | scsi_status; | ||
722 | if (scsi_state == 0) { | 738 | if (scsi_state == 0) { |
723 | ; | 739 | ; |
724 | } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { | 740 | } else if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID) { |
@@ -890,12 +906,13 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun) | |||
890 | SCSIIORequest_t *mf = NULL; | 906 | SCSIIORequest_t *mf = NULL; |
891 | int ii; | 907 | int ii; |
892 | int max = hd->ioc->req_depth; | 908 | int max = hd->ioc->req_depth; |
909 | struct scsi_cmnd *sc; | ||
893 | 910 | ||
894 | dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n", | 911 | dsprintk((KERN_INFO MYNAM ": search_running target %d lun %d max %d\n", |
895 | target, lun, max)); | 912 | target, lun, max)); |
896 | 913 | ||
897 | for (ii=0; ii < max; ii++) { | 914 | for (ii=0; ii < max; ii++) { |
898 | if (hd->ScsiLookup[ii] != NULL) { | 915 | if ((sc = hd->ScsiLookup[ii]) != NULL) { |
899 | 916 | ||
900 | mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); | 917 | mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); |
901 | 918 | ||
@@ -910,9 +927,22 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun) | |||
910 | hd->ScsiLookup[ii] = NULL; | 927 | hd->ScsiLookup[ii] = NULL; |
911 | mptscsih_freeChainBuffers(hd->ioc, ii); | 928 | mptscsih_freeChainBuffers(hd->ioc, ii); |
912 | mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf); | 929 | mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf); |
930 | if (sc->use_sg) { | ||
931 | pci_unmap_sg(hd->ioc->pcidev, | ||
932 | (struct scatterlist *) sc->request_buffer, | ||
933 | sc->use_sg, | ||
934 | sc->sc_data_direction); | ||
935 | } else if (sc->request_bufflen) { | ||
936 | pci_unmap_single(hd->ioc->pcidev, | ||
937 | sc->SCp.dma_handle, | ||
938 | sc->request_bufflen, | ||
939 | sc->sc_data_direction); | ||
940 | } | ||
941 | sc->host_scribble = NULL; | ||
942 | sc->result = DID_NO_CONNECT << 16; | ||
943 | sc->scsi_done(sc); | ||
913 | } | 944 | } |
914 | } | 945 | } |
915 | |||
916 | return; | 946 | return; |
917 | } | 947 | } |
918 | 948 | ||
@@ -967,8 +997,10 @@ mptscsih_remove(struct pci_dev *pdev) | |||
967 | unsigned long flags; | 997 | unsigned long flags; |
968 | int sz1; | 998 | int sz1; |
969 | 999 | ||
970 | if(!host) | 1000 | if(!host) { |
1001 | mpt_detach(pdev); | ||
971 | return; | 1002 | return; |
1003 | } | ||
972 | 1004 | ||
973 | scsi_remove_host(host); | 1005 | scsi_remove_host(host); |
974 | 1006 | ||
@@ -1256,8 +1288,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1256 | MPT_SCSI_HOST *hd; | 1288 | MPT_SCSI_HOST *hd; |
1257 | MPT_FRAME_HDR *mf; | 1289 | MPT_FRAME_HDR *mf; |
1258 | SCSIIORequest_t *pScsiReq; | 1290 | SCSIIORequest_t *pScsiReq; |
1259 | VirtDevice *pTarget; | 1291 | VirtDevice *pTarget = SCpnt->device->hostdata; |
1260 | int target; | ||
1261 | int lun; | 1292 | int lun; |
1262 | u32 datalen; | 1293 | u32 datalen; |
1263 | u32 scsictl; | 1294 | u32 scsictl; |
@@ -1267,12 +1298,9 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1267 | int ii; | 1298 | int ii; |
1268 | 1299 | ||
1269 | hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; | 1300 | hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; |
1270 | target = SCpnt->device->id; | ||
1271 | lun = SCpnt->device->lun; | 1301 | lun = SCpnt->device->lun; |
1272 | SCpnt->scsi_done = done; | 1302 | SCpnt->scsi_done = done; |
1273 | 1303 | ||
1274 | pTarget = hd->Targets[target]; | ||
1275 | |||
1276 | dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n", | 1304 | dmfprintk((MYIOC_s_INFO_FMT "qcmd: SCpnt=%p, done()=%p\n", |
1277 | (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done)); | 1305 | (hd && hd->ioc) ? hd->ioc->name : "ioc?", SCpnt, done)); |
1278 | 1306 | ||
@@ -1315,7 +1343,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1315 | /* Default to untagged. Once a target structure has been allocated, | 1343 | /* Default to untagged. Once a target structure has been allocated, |
1316 | * use the Inquiry data to determine if device supports tagged. | 1344 | * use the Inquiry data to determine if device supports tagged. |
1317 | */ | 1345 | */ |
1318 | if ( pTarget | 1346 | if (pTarget |
1319 | && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES) | 1347 | && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES) |
1320 | && (SCpnt->device->tagged_supported)) { | 1348 | && (SCpnt->device->tagged_supported)) { |
1321 | scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ; | 1349 | scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ; |
@@ -1325,8 +1353,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1325 | 1353 | ||
1326 | /* Use the above information to set up the message frame | 1354 | /* Use the above information to set up the message frame |
1327 | */ | 1355 | */ |
1328 | pScsiReq->TargetID = (u8) target; | 1356 | pScsiReq->TargetID = (u8) pTarget->target_id; |
1329 | pScsiReq->Bus = (u8) SCpnt->device->channel; | 1357 | pScsiReq->Bus = pTarget->bus_id; |
1330 | pScsiReq->ChainOffset = 0; | 1358 | pScsiReq->ChainOffset = 0; |
1331 | pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; | 1359 | pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; |
1332 | pScsiReq->CDBLength = SCpnt->cmd_len; | 1360 | pScsiReq->CDBLength = SCpnt->cmd_len; |
@@ -1378,7 +1406,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1378 | 1406 | ||
1379 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | 1407 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION |
1380 | if (hd->ioc->bus_type == SCSI) { | 1408 | if (hd->ioc->bus_type == SCSI) { |
1381 | int dvStatus = hd->ioc->spi_data.dvStatus[target]; | 1409 | int dvStatus = hd->ioc->spi_data.dvStatus[pTarget->target_id]; |
1382 | int issueCmd = 1; | 1410 | int issueCmd = 1; |
1383 | 1411 | ||
1384 | if (dvStatus || hd->ioc->spi_data.forceDv) { | 1412 | if (dvStatus || hd->ioc->spi_data.forceDv) { |
@@ -1426,6 +1454,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) | |||
1426 | return 0; | 1454 | return 0; |
1427 | 1455 | ||
1428 | fail: | 1456 | fail: |
1457 | hd->ScsiLookup[my_idx] = NULL; | ||
1429 | mptscsih_freeChainBuffers(hd->ioc, my_idx); | 1458 | mptscsih_freeChainBuffers(hd->ioc, my_idx); |
1430 | mpt_free_msg_frame(hd->ioc, mf); | 1459 | mpt_free_msg_frame(hd->ioc, mf); |
1431 | return SCSI_MLQUEUE_HOST_BUSY; | 1460 | return SCSI_MLQUEUE_HOST_BUSY; |
@@ -1713,24 +1742,23 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) | |||
1713 | MPT_FRAME_HDR *mf; | 1742 | MPT_FRAME_HDR *mf; |
1714 | u32 ctx2abort; | 1743 | u32 ctx2abort; |
1715 | int scpnt_idx; | 1744 | int scpnt_idx; |
1745 | int retval; | ||
1716 | 1746 | ||
1717 | /* If we can't locate our host adapter structure, return FAILED status. | 1747 | /* If we can't locate our host adapter structure, return FAILED status. |
1718 | */ | 1748 | */ |
1719 | if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) { | 1749 | if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) { |
1720 | SCpnt->result = DID_RESET << 16; | 1750 | SCpnt->result = DID_RESET << 16; |
1721 | SCpnt->scsi_done(SCpnt); | 1751 | SCpnt->scsi_done(SCpnt); |
1722 | dfailprintk((KERN_WARNING MYNAM ": mptscsih_abort: " | 1752 | dfailprintk((KERN_INFO MYNAM ": mptscsih_abort: " |
1723 | "Can't locate host! (sc=%p)\n", | 1753 | "Can't locate host! (sc=%p)\n", |
1724 | SCpnt)); | 1754 | SCpnt)); |
1725 | return FAILED; | 1755 | return FAILED; |
1726 | } | 1756 | } |
1727 | 1757 | ||
1728 | ioc = hd->ioc; | 1758 | ioc = hd->ioc; |
1729 | if (hd->resetPending) | 1759 | if (hd->resetPending) { |
1730 | return FAILED; | 1760 | return FAILED; |
1731 | 1761 | } | |
1732 | printk(KERN_WARNING MYNAM ": %s: >> Attempting task abort! (sc=%p)\n", | ||
1733 | hd->ioc->name, SCpnt); | ||
1734 | 1762 | ||
1735 | if (hd->timeouts < -1) | 1763 | if (hd->timeouts < -1) |
1736 | hd->timeouts++; | 1764 | hd->timeouts++; |
@@ -1738,16 +1766,20 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) | |||
1738 | /* Find this command | 1766 | /* Find this command |
1739 | */ | 1767 | */ |
1740 | if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { | 1768 | if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { |
1741 | /* Cmd not found in ScsiLookup. | 1769 | /* Cmd not found in ScsiLookup. |
1742 | * Do OS callback. | 1770 | * Do OS callback. |
1743 | */ | 1771 | */ |
1744 | SCpnt->result = DID_RESET << 16; | 1772 | SCpnt->result = DID_RESET << 16; |
1745 | dtmprintk((KERN_WARNING MYNAM ": %s: mptscsih_abort: " | 1773 | dtmprintk((KERN_INFO MYNAM ": %s: mptscsih_abort: " |
1746 | "Command not in the active list! (sc=%p)\n", | 1774 | "Command not in the active list! (sc=%p)\n", |
1747 | hd->ioc->name, SCpnt)); | 1775 | hd->ioc->name, SCpnt)); |
1748 | return SUCCESS; | 1776 | return SUCCESS; |
1749 | } | 1777 | } |
1750 | 1778 | ||
1779 | printk(KERN_WARNING MYNAM ": %s: attempting task abort! (sc=%p)\n", | ||
1780 | hd->ioc->name, SCpnt); | ||
1781 | scsi_print_command(SCpnt); | ||
1782 | |||
1751 | /* Most important! Set TaskMsgContext to SCpnt's MsgContext! | 1783 | /* Most important! Set TaskMsgContext to SCpnt's MsgContext! |
1752 | * (the IO to be ABORT'd) | 1784 | * (the IO to be ABORT'd) |
1753 | * | 1785 | * |
@@ -1760,38 +1792,22 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) | |||
1760 | 1792 | ||
1761 | hd->abortSCpnt = SCpnt; | 1793 | hd->abortSCpnt = SCpnt; |
1762 | 1794 | ||
1763 | if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, | 1795 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK, |
1764 | SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun, | 1796 | SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun, |
1765 | ctx2abort, 2 /* 2 second timeout */) | 1797 | ctx2abort, 2 /* 2 second timeout */); |
1766 | < 0) { | ||
1767 | 1798 | ||
1768 | /* The TM request failed and the subsequent FW-reload failed! | 1799 | printk (KERN_WARNING MYNAM ": %s: task abort: %s (sc=%p)\n", |
1769 | * Fatal error case. | 1800 | hd->ioc->name, |
1770 | */ | 1801 | ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); |
1771 | printk(MYIOC_s_WARN_FMT "Error issuing abort task! (sc=%p)\n", | ||
1772 | hd->ioc->name, SCpnt); | ||
1773 | 1802 | ||
1774 | /* We must clear our pending flag before clearing our state. | 1803 | if (retval == 0) |
1775 | */ | 1804 | return SUCCESS; |
1805 | |||
1806 | if(retval != FAILED ) { | ||
1776 | hd->tmPending = 0; | 1807 | hd->tmPending = 0; |
1777 | hd->tmState = TM_STATE_NONE; | 1808 | hd->tmState = TM_STATE_NONE; |
1778 | |||
1779 | /* Unmap the DMA buffers, if any. */ | ||
1780 | if (SCpnt->use_sg) { | ||
1781 | pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer, | ||
1782 | SCpnt->use_sg, SCpnt->sc_data_direction); | ||
1783 | } else if (SCpnt->request_bufflen) { | ||
1784 | pci_unmap_single(ioc->pcidev, SCpnt->SCp.dma_handle, | ||
1785 | SCpnt->request_bufflen, SCpnt->sc_data_direction); | ||
1786 | } | ||
1787 | hd->ScsiLookup[scpnt_idx] = NULL; | ||
1788 | SCpnt->result = DID_RESET << 16; | ||
1789 | SCpnt->scsi_done(SCpnt); /* Issue the command callback */ | ||
1790 | mptscsih_freeChainBuffers(ioc, scpnt_idx); | ||
1791 | mpt_free_msg_frame(ioc, mf); | ||
1792 | return FAILED; | ||
1793 | } | 1809 | } |
1794 | return SUCCESS; | 1810 | return FAILED; |
1795 | } | 1811 | } |
1796 | 1812 | ||
1797 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1813 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -1807,11 +1823,12 @@ int | |||
1807 | mptscsih_dev_reset(struct scsi_cmnd * SCpnt) | 1823 | mptscsih_dev_reset(struct scsi_cmnd * SCpnt) |
1808 | { | 1824 | { |
1809 | MPT_SCSI_HOST *hd; | 1825 | MPT_SCSI_HOST *hd; |
1826 | int retval; | ||
1810 | 1827 | ||
1811 | /* If we can't locate our host adapter structure, return FAILED status. | 1828 | /* If we can't locate our host adapter structure, return FAILED status. |
1812 | */ | 1829 | */ |
1813 | if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ | 1830 | if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ |
1814 | dtmprintk((KERN_WARNING MYNAM ": mptscsih_dev_reset: " | 1831 | dtmprintk((KERN_INFO MYNAM ": mptscsih_dev_reset: " |
1815 | "Can't locate host! (sc=%p)\n", | 1832 | "Can't locate host! (sc=%p)\n", |
1816 | SCpnt)); | 1833 | SCpnt)); |
1817 | return FAILED; | 1834 | return FAILED; |
@@ -1820,24 +1837,26 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) | |||
1820 | if (hd->resetPending) | 1837 | if (hd->resetPending) |
1821 | return FAILED; | 1838 | return FAILED; |
1822 | 1839 | ||
1823 | printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n", | 1840 | printk(KERN_WARNING MYNAM ": %s: attempting target reset! (sc=%p)\n", |
1824 | hd->ioc->name, SCpnt); | 1841 | hd->ioc->name, SCpnt); |
1842 | scsi_print_command(SCpnt); | ||
1825 | 1843 | ||
1826 | if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, | 1844 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, |
1827 | SCpnt->device->channel, SCpnt->device->id, | 1845 | SCpnt->device->channel, SCpnt->device->id, |
1828 | 0, 0, 5 /* 5 second timeout */) | 1846 | 0, 0, 5 /* 5 second timeout */); |
1829 | < 0){ | 1847 | |
1830 | /* The TM request failed and the subsequent FW-reload failed! | 1848 | printk (KERN_WARNING MYNAM ": %s: target reset: %s (sc=%p)\n", |
1831 | * Fatal error case. | 1849 | hd->ioc->name, |
1832 | */ | 1850 | ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); |
1833 | printk(MYIOC_s_WARN_FMT "Error processing TaskMgmt request (sc=%p)\n", | 1851 | |
1834 | hd->ioc->name, SCpnt); | 1852 | if (retval == 0) |
1853 | return SUCCESS; | ||
1854 | |||
1855 | if(retval != FAILED ) { | ||
1835 | hd->tmPending = 0; | 1856 | hd->tmPending = 0; |
1836 | hd->tmState = TM_STATE_NONE; | 1857 | hd->tmState = TM_STATE_NONE; |
1837 | return FAILED; | ||
1838 | } | 1858 | } |
1839 | 1859 | return FAILED; | |
1840 | return SUCCESS; | ||
1841 | } | 1860 | } |
1842 | 1861 | ||
1843 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1862 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -1853,41 +1872,39 @@ int | |||
1853 | mptscsih_bus_reset(struct scsi_cmnd * SCpnt) | 1872 | mptscsih_bus_reset(struct scsi_cmnd * SCpnt) |
1854 | { | 1873 | { |
1855 | MPT_SCSI_HOST *hd; | 1874 | MPT_SCSI_HOST *hd; |
1856 | spinlock_t *host_lock = SCpnt->device->host->host_lock; | 1875 | int retval; |
1857 | 1876 | ||
1858 | /* If we can't locate our host adapter structure, return FAILED status. | 1877 | /* If we can't locate our host adapter structure, return FAILED status. |
1859 | */ | 1878 | */ |
1860 | if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ | 1879 | if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ |
1861 | dtmprintk((KERN_WARNING MYNAM ": mptscsih_bus_reset: " | 1880 | dtmprintk((KERN_INFO MYNAM ": mptscsih_bus_reset: " |
1862 | "Can't locate host! (sc=%p)\n", | 1881 | "Can't locate host! (sc=%p)\n", |
1863 | SCpnt ) ); | 1882 | SCpnt ) ); |
1864 | return FAILED; | 1883 | return FAILED; |
1865 | } | 1884 | } |
1866 | 1885 | ||
1867 | printk(KERN_WARNING MYNAM ": %s: >> Attempting bus reset! (sc=%p)\n", | 1886 | printk(KERN_WARNING MYNAM ": %s: attempting bus reset! (sc=%p)\n", |
1868 | hd->ioc->name, SCpnt); | 1887 | hd->ioc->name, SCpnt); |
1888 | scsi_print_command(SCpnt); | ||
1869 | 1889 | ||
1870 | if (hd->timeouts < -1) | 1890 | if (hd->timeouts < -1) |
1871 | hd->timeouts++; | 1891 | hd->timeouts++; |
1872 | 1892 | ||
1873 | /* We are now ready to execute the task management request. */ | 1893 | retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, |
1874 | if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, | 1894 | SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */); |
1875 | SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */) | ||
1876 | < 0){ | ||
1877 | 1895 | ||
1878 | /* The TM request failed and the subsequent FW-reload failed! | 1896 | printk (KERN_WARNING MYNAM ": %s: bus reset: %s (sc=%p)\n", |
1879 | * Fatal error case. | 1897 | hd->ioc->name, |
1880 | */ | 1898 | ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); |
1881 | printk(MYIOC_s_WARN_FMT | 1899 | |
1882 | "Error processing TaskMgmt request (sc=%p)\n", | 1900 | if (retval == 0) |
1883 | hd->ioc->name, SCpnt); | 1901 | return SUCCESS; |
1902 | |||
1903 | if(retval != FAILED ) { | ||
1884 | hd->tmPending = 0; | 1904 | hd->tmPending = 0; |
1885 | hd->tmState = TM_STATE_NONE; | 1905 | hd->tmState = TM_STATE_NONE; |
1886 | spin_lock_irq(host_lock); | ||
1887 | return FAILED; | ||
1888 | } | 1906 | } |
1889 | 1907 | return FAILED; | |
1890 | return SUCCESS; | ||
1891 | } | 1908 | } |
1892 | 1909 | ||
1893 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1910 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
@@ -2169,7 +2186,7 @@ mptscsih_slave_alloc(struct scsi_device *device) | |||
2169 | vdev->raidVolume = 0; | 2186 | vdev->raidVolume = 0; |
2170 | hd->Targets[device->id] = vdev; | 2187 | hd->Targets[device->id] = vdev; |
2171 | if (hd->ioc->bus_type == SCSI) { | 2188 | if (hd->ioc->bus_type == SCSI) { |
2172 | if (hd->ioc->spi_data.isRaid & (1 << device->id)) { | 2189 | if (hd->ioc->raid_data.isRaid & (1 << device->id)) { |
2173 | vdev->raidVolume = 1; | 2190 | vdev->raidVolume = 1; |
2174 | ddvtprintk((KERN_INFO | 2191 | ddvtprintk((KERN_INFO |
2175 | "RAID Volume @ id %d\n", device->id)); | 2192 | "RAID Volume @ id %d\n", device->id)); |
@@ -2180,22 +2197,7 @@ mptscsih_slave_alloc(struct scsi_device *device) | |||
2180 | 2197 | ||
2181 | out: | 2198 | out: |
2182 | vdev->num_luns++; | 2199 | vdev->num_luns++; |
2183 | return 0; | 2200 | device->hostdata = vdev; |
2184 | } | ||
2185 | |||
2186 | static int | ||
2187 | mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id) | ||
2188 | { | ||
2189 | int i; | ||
2190 | |||
2191 | if (!hd->ioc->spi_data.isRaid || !hd->ioc->spi_data.pIocPg3) | ||
2192 | return 0; | ||
2193 | |||
2194 | for (i = 0; i < hd->ioc->spi_data.pIocPg3->NumPhysDisks; i++) { | ||
2195 | if (id == hd->ioc->spi_data.pIocPg3->PhysDisk[i].PhysDiskID) | ||
2196 | return 1; | ||
2197 | } | ||
2198 | |||
2199 | return 0; | 2201 | return 0; |
2200 | } | 2202 | } |
2201 | 2203 | ||
@@ -2226,7 +2228,7 @@ mptscsih_slave_destroy(struct scsi_device *device) | |||
2226 | hd->Targets[target] = NULL; | 2228 | hd->Targets[target] = NULL; |
2227 | 2229 | ||
2228 | if (hd->ioc->bus_type == SCSI) { | 2230 | if (hd->ioc->bus_type == SCSI) { |
2229 | if (mptscsih_is_raid_volume(hd, target)) { | 2231 | if (mptscsih_is_phys_disk(hd->ioc, target)) { |
2230 | hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; | 2232 | hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3; |
2231 | } else { | 2233 | } else { |
2232 | hd->ioc->spi_data.dvStatus[target] = | 2234 | hd->ioc->spi_data.dvStatus[target] = |
@@ -2439,6 +2441,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | |||
2439 | { | 2441 | { |
2440 | MPT_SCSI_HOST *hd; | 2442 | MPT_SCSI_HOST *hd; |
2441 | unsigned long flags; | 2443 | unsigned long flags; |
2444 | int ii; | ||
2442 | 2445 | ||
2443 | dtmprintk((KERN_WARNING MYNAM | 2446 | dtmprintk((KERN_WARNING MYNAM |
2444 | ": IOC %s_reset routed to SCSI host driver!\n", | 2447 | ": IOC %s_reset routed to SCSI host driver!\n", |
@@ -2496,11 +2499,8 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | |||
2496 | 2499 | ||
2497 | /* ScsiLookup initialization | 2500 | /* ScsiLookup initialization |
2498 | */ | 2501 | */ |
2499 | { | 2502 | for (ii=0; ii < hd->ioc->req_depth; ii++) |
2500 | int ii; | 2503 | hd->ScsiLookup[ii] = NULL; |
2501 | for (ii=0; ii < hd->ioc->req_depth; ii++) | ||
2502 | hd->ScsiLookup[ii] = NULL; | ||
2503 | } | ||
2504 | 2504 | ||
2505 | /* 2. Chain Buffer initialization | 2505 | /* 2. Chain Buffer initialization |
2506 | */ | 2506 | */ |
@@ -2549,6 +2549,16 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) | |||
2549 | } | 2549 | } |
2550 | 2550 | ||
2551 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 2551 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
2552 | /* work queue thread to clear the persitency table */ | ||
2553 | static void | ||
2554 | mptscsih_sas_persist_clear_table(void * arg) | ||
2555 | { | ||
2556 | MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg; | ||
2557 | |||
2558 | mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT); | ||
2559 | } | ||
2560 | |||
2561 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
2552 | int | 2562 | int |
2553 | mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | 2563 | mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) |
2554 | { | 2564 | { |
@@ -2558,18 +2568,18 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
2558 | devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", | 2568 | devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n", |
2559 | ioc->name, event)); | 2569 | ioc->name, event)); |
2560 | 2570 | ||
2571 | if (ioc->sh == NULL || | ||
2572 | ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) | ||
2573 | return 1; | ||
2574 | |||
2561 | switch (event) { | 2575 | switch (event) { |
2562 | case MPI_EVENT_UNIT_ATTENTION: /* 03 */ | 2576 | case MPI_EVENT_UNIT_ATTENTION: /* 03 */ |
2563 | /* FIXME! */ | 2577 | /* FIXME! */ |
2564 | break; | 2578 | break; |
2565 | case MPI_EVENT_IOC_BUS_RESET: /* 04 */ | 2579 | case MPI_EVENT_IOC_BUS_RESET: /* 04 */ |
2566 | case MPI_EVENT_EXT_BUS_RESET: /* 05 */ | 2580 | case MPI_EVENT_EXT_BUS_RESET: /* 05 */ |
2567 | hd = NULL; | 2581 | if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1)) |
2568 | if (ioc->sh) { | 2582 | hd->soft_resets++; |
2569 | hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; | ||
2570 | if (hd && (ioc->bus_type == SCSI) && (hd->soft_resets < -1)) | ||
2571 | hd->soft_resets++; | ||
2572 | } | ||
2573 | break; | 2583 | break; |
2574 | case MPI_EVENT_LOGOUT: /* 09 */ | 2584 | case MPI_EVENT_LOGOUT: /* 09 */ |
2575 | /* FIXME! */ | 2585 | /* FIXME! */ |
@@ -2588,69 +2598,24 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) | |||
2588 | break; | 2598 | break; |
2589 | 2599 | ||
2590 | case MPI_EVENT_INTEGRATED_RAID: /* 0B */ | 2600 | case MPI_EVENT_INTEGRATED_RAID: /* 0B */ |
2601 | { | ||
2602 | pMpiEventDataRaid_t pRaidEventData = | ||
2603 | (pMpiEventDataRaid_t) pEvReply->Data; | ||
2591 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION | 2604 | #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION |
2592 | /* negoNvram set to 0 if DV enabled and to USE_NVRAM if | 2605 | /* Domain Validation Needed */ |
2593 | * if DV disabled. Need to check for target mode. | 2606 | if (ioc->bus_type == SCSI && |
2594 | */ | 2607 | pRaidEventData->ReasonCode == |
2595 | hd = NULL; | 2608 | MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) |
2596 | if (ioc->sh) | 2609 | mptscsih_set_dvflags_raid(hd, pRaidEventData->PhysDiskNum); |
2597 | hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; | ||
2598 | |||
2599 | if (hd && (ioc->bus_type == SCSI) && (hd->negoNvram == 0)) { | ||
2600 | ScsiCfgData *pSpi; | ||
2601 | Ioc3PhysDisk_t *pPDisk; | ||
2602 | int numPDisk; | ||
2603 | u8 reason; | ||
2604 | u8 physDiskNum; | ||
2605 | |||
2606 | reason = (le32_to_cpu(pEvReply->Data[0]) & 0x00FF0000) >> 16; | ||
2607 | if (reason == MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED) { | ||
2608 | /* New or replaced disk. | ||
2609 | * Set DV flag and schedule DV. | ||
2610 | */ | ||
2611 | pSpi = &ioc->spi_data; | ||
2612 | physDiskNum = (le32_to_cpu(pEvReply->Data[0]) & 0xFF000000) >> 24; | ||
2613 | ddvtprintk(("DV requested for phys disk id %d\n", physDiskNum)); | ||
2614 | if (pSpi->pIocPg3) { | ||
2615 | pPDisk = pSpi->pIocPg3->PhysDisk; | ||
2616 | numPDisk =pSpi->pIocPg3->NumPhysDisks; | ||
2617 | |||
2618 | while (numPDisk) { | ||
2619 | if (physDiskNum == pPDisk->PhysDiskNum) { | ||
2620 | pSpi->dvStatus[pPDisk->PhysDiskID] = (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE); | ||
2621 | pSpi->forceDv = MPT_SCSICFG_NEED_DV; | ||
2622 | ddvtprintk(("NEED_DV set for phys disk id %d\n", pPDisk->PhysDiskID)); | ||
2623 | break; | ||
2624 | } | ||
2625 | pPDisk++; | ||
2626 | numPDisk--; | ||
2627 | } | ||
2628 | |||
2629 | if (numPDisk == 0) { | ||
2630 | /* The physical disk that needs DV was not found | ||
2631 | * in the stored IOC Page 3. The driver must reload | ||
2632 | * this page. DV routine will set the NEED_DV flag for | ||
2633 | * all phys disks that have DV_NOT_DONE set. | ||
2634 | */ | ||
2635 | pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; | ||
2636 | ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n", physDiskNum)); | ||
2637 | } | ||
2638 | } | ||
2639 | } | ||
2640 | } | ||
2641 | #endif | 2610 | #endif |
2611 | break; | ||
2612 | } | ||
2642 | 2613 | ||
2643 | #if defined(MPT_DEBUG_DV) || defined(MPT_DEBUG_DV_TINY) | 2614 | /* Persistent table is full. */ |
2644 | printk("Raid Event RF: "); | 2615 | case MPI_EVENT_PERSISTENT_TABLE_FULL: |
2645 | { | 2616 | INIT_WORK(&mptscsih_persistTask, |
2646 | u32 *m = (u32 *)pEvReply; | 2617 | mptscsih_sas_persist_clear_table,(void *)ioc); |
2647 | int ii; | 2618 | schedule_work(&mptscsih_persistTask); |
2648 | int n = (int)pEvReply->MsgLength; | ||
2649 | for (ii=6; ii < n; ii++) | ||
2650 | printk(" %08x", le32_to_cpu(m[ii])); | ||
2651 | printk("\n"); | ||
2652 | } | ||
2653 | #endif | ||
2654 | break; | 2619 | break; |
2655 | 2620 | ||
2656 | case MPI_EVENT_NONE: /* 00 */ | 2621 | case MPI_EVENT_NONE: /* 00 */ |
@@ -2687,7 +2652,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char * | |||
2687 | { | 2652 | { |
2688 | int indexed_lun, lun_index; | 2653 | int indexed_lun, lun_index; |
2689 | VirtDevice *vdev; | 2654 | VirtDevice *vdev; |
2690 | ScsiCfgData *pSpi; | 2655 | SpiCfgData *pSpi; |
2691 | char data_56; | 2656 | char data_56; |
2692 | 2657 | ||
2693 | dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", | 2658 | dinitprintk((MYIOC_s_INFO_FMT "initTarget bus=%d id=%d lun=%d hd=%p\n", |
@@ -2794,7 +2759,7 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char * | |||
2794 | static void | 2759 | static void |
2795 | mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) | 2760 | mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) |
2796 | { | 2761 | { |
2797 | ScsiCfgData *pspi_data = &hd->ioc->spi_data; | 2762 | SpiCfgData *pspi_data = &hd->ioc->spi_data; |
2798 | int id = (int) target->target_id; | 2763 | int id = (int) target->target_id; |
2799 | int nvram; | 2764 | int nvram; |
2800 | VirtDevice *vdev; | 2765 | VirtDevice *vdev; |
@@ -2973,11 +2938,13 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56) | |||
2973 | static void | 2938 | static void |
2974 | mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) | 2939 | mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) |
2975 | { | 2940 | { |
2941 | MPT_ADAPTER *ioc = hd->ioc; | ||
2976 | u8 cmd; | 2942 | u8 cmd; |
2977 | ScsiCfgData *pSpi; | 2943 | SpiCfgData *pSpi; |
2978 | 2944 | ||
2979 | ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", | 2945 | ddvtprintk((MYIOC_s_NOTE_FMT |
2980 | pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0])); | 2946 | " set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", |
2947 | hd->ioc->name, pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0])); | ||
2981 | 2948 | ||
2982 | if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0)) | 2949 | if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0)) |
2983 | return; | 2950 | return; |
@@ -2985,12 +2952,12 @@ mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) | |||
2985 | cmd = pReq->CDB[0]; | 2952 | cmd = pReq->CDB[0]; |
2986 | 2953 | ||
2987 | if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) { | 2954 | if ((cmd == READ_CAPACITY) || (cmd == MODE_SENSE)) { |
2988 | pSpi = &hd->ioc->spi_data; | 2955 | pSpi = &ioc->spi_data; |
2989 | if ((pSpi->isRaid & (1 << pReq->TargetID)) && pSpi->pIocPg3) { | 2956 | if ((ioc->raid_data.isRaid & (1 << pReq->TargetID)) && ioc->raid_data.pIocPg3) { |
2990 | /* Set NEED_DV for all hidden disks | 2957 | /* Set NEED_DV for all hidden disks |
2991 | */ | 2958 | */ |
2992 | Ioc3PhysDisk_t *pPDisk = pSpi->pIocPg3->PhysDisk; | 2959 | Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; |
2993 | int numPDisk = pSpi->pIocPg3->NumPhysDisks; | 2960 | int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; |
2994 | 2961 | ||
2995 | while (numPDisk) { | 2962 | while (numPDisk) { |
2996 | pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; | 2963 | pSpi->dvStatus[pPDisk->PhysDiskID] |= MPT_SCSICFG_NEED_DV; |
@@ -3004,6 +2971,50 @@ mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq) | |||
3004 | } | 2971 | } |
3005 | } | 2972 | } |
3006 | 2973 | ||
2974 | /* mptscsih_raid_set_dv_flags() | ||
2975 | * | ||
2976 | * New or replaced disk. Set DV flag and schedule DV. | ||
2977 | */ | ||
2978 | static void | ||
2979 | mptscsih_set_dvflags_raid(MPT_SCSI_HOST *hd, int id) | ||
2980 | { | ||
2981 | MPT_ADAPTER *ioc = hd->ioc; | ||
2982 | SpiCfgData *pSpi = &ioc->spi_data; | ||
2983 | Ioc3PhysDisk_t *pPDisk; | ||
2984 | int numPDisk; | ||
2985 | |||
2986 | if (hd->negoNvram != 0) | ||
2987 | return; | ||
2988 | |||
2989 | ddvtprintk(("DV requested for phys disk id %d\n", id)); | ||
2990 | if (ioc->raid_data.pIocPg3) { | ||
2991 | pPDisk = ioc->raid_data.pIocPg3->PhysDisk; | ||
2992 | numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; | ||
2993 | while (numPDisk) { | ||
2994 | if (id == pPDisk->PhysDiskNum) { | ||
2995 | pSpi->dvStatus[pPDisk->PhysDiskID] = | ||
2996 | (MPT_SCSICFG_NEED_DV | MPT_SCSICFG_DV_NOT_DONE); | ||
2997 | pSpi->forceDv = MPT_SCSICFG_NEED_DV; | ||
2998 | ddvtprintk(("NEED_DV set for phys disk id %d\n", | ||
2999 | pPDisk->PhysDiskID)); | ||
3000 | break; | ||
3001 | } | ||
3002 | pPDisk++; | ||
3003 | numPDisk--; | ||
3004 | } | ||
3005 | |||
3006 | if (numPDisk == 0) { | ||
3007 | /* The physical disk that needs DV was not found | ||
3008 | * in the stored IOC Page 3. The driver must reload | ||
3009 | * this page. DV routine will set the NEED_DV flag for | ||
3010 | * all phys disks that have DV_NOT_DONE set. | ||
3011 | */ | ||
3012 | pSpi->forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3; | ||
3013 | ddvtprintk(("phys disk %d not found. Setting reload IOC Pg3 Flag\n",id)); | ||
3014 | } | ||
3015 | } | ||
3016 | } | ||
3017 | |||
3007 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 3018 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
3008 | /* | 3019 | /* |
3009 | * If no Target, bus reset on 1st I/O. Set the flag to | 3020 | * If no Target, bus reset on 1st I/O. Set the flag to |
@@ -3091,7 +3102,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) | |||
3091 | MPT_ADAPTER *ioc = hd->ioc; | 3102 | MPT_ADAPTER *ioc = hd->ioc; |
3092 | Config_t *pReq; | 3103 | Config_t *pReq; |
3093 | SCSIDevicePage1_t *pData; | 3104 | SCSIDevicePage1_t *pData; |
3094 | VirtDevice *pTarget; | 3105 | VirtDevice *pTarget=NULL; |
3095 | MPT_FRAME_HDR *mf; | 3106 | MPT_FRAME_HDR *mf; |
3096 | dma_addr_t dataDma; | 3107 | dma_addr_t dataDma; |
3097 | u16 req_idx; | 3108 | u16 req_idx; |
@@ -3190,7 +3201,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags) | |||
3190 | #endif | 3201 | #endif |
3191 | 3202 | ||
3192 | if (flags & MPT_SCSICFG_BLK_NEGO) | 3203 | if (flags & MPT_SCSICFG_BLK_NEGO) |
3193 | negoFlags = MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC; | 3204 | negoFlags |= MPT_TARGET_NO_NEGO_WIDE | MPT_TARGET_NO_NEGO_SYNC; |
3194 | 3205 | ||
3195 | mptscsih_setDevicePage1Flags(width, factor, offset, | 3206 | mptscsih_setDevicePage1Flags(width, factor, offset, |
3196 | &requested, &configuration, negoFlags); | 3207 | &requested, &configuration, negoFlags); |
@@ -4011,7 +4022,7 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum) | |||
4011 | 4022 | ||
4012 | /* If target Ptr NULL or if this target is NOT a disk, skip. | 4023 | /* If target Ptr NULL or if this target is NOT a disk, skip. |
4013 | */ | 4024 | */ |
4014 | if ((pTarget) && (pTarget->tflags & MPT_TARGET_FLAGS_Q_YES)){ | 4025 | if ((pTarget) && (pTarget->inq_data[0] == TYPE_DISK)){ |
4015 | for (lun=0; lun <= MPT_LAST_LUN; lun++) { | 4026 | for (lun=0; lun <= MPT_LAST_LUN; lun++) { |
4016 | /* If LUN present, issue the command | 4027 | /* If LUN present, issue the command |
4017 | */ | 4028 | */ |
@@ -4106,9 +4117,9 @@ mptscsih_domainValidation(void *arg) | |||
4106 | 4117 | ||
4107 | if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) { | 4118 | if ((ioc->spi_data.forceDv & MPT_SCSICFG_RELOAD_IOC_PG3) != 0) { |
4108 | mpt_read_ioc_pg_3(ioc); | 4119 | mpt_read_ioc_pg_3(ioc); |
4109 | if (ioc->spi_data.pIocPg3) { | 4120 | if (ioc->raid_data.pIocPg3) { |
4110 | Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; | 4121 | Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; |
4111 | int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; | 4122 | int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; |
4112 | 4123 | ||
4113 | while (numPDisk) { | 4124 | while (numPDisk) { |
4114 | if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE) | 4125 | if (ioc->spi_data.dvStatus[pPDisk->PhysDiskID] & MPT_SCSICFG_DV_NOT_DONE) |
@@ -4147,7 +4158,7 @@ mptscsih_domainValidation(void *arg) | |||
4147 | isPhysDisk = mptscsih_is_phys_disk(ioc, id); | 4158 | isPhysDisk = mptscsih_is_phys_disk(ioc, id); |
4148 | if (isPhysDisk) { | 4159 | if (isPhysDisk) { |
4149 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { | 4160 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { |
4150 | if (hd->ioc->spi_data.isRaid & (1 << ii)) { | 4161 | if (hd->ioc->raid_data.isRaid & (1 << ii)) { |
4151 | hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING; | 4162 | hd->ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_DV_PENDING; |
4152 | } | 4163 | } |
4153 | } | 4164 | } |
@@ -4166,7 +4177,7 @@ mptscsih_domainValidation(void *arg) | |||
4166 | 4177 | ||
4167 | if (isPhysDisk) { | 4178 | if (isPhysDisk) { |
4168 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { | 4179 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { |
4169 | if (hd->ioc->spi_data.isRaid & (1 << ii)) { | 4180 | if (hd->ioc->raid_data.isRaid & (1 << ii)) { |
4170 | hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING; | 4181 | hd->ioc->spi_data.dvStatus[ii] &= ~MPT_SCSICFG_DV_PENDING; |
4171 | } | 4182 | } |
4172 | } | 4183 | } |
@@ -4188,21 +4199,21 @@ mptscsih_domainValidation(void *arg) | |||
4188 | 4199 | ||
4189 | /* Search IOC page 3 to determine if this is hidden physical disk | 4200 | /* Search IOC page 3 to determine if this is hidden physical disk |
4190 | */ | 4201 | */ |
4191 | static int | 4202 | /* Search IOC page 3 to determine if this is hidden physical disk |
4203 | */ | ||
4204 | static int | ||
4192 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) | 4205 | mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id) |
4193 | { | 4206 | { |
4194 | if (ioc->spi_data.pIocPg3) { | 4207 | int i; |
4195 | Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; | ||
4196 | int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; | ||
4197 | 4208 | ||
4198 | while (numPDisk) { | 4209 | if (!ioc->raid_data.isRaid || !ioc->raid_data.pIocPg3) |
4199 | if (pPDisk->PhysDiskID == id) { | 4210 | return 0; |
4200 | return 1; | 4211 | |
4201 | } | 4212 | for (i = 0; i < ioc->raid_data.pIocPg3->NumPhysDisks; i++) { |
4202 | pPDisk++; | 4213 | if (id == ioc->raid_data.pIocPg3->PhysDisk[i].PhysDiskID) |
4203 | numPDisk--; | 4214 | return 1; |
4204 | } | ||
4205 | } | 4215 | } |
4216 | |||
4206 | return 0; | 4217 | return 0; |
4207 | } | 4218 | } |
4208 | 4219 | ||
@@ -4408,7 +4419,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) | |||
4408 | /* Skip this ID? Set cfg.cfghdr.hdr to force config page write | 4419 | /* Skip this ID? Set cfg.cfghdr.hdr to force config page write |
4409 | */ | 4420 | */ |
4410 | { | 4421 | { |
4411 | ScsiCfgData *pspi_data = &hd->ioc->spi_data; | 4422 | SpiCfgData *pspi_data = &hd->ioc->spi_data; |
4412 | if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { | 4423 | if (pspi_data->nvram && (pspi_data->nvram[id] != MPT_HOST_NVRAM_INVALID)) { |
4413 | /* Set the factor from nvram */ | 4424 | /* Set the factor from nvram */ |
4414 | nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8; | 4425 | nfactor = (pspi_data->nvram[id] & MPT_NVRAM_SYNC_MASK) >> 8; |
@@ -4438,11 +4449,11 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) | |||
4438 | } | 4449 | } |
4439 | 4450 | ||
4440 | /* Finish iocmd inititialization - hidden or visible disk? */ | 4451 | /* Finish iocmd inititialization - hidden or visible disk? */ |
4441 | if (ioc->spi_data.pIocPg3) { | 4452 | if (ioc->raid_data.pIocPg3) { |
4442 | /* Search IOC page 3 for matching id | 4453 | /* Search IOC page 3 for matching id |
4443 | */ | 4454 | */ |
4444 | Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk; | 4455 | Ioc3PhysDisk_t *pPDisk = ioc->raid_data.pIocPg3->PhysDisk; |
4445 | int numPDisk = ioc->spi_data.pIocPg3->NumPhysDisks; | 4456 | int numPDisk = ioc->raid_data.pIocPg3->NumPhysDisks; |
4446 | 4457 | ||
4447 | while (numPDisk) { | 4458 | while (numPDisk) { |
4448 | if (pPDisk->PhysDiskID == id) { | 4459 | if (pPDisk->PhysDiskID == id) { |
@@ -4466,7 +4477,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) | |||
4466 | /* RAID Volume ID's may double for a physical device. If RAID but | 4477 | /* RAID Volume ID's may double for a physical device. If RAID but |
4467 | * not a physical ID as well, skip DV. | 4478 | * not a physical ID as well, skip DV. |
4468 | */ | 4479 | */ |
4469 | if ((hd->ioc->spi_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK)) | 4480 | if ((hd->ioc->raid_data.isRaid & (1 << id)) && !(iocmd.flags & MPT_ICFLAG_PHYS_DISK)) |
4470 | goto target_done; | 4481 | goto target_done; |
4471 | 4482 | ||
4472 | 4483 | ||
@@ -4815,6 +4826,8 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) | |||
4815 | notDone = 0; | 4826 | notDone = 0; |
4816 | if (iocmd.flags & MPT_ICFLAG_ECHO) { | 4827 | if (iocmd.flags & MPT_ICFLAG_ECHO) { |
4817 | bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3]; | 4828 | bufsize = ((pbuf1[2] & 0x1F) <<8) | pbuf1[3]; |
4829 | if (pbuf1[0] & 0x01) | ||
4830 | iocmd.flags |= MPT_ICFLAG_EBOS; | ||
4818 | } else { | 4831 | } else { |
4819 | bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3]; | 4832 | bufsize = pbuf1[1]<<16 | pbuf1[2]<<8 | pbuf1[3]; |
4820 | } | 4833 | } |
@@ -4911,6 +4924,9 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) | |||
4911 | } | 4924 | } |
4912 | iocmd.flags &= ~MPT_ICFLAG_DID_RESET; | 4925 | iocmd.flags &= ~MPT_ICFLAG_DID_RESET; |
4913 | 4926 | ||
4927 | if (iocmd.flags & MPT_ICFLAG_EBOS) | ||
4928 | goto skip_Reserve; | ||
4929 | |||
4914 | repeat = 5; | 4930 | repeat = 5; |
4915 | while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) { | 4931 | while (repeat && (!(iocmd.flags & MPT_ICFLAG_RESERVED))) { |
4916 | iocmd.cmd = RESERVE; | 4932 | iocmd.cmd = RESERVE; |
@@ -4954,6 +4970,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id) | |||
4954 | } | 4970 | } |
4955 | } | 4971 | } |
4956 | 4972 | ||
4973 | skip_Reserve: | ||
4957 | mptscsih_fillbuf(pbuf1, sz, patt, 1); | 4974 | mptscsih_fillbuf(pbuf1, sz, patt, 1); |
4958 | iocmd.cmd = WRITE_BUFFER; | 4975 | iocmd.cmd = WRITE_BUFFER; |
4959 | iocmd.data_dma = buf1_dma; | 4976 | iocmd.data_dma = buf1_dma; |
@@ -5198,11 +5215,12 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) | |||
5198 | * If not an LVD bus, the adapter minSyncFactor has been | 5215 | * If not an LVD bus, the adapter minSyncFactor has been |
5199 | * already throttled back. | 5216 | * already throttled back. |
5200 | */ | 5217 | */ |
5218 | negoFlags = hd->ioc->spi_data.noQas; | ||
5201 | if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) { | 5219 | if ((hd->Targets)&&((pTarget = hd->Targets[(int)id]) != NULL) && !pTarget->raidVolume) { |
5202 | width = pTarget->maxWidth; | 5220 | width = pTarget->maxWidth; |
5203 | offset = pTarget->maxOffset; | 5221 | offset = pTarget->maxOffset; |
5204 | factor = pTarget->minSyncFactor; | 5222 | factor = pTarget->minSyncFactor; |
5205 | negoFlags = pTarget->negoFlags; | 5223 | negoFlags |= pTarget->negoFlags; |
5206 | } else { | 5224 | } else { |
5207 | if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { | 5225 | if (hd->ioc->spi_data.nvram && (hd->ioc->spi_data.nvram[id] != MPT_HOST_NVRAM_INVALID)) { |
5208 | data = hd->ioc->spi_data.nvram[id]; | 5226 | data = hd->ioc->spi_data.nvram[id]; |
@@ -5223,7 +5241,6 @@ mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage) | |||
5223 | } | 5241 | } |
5224 | 5242 | ||
5225 | /* Set the negotiation flags */ | 5243 | /* Set the negotiation flags */ |
5226 | negoFlags = hd->ioc->spi_data.noQas; | ||
5227 | if (!width) | 5244 | if (!width) |
5228 | negoFlags |= MPT_TARGET_NO_NEGO_WIDE; | 5245 | negoFlags |= MPT_TARGET_NO_NEGO_WIDE; |
5229 | 5246 | ||
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 51c0255ac16e..971fda4b8b57 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/message/fusion/mptscsi.h | 2 | * linux/drivers/message/fusion/mptscsih.h |
3 | * High performance SCSI / Fibre Channel SCSI Host device driver. | 3 | * High performance SCSI / Fibre Channel SCSI Host device driver. |
4 | * For use with PCI chip/adapter(s): | 4 | * For use with PCI chip/adapter(s): |
5 | * LSIFC9xx/LSI409xx Fibre Channel | 5 | * LSIFC9xx/LSI409xx Fibre Channel |
@@ -53,8 +53,8 @@ | |||
53 | * SCSI Public stuff... | 53 | * SCSI Public stuff... |
54 | */ | 54 | */ |
55 | 55 | ||
56 | #define MPT_SCSI_CMD_PER_DEV_HIGH 31 | 56 | #define MPT_SCSI_CMD_PER_DEV_HIGH 64 |
57 | #define MPT_SCSI_CMD_PER_DEV_LOW 7 | 57 | #define MPT_SCSI_CMD_PER_DEV_LOW 32 |
58 | 58 | ||
59 | #define MPT_SCSI_CMD_PER_LUN 7 | 59 | #define MPT_SCSI_CMD_PER_LUN 7 |
60 | 60 | ||
@@ -77,6 +77,7 @@ | |||
77 | #define MPTSCSIH_MAX_WIDTH 1 | 77 | #define MPTSCSIH_MAX_WIDTH 1 |
78 | #define MPTSCSIH_MIN_SYNC 0x08 | 78 | #define MPTSCSIH_MIN_SYNC 0x08 |
79 | #define MPTSCSIH_SAF_TE 0 | 79 | #define MPTSCSIH_SAF_TE 0 |
80 | #define MPTSCSIH_PT_CLEAR 0 | ||
80 | 81 | ||
81 | 82 | ||
82 | #endif | 83 | #endif |
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 587d1274fd74..5c0e307d1d5d 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c | |||
@@ -199,7 +199,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
199 | printk(MYIOC_s_WARN_FMT | 199 | printk(MYIOC_s_WARN_FMT |
200 | "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", | 200 | "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n", |
201 | ioc->name, ioc); | 201 | ioc->name, ioc); |
202 | return -ENODEV; | 202 | return 0; |
203 | } | 203 | } |
204 | 204 | ||
205 | sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST)); | 205 | sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST)); |
diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c index af32ab4e90cd..10432f665201 100644 --- a/drivers/message/i2o/config-osm.c +++ b/drivers/message/i2o/config-osm.c | |||
@@ -56,8 +56,11 @@ static int __init i2o_config_init(void) | |||
56 | return -EBUSY; | 56 | return -EBUSY; |
57 | } | 57 | } |
58 | #ifdef CONFIG_I2O_CONFIG_OLD_IOCTL | 58 | #ifdef CONFIG_I2O_CONFIG_OLD_IOCTL |
59 | if (i2o_config_old_init()) | 59 | if (i2o_config_old_init()) { |
60 | osm_err("old config handler initialization failed\n"); | ||
60 | i2o_driver_unregister(&i2o_config_driver); | 61 | i2o_driver_unregister(&i2o_config_driver); |
62 | return -EBUSY; | ||
63 | } | ||
61 | #endif | 64 | #endif |
62 | 65 | ||
63 | return 0; | 66 | return 0; |
diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c index d15da6fd84c1..b7f093fbf9b0 100644 --- a/drivers/mtd/maps/sharpsl-flash.c +++ b/drivers/mtd/maps/sharpsl-flash.c | |||
@@ -82,7 +82,7 @@ int __init init_sharpsl(void) | |||
82 | } else if (machine_is_tosa()) { | 82 | } else if (machine_is_tosa()) { |
83 | sharpsl_partitions[0].size=0x006a0000; | 83 | sharpsl_partitions[0].size=0x006a0000; |
84 | sharpsl_partitions[0].offset=0x00160000; | 84 | sharpsl_partitions[0].offset=0x00160000; |
85 | } else if (machine_is_spitz()) { | 85 | } else if (machine_is_spitz() || machine_is_akita() || machine_is_borzoi()) { |
86 | sharpsl_partitions[0].size=0x006b0000; | 86 | sharpsl_partitions[0].size=0x006b0000; |
87 | sharpsl_partitions[0].offset=0x00140000; | 87 | sharpsl_partitions[0].offset=0x00140000; |
88 | } else { | 88 | } else { |
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 9853b87bb756..88b5b5b40b43 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c | |||
@@ -221,10 +221,16 @@ sharpsl_nand_init(void) | |||
221 | sharpsl_partition_info[1].size=25 * 1024 * 1024; | 221 | sharpsl_partition_info[1].size=25 * 1024 * 1024; |
222 | } else if (machine_is_husky()) { | 222 | } else if (machine_is_husky()) { |
223 | sharpsl_partition_info[1].size=53 * 1024 * 1024; | 223 | sharpsl_partition_info[1].size=53 * 1024 * 1024; |
224 | } | 224 | } else if (machine_is_spitz()) { |
225 | sharpsl_partition_info[1].size=5 * 1024 * 1024; | ||
226 | } else if (machine_is_akita()) { | ||
227 | sharpsl_partition_info[1].size=58 * 1024 * 1024; | ||
228 | } else if (machine_is_borzoi()) { | ||
229 | sharpsl_partition_info[1].size=32 * 1024 * 1024; | ||
230 | } | ||
225 | } | 231 | } |
226 | 232 | ||
227 | if (machine_is_husky()) { | 233 | if (machine_is_husky() || machine_is_borzoi()) { |
228 | /* Need to use small eraseblock size for backward compatibility */ | 234 | /* Need to use small eraseblock size for backward compatibility */ |
229 | sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS; | 235 | sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS; |
230 | } | 236 | } |
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index bd99c268e2da..f822cd3025ff 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c | |||
@@ -353,8 +353,6 @@ struct cp_private { | |||
353 | 353 | ||
354 | struct net_device_stats net_stats; | 354 | struct net_device_stats net_stats; |
355 | struct cp_extra_stats cp_stats; | 355 | struct cp_extra_stats cp_stats; |
356 | struct cp_dma_stats *nic_stats; | ||
357 | dma_addr_t nic_stats_dma; | ||
358 | 356 | ||
359 | unsigned rx_tail ____cacheline_aligned; | 357 | unsigned rx_tail ____cacheline_aligned; |
360 | struct cp_desc *rx_ring; | 358 | struct cp_desc *rx_ring; |
@@ -1142,10 +1140,6 @@ static int cp_alloc_rings (struct cp_private *cp) | |||
1142 | cp->rx_ring = mem; | 1140 | cp->rx_ring = mem; |
1143 | cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE]; | 1141 | cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE]; |
1144 | 1142 | ||
1145 | mem += (CP_RING_BYTES - CP_STATS_SIZE); | ||
1146 | cp->nic_stats = mem; | ||
1147 | cp->nic_stats_dma = cp->ring_dma + (CP_RING_BYTES - CP_STATS_SIZE); | ||
1148 | |||
1149 | return cp_init_rings(cp); | 1143 | return cp_init_rings(cp); |
1150 | } | 1144 | } |
1151 | 1145 | ||
@@ -1186,7 +1180,6 @@ static void cp_free_rings (struct cp_private *cp) | |||
1186 | pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma); | 1180 | pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma); |
1187 | cp->rx_ring = NULL; | 1181 | cp->rx_ring = NULL; |
1188 | cp->tx_ring = NULL; | 1182 | cp->tx_ring = NULL; |
1189 | cp->nic_stats = NULL; | ||
1190 | } | 1183 | } |
1191 | 1184 | ||
1192 | static int cp_open (struct net_device *dev) | 1185 | static int cp_open (struct net_device *dev) |
@@ -1515,13 +1508,17 @@ static void cp_get_ethtool_stats (struct net_device *dev, | |||
1515 | struct ethtool_stats *estats, u64 *tmp_stats) | 1508 | struct ethtool_stats *estats, u64 *tmp_stats) |
1516 | { | 1509 | { |
1517 | struct cp_private *cp = netdev_priv(dev); | 1510 | struct cp_private *cp = netdev_priv(dev); |
1511 | struct cp_dma_stats *nic_stats; | ||
1512 | dma_addr_t dma; | ||
1518 | int i; | 1513 | int i; |
1519 | 1514 | ||
1520 | memset(cp->nic_stats, 0, sizeof(struct cp_dma_stats)); | 1515 | nic_stats = pci_alloc_consistent(cp->pdev, sizeof(*nic_stats), &dma); |
1516 | if (!nic_stats) | ||
1517 | return; | ||
1521 | 1518 | ||
1522 | /* begin NIC statistics dump */ | 1519 | /* begin NIC statistics dump */ |
1523 | cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16); | 1520 | cpw32(StatsAddr + 4, (u64)dma >> 32); |
1524 | cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats); | 1521 | cpw32(StatsAddr, ((u64)dma & DMA_32BIT_MASK) | DumpStats); |
1525 | cpr32(StatsAddr); | 1522 | cpr32(StatsAddr); |
1526 | 1523 | ||
1527 | for (i = 0; i < 1000; i++) { | 1524 | for (i = 0; i < 1000; i++) { |
@@ -1531,24 +1528,27 @@ static void cp_get_ethtool_stats (struct net_device *dev, | |||
1531 | } | 1528 | } |
1532 | cpw32(StatsAddr, 0); | 1529 | cpw32(StatsAddr, 0); |
1533 | cpw32(StatsAddr + 4, 0); | 1530 | cpw32(StatsAddr + 4, 0); |
1531 | cpr32(StatsAddr); | ||
1534 | 1532 | ||
1535 | i = 0; | 1533 | i = 0; |
1536 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok); | 1534 | tmp_stats[i++] = le64_to_cpu(nic_stats->tx_ok); |
1537 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok); | 1535 | tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok); |
1538 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_err); | 1536 | tmp_stats[i++] = le64_to_cpu(nic_stats->tx_err); |
1539 | tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_err); | 1537 | tmp_stats[i++] = le32_to_cpu(nic_stats->rx_err); |
1540 | tmp_stats[i++] = le16_to_cpu(cp->nic_stats->rx_fifo); | 1538 | tmp_stats[i++] = le16_to_cpu(nic_stats->rx_fifo); |
1541 | tmp_stats[i++] = le16_to_cpu(cp->nic_stats->frame_align); | 1539 | tmp_stats[i++] = le16_to_cpu(nic_stats->frame_align); |
1542 | tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_1col); | 1540 | tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_1col); |
1543 | tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_mcol); | 1541 | tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_mcol); |
1544 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_phys); | 1542 | tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_phys); |
1545 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_bcast); | 1543 | tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_bcast); |
1546 | tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_ok_mcast); | 1544 | tmp_stats[i++] = le32_to_cpu(nic_stats->rx_ok_mcast); |
1547 | tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_abort); | 1545 | tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort); |
1548 | tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_underrun); | 1546 | tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun); |
1549 | tmp_stats[i++] = cp->cp_stats.rx_frags; | 1547 | tmp_stats[i++] = cp->cp_stats.rx_frags; |
1550 | if (i != CP_NUM_STATS) | 1548 | if (i != CP_NUM_STATS) |
1551 | BUG(); | 1549 | BUG(); |
1550 | |||
1551 | pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma); | ||
1552 | } | 1552 | } |
1553 | 1553 | ||
1554 | static struct ethtool_ops cp_ethtool_ops = { | 1554 | static struct ethtool_ops cp_ethtool_ops = { |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 82603e419d76..ff3fccd7513b 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -1951,7 +1951,7 @@ config SKGE | |||
1951 | ---help--- | 1951 | ---help--- |
1952 | This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx | 1952 | This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx |
1953 | and related Gigabit Ethernet adapters. It is a new smaller driver | 1953 | and related Gigabit Ethernet adapters. It is a new smaller driver |
1954 | driver with better performance and more complete ethtool support. | 1954 | with better performance and more complete ethtool support. |
1955 | 1955 | ||
1956 | It does not support the link failover and network management | 1956 | It does not support the link failover and network management |
1957 | features that "portable" vendor supplied sk98lin driver does. | 1957 | features that "portable" vendor supplied sk98lin driver does. |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 94c9f68dd16b..90449a0f2a6c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -2879,6 +2879,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) | |||
2879 | * This target is not on a VLAN | 2879 | * This target is not on a VLAN |
2880 | */ | 2880 | */ |
2881 | if (rt->u.dst.dev == bond->dev) { | 2881 | if (rt->u.dst.dev == bond->dev) { |
2882 | ip_rt_put(rt); | ||
2882 | dprintk("basa: rtdev == bond->dev: arp_send\n"); | 2883 | dprintk("basa: rtdev == bond->dev: arp_send\n"); |
2883 | bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], | 2884 | bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], |
2884 | bond->master_ip, 0); | 2885 | bond->master_ip, 0); |
@@ -2898,6 +2899,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) | |||
2898 | } | 2899 | } |
2899 | 2900 | ||
2900 | if (vlan_id) { | 2901 | if (vlan_id) { |
2902 | ip_rt_put(rt); | ||
2901 | bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], | 2903 | bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], |
2902 | vlan->vlan_ip, vlan_id); | 2904 | vlan->vlan_ip, vlan_id); |
2903 | continue; | 2905 | continue; |
@@ -2909,6 +2911,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) | |||
2909 | bond->dev->name, NIPQUAD(fl.fl4_dst), | 2911 | bond->dev->name, NIPQUAD(fl.fl4_dst), |
2910 | rt->u.dst.dev ? rt->u.dst.dev->name : "NULL"); | 2912 | rt->u.dst.dev ? rt->u.dst.dev->name : "NULL"); |
2911 | } | 2913 | } |
2914 | ip_rt_put(rt); | ||
2912 | } | 2915 | } |
2913 | } | 2916 | } |
2914 | 2917 | ||
@@ -5036,6 +5039,14 @@ static int __init bonding_init(void) | |||
5036 | return 0; | 5039 | return 0; |
5037 | 5040 | ||
5038 | out_err: | 5041 | out_err: |
5042 | /* | ||
5043 | * rtnl_unlock() will run netdev_run_todo(), putting the | ||
5044 | * thus-far-registered bonding devices into a state which | ||
5045 | * unregigister_netdevice() will accept | ||
5046 | */ | ||
5047 | rtnl_unlock(); | ||
5048 | rtnl_lock(); | ||
5049 | |||
5039 | /* free and unregister all bonds that were successfully added */ | 5050 | /* free and unregister all bonds that were successfully added */ |
5040 | bond_free_all(); | 5051 | bond_free_all(); |
5041 | 5052 | ||
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 1c918309539f..c15406d46418 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c | |||
@@ -1387,13 +1387,13 @@ static void e100_update_stats(struct nic *nic) | |||
1387 | ns->collisions += nic->tx_collisions; | 1387 | ns->collisions += nic->tx_collisions; |
1388 | ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + | 1388 | ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + |
1389 | le32_to_cpu(s->tx_lost_crs); | 1389 | le32_to_cpu(s->tx_lost_crs); |
1390 | ns->rx_dropped += le32_to_cpu(s->rx_resource_errors); | ||
1391 | ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + | 1390 | ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + |
1392 | nic->rx_over_length_errors; | 1391 | nic->rx_over_length_errors; |
1393 | ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); | 1392 | ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); |
1394 | ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); | 1393 | ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); |
1395 | ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); | 1394 | ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); |
1396 | ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); | 1395 | ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); |
1396 | ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); | ||
1397 | ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + | 1397 | ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + |
1398 | le32_to_cpu(s->rx_alignment_errors) + | 1398 | le32_to_cpu(s->rx_alignment_errors) + |
1399 | le32_to_cpu(s->rx_short_frame_errors) + | 1399 | le32_to_cpu(s->rx_short_frame_errors) + |
@@ -1727,12 +1727,10 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
1727 | 1727 | ||
1728 | if(unlikely(!(rfd_status & cb_ok))) { | 1728 | if(unlikely(!(rfd_status & cb_ok))) { |
1729 | /* Don't indicate if hardware indicates errors */ | 1729 | /* Don't indicate if hardware indicates errors */ |
1730 | nic->net_stats.rx_dropped++; | ||
1731 | dev_kfree_skb_any(skb); | 1730 | dev_kfree_skb_any(skb); |
1732 | } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { | 1731 | } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { |
1733 | /* Don't indicate oversized frames */ | 1732 | /* Don't indicate oversized frames */ |
1734 | nic->rx_over_length_errors++; | 1733 | nic->rx_over_length_errors++; |
1735 | nic->net_stats.rx_dropped++; | ||
1736 | dev_kfree_skb_any(skb); | 1734 | dev_kfree_skb_any(skb); |
1737 | } else { | 1735 | } else { |
1738 | nic->net_stats.rx_packets++; | 1736 | nic->net_stats.rx_packets++; |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index d02883dcc9b3..c062b0ad8262 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -2545,7 +2545,6 @@ e1000_update_stats(struct e1000_adapter *adapter) | |||
2545 | adapter->stats.crcerrs + adapter->stats.algnerrc + | 2545 | adapter->stats.crcerrs + adapter->stats.algnerrc + |
2546 | adapter->stats.rlec + adapter->stats.mpc + | 2546 | adapter->stats.rlec + adapter->stats.mpc + |
2547 | adapter->stats.cexterr; | 2547 | adapter->stats.cexterr; |
2548 | adapter->net_stats.rx_dropped = adapter->stats.mpc; | ||
2549 | adapter->net_stats.rx_length_errors = adapter->stats.rlec; | 2548 | adapter->net_stats.rx_length_errors = adapter->stats.rlec; |
2550 | adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; | 2549 | adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; |
2551 | adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; | 2550 | adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; |
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 5015eaf4e20a..176680cb153e 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c | |||
@@ -1617,8 +1617,6 @@ ixgb_update_stats(struct ixgb_adapter *adapter) | |||
1617 | adapter->stats.icbc + | 1617 | adapter->stats.icbc + |
1618 | adapter->stats.ecbc + adapter->stats.mpc; | 1618 | adapter->stats.ecbc + adapter->stats.mpc; |
1619 | 1619 | ||
1620 | adapter->net_stats.rx_dropped = adapter->stats.mpc; | ||
1621 | |||
1622 | /* see above | 1620 | /* see above |
1623 | * adapter->net_stats.rx_length_errors = adapter->stats.rlec; | 1621 | * adapter->net_stats.rx_length_errors = adapter->stats.rlec; |
1624 | */ | 1622 | */ |
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index c829e6a2e8a6..dd451e099a4c 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c | |||
@@ -428,7 +428,7 @@ static int init_shared_mem(struct s2io_nic *nic) | |||
428 | DBG_PRINT(INIT_DBG, | 428 | DBG_PRINT(INIT_DBG, |
429 | "%s: Zero DMA address for TxDL. ", dev->name); | 429 | "%s: Zero DMA address for TxDL. ", dev->name); |
430 | DBG_PRINT(INIT_DBG, | 430 | DBG_PRINT(INIT_DBG, |
431 | "Virtual address %llx\n", (u64)tmp_v); | 431 | "Virtual address %p\n", tmp_v); |
432 | tmp_v = pci_alloc_consistent(nic->pdev, | 432 | tmp_v = pci_alloc_consistent(nic->pdev, |
433 | PAGE_SIZE, &tmp_p); | 433 | PAGE_SIZE, &tmp_p); |
434 | if (!tmp_v) { | 434 | if (!tmp_v) { |
@@ -657,9 +657,10 @@ static void free_shared_mem(struct s2io_nic *nic) | |||
657 | mac_control->zerodma_virt_addr, | 657 | mac_control->zerodma_virt_addr, |
658 | (dma_addr_t)0); | 658 | (dma_addr_t)0); |
659 | DBG_PRINT(INIT_DBG, | 659 | DBG_PRINT(INIT_DBG, |
660 | "%s: Freeing TxDL with zero DMA addr. ", dev->name); | 660 | "%s: Freeing TxDL with zero DMA addr. ", |
661 | DBG_PRINT(INIT_DBG, "Virtual address %llx\n", | 661 | dev->name); |
662 | (u64)(mac_control->zerodma_virt_addr)); | 662 | DBG_PRINT(INIT_DBG, "Virtual address %p\n", |
663 | mac_control->zerodma_virt_addr); | ||
663 | } | 664 | } |
664 | kfree(mac_control->fifos[i].list_info); | 665 | kfree(mac_control->fifos[i].list_info); |
665 | } | 666 | } |
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 6ee4771addf1..2e72d79a143c 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c | |||
@@ -5216,17 +5216,15 @@ static struct pci_device_id skge_pci_tbl[] = { | |||
5216 | { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5216 | { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
5217 | { PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5217 | { PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
5218 | { PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5218 | { PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
5219 | { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5219 | /* DLink card does not have valid VPD so this driver gags |
5220 | * { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
5221 | */ | ||
5220 | { PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5222 | { PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
5221 | #if 0 /* don't handle Yukon2 cards at the moment -- mlindner@syskonnect.de */ | ||
5222 | { PCI_VENDOR_ID_MARVELL, 0x4360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
5223 | { PCI_VENDOR_ID_MARVELL, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
5224 | #endif | ||
5225 | { PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5223 | { PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
5226 | { PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5224 | { PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
5227 | { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5225 | { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, }, |
5228 | { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5226 | { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
5229 | { 0, } | 5227 | { 0 } |
5230 | }; | 5228 | }; |
5231 | 5229 | ||
5232 | MODULE_DEVICE_TABLE(pci, skge_pci_tbl); | 5230 | MODULE_DEVICE_TABLE(pci, skge_pci_tbl); |
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 757c83387a29..7ce734ec6ba8 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include "skge.h" | 42 | #include "skge.h" |
43 | 43 | ||
44 | #define DRV_NAME "skge" | 44 | #define DRV_NAME "skge" |
45 | #define DRV_VERSION "0.9" | 45 | #define DRV_VERSION "1.0" |
46 | #define PFX DRV_NAME " " | 46 | #define PFX DRV_NAME " " |
47 | 47 | ||
48 | #define DEFAULT_TX_RING_SIZE 128 | 48 | #define DEFAULT_TX_RING_SIZE 128 |
@@ -669,7 +669,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode) | |||
669 | PHY_M_LED_BLINK_RT(BLINK_84MS) | | 669 | PHY_M_LED_BLINK_RT(BLINK_84MS) | |
670 | PHY_M_LEDC_TX_CTRL | | 670 | PHY_M_LEDC_TX_CTRL | |
671 | PHY_M_LEDC_DP_CTRL); | 671 | PHY_M_LEDC_DP_CTRL); |
672 | 672 | ||
673 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, | 673 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, |
674 | PHY_M_LED_MO_RX(MO_LED_OFF) | | 674 | PHY_M_LED_MO_RX(MO_LED_OFF) | |
675 | (skge->speed == SPEED_100 ? | 675 | (skge->speed == SPEED_100 ? |
@@ -877,7 +877,7 @@ static int skge_rx_fill(struct skge_port *skge) | |||
877 | 877 | ||
878 | static void skge_link_up(struct skge_port *skge) | 878 | static void skge_link_up(struct skge_port *skge) |
879 | { | 879 | { |
880 | skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), | 880 | skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), |
881 | LED_BLK_OFF|LED_SYNC_OFF|LED_ON); | 881 | LED_BLK_OFF|LED_SYNC_OFF|LED_ON); |
882 | 882 | ||
883 | netif_carrier_on(skge->netdev); | 883 | netif_carrier_on(skge->netdev); |
@@ -988,6 +988,8 @@ static void genesis_reset(struct skge_hw *hw, int port) | |||
988 | { | 988 | { |
989 | const u8 zero[8] = { 0 }; | 989 | const u8 zero[8] = { 0 }; |
990 | 990 | ||
991 | skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); | ||
992 | |||
991 | /* reset the statistics module */ | 993 | /* reset the statistics module */ |
992 | xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT); | 994 | xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT); |
993 | xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */ | 995 | xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */ |
@@ -1022,8 +1024,6 @@ static void bcom_check_link(struct skge_hw *hw, int port) | |||
1022 | (void) xm_phy_read(hw, port, PHY_BCOM_STAT); | 1024 | (void) xm_phy_read(hw, port, PHY_BCOM_STAT); |
1023 | status = xm_phy_read(hw, port, PHY_BCOM_STAT); | 1025 | status = xm_phy_read(hw, port, PHY_BCOM_STAT); |
1024 | 1026 | ||
1025 | pr_debug("bcom_check_link status=0x%x\n", status); | ||
1026 | |||
1027 | if ((status & PHY_ST_LSYNC) == 0) { | 1027 | if ((status & PHY_ST_LSYNC) == 0) { |
1028 | u16 cmd = xm_read16(hw, port, XM_MMU_CMD); | 1028 | u16 cmd = xm_read16(hw, port, XM_MMU_CMD); |
1029 | cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); | 1029 | cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); |
@@ -1107,8 +1107,6 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo) | |||
1107 | { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 }, | 1107 | { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 }, |
1108 | }; | 1108 | }; |
1109 | 1109 | ||
1110 | pr_debug("bcom_phy_init\n"); | ||
1111 | |||
1112 | /* read Id from external PHY (all have the same address) */ | 1110 | /* read Id from external PHY (all have the same address) */ |
1113 | id1 = xm_phy_read(hw, port, PHY_XMAC_ID1); | 1111 | id1 = xm_phy_read(hw, port, PHY_XMAC_ID1); |
1114 | 1112 | ||
@@ -1341,6 +1339,8 @@ static void genesis_stop(struct skge_port *skge) | |||
1341 | int port = skge->port; | 1339 | int port = skge->port; |
1342 | u32 reg; | 1340 | u32 reg; |
1343 | 1341 | ||
1342 | genesis_reset(hw, port); | ||
1343 | |||
1344 | /* Clear Tx packet arbiter timeout IRQ */ | 1344 | /* Clear Tx packet arbiter timeout IRQ */ |
1345 | skge_write16(hw, B3_PA_CTRL, | 1345 | skge_write16(hw, B3_PA_CTRL, |
1346 | port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2); | 1346 | port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2); |
@@ -1466,7 +1466,6 @@ static void genesis_link_up(struct skge_port *skge) | |||
1466 | u16 cmd; | 1466 | u16 cmd; |
1467 | u32 mode, msk; | 1467 | u32 mode, msk; |
1468 | 1468 | ||
1469 | pr_debug("genesis_link_up\n"); | ||
1470 | cmd = xm_read16(hw, port, XM_MMU_CMD); | 1469 | cmd = xm_read16(hw, port, XM_MMU_CMD); |
1471 | 1470 | ||
1472 | /* | 1471 | /* |
@@ -1579,7 +1578,6 @@ static void yukon_init(struct skge_hw *hw, int port) | |||
1579 | struct skge_port *skge = netdev_priv(hw->dev[port]); | 1578 | struct skge_port *skge = netdev_priv(hw->dev[port]); |
1580 | u16 ctrl, ct1000, adv; | 1579 | u16 ctrl, ct1000, adv; |
1581 | 1580 | ||
1582 | pr_debug("yukon_init\n"); | ||
1583 | if (skge->autoneg == AUTONEG_ENABLE) { | 1581 | if (skge->autoneg == AUTONEG_ENABLE) { |
1584 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); | 1582 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); |
1585 | 1583 | ||
@@ -1678,9 +1676,11 @@ static void yukon_mac_init(struct skge_hw *hw, int port) | |||
1678 | 1676 | ||
1679 | /* WA code for COMA mode -- set PHY reset */ | 1677 | /* WA code for COMA mode -- set PHY reset */ |
1680 | if (hw->chip_id == CHIP_ID_YUKON_LITE && | 1678 | if (hw->chip_id == CHIP_ID_YUKON_LITE && |
1681 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) | 1679 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) { |
1682 | skge_write32(hw, B2_GP_IO, | 1680 | reg = skge_read32(hw, B2_GP_IO); |
1683 | (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9)); | 1681 | reg |= GP_DIR_9 | GP_IO_9; |
1682 | skge_write32(hw, B2_GP_IO, reg); | ||
1683 | } | ||
1684 | 1684 | ||
1685 | /* hard reset */ | 1685 | /* hard reset */ |
1686 | skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); | 1686 | skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); |
@@ -1688,10 +1688,12 @@ static void yukon_mac_init(struct skge_hw *hw, int port) | |||
1688 | 1688 | ||
1689 | /* WA code for COMA mode -- clear PHY reset */ | 1689 | /* WA code for COMA mode -- clear PHY reset */ |
1690 | if (hw->chip_id == CHIP_ID_YUKON_LITE && | 1690 | if (hw->chip_id == CHIP_ID_YUKON_LITE && |
1691 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) | 1691 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) { |
1692 | skge_write32(hw, B2_GP_IO, | 1692 | reg = skge_read32(hw, B2_GP_IO); |
1693 | (skge_read32(hw, B2_GP_IO) | GP_DIR_9) | 1693 | reg |= GP_DIR_9; |
1694 | & ~GP_IO_9); | 1694 | reg &= ~GP_IO_9; |
1695 | skge_write32(hw, B2_GP_IO, reg); | ||
1696 | } | ||
1695 | 1697 | ||
1696 | /* Set hardware config mode */ | 1698 | /* Set hardware config mode */ |
1697 | reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | | 1699 | reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | |
@@ -1730,7 +1732,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) | |||
1730 | } | 1732 | } |
1731 | 1733 | ||
1732 | gma_write16(hw, port, GM_GP_CTRL, reg); | 1734 | gma_write16(hw, port, GM_GP_CTRL, reg); |
1733 | skge_read16(hw, GMAC_IRQ_SRC); | 1735 | skge_read16(hw, SK_REG(port, GMAC_IRQ_SRC)); |
1734 | 1736 | ||
1735 | yukon_init(hw, port); | 1737 | yukon_init(hw, port); |
1736 | 1738 | ||
@@ -1802,20 +1804,26 @@ static void yukon_stop(struct skge_port *skge) | |||
1802 | struct skge_hw *hw = skge->hw; | 1804 | struct skge_hw *hw = skge->hw; |
1803 | int port = skge->port; | 1805 | int port = skge->port; |
1804 | 1806 | ||
1805 | if (hw->chip_id == CHIP_ID_YUKON_LITE && | 1807 | skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); |
1806 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) { | 1808 | yukon_reset(hw, port); |
1807 | skge_write32(hw, B2_GP_IO, | ||
1808 | skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9); | ||
1809 | } | ||
1810 | 1809 | ||
1811 | gma_write16(hw, port, GM_GP_CTRL, | 1810 | gma_write16(hw, port, GM_GP_CTRL, |
1812 | gma_read16(hw, port, GM_GP_CTRL) | 1811 | gma_read16(hw, port, GM_GP_CTRL) |
1813 | & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA)); | 1812 | & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA)); |
1814 | gma_read16(hw, port, GM_GP_CTRL); | 1813 | gma_read16(hw, port, GM_GP_CTRL); |
1815 | 1814 | ||
1815 | if (hw->chip_id == CHIP_ID_YUKON_LITE && | ||
1816 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) { | ||
1817 | u32 io = skge_read32(hw, B2_GP_IO); | ||
1818 | |||
1819 | io |= GP_DIR_9 | GP_IO_9; | ||
1820 | skge_write32(hw, B2_GP_IO, io); | ||
1821 | skge_read32(hw, B2_GP_IO); | ||
1822 | } | ||
1823 | |||
1816 | /* set GPHY Control reset */ | 1824 | /* set GPHY Control reset */ |
1817 | skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); | 1825 | skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); |
1818 | skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); | 1826 | skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); |
1819 | } | 1827 | } |
1820 | 1828 | ||
1821 | static void yukon_get_stats(struct skge_port *skge, u64 *data) | 1829 | static void yukon_get_stats(struct skge_port *skge, u64 *data) |
@@ -1874,10 +1882,8 @@ static void yukon_link_up(struct skge_port *skge) | |||
1874 | int port = skge->port; | 1882 | int port = skge->port; |
1875 | u16 reg; | 1883 | u16 reg; |
1876 | 1884 | ||
1877 | pr_debug("yukon_link_up\n"); | ||
1878 | |||
1879 | /* Enable Transmit FIFO Underrun */ | 1885 | /* Enable Transmit FIFO Underrun */ |
1880 | skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK); | 1886 | skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK); |
1881 | 1887 | ||
1882 | reg = gma_read16(hw, port, GM_GP_CTRL); | 1888 | reg = gma_read16(hw, port, GM_GP_CTRL); |
1883 | if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE) | 1889 | if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE) |
@@ -1897,7 +1903,6 @@ static void yukon_link_down(struct skge_port *skge) | |||
1897 | int port = skge->port; | 1903 | int port = skge->port; |
1898 | u16 ctrl; | 1904 | u16 ctrl; |
1899 | 1905 | ||
1900 | pr_debug("yukon_link_down\n"); | ||
1901 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); | 1906 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); |
1902 | 1907 | ||
1903 | ctrl = gma_read16(hw, port, GM_GP_CTRL); | 1908 | ctrl = gma_read16(hw, port, GM_GP_CTRL); |
@@ -2113,7 +2118,6 @@ static int skge_up(struct net_device *dev) | |||
2113 | skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); | 2118 | skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); |
2114 | skge_led(skge, LED_MODE_ON); | 2119 | skge_led(skge, LED_MODE_ON); |
2115 | 2120 | ||
2116 | pr_debug("skge_up completed\n"); | ||
2117 | return 0; | 2121 | return 0; |
2118 | 2122 | ||
2119 | free_rx_ring: | 2123 | free_rx_ring: |
@@ -2136,15 +2140,20 @@ static int skge_down(struct net_device *dev) | |||
2136 | 2140 | ||
2137 | netif_stop_queue(dev); | 2141 | netif_stop_queue(dev); |
2138 | 2142 | ||
2143 | skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); | ||
2144 | if (hw->chip_id == CHIP_ID_GENESIS) | ||
2145 | genesis_stop(skge); | ||
2146 | else | ||
2147 | yukon_stop(skge); | ||
2148 | |||
2149 | hw->intr_mask &= ~portirqmask[skge->port]; | ||
2150 | skge_write32(hw, B0_IMSK, hw->intr_mask); | ||
2151 | |||
2139 | /* Stop transmitter */ | 2152 | /* Stop transmitter */ |
2140 | skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); | 2153 | skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); |
2141 | skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), | 2154 | skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), |
2142 | RB_RST_SET|RB_DIS_OP_MD); | 2155 | RB_RST_SET|RB_DIS_OP_MD); |
2143 | 2156 | ||
2144 | if (hw->chip_id == CHIP_ID_GENESIS) | ||
2145 | genesis_stop(skge); | ||
2146 | else | ||
2147 | yukon_stop(skge); | ||
2148 | 2157 | ||
2149 | /* Disable Force Sync bit and Enable Alloc bit */ | 2158 | /* Disable Force Sync bit and Enable Alloc bit */ |
2150 | skge_write8(hw, SK_REG(port, TXA_CTRL), | 2159 | skge_write8(hw, SK_REG(port, TXA_CTRL), |
@@ -2368,8 +2377,6 @@ static void genesis_set_multicast(struct net_device *dev) | |||
2368 | u32 mode; | 2377 | u32 mode; |
2369 | u8 filter[8]; | 2378 | u8 filter[8]; |
2370 | 2379 | ||
2371 | pr_debug("genesis_set_multicast flags=%x count=%d\n", dev->flags, dev->mc_count); | ||
2372 | |||
2373 | mode = xm_read32(hw, port, XM_MODE); | 2380 | mode = xm_read32(hw, port, XM_MODE); |
2374 | mode |= XM_MD_ENA_HASH; | 2381 | mode |= XM_MD_ENA_HASH; |
2375 | if (dev->flags & IFF_PROMISC) | 2382 | if (dev->flags & IFF_PROMISC) |
@@ -2531,8 +2538,6 @@ static int skge_poll(struct net_device *dev, int *budget) | |||
2531 | unsigned int to_do = min(dev->quota, *budget); | 2538 | unsigned int to_do = min(dev->quota, *budget); |
2532 | unsigned int work_done = 0; | 2539 | unsigned int work_done = 0; |
2533 | 2540 | ||
2534 | pr_debug("skge_poll\n"); | ||
2535 | |||
2536 | for (e = ring->to_clean; work_done < to_do; e = e->next) { | 2541 | for (e = ring->to_clean; work_done < to_do; e = e->next) { |
2537 | struct skge_rx_desc *rd = e->desc; | 2542 | struct skge_rx_desc *rd = e->desc; |
2538 | struct sk_buff *skb; | 2543 | struct sk_buff *skb; |
@@ -2673,9 +2678,9 @@ static void skge_error_irq(struct skge_hw *hw) | |||
2673 | if (hw->chip_id == CHIP_ID_GENESIS) { | 2678 | if (hw->chip_id == CHIP_ID_GENESIS) { |
2674 | /* clear xmac errors */ | 2679 | /* clear xmac errors */ |
2675 | if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1)) | 2680 | if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1)) |
2676 | skge_write16(hw, SK_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT); | 2681 | skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT); |
2677 | if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2)) | 2682 | if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2)) |
2678 | skge_write16(hw, SK_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT); | 2683 | skge_write16(hw, RX_MFF_CTRL2, MFF_CLR_INSTAT); |
2679 | } else { | 2684 | } else { |
2680 | /* Timestamp (unused) overflow */ | 2685 | /* Timestamp (unused) overflow */ |
2681 | if (hwstatus & IS_IRQ_TIST_OV) | 2686 | if (hwstatus & IS_IRQ_TIST_OV) |
@@ -3001,9 +3006,6 @@ static int skge_reset(struct skge_hw *hw) | |||
3001 | 3006 | ||
3002 | skge_write32(hw, B0_IMSK, hw->intr_mask); | 3007 | skge_write32(hw, B0_IMSK, hw->intr_mask); |
3003 | 3008 | ||
3004 | if (hw->chip_id != CHIP_ID_GENESIS) | ||
3005 | skge_write8(hw, GMAC_IRQ_MSK, 0); | ||
3006 | |||
3007 | spin_lock_bh(&hw->phy_lock); | 3009 | spin_lock_bh(&hw->phy_lock); |
3008 | for (i = 0; i < hw->ports; i++) { | 3010 | for (i = 0; i < hw->ports; i++) { |
3009 | if (hw->chip_id == CHIP_ID_GENESIS) | 3011 | if (hw->chip_id == CHIP_ID_GENESIS) |
@@ -3232,6 +3234,11 @@ static void __devexit skge_remove(struct pci_dev *pdev) | |||
3232 | dev0 = hw->dev[0]; | 3234 | dev0 = hw->dev[0]; |
3233 | unregister_netdev(dev0); | 3235 | unregister_netdev(dev0); |
3234 | 3236 | ||
3237 | skge_write32(hw, B0_IMSK, 0); | ||
3238 | skge_write16(hw, B0_LED, LED_STAT_OFF); | ||
3239 | skge_pci_clear(hw); | ||
3240 | skge_write8(hw, B0_CTST, CS_RST_SET); | ||
3241 | |||
3235 | tasklet_kill(&hw->ext_tasklet); | 3242 | tasklet_kill(&hw->ext_tasklet); |
3236 | 3243 | ||
3237 | free_irq(pdev->irq, hw); | 3244 | free_irq(pdev->irq, hw); |
@@ -3240,7 +3247,7 @@ static void __devexit skge_remove(struct pci_dev *pdev) | |||
3240 | if (dev1) | 3247 | if (dev1) |
3241 | free_netdev(dev1); | 3248 | free_netdev(dev1); |
3242 | free_netdev(dev0); | 3249 | free_netdev(dev0); |
3243 | skge_write16(hw, B0_LED, LED_STAT_OFF); | 3250 | |
3244 | iounmap(hw->regs); | 3251 | iounmap(hw->regs); |
3245 | kfree(hw); | 3252 | kfree(hw); |
3246 | pci_set_drvdata(pdev, NULL); | 3253 | pci_set_drvdata(pdev, NULL); |
@@ -3259,7 +3266,10 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3259 | struct skge_port *skge = netdev_priv(dev); | 3266 | struct skge_port *skge = netdev_priv(dev); |
3260 | if (netif_running(dev)) { | 3267 | if (netif_running(dev)) { |
3261 | netif_carrier_off(dev); | 3268 | netif_carrier_off(dev); |
3262 | skge_down(dev); | 3269 | if (skge->wol) |
3270 | netif_stop_queue(dev); | ||
3271 | else | ||
3272 | skge_down(dev); | ||
3263 | } | 3273 | } |
3264 | netif_device_detach(dev); | 3274 | netif_device_detach(dev); |
3265 | wol |= skge->wol; | 3275 | wol |= skge->wol; |
diff --git a/drivers/net/skge.h b/drivers/net/skge.h index f1680beb8e68..efbf98c675d2 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h | |||
@@ -2008,7 +2008,7 @@ enum { | |||
2008 | GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */ | 2008 | GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */ |
2009 | GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */ | 2009 | GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */ |
2010 | 2010 | ||
2011 | #define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | GM_IS_TX_FF_UR) | 2011 | #define GMAC_DEF_MSK (GM_IS_RX_FF_OR | GM_IS_TX_FF_UR) |
2012 | 2012 | ||
2013 | /* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ | 2013 | /* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ |
2014 | /* Bits 15.. 2: reserved */ | 2014 | /* Bits 15.. 2: reserved */ |
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 4e19220473d0..c796f41b4a52 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c | |||
@@ -1817,6 +1817,10 @@ spider_net_setup_phy(struct spider_net_card *card) | |||
1817 | /* LEDs active in both modes, autosense prio = fiber */ | 1817 | /* LEDs active in both modes, autosense prio = fiber */ |
1818 | spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f); | 1818 | spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f); |
1819 | 1819 | ||
1820 | /* switch off fibre autoneg */ | ||
1821 | spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01); | ||
1822 | spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004); | ||
1823 | |||
1820 | phy->def->ops->read_link(phy); | 1824 | phy->def->ops->read_link(phy); |
1821 | pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name, | 1825 | pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name, |
1822 | phy->speed, phy->duplex==1 ? "Full" : "Half"); | 1826 | phy->speed, phy->duplex==1 ? "Full" : "Half"); |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7599f52e15b3..81f4aedf534c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -67,8 +67,8 @@ | |||
67 | 67 | ||
68 | #define DRV_MODULE_NAME "tg3" | 68 | #define DRV_MODULE_NAME "tg3" |
69 | #define PFX DRV_MODULE_NAME ": " | 69 | #define PFX DRV_MODULE_NAME ": " |
70 | #define DRV_MODULE_VERSION "3.39" | 70 | #define DRV_MODULE_VERSION "3.40" |
71 | #define DRV_MODULE_RELDATE "September 5, 2005" | 71 | #define DRV_MODULE_RELDATE "September 15, 2005" |
72 | 72 | ||
73 | #define TG3_DEF_MAC_MODE 0 | 73 | #define TG3_DEF_MAC_MODE 0 |
74 | #define TG3_DEF_RX_MODE 0 | 74 | #define TG3_DEF_RX_MODE 0 |
@@ -3442,31 +3442,47 @@ static void tg3_tx_timeout(struct net_device *dev) | |||
3442 | schedule_work(&tp->reset_task); | 3442 | schedule_work(&tp->reset_task); |
3443 | } | 3443 | } |
3444 | 3444 | ||
3445 | /* Test for DMA buffers crossing any 4GB boundaries: 4G, 8G, etc */ | ||
3446 | static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len) | ||
3447 | { | ||
3448 | u32 base = (u32) mapping & 0xffffffff; | ||
3449 | |||
3450 | return ((base > 0xffffdcc0) && | ||
3451 | (base + len + 8 < base)); | ||
3452 | } | ||
3453 | |||
3445 | static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32); | 3454 | static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32); |
3446 | 3455 | ||
3447 | static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, | 3456 | static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, |
3448 | u32 guilty_entry, int guilty_len, | 3457 | u32 last_plus_one, u32 *start, |
3449 | u32 last_plus_one, u32 *start, u32 mss) | 3458 | u32 base_flags, u32 mss) |
3450 | { | 3459 | { |
3451 | struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC); | 3460 | struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC); |
3452 | dma_addr_t new_addr; | 3461 | dma_addr_t new_addr = 0; |
3453 | u32 entry = *start; | 3462 | u32 entry = *start; |
3454 | int i; | 3463 | int i, ret = 0; |
3455 | 3464 | ||
3456 | if (!new_skb) { | 3465 | if (!new_skb) { |
3457 | dev_kfree_skb(skb); | 3466 | ret = -1; |
3458 | return -1; | 3467 | } else { |
3468 | /* New SKB is guaranteed to be linear. */ | ||
3469 | entry = *start; | ||
3470 | new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len, | ||
3471 | PCI_DMA_TODEVICE); | ||
3472 | /* Make sure new skb does not cross any 4G boundaries. | ||
3473 | * Drop the packet if it does. | ||
3474 | */ | ||
3475 | if (tg3_4g_overflow_test(new_addr, new_skb->len)) { | ||
3476 | ret = -1; | ||
3477 | dev_kfree_skb(new_skb); | ||
3478 | new_skb = NULL; | ||
3479 | } else { | ||
3480 | tg3_set_txd(tp, entry, new_addr, new_skb->len, | ||
3481 | base_flags, 1 | (mss << 1)); | ||
3482 | *start = NEXT_TX(entry); | ||
3483 | } | ||
3459 | } | 3484 | } |
3460 | 3485 | ||
3461 | /* New SKB is guaranteed to be linear. */ | ||
3462 | entry = *start; | ||
3463 | new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len, | ||
3464 | PCI_DMA_TODEVICE); | ||
3465 | tg3_set_txd(tp, entry, new_addr, new_skb->len, | ||
3466 | (skb->ip_summed == CHECKSUM_HW) ? | ||
3467 | TXD_FLAG_TCPUDP_CSUM : 0, 1 | (mss << 1)); | ||
3468 | *start = NEXT_TX(entry); | ||
3469 | |||
3470 | /* Now clean up the sw ring entries. */ | 3486 | /* Now clean up the sw ring entries. */ |
3471 | i = 0; | 3487 | i = 0; |
3472 | while (entry != last_plus_one) { | 3488 | while (entry != last_plus_one) { |
@@ -3491,7 +3507,7 @@ static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, | |||
3491 | 3507 | ||
3492 | dev_kfree_skb(skb); | 3508 | dev_kfree_skb(skb); |
3493 | 3509 | ||
3494 | return 0; | 3510 | return ret; |
3495 | } | 3511 | } |
3496 | 3512 | ||
3497 | static void tg3_set_txd(struct tg3 *tp, int entry, | 3513 | static void tg3_set_txd(struct tg3 *tp, int entry, |
@@ -3517,19 +3533,10 @@ static void tg3_set_txd(struct tg3 *tp, int entry, | |||
3517 | txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; | 3533 | txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; |
3518 | } | 3534 | } |
3519 | 3535 | ||
3520 | static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len) | ||
3521 | { | ||
3522 | u32 base = (u32) mapping & 0xffffffff; | ||
3523 | |||
3524 | return ((base > 0xffffdcc0) && | ||
3525 | (base + len + 8 < base)); | ||
3526 | } | ||
3527 | |||
3528 | static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | 3536 | static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) |
3529 | { | 3537 | { |
3530 | struct tg3 *tp = netdev_priv(dev); | 3538 | struct tg3 *tp = netdev_priv(dev); |
3531 | dma_addr_t mapping; | 3539 | dma_addr_t mapping; |
3532 | unsigned int i; | ||
3533 | u32 len, entry, base_flags, mss; | 3540 | u32 len, entry, base_flags, mss; |
3534 | int would_hit_hwbug; | 3541 | int would_hit_hwbug; |
3535 | 3542 | ||
@@ -3624,7 +3631,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3624 | would_hit_hwbug = 0; | 3631 | would_hit_hwbug = 0; |
3625 | 3632 | ||
3626 | if (tg3_4g_overflow_test(mapping, len)) | 3633 | if (tg3_4g_overflow_test(mapping, len)) |
3627 | would_hit_hwbug = entry + 1; | 3634 | would_hit_hwbug = 1; |
3628 | 3635 | ||
3629 | tg3_set_txd(tp, entry, mapping, len, base_flags, | 3636 | tg3_set_txd(tp, entry, mapping, len, base_flags, |
3630 | (skb_shinfo(skb)->nr_frags == 0) | (mss << 1)); | 3637 | (skb_shinfo(skb)->nr_frags == 0) | (mss << 1)); |
@@ -3648,12 +3655,8 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3648 | tp->tx_buffers[entry].skb = NULL; | 3655 | tp->tx_buffers[entry].skb = NULL; |
3649 | pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); | 3656 | pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); |
3650 | 3657 | ||
3651 | if (tg3_4g_overflow_test(mapping, len)) { | 3658 | if (tg3_4g_overflow_test(mapping, len)) |
3652 | /* Only one should match. */ | 3659 | would_hit_hwbug = 1; |
3653 | if (would_hit_hwbug) | ||
3654 | BUG(); | ||
3655 | would_hit_hwbug = entry + 1; | ||
3656 | } | ||
3657 | 3660 | ||
3658 | if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) | 3661 | if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) |
3659 | tg3_set_txd(tp, entry, mapping, len, | 3662 | tg3_set_txd(tp, entry, mapping, len, |
@@ -3669,34 +3672,15 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3669 | if (would_hit_hwbug) { | 3672 | if (would_hit_hwbug) { |
3670 | u32 last_plus_one = entry; | 3673 | u32 last_plus_one = entry; |
3671 | u32 start; | 3674 | u32 start; |
3672 | unsigned int len = 0; | ||
3673 | |||
3674 | would_hit_hwbug -= 1; | ||
3675 | entry = entry - 1 - skb_shinfo(skb)->nr_frags; | ||
3676 | entry &= (TG3_TX_RING_SIZE - 1); | ||
3677 | start = entry; | ||
3678 | i = 0; | ||
3679 | while (entry != last_plus_one) { | ||
3680 | if (i == 0) | ||
3681 | len = skb_headlen(skb); | ||
3682 | else | ||
3683 | len = skb_shinfo(skb)->frags[i-1].size; | ||
3684 | 3675 | ||
3685 | if (entry == would_hit_hwbug) | 3676 | start = entry - 1 - skb_shinfo(skb)->nr_frags; |
3686 | break; | 3677 | start &= (TG3_TX_RING_SIZE - 1); |
3687 | |||
3688 | i++; | ||
3689 | entry = NEXT_TX(entry); | ||
3690 | |||
3691 | } | ||
3692 | 3678 | ||
3693 | /* If the workaround fails due to memory/mapping | 3679 | /* If the workaround fails due to memory/mapping |
3694 | * failure, silently drop this packet. | 3680 | * failure, silently drop this packet. |
3695 | */ | 3681 | */ |
3696 | if (tigon3_4gb_hwbug_workaround(tp, skb, | 3682 | if (tigon3_4gb_hwbug_workaround(tp, skb, last_plus_one, |
3697 | entry, len, | 3683 | &start, base_flags, mss)) |
3698 | last_plus_one, | ||
3699 | &start, mss)) | ||
3700 | goto out_unlock; | 3684 | goto out_unlock; |
3701 | 3685 | ||
3702 | entry = start; | 3686 | entry = start; |
@@ -9271,6 +9255,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
9271 | static struct pci_device_id write_reorder_chipsets[] = { | 9255 | static struct pci_device_id write_reorder_chipsets[] = { |
9272 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, | 9256 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, |
9273 | PCI_DEVICE_ID_AMD_FE_GATE_700C) }, | 9257 | PCI_DEVICE_ID_AMD_FE_GATE_700C) }, |
9258 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, | ||
9259 | PCI_DEVICE_ID_AMD_K8_NB) }, | ||
9274 | { }, | 9260 | { }, |
9275 | }; | 9261 | }; |
9276 | u32 misc_ctrl_reg; | 9262 | u32 misc_ctrl_reg; |
@@ -9285,7 +9271,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
9285 | tp->tg3_flags2 |= TG3_FLG2_SUN_570X; | 9271 | tp->tg3_flags2 |= TG3_FLG2_SUN_570X; |
9286 | #endif | 9272 | #endif |
9287 | 9273 | ||
9288 | /* If we have an AMD 762 chipset, write | 9274 | /* If we have an AMD 762 or K8 chipset, write |
9289 | * reordering to the mailbox registers done by the host | 9275 | * reordering to the mailbox registers done by the host |
9290 | * controller can cause major troubles. We read back from | 9276 | * controller can cause major troubles. We read back from |
9291 | * every mailbox register write to force the writes to be | 9277 | * every mailbox register write to force the writes to be |
@@ -9532,7 +9518,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
9532 | tp->write32_rx_mbox = tg3_write_indirect_mbox; | 9518 | tp->write32_rx_mbox = tg3_write_indirect_mbox; |
9533 | 9519 | ||
9534 | iounmap(tp->regs); | 9520 | iounmap(tp->regs); |
9535 | tp->regs = 0; | 9521 | tp->regs = NULL; |
9536 | 9522 | ||
9537 | pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd); | 9523 | pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd); |
9538 | pci_cmd &= ~PCI_COMMAND_MEMORY; | 9524 | pci_cmd &= ~PCI_COMMAND_MEMORY; |
@@ -10680,7 +10666,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
10680 | err_out_iounmap: | 10666 | err_out_iounmap: |
10681 | if (tp->regs) { | 10667 | if (tp->regs) { |
10682 | iounmap(tp->regs); | 10668 | iounmap(tp->regs); |
10683 | tp->regs = 0; | 10669 | tp->regs = NULL; |
10684 | } | 10670 | } |
10685 | 10671 | ||
10686 | err_out_free_dev: | 10672 | err_out_free_dev: |
@@ -10705,7 +10691,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) | |||
10705 | unregister_netdev(dev); | 10691 | unregister_netdev(dev); |
10706 | if (tp->regs) { | 10692 | if (tp->regs) { |
10707 | iounmap(tp->regs); | 10693 | iounmap(tp->regs); |
10708 | tp->regs = 0; | 10694 | tp->regs = NULL; |
10709 | } | 10695 | } |
10710 | free_netdev(dev); | 10696 | free_netdev(dev); |
10711 | pci_release_regions(pdev); | 10697 | pci_release_regions(pdev); |
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 26cc4f6378c7..60d1e05ab732 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c | |||
@@ -117,7 +117,7 @@ static int xircom_open(struct net_device *dev); | |||
117 | static int xircom_close(struct net_device *dev); | 117 | static int xircom_close(struct net_device *dev); |
118 | static void xircom_up(struct xircom_private *card); | 118 | static void xircom_up(struct xircom_private *card); |
119 | static struct net_device_stats *xircom_get_stats(struct net_device *dev); | 119 | static struct net_device_stats *xircom_get_stats(struct net_device *dev); |
120 | #if CONFIG_NET_POLL_CONTROLLER | 120 | #ifdef CONFIG_NET_POLL_CONTROLLER |
121 | static void xircom_poll_controller(struct net_device *dev); | 121 | static void xircom_poll_controller(struct net_device *dev); |
122 | #endif | 122 | #endif |
123 | 123 | ||
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index 48c03c11cd9a..a01efa6d5c62 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c | |||
@@ -72,7 +72,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type, | |||
72 | } | 72 | } |
73 | skb_reserve(skb, 4); | 73 | skb_reserve(skb, 4); |
74 | cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0); | 74 | cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0); |
75 | data = (cisco_packet*)skb->data; | 75 | data = (cisco_packet*)(skb->data + 4); |
76 | 76 | ||
77 | data->type = htonl(type); | 77 | data->type = htonl(type); |
78 | data->par1 = htonl(par1); | 78 | data->par1 = htonl(par1); |
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 2be65d308fbe..06998c2240d9 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -6852,7 +6852,10 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
6852 | /* Add frequency */ | 6852 | /* Add frequency */ |
6853 | iwe.cmd = SIOCGIWFREQ; | 6853 | iwe.cmd = SIOCGIWFREQ; |
6854 | iwe.u.freq.m = le16_to_cpu(bss->dsChannel); | 6854 | iwe.u.freq.m = le16_to_cpu(bss->dsChannel); |
6855 | iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000; | 6855 | /* iwe.u.freq.m containt the channel (starting 1), our |
6856 | * frequency_list array start at index 0... | ||
6857 | */ | ||
6858 | iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000; | ||
6856 | iwe.u.freq.e = 1; | 6859 | iwe.u.freq.e = 1; |
6857 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); | 6860 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); |
6858 | 6861 | ||
diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index 8122fe734aa7..b1ba429e0a2d 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c | |||
@@ -558,7 +558,7 @@ static int configure_device (struct pci_func *func) | |||
558 | pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE); | 558 | pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE); |
559 | pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY); | 559 | pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY); |
560 | 560 | ||
561 | pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L); | 561 | pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L); |
562 | pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE); | 562 | pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE); |
563 | 563 | ||
564 | return 0; | 564 | return 0; |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 0e0947601526..898f6da6f0de 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -2526,7 +2526,6 @@ configure_new_function(struct controller *ctrl, struct pci_func *func, | |||
2526 | int cloop; | 2526 | int cloop; |
2527 | u8 temp_byte; | 2527 | u8 temp_byte; |
2528 | u8 class_code; | 2528 | u8 class_code; |
2529 | u16 temp_word; | ||
2530 | u32 rc; | 2529 | u32 rc; |
2531 | u32 temp_register; | 2530 | u32 temp_register; |
2532 | u32 base; | 2531 | u32 base; |
@@ -2682,8 +2681,7 @@ configure_new_function(struct controller *ctrl, struct pci_func *func, | |||
2682 | } /* End of base register loop */ | 2681 | } /* End of base register loop */ |
2683 | 2682 | ||
2684 | /* disable ROM base Address */ | 2683 | /* disable ROM base Address */ |
2685 | temp_word = 0x00L; | 2684 | rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00); |
2686 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word); | ||
2687 | 2685 | ||
2688 | /* Set HP parameters (Cache Line Size, Latency Timer) */ | 2686 | /* Set HP parameters (Cache Line Size, Latency Timer) */ |
2689 | rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); | 2687 | rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); |
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 783b5abb0717..91c9903e621f 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
@@ -2824,8 +2824,7 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f | |||
2824 | } | 2824 | } |
2825 | #endif | 2825 | #endif |
2826 | /* Disable ROM base Address */ | 2826 | /* Disable ROM base Address */ |
2827 | temp_word = 0x00L; | 2827 | rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00); |
2828 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word); | ||
2829 | 2828 | ||
2830 | /* Set HP parameters (Cache Line Size, Latency Timer) */ | 2829 | /* Set HP parameters (Cache Line Size, Latency Timer) */ |
2831 | rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); | 2830 | rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 992db89adce7..259d247b7551 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -309,17 +309,25 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
309 | 309 | ||
310 | pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr); | 310 | pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr); |
311 | 311 | ||
312 | /* If we're in D3, force entire word to 0. | 312 | /* If we're (effectively) in D3, force entire word to 0. |
313 | * This doesn't affect PME_Status, disables PME_En, and | 313 | * This doesn't affect PME_Status, disables PME_En, and |
314 | * sets PowerState to 0. | 314 | * sets PowerState to 0. |
315 | */ | 315 | */ |
316 | if (dev->current_state >= PCI_D3hot) { | 316 | switch (dev->current_state) { |
317 | if (!(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) | 317 | case PCI_UNKNOWN: /* Boot-up */ |
318 | if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot | ||
319 | && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) | ||
318 | need_restore = 1; | 320 | need_restore = 1; |
321 | /* Fall-through: force to D0 */ | ||
322 | case PCI_D3hot: | ||
323 | case PCI_D3cold: | ||
324 | case PCI_POWER_ERROR: | ||
319 | pmcsr = 0; | 325 | pmcsr = 0; |
320 | } else { | 326 | break; |
327 | default: | ||
321 | pmcsr &= ~PCI_PM_CTRL_STATE_MASK; | 328 | pmcsr &= ~PCI_PM_CTRL_STATE_MASK; |
322 | pmcsr |= state; | 329 | pmcsr |= state; |
330 | break; | ||
323 | } | 331 | } |
324 | 332 | ||
325 | /* enter specified state */ | 333 | /* enter specified state */ |
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index f0997c36c9b7..ba4d78e5b121 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
@@ -1045,7 +1045,18 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i | |||
1045 | { | 1045 | { |
1046 | struct yenta_socket *socket; | 1046 | struct yenta_socket *socket; |
1047 | int ret; | 1047 | int ret; |
1048 | 1048 | ||
1049 | /* | ||
1050 | * If we failed to assign proper bus numbers for this cardbus | ||
1051 | * controller during PCI probe, its subordinate pci_bus is NULL. | ||
1052 | * Bail out if so. | ||
1053 | */ | ||
1054 | if (!dev->subordinate) { | ||
1055 | printk(KERN_ERR "Yenta: no bus associated with %s! " | ||
1056 | "(try 'pci=assign-busses')\n", pci_name(dev)); | ||
1057 | return -ENODEV; | ||
1058 | } | ||
1059 | |||
1049 | socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL); | 1060 | socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL); |
1050 | if (!socket) | 1061 | if (!socket) |
1051 | return -ENOMEM; | 1062 | return -ENOMEM; |
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index aac83ce6469c..a1c52a682191 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/cio/blacklist.c | 2 | * drivers/s390/cio/blacklist.c |
3 | * S/390 common I/O routines -- blacklisting of specific devices | 3 | * S/390 common I/O routines -- blacklisting of specific devices |
4 | * $Revision: 1.34 $ | 4 | * $Revision: 1.35 $ |
5 | * | 5 | * |
6 | * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, | 6 | * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, |
7 | * IBM Corporation | 7 | * IBM Corporation |
@@ -35,7 +35,7 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | /* 65536 bits to indicate if a devno is blacklisted or not */ | 37 | /* 65536 bits to indicate if a devno is blacklisted or not */ |
38 | #define __BL_DEV_WORDS (__MAX_SUBCHANNELS + (8*sizeof(long) - 1) / \ | 38 | #define __BL_DEV_WORDS ((__MAX_SUBCHANNELS + (8*sizeof(long) - 1)) / \ |
39 | (8*sizeof(long))) | 39 | (8*sizeof(long))) |
40 | static unsigned long bl_dev[__BL_DEV_WORDS]; | 40 | static unsigned long bl_dev[__BL_DEV_WORDS]; |
41 | typedef enum {add, free} range_action; | 41 | typedef enum {add, free} range_action; |
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c index 6aeef3bacc33..0cb47eca91f3 100644 --- a/drivers/s390/crypto/z90main.c +++ b/drivers/s390/crypto/z90main.c | |||
@@ -682,9 +682,6 @@ z90crypt_cleanup_module(void) | |||
682 | del_timer(&config_timer); | 682 | del_timer(&config_timer); |
683 | del_timer(&cleanup_timer); | 683 | del_timer(&cleanup_timer); |
684 | 684 | ||
685 | if (z90_device_work) | ||
686 | destroy_workqueue(z90_device_work); | ||
687 | |||
688 | destroy_z90crypt(); | 685 | destroy_z90crypt(); |
689 | 686 | ||
690 | PRINTKN("Unloaded.\n"); | 687 | PRINTKN("Unloaded.\n"); |
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 96ca863eaff2..0db4f57a6a95 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $ | 2 | * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $ |
3 | * | 3 | * |
4 | * CTC / ESCON network driver | 4 | * CTC / ESCON network driver |
5 | * | 5 | * |
@@ -37,10 +37,9 @@ | |||
37 | * along with this program; if not, write to the Free Software | 37 | * along with this program; if not, write to the Free Software |
38 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 38 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
39 | * | 39 | * |
40 | * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $ | 40 | * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $ |
41 | * | 41 | * |
42 | */ | 42 | */ |
43 | |||
44 | #undef DEBUG | 43 | #undef DEBUG |
45 | #include <linux/module.h> | 44 | #include <linux/module.h> |
46 | #include <linux/init.h> | 45 | #include <linux/init.h> |
@@ -135,7 +134,7 @@ static const char *dev_event_names[] = { | |||
135 | "TX down", | 134 | "TX down", |
136 | "Restart", | 135 | "Restart", |
137 | }; | 136 | }; |
138 | 137 | ||
139 | /** | 138 | /** |
140 | * Events of the channel statemachine | 139 | * Events of the channel statemachine |
141 | */ | 140 | */ |
@@ -249,7 +248,7 @@ static void | |||
249 | print_banner(void) | 248 | print_banner(void) |
250 | { | 249 | { |
251 | static int printed = 0; | 250 | static int printed = 0; |
252 | char vbuf[] = "$Revision: 1.74 $"; | 251 | char vbuf[] = "$Revision: 1.78 $"; |
253 | char *version = vbuf; | 252 | char *version = vbuf; |
254 | 253 | ||
255 | if (printed) | 254 | if (printed) |
@@ -334,7 +333,7 @@ static const char *ch_state_names[] = { | |||
334 | "Restarting", | 333 | "Restarting", |
335 | "Not operational", | 334 | "Not operational", |
336 | }; | 335 | }; |
337 | 336 | ||
338 | #ifdef DEBUG | 337 | #ifdef DEBUG |
339 | /** | 338 | /** |
340 | * Dump header and first 16 bytes of an sk_buff for debugging purposes. | 339 | * Dump header and first 16 bytes of an sk_buff for debugging purposes. |
@@ -671,7 +670,7 @@ static void | |||
671 | fsm_action_nop(fsm_instance * fi, int event, void *arg) | 670 | fsm_action_nop(fsm_instance * fi, int event, void *arg) |
672 | { | 671 | { |
673 | } | 672 | } |
674 | 673 | ||
675 | /** | 674 | /** |
676 | * Actions for channel - statemachines. | 675 | * Actions for channel - statemachines. |
677 | *****************************************************************************/ | 676 | *****************************************************************************/ |
@@ -1514,7 +1513,6 @@ ch_action_reinit(fsm_instance *fi, int event, void *arg) | |||
1514 | fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev); | 1513 | fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev); |
1515 | } | 1514 | } |
1516 | 1515 | ||
1517 | |||
1518 | /** | 1516 | /** |
1519 | * The statemachine for a channel. | 1517 | * The statemachine for a channel. |
1520 | */ | 1518 | */ |
@@ -1625,7 +1623,7 @@ static const fsm_node ch_fsm[] = { | |||
1625 | }; | 1623 | }; |
1626 | 1624 | ||
1627 | static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node); | 1625 | static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node); |
1628 | 1626 | ||
1629 | /** | 1627 | /** |
1630 | * Functions related to setup and device detection. | 1628 | * Functions related to setup and device detection. |
1631 | *****************************************************************************/ | 1629 | *****************************************************************************/ |
@@ -1976,7 +1974,7 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
1976 | fsm_event(ch->fsm, CH_EVENT_IRQ, ch); | 1974 | fsm_event(ch->fsm, CH_EVENT_IRQ, ch); |
1977 | 1975 | ||
1978 | } | 1976 | } |
1979 | 1977 | ||
1980 | /** | 1978 | /** |
1981 | * Actions for interface - statemachine. | 1979 | * Actions for interface - statemachine. |
1982 | *****************************************************************************/ | 1980 | *****************************************************************************/ |
@@ -2209,13 +2207,18 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
2209 | int rc = 0; | 2207 | int rc = 0; |
2210 | 2208 | ||
2211 | DBF_TEXT(trace, 5, __FUNCTION__); | 2209 | DBF_TEXT(trace, 5, __FUNCTION__); |
2210 | /* we need to acquire the lock for testing the state | ||
2211 | * otherwise we can have an IRQ changing the state to | ||
2212 | * TXIDLE after the test but before acquiring the lock. | ||
2213 | */ | ||
2214 | spin_lock_irqsave(&ch->collect_lock, saveflags); | ||
2212 | if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) { | 2215 | if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) { |
2213 | int l = skb->len + LL_HEADER_LENGTH; | 2216 | int l = skb->len + LL_HEADER_LENGTH; |
2214 | 2217 | ||
2215 | spin_lock_irqsave(&ch->collect_lock, saveflags); | 2218 | if (ch->collect_len + l > ch->max_bufsize - 2) { |
2216 | if (ch->collect_len + l > ch->max_bufsize - 2) | 2219 | spin_unlock_irqrestore(&ch->collect_lock, saveflags); |
2217 | rc = -EBUSY; | 2220 | return -EBUSY; |
2218 | else { | 2221 | } else { |
2219 | atomic_inc(&skb->users); | 2222 | atomic_inc(&skb->users); |
2220 | header.length = l; | 2223 | header.length = l; |
2221 | header.type = skb->protocol; | 2224 | header.type = skb->protocol; |
@@ -2231,7 +2234,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
2231 | int ccw_idx; | 2234 | int ccw_idx; |
2232 | struct sk_buff *nskb; | 2235 | struct sk_buff *nskb; |
2233 | unsigned long hi; | 2236 | unsigned long hi; |
2234 | 2237 | spin_unlock_irqrestore(&ch->collect_lock, saveflags); | |
2235 | /** | 2238 | /** |
2236 | * Protect skb against beeing free'd by upper | 2239 | * Protect skb against beeing free'd by upper |
2237 | * layers. | 2240 | * layers. |
@@ -2256,6 +2259,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
2256 | if (!nskb) { | 2259 | if (!nskb) { |
2257 | atomic_dec(&skb->users); | 2260 | atomic_dec(&skb->users); |
2258 | skb_pull(skb, LL_HEADER_LENGTH + 2); | 2261 | skb_pull(skb, LL_HEADER_LENGTH + 2); |
2262 | ctc_clear_busy(ch->netdev); | ||
2259 | return -ENOMEM; | 2263 | return -ENOMEM; |
2260 | } else { | 2264 | } else { |
2261 | memcpy(skb_put(nskb, skb->len), | 2265 | memcpy(skb_put(nskb, skb->len), |
@@ -2281,6 +2285,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
2281 | */ | 2285 | */ |
2282 | atomic_dec(&skb->users); | 2286 | atomic_dec(&skb->users); |
2283 | skb_pull(skb, LL_HEADER_LENGTH + 2); | 2287 | skb_pull(skb, LL_HEADER_LENGTH + 2); |
2288 | ctc_clear_busy(ch->netdev); | ||
2284 | return -EBUSY; | 2289 | return -EBUSY; |
2285 | } | 2290 | } |
2286 | 2291 | ||
@@ -2327,9 +2332,10 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
2327 | } | 2332 | } |
2328 | } | 2333 | } |
2329 | 2334 | ||
2335 | ctc_clear_busy(ch->netdev); | ||
2330 | return rc; | 2336 | return rc; |
2331 | } | 2337 | } |
2332 | 2338 | ||
2333 | /** | 2339 | /** |
2334 | * Interface API for upper network layers | 2340 | * Interface API for upper network layers |
2335 | *****************************************************************************/ | 2341 | *****************************************************************************/ |
@@ -2421,7 +2427,6 @@ ctc_tx(struct sk_buff *skb, struct net_device * dev) | |||
2421 | dev->trans_start = jiffies; | 2427 | dev->trans_start = jiffies; |
2422 | if (transmit_skb(privptr->channel[WRITE], skb) != 0) | 2428 | if (transmit_skb(privptr->channel[WRITE], skb) != 0) |
2423 | rc = 1; | 2429 | rc = 1; |
2424 | ctc_clear_busy(dev); | ||
2425 | return rc; | 2430 | return rc; |
2426 | } | 2431 | } |
2427 | 2432 | ||
@@ -2610,7 +2615,6 @@ stats_write(struct device *dev, struct device_attribute *attr, const char *buf, | |||
2610 | return count; | 2615 | return count; |
2611 | } | 2616 | } |
2612 | 2617 | ||
2613 | |||
2614 | static void | 2618 | static void |
2615 | ctc_netdev_unregister(struct net_device * dev) | 2619 | ctc_netdev_unregister(struct net_device * dev) |
2616 | { | 2620 | { |
@@ -2685,7 +2689,6 @@ ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *b | |||
2685 | return count; | 2689 | return count; |
2686 | } | 2690 | } |
2687 | 2691 | ||
2688 | |||
2689 | static ssize_t | 2692 | static ssize_t |
2690 | ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf) | 2693 | ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf) |
2691 | { | 2694 | { |
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 3a0285669adf..2ad4797ce024 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #include "qeth_mpc.h" | 25 | #include "qeth_mpc.h" |
26 | 26 | ||
27 | #define VERSION_QETH_H "$Revision: 1.139 $" | 27 | #define VERSION_QETH_H "$Revision: 1.142 $" |
28 | 28 | ||
29 | #ifdef CONFIG_QETH_IPV6 | 29 | #ifdef CONFIG_QETH_IPV6 |
30 | #define QETH_VERSION_IPV6 ":IPv6" | 30 | #define QETH_VERSION_IPV6 ":IPv6" |
@@ -1172,7 +1172,7 @@ extern int | |||
1172 | qeth_realloc_buffer_pool(struct qeth_card *, int); | 1172 | qeth_realloc_buffer_pool(struct qeth_card *, int); |
1173 | 1173 | ||
1174 | extern int | 1174 | extern int |
1175 | qeth_set_large_send(struct qeth_card *); | 1175 | qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types); |
1176 | 1176 | ||
1177 | extern void | 1177 | extern void |
1178 | qeth_fill_header(struct qeth_card *, struct qeth_hdr *, | 1178 | qeth_fill_header(struct qeth_card *, struct qeth_hdr *, |
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 79c74f3a11f5..86582cf1e19e 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $) | 3 | * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $) |
4 | * | 4 | * |
5 | * Linux on zSeries OSA Express and HiperSockets support | 5 | * Linux on zSeries OSA Express and HiperSockets support |
6 | * | 6 | * |
@@ -12,7 +12,7 @@ | |||
12 | * Frank Pavlic (pavlic@de.ibm.com) and | 12 | * Frank Pavlic (pavlic@de.ibm.com) and |
13 | * Thomas Spatzier <tspat@de.ibm.com> | 13 | * Thomas Spatzier <tspat@de.ibm.com> |
14 | * | 14 | * |
15 | * $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $ | 15 | * $Revision: 1.224 $ $Date: 2005/05/04 20:19:18 $ |
16 | * | 16 | * |
17 | * This program is free software; you can redistribute it and/or modify | 17 | * This program is free software; you can redistribute it and/or modify |
18 | * it under the terms of the GNU General Public License as published by | 18 | * it under the terms of the GNU General Public License as published by |
@@ -29,14 +29,6 @@ | |||
29 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 29 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
30 | */ | 30 | */ |
31 | 31 | ||
32 | /*** | ||
33 | * eye catcher; just for debugging purposes | ||
34 | */ | ||
35 | void volatile | ||
36 | qeth_eyecatcher(void) | ||
37 | { | ||
38 | return; | ||
39 | } | ||
40 | 32 | ||
41 | #include <linux/config.h> | 33 | #include <linux/config.h> |
42 | #include <linux/module.h> | 34 | #include <linux/module.h> |
@@ -80,7 +72,7 @@ qeth_eyecatcher(void) | |||
80 | #include "qeth_eddp.h" | 72 | #include "qeth_eddp.h" |
81 | #include "qeth_tso.h" | 73 | #include "qeth_tso.h" |
82 | 74 | ||
83 | #define VERSION_QETH_C "$Revision: 1.214 $" | 75 | #define VERSION_QETH_C "$Revision: 1.224 $" |
84 | static const char *version = "qeth S/390 OSA-Express driver"; | 76 | static const char *version = "qeth S/390 OSA-Express driver"; |
85 | 77 | ||
86 | /** | 78 | /** |
@@ -2759,11 +2751,9 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, | |||
2759 | queue->card->perf_stats.outbound_do_qdio_start_time; | 2751 | queue->card->perf_stats.outbound_do_qdio_start_time; |
2760 | #endif | 2752 | #endif |
2761 | if (rc){ | 2753 | if (rc){ |
2762 | QETH_DBF_SPRINTF(trace, 0, "qeth_flush_buffers: do_QDIO " | ||
2763 | "returned error (%i) on device %s.", | ||
2764 | rc, CARD_DDEV_ID(queue->card)); | ||
2765 | QETH_DBF_TEXT(trace, 2, "flushbuf"); | 2754 | QETH_DBF_TEXT(trace, 2, "flushbuf"); |
2766 | QETH_DBF_TEXT_(trace, 2, " err%d", rc); | 2755 | QETH_DBF_TEXT_(trace, 2, " err%d", rc); |
2756 | QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card)); | ||
2767 | queue->card->stats.tx_errors += count; | 2757 | queue->card->stats.tx_errors += count; |
2768 | /* this must not happen under normal circumstances. if it | 2758 | /* this must not happen under normal circumstances. if it |
2769 | * happens something is really wrong -> recover */ | 2759 | * happens something is really wrong -> recover */ |
@@ -2909,11 +2899,8 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, | |||
2909 | QETH_DBF_TEXT(trace, 6, "qdouhdl"); | 2899 | QETH_DBF_TEXT(trace, 6, "qdouhdl"); |
2910 | if (status & QDIO_STATUS_LOOK_FOR_ERROR) { | 2900 | if (status & QDIO_STATUS_LOOK_FOR_ERROR) { |
2911 | if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ | 2901 | if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ |
2912 | QETH_DBF_SPRINTF(trace, 2, "On device %s: " | 2902 | QETH_DBF_TEXT(trace, 2, "achkcond"); |
2913 | "received active check " | 2903 | QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card)); |
2914 | "condition (0x%08x).", | ||
2915 | CARD_BUS_ID(card), status); | ||
2916 | QETH_DBF_TEXT(trace, 2, "chkcond"); | ||
2917 | QETH_DBF_TEXT_(trace, 2, "%08x", status); | 2904 | QETH_DBF_TEXT_(trace, 2, "%08x", status); |
2918 | netif_stop_queue(card->dev); | 2905 | netif_stop_queue(card->dev); |
2919 | qeth_schedule_recovery(card); | 2906 | qeth_schedule_recovery(card); |
@@ -3356,26 +3343,32 @@ qeth_halt_channel(struct qeth_channel *channel) | |||
3356 | static int | 3343 | static int |
3357 | qeth_halt_channels(struct qeth_card *card) | 3344 | qeth_halt_channels(struct qeth_card *card) |
3358 | { | 3345 | { |
3359 | int rc = 0; | 3346 | int rc1 = 0, rc2=0, rc3 = 0; |
3360 | 3347 | ||
3361 | QETH_DBF_TEXT(trace,3,"haltchs"); | 3348 | QETH_DBF_TEXT(trace,3,"haltchs"); |
3362 | if ((rc = qeth_halt_channel(&card->read))) | 3349 | rc1 = qeth_halt_channel(&card->read); |
3363 | return rc; | 3350 | rc2 = qeth_halt_channel(&card->write); |
3364 | if ((rc = qeth_halt_channel(&card->write))) | 3351 | rc3 = qeth_halt_channel(&card->data); |
3365 | return rc; | 3352 | if (rc1) |
3366 | return qeth_halt_channel(&card->data); | 3353 | return rc1; |
3354 | if (rc2) | ||
3355 | return rc2; | ||
3356 | return rc3; | ||
3367 | } | 3357 | } |
3368 | static int | 3358 | static int |
3369 | qeth_clear_channels(struct qeth_card *card) | 3359 | qeth_clear_channels(struct qeth_card *card) |
3370 | { | 3360 | { |
3371 | int rc = 0; | 3361 | int rc1 = 0, rc2=0, rc3 = 0; |
3372 | 3362 | ||
3373 | QETH_DBF_TEXT(trace,3,"clearchs"); | 3363 | QETH_DBF_TEXT(trace,3,"clearchs"); |
3374 | if ((rc = qeth_clear_channel(&card->read))) | 3364 | rc1 = qeth_clear_channel(&card->read); |
3375 | return rc; | 3365 | rc2 = qeth_clear_channel(&card->write); |
3376 | if ((rc = qeth_clear_channel(&card->write))) | 3366 | rc3 = qeth_clear_channel(&card->data); |
3377 | return rc; | 3367 | if (rc1) |
3378 | return qeth_clear_channel(&card->data); | 3368 | return rc1; |
3369 | if (rc2) | ||
3370 | return rc2; | ||
3371 | return rc3; | ||
3379 | } | 3372 | } |
3380 | 3373 | ||
3381 | static int | 3374 | static int |
@@ -3445,23 +3438,23 @@ qeth_mpc_initialize(struct qeth_card *card) | |||
3445 | } | 3438 | } |
3446 | if ((rc = qeth_cm_enable(card))){ | 3439 | if ((rc = qeth_cm_enable(card))){ |
3447 | QETH_DBF_TEXT_(setup, 2, "2err%d", rc); | 3440 | QETH_DBF_TEXT_(setup, 2, "2err%d", rc); |
3448 | return rc; | 3441 | goto out_qdio; |
3449 | } | 3442 | } |
3450 | if ((rc = qeth_cm_setup(card))){ | 3443 | if ((rc = qeth_cm_setup(card))){ |
3451 | QETH_DBF_TEXT_(setup, 2, "3err%d", rc); | 3444 | QETH_DBF_TEXT_(setup, 2, "3err%d", rc); |
3452 | return rc; | 3445 | goto out_qdio; |
3453 | } | 3446 | } |
3454 | if ((rc = qeth_ulp_enable(card))){ | 3447 | if ((rc = qeth_ulp_enable(card))){ |
3455 | QETH_DBF_TEXT_(setup, 2, "4err%d", rc); | 3448 | QETH_DBF_TEXT_(setup, 2, "4err%d", rc); |
3456 | return rc; | 3449 | goto out_qdio; |
3457 | } | 3450 | } |
3458 | if ((rc = qeth_ulp_setup(card))){ | 3451 | if ((rc = qeth_ulp_setup(card))){ |
3459 | QETH_DBF_TEXT_(setup, 2, "5err%d", rc); | 3452 | QETH_DBF_TEXT_(setup, 2, "5err%d", rc); |
3460 | return rc; | 3453 | goto out_qdio; |
3461 | } | 3454 | } |
3462 | if ((rc = qeth_alloc_qdio_buffers(card))){ | 3455 | if ((rc = qeth_alloc_qdio_buffers(card))){ |
3463 | QETH_DBF_TEXT_(setup, 2, "5err%d", rc); | 3456 | QETH_DBF_TEXT_(setup, 2, "5err%d", rc); |
3464 | return rc; | 3457 | goto out_qdio; |
3465 | } | 3458 | } |
3466 | if ((rc = qeth_qdio_establish(card))){ | 3459 | if ((rc = qeth_qdio_establish(card))){ |
3467 | QETH_DBF_TEXT_(setup, 2, "6err%d", rc); | 3460 | QETH_DBF_TEXT_(setup, 2, "6err%d", rc); |
@@ -3795,12 +3788,16 @@ static inline int | |||
3795 | qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, | 3788 | qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, |
3796 | struct qeth_hdr **hdr, int ipv) | 3789 | struct qeth_hdr **hdr, int ipv) |
3797 | { | 3790 | { |
3791 | int rc; | ||
3798 | #ifdef CONFIG_QETH_VLAN | 3792 | #ifdef CONFIG_QETH_VLAN |
3799 | u16 *tag; | 3793 | u16 *tag; |
3800 | #endif | 3794 | #endif |
3801 | 3795 | ||
3802 | QETH_DBF_TEXT(trace, 6, "prepskb"); | 3796 | QETH_DBF_TEXT(trace, 6, "prepskb"); |
3803 | 3797 | ||
3798 | rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); | ||
3799 | if (rc) | ||
3800 | return rc; | ||
3804 | #ifdef CONFIG_QETH_VLAN | 3801 | #ifdef CONFIG_QETH_VLAN |
3805 | if (card->vlangrp && vlan_tx_tag_present(*skb) && | 3802 | if (card->vlangrp && vlan_tx_tag_present(*skb) && |
3806 | ((ipv == 6) || card->options.layer2) ) { | 3803 | ((ipv == 6) || card->options.layer2) ) { |
@@ -4251,7 +4248,8 @@ out: | |||
4251 | } | 4248 | } |
4252 | 4249 | ||
4253 | static inline int | 4250 | static inline int |
4254 | qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) | 4251 | qeth_get_elements_no(struct qeth_card *card, void *hdr, |
4252 | struct sk_buff *skb, int elems) | ||
4255 | { | 4253 | { |
4256 | int elements_needed = 0; | 4254 | int elements_needed = 0; |
4257 | 4255 | ||
@@ -4261,9 +4259,10 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) | |||
4261 | if (elements_needed == 0 ) | 4259 | if (elements_needed == 0 ) |
4262 | elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) | 4260 | elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) |
4263 | + skb->len) >> PAGE_SHIFT); | 4261 | + skb->len) >> PAGE_SHIFT); |
4264 | if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ | 4262 | if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){ |
4265 | PRINT_ERR("qeth_do_send_packet: invalid size of " | 4263 | PRINT_ERR("qeth_do_send_packet: invalid size of " |
4266 | "IP packet. Discarded."); | 4264 | "IP packet (Number=%d / Length=%d). Discarded.\n", |
4265 | (elements_needed+elems), skb->len); | ||
4267 | return 0; | 4266 | return 0; |
4268 | } | 4267 | } |
4269 | return elements_needed; | 4268 | return elements_needed; |
@@ -4275,7 +4274,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) | |||
4275 | int ipv = 0; | 4274 | int ipv = 0; |
4276 | int cast_type; | 4275 | int cast_type; |
4277 | struct qeth_qdio_out_q *queue; | 4276 | struct qeth_qdio_out_q *queue; |
4278 | struct qeth_hdr *hdr; | 4277 | struct qeth_hdr *hdr = NULL; |
4279 | int elements_needed = 0; | 4278 | int elements_needed = 0; |
4280 | enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; | 4279 | enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; |
4281 | struct qeth_eddp_context *ctx = NULL; | 4280 | struct qeth_eddp_context *ctx = NULL; |
@@ -4337,9 +4336,11 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) | |||
4337 | return -EINVAL; | 4336 | return -EINVAL; |
4338 | } | 4337 | } |
4339 | } else { | 4338 | } else { |
4340 | elements_needed += qeth_get_elements_no(card,(void*) hdr, skb); | 4339 | int elems = qeth_get_elements_no(card,(void*) hdr, skb, |
4341 | if (!elements_needed) | 4340 | elements_needed); |
4341 | if (!elems) | ||
4342 | return -EINVAL; | 4342 | return -EINVAL; |
4343 | elements_needed += elems; | ||
4343 | } | 4344 | } |
4344 | 4345 | ||
4345 | if (card->info.type != QETH_CARD_TYPE_IQD) | 4346 | if (card->info.type != QETH_CARD_TYPE_IQD) |
@@ -4504,7 +4505,11 @@ qeth_arp_set_no_entries(struct qeth_card *card, int no_entries) | |||
4504 | 4505 | ||
4505 | QETH_DBF_TEXT(trace,3,"arpstnoe"); | 4506 | QETH_DBF_TEXT(trace,3,"arpstnoe"); |
4506 | 4507 | ||
4507 | /* TODO: really not supported by GuestLAN? */ | 4508 | /* |
4509 | * currently GuestLAN only supports the ARP assist function | ||
4510 | * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES; | ||
4511 | * thus we say EOPNOTSUPP for this ARP function | ||
4512 | */ | ||
4508 | if (card->info.guestlan) | 4513 | if (card->info.guestlan) |
4509 | return -EOPNOTSUPP; | 4514 | return -EOPNOTSUPP; |
4510 | if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { | 4515 | if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { |
@@ -4681,14 +4686,6 @@ qeth_arp_query(struct qeth_card *card, char *udata) | |||
4681 | 4686 | ||
4682 | QETH_DBF_TEXT(trace,3,"arpquery"); | 4687 | QETH_DBF_TEXT(trace,3,"arpquery"); |
4683 | 4688 | ||
4684 | /* | ||
4685 | * currently GuestLAN does only deliver all zeros on query arp, | ||
4686 | * even though arp processing is supported (according to IPA supp. | ||
4687 | * funcs flags); since all zeros is no valueable information, | ||
4688 | * we say EOPNOTSUPP for all ARP functions | ||
4689 | */ | ||
4690 | /*if (card->info.guestlan) | ||
4691 | return -EOPNOTSUPP; */ | ||
4692 | if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ | 4689 | if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ |
4693 | IPA_ARP_PROCESSING)) { | 4690 | IPA_ARP_PROCESSING)) { |
4694 | PRINT_WARN("ARP processing not supported " | 4691 | PRINT_WARN("ARP processing not supported " |
@@ -4894,10 +4891,9 @@ qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry) | |||
4894 | QETH_DBF_TEXT(trace,3,"arpadent"); | 4891 | QETH_DBF_TEXT(trace,3,"arpadent"); |
4895 | 4892 | ||
4896 | /* | 4893 | /* |
4897 | * currently GuestLAN does only deliver all zeros on query arp, | 4894 | * currently GuestLAN only supports the ARP assist function |
4898 | * even though arp processing is supported (according to IPA supp. | 4895 | * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY; |
4899 | * funcs flags); since all zeros is no valueable information, | 4896 | * thus we say EOPNOTSUPP for this ARP function |
4900 | * we say EOPNOTSUPP for all ARP functions | ||
4901 | */ | 4897 | */ |
4902 | if (card->info.guestlan) | 4898 | if (card->info.guestlan) |
4903 | return -EOPNOTSUPP; | 4899 | return -EOPNOTSUPP; |
@@ -4937,10 +4933,9 @@ qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry | |||
4937 | QETH_DBF_TEXT(trace,3,"arprment"); | 4933 | QETH_DBF_TEXT(trace,3,"arprment"); |
4938 | 4934 | ||
4939 | /* | 4935 | /* |
4940 | * currently GuestLAN does only deliver all zeros on query arp, | 4936 | * currently GuestLAN only supports the ARP assist function |
4941 | * even though arp processing is supported (according to IPA supp. | 4937 | * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY; |
4942 | * funcs flags); since all zeros is no valueable information, | 4938 | * thus we say EOPNOTSUPP for this ARP function |
4943 | * we say EOPNOTSUPP for all ARP functions | ||
4944 | */ | 4939 | */ |
4945 | if (card->info.guestlan) | 4940 | if (card->info.guestlan) |
4946 | return -EOPNOTSUPP; | 4941 | return -EOPNOTSUPP; |
@@ -4978,11 +4973,10 @@ qeth_arp_flush_cache(struct qeth_card *card) | |||
4978 | QETH_DBF_TEXT(trace,3,"arpflush"); | 4973 | QETH_DBF_TEXT(trace,3,"arpflush"); |
4979 | 4974 | ||
4980 | /* | 4975 | /* |
4981 | * currently GuestLAN does only deliver all zeros on query arp, | 4976 | * currently GuestLAN only supports the ARP assist function |
4982 | * even though arp processing is supported (according to IPA supp. | 4977 | * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE; |
4983 | * funcs flags); since all zeros is no valueable information, | 4978 | * thus we say EOPNOTSUPP for this ARP function |
4984 | * we say EOPNOTSUPP for all ARP functions | 4979 | */ |
4985 | */ | ||
4986 | if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD)) | 4980 | if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD)) |
4987 | return -EOPNOTSUPP; | 4981 | return -EOPNOTSUPP; |
4988 | if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { | 4982 | if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { |
@@ -7038,14 +7032,16 @@ qeth_setrouting_v6(struct qeth_card *card) | |||
7038 | } | 7032 | } |
7039 | 7033 | ||
7040 | int | 7034 | int |
7041 | qeth_set_large_send(struct qeth_card *card) | 7035 | qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type) |
7042 | { | 7036 | { |
7043 | int rc = 0; | 7037 | int rc = 0; |
7044 | 7038 | ||
7045 | if (card->dev == NULL) | 7039 | if (card->dev == NULL) { |
7040 | card->options.large_send = type; | ||
7046 | return 0; | 7041 | return 0; |
7047 | 7042 | } | |
7048 | netif_stop_queue(card->dev); | 7043 | netif_stop_queue(card->dev); |
7044 | card->options.large_send = type; | ||
7049 | switch (card->options.large_send) { | 7045 | switch (card->options.large_send) { |
7050 | case QETH_LARGE_SEND_EDDP: | 7046 | case QETH_LARGE_SEND_EDDP: |
7051 | card->dev->features |= NETIF_F_TSO | NETIF_F_SG; | 7047 | card->dev->features |= NETIF_F_TSO | NETIF_F_SG; |
@@ -7066,7 +7062,6 @@ qeth_set_large_send(struct qeth_card *card) | |||
7066 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); | 7062 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); |
7067 | break; | 7063 | break; |
7068 | } | 7064 | } |
7069 | |||
7070 | netif_wake_queue(card->dev); | 7065 | netif_wake_queue(card->dev); |
7071 | return rc; | 7066 | return rc; |
7072 | } | 7067 | } |
@@ -8257,7 +8252,6 @@ qeth_init(void) | |||
8257 | { | 8252 | { |
8258 | int rc=0; | 8253 | int rc=0; |
8259 | 8254 | ||
8260 | qeth_eyecatcher(); | ||
8261 | PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n", | 8255 | PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n", |
8262 | version, VERSION_QETH_C, VERSION_QETH_H, | 8256 | version, VERSION_QETH_C, VERSION_QETH_H, |
8263 | VERSION_QETH_MPC_H, VERSION_QETH_MPC_C, | 8257 | VERSION_QETH_MPC_H, VERSION_QETH_MPC_C, |
@@ -8338,7 +8332,6 @@ again: | |||
8338 | printk("qeth: removed\n"); | 8332 | printk("qeth: removed\n"); |
8339 | } | 8333 | } |
8340 | 8334 | ||
8341 | EXPORT_SYMBOL(qeth_eyecatcher); | ||
8342 | module_init(qeth_init); | 8335 | module_init(qeth_init); |
8343 | module_exit(qeth_exit); | 8336 | module_exit(qeth_exit); |
8344 | MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>"); | 8337 | MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>"); |
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index 98bedb0cb387..dda105b73063 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.51 $) | 3 | * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.54 $) |
4 | * | 4 | * |
5 | * Linux on zSeries OSA Express and HiperSockets support | 5 | * Linux on zSeries OSA Express and HiperSockets support |
6 | * This file contains code related to sysfs. | 6 | * This file contains code related to sysfs. |
@@ -20,7 +20,7 @@ | |||
20 | #include "qeth_mpc.h" | 20 | #include "qeth_mpc.h" |
21 | #include "qeth_fs.h" | 21 | #include "qeth_fs.h" |
22 | 22 | ||
23 | const char *VERSION_QETH_SYS_C = "$Revision: 1.51 $"; | 23 | const char *VERSION_QETH_SYS_C = "$Revision: 1.54 $"; |
24 | 24 | ||
25 | /*****************************************************************************/ | 25 | /*****************************************************************************/ |
26 | /* */ | 26 | /* */ |
@@ -722,10 +722,13 @@ qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const c | |||
722 | 722 | ||
723 | if (!card) | 723 | if (!card) |
724 | return -EINVAL; | 724 | return -EINVAL; |
725 | if (card->info.type == QETH_CARD_TYPE_IQD) { | ||
726 | PRINT_WARN("Layer2 on Hipersockets is not supported! \n"); | ||
727 | return -EPERM; | ||
728 | } | ||
725 | 729 | ||
726 | if (((card->state != CARD_STATE_DOWN) && | 730 | if (((card->state != CARD_STATE_DOWN) && |
727 | (card->state != CARD_STATE_RECOVER)) || | 731 | (card->state != CARD_STATE_RECOVER))) |
728 | (card->info.type != QETH_CARD_TYPE_OSAE)) | ||
729 | return -EPERM; | 732 | return -EPERM; |
730 | 733 | ||
731 | i = simple_strtoul(buf, &tmp, 16); | 734 | i = simple_strtoul(buf, &tmp, 16); |
@@ -771,9 +774,7 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con | |||
771 | 774 | ||
772 | if (!card) | 775 | if (!card) |
773 | return -EINVAL; | 776 | return -EINVAL; |
774 | |||
775 | tmp = strsep((char **) &buf, "\n"); | 777 | tmp = strsep((char **) &buf, "\n"); |
776 | |||
777 | if (!strcmp(tmp, "no")){ | 778 | if (!strcmp(tmp, "no")){ |
778 | type = QETH_LARGE_SEND_NO; | 779 | type = QETH_LARGE_SEND_NO; |
779 | } else if (!strcmp(tmp, "EDDP")) { | 780 | } else if (!strcmp(tmp, "EDDP")) { |
@@ -786,10 +787,8 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con | |||
786 | } | 787 | } |
787 | if (card->options.large_send == type) | 788 | if (card->options.large_send == type) |
788 | return count; | 789 | return count; |
789 | card->options.large_send = type; | 790 | if ((rc = qeth_set_large_send(card, type))) |
790 | if ((rc = qeth_set_large_send(card))) | ||
791 | return rc; | 791 | return rc; |
792 | |||
793 | return count; | 792 | return count; |
794 | } | 793 | } |
795 | 794 | ||
diff --git a/drivers/s390/scsi/Makefile b/drivers/s390/scsi/Makefile index fc145307a7d4..d6a78f1a2f16 100644 --- a/drivers/s390/scsi/Makefile +++ b/drivers/s390/scsi/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \ | 5 | zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \ |
6 | zfcp_fsf.o zfcp_sysfs_adapter.o zfcp_sysfs_port.o \ | 6 | zfcp_fsf.o zfcp_dbf.o zfcp_sysfs_adapter.o zfcp_sysfs_port.o \ |
7 | zfcp_sysfs_unit.o zfcp_sysfs_driver.o | 7 | zfcp_sysfs_unit.o zfcp_sysfs_driver.o |
8 | 8 | ||
9 | obj-$(CONFIG_ZFCP) += zfcp.o | 9 | obj-$(CONFIG_ZFCP) += zfcp.o |
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index bfe3ba73bc0f..0b5087f7cabc 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -122,95 +122,6 @@ _zfcp_hex_dump(char *addr, int count) | |||
122 | 122 | ||
123 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER | 123 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER |
124 | 124 | ||
125 | static inline int | ||
126 | zfcp_fsf_req_is_scsi_cmnd(struct zfcp_fsf_req *fsf_req) | ||
127 | { | ||
128 | return ((fsf_req->fsf_command == FSF_QTCB_FCP_CMND) && | ||
129 | !(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)); | ||
130 | } | ||
131 | |||
132 | void | ||
133 | zfcp_cmd_dbf_event_fsf(const char *text, struct zfcp_fsf_req *fsf_req, | ||
134 | void *add_data, int add_length) | ||
135 | { | ||
136 | struct zfcp_adapter *adapter = fsf_req->adapter; | ||
137 | struct scsi_cmnd *scsi_cmnd; | ||
138 | int level = 3; | ||
139 | int i; | ||
140 | unsigned long flags; | ||
141 | |||
142 | spin_lock_irqsave(&adapter->dbf_lock, flags); | ||
143 | if (zfcp_fsf_req_is_scsi_cmnd(fsf_req)) { | ||
144 | scsi_cmnd = fsf_req->data.send_fcp_command_task.scsi_cmnd; | ||
145 | debug_text_event(adapter->cmd_dbf, level, "fsferror"); | ||
146 | debug_text_event(adapter->cmd_dbf, level, text); | ||
147 | debug_event(adapter->cmd_dbf, level, &fsf_req, | ||
148 | sizeof (unsigned long)); | ||
149 | debug_event(adapter->cmd_dbf, level, &fsf_req->seq_no, | ||
150 | sizeof (u32)); | ||
151 | debug_event(adapter->cmd_dbf, level, &scsi_cmnd, | ||
152 | sizeof (unsigned long)); | ||
153 | debug_event(adapter->cmd_dbf, level, &scsi_cmnd->cmnd, | ||
154 | min(ZFCP_CMD_DBF_LENGTH, (int)scsi_cmnd->cmd_len)); | ||
155 | for (i = 0; i < add_length; i += ZFCP_CMD_DBF_LENGTH) | ||
156 | debug_event(adapter->cmd_dbf, | ||
157 | level, | ||
158 | (char *) add_data + i, | ||
159 | min(ZFCP_CMD_DBF_LENGTH, add_length - i)); | ||
160 | } | ||
161 | spin_unlock_irqrestore(&adapter->dbf_lock, flags); | ||
162 | } | ||
163 | |||
164 | /* XXX additionally log unit if available */ | ||
165 | /* ---> introduce new parameter for unit, see 2.4 code */ | ||
166 | void | ||
167 | zfcp_cmd_dbf_event_scsi(const char *text, struct scsi_cmnd *scsi_cmnd) | ||
168 | { | ||
169 | struct zfcp_adapter *adapter; | ||
170 | union zfcp_req_data *req_data; | ||
171 | struct zfcp_fsf_req *fsf_req; | ||
172 | int level = ((host_byte(scsi_cmnd->result) != 0) ? 1 : 5); | ||
173 | unsigned long flags; | ||
174 | |||
175 | adapter = (struct zfcp_adapter *) scsi_cmnd->device->host->hostdata[0]; | ||
176 | req_data = (union zfcp_req_data *) scsi_cmnd->host_scribble; | ||
177 | fsf_req = (req_data ? req_data->send_fcp_command_task.fsf_req : NULL); | ||
178 | spin_lock_irqsave(&adapter->dbf_lock, flags); | ||
179 | debug_text_event(adapter->cmd_dbf, level, "hostbyte"); | ||
180 | debug_text_event(adapter->cmd_dbf, level, text); | ||
181 | debug_event(adapter->cmd_dbf, level, &scsi_cmnd->result, sizeof (u32)); | ||
182 | debug_event(adapter->cmd_dbf, level, &scsi_cmnd, | ||
183 | sizeof (unsigned long)); | ||
184 | debug_event(adapter->cmd_dbf, level, &scsi_cmnd->cmnd, | ||
185 | min(ZFCP_CMD_DBF_LENGTH, (int)scsi_cmnd->cmd_len)); | ||
186 | if (likely(fsf_req)) { | ||
187 | debug_event(adapter->cmd_dbf, level, &fsf_req, | ||
188 | sizeof (unsigned long)); | ||
189 | debug_event(adapter->cmd_dbf, level, &fsf_req->seq_no, | ||
190 | sizeof (u32)); | ||
191 | } else { | ||
192 | debug_text_event(adapter->cmd_dbf, level, ""); | ||
193 | debug_text_event(adapter->cmd_dbf, level, ""); | ||
194 | } | ||
195 | spin_unlock_irqrestore(&adapter->dbf_lock, flags); | ||
196 | } | ||
197 | |||
198 | void | ||
199 | zfcp_in_els_dbf_event(struct zfcp_adapter *adapter, const char *text, | ||
200 | struct fsf_status_read_buffer *status_buffer, int length) | ||
201 | { | ||
202 | int level = 1; | ||
203 | int i; | ||
204 | |||
205 | debug_text_event(adapter->in_els_dbf, level, text); | ||
206 | debug_event(adapter->in_els_dbf, level, &status_buffer->d_id, 8); | ||
207 | for (i = 0; i < length; i += ZFCP_IN_ELS_DBF_LENGTH) | ||
208 | debug_event(adapter->in_els_dbf, | ||
209 | level, | ||
210 | (char *) status_buffer->payload + i, | ||
211 | min(ZFCP_IN_ELS_DBF_LENGTH, length - i)); | ||
212 | } | ||
213 | |||
214 | /** | 125 | /** |
215 | * zfcp_device_setup - setup function | 126 | * zfcp_device_setup - setup function |
216 | * @str: pointer to parameter string | 127 | * @str: pointer to parameter string |
@@ -1017,81 +928,6 @@ zfcp_free_low_mem_buffers(struct zfcp_adapter *adapter) | |||
1017 | mempool_destroy(adapter->pool.data_gid_pn); | 928 | mempool_destroy(adapter->pool.data_gid_pn); |
1018 | } | 929 | } |
1019 | 930 | ||
1020 | /** | ||
1021 | * zfcp_adapter_debug_register - registers debug feature for an adapter | ||
1022 | * @adapter: pointer to adapter for which debug features should be registered | ||
1023 | * return: -ENOMEM on error, 0 otherwise | ||
1024 | */ | ||
1025 | int | ||
1026 | zfcp_adapter_debug_register(struct zfcp_adapter *adapter) | ||
1027 | { | ||
1028 | char dbf_name[20]; | ||
1029 | |||
1030 | /* debug feature area which records SCSI command failures (hostbyte) */ | ||
1031 | spin_lock_init(&adapter->dbf_lock); | ||
1032 | |||
1033 | sprintf(dbf_name, ZFCP_CMD_DBF_NAME "%s", | ||
1034 | zfcp_get_busid_by_adapter(adapter)); | ||
1035 | adapter->cmd_dbf = debug_register(dbf_name, ZFCP_CMD_DBF_INDEX, | ||
1036 | ZFCP_CMD_DBF_AREAS, | ||
1037 | ZFCP_CMD_DBF_LENGTH); | ||
1038 | debug_register_view(adapter->cmd_dbf, &debug_hex_ascii_view); | ||
1039 | debug_set_level(adapter->cmd_dbf, ZFCP_CMD_DBF_LEVEL); | ||
1040 | |||
1041 | /* debug feature area which records SCSI command aborts */ | ||
1042 | sprintf(dbf_name, ZFCP_ABORT_DBF_NAME "%s", | ||
1043 | zfcp_get_busid_by_adapter(adapter)); | ||
1044 | adapter->abort_dbf = debug_register(dbf_name, ZFCP_ABORT_DBF_INDEX, | ||
1045 | ZFCP_ABORT_DBF_AREAS, | ||
1046 | ZFCP_ABORT_DBF_LENGTH); | ||
1047 | debug_register_view(adapter->abort_dbf, &debug_hex_ascii_view); | ||
1048 | debug_set_level(adapter->abort_dbf, ZFCP_ABORT_DBF_LEVEL); | ||
1049 | |||
1050 | /* debug feature area which records incoming ELS commands */ | ||
1051 | sprintf(dbf_name, ZFCP_IN_ELS_DBF_NAME "%s", | ||
1052 | zfcp_get_busid_by_adapter(adapter)); | ||
1053 | adapter->in_els_dbf = debug_register(dbf_name, ZFCP_IN_ELS_DBF_INDEX, | ||
1054 | ZFCP_IN_ELS_DBF_AREAS, | ||
1055 | ZFCP_IN_ELS_DBF_LENGTH); | ||
1056 | debug_register_view(adapter->in_els_dbf, &debug_hex_ascii_view); | ||
1057 | debug_set_level(adapter->in_els_dbf, ZFCP_IN_ELS_DBF_LEVEL); | ||
1058 | |||
1059 | /* debug feature area which records erp events */ | ||
1060 | sprintf(dbf_name, ZFCP_ERP_DBF_NAME "%s", | ||
1061 | zfcp_get_busid_by_adapter(adapter)); | ||
1062 | adapter->erp_dbf = debug_register(dbf_name, ZFCP_ERP_DBF_INDEX, | ||
1063 | ZFCP_ERP_DBF_AREAS, | ||
1064 | ZFCP_ERP_DBF_LENGTH); | ||
1065 | debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view); | ||
1066 | debug_set_level(adapter->erp_dbf, ZFCP_ERP_DBF_LEVEL); | ||
1067 | |||
1068 | if (!(adapter->cmd_dbf && adapter->abort_dbf && | ||
1069 | adapter->in_els_dbf && adapter->erp_dbf)) { | ||
1070 | zfcp_adapter_debug_unregister(adapter); | ||
1071 | return -ENOMEM; | ||
1072 | } | ||
1073 | |||
1074 | return 0; | ||
1075 | |||
1076 | } | ||
1077 | |||
1078 | /** | ||
1079 | * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter | ||
1080 | * @adapter: pointer to adapter for which debug features should be unregistered | ||
1081 | */ | ||
1082 | void | ||
1083 | zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter) | ||
1084 | { | ||
1085 | debug_unregister(adapter->abort_dbf); | ||
1086 | debug_unregister(adapter->cmd_dbf); | ||
1087 | debug_unregister(adapter->erp_dbf); | ||
1088 | debug_unregister(adapter->in_els_dbf); | ||
1089 | adapter->abort_dbf = NULL; | ||
1090 | adapter->cmd_dbf = NULL; | ||
1091 | adapter->erp_dbf = NULL; | ||
1092 | adapter->in_els_dbf = NULL; | ||
1093 | } | ||
1094 | |||
1095 | void | 931 | void |
1096 | zfcp_dummy_release(struct device *dev) | 932 | zfcp_dummy_release(struct device *dev) |
1097 | { | 933 | { |
@@ -1462,10 +1298,6 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter, | |||
1462 | /* see FC-FS */ | 1298 | /* see FC-FS */ |
1463 | no_entries = (fcp_rscn_head->payload_len / 4); | 1299 | no_entries = (fcp_rscn_head->payload_len / 4); |
1464 | 1300 | ||
1465 | zfcp_in_els_dbf_event(adapter, "##rscn", status_buffer, | ||
1466 | fcp_rscn_head->payload_len); | ||
1467 | |||
1468 | debug_text_event(adapter->erp_dbf, 1, "unsol_els_rscn:"); | ||
1469 | for (i = 1; i < no_entries; i++) { | 1301 | for (i = 1; i < no_entries; i++) { |
1470 | /* skip head and start with 1st element */ | 1302 | /* skip head and start with 1st element */ |
1471 | fcp_rscn_element++; | 1303 | fcp_rscn_element++; |
@@ -1497,8 +1329,6 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter, | |||
1497 | (ZFCP_STATUS_PORT_DID_DID, &port->status)) { | 1329 | (ZFCP_STATUS_PORT_DID_DID, &port->status)) { |
1498 | ZFCP_LOG_INFO("incoming RSCN, trying to open " | 1330 | ZFCP_LOG_INFO("incoming RSCN, trying to open " |
1499 | "port 0x%016Lx\n", port->wwpn); | 1331 | "port 0x%016Lx\n", port->wwpn); |
1500 | debug_text_event(adapter->erp_dbf, 1, | ||
1501 | "unsol_els_rscnu:"); | ||
1502 | zfcp_erp_port_reopen(port, | 1332 | zfcp_erp_port_reopen(port, |
1503 | ZFCP_STATUS_COMMON_ERP_FAILED); | 1333 | ZFCP_STATUS_COMMON_ERP_FAILED); |
1504 | continue; | 1334 | continue; |
@@ -1524,8 +1354,6 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter, | |||
1524 | */ | 1354 | */ |
1525 | ZFCP_LOG_INFO("incoming RSCN, trying to open " | 1355 | ZFCP_LOG_INFO("incoming RSCN, trying to open " |
1526 | "port 0x%016Lx\n", port->wwpn); | 1356 | "port 0x%016Lx\n", port->wwpn); |
1527 | debug_text_event(adapter->erp_dbf, 1, | ||
1528 | "unsol_els_rscnk:"); | ||
1529 | zfcp_test_link(port); | 1357 | zfcp_test_link(port); |
1530 | } | 1358 | } |
1531 | } | 1359 | } |
@@ -1541,8 +1369,6 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter, | |||
1541 | struct zfcp_port *port; | 1369 | struct zfcp_port *port; |
1542 | unsigned long flags; | 1370 | unsigned long flags; |
1543 | 1371 | ||
1544 | zfcp_in_els_dbf_event(adapter, "##plogi", status_buffer, 28); | ||
1545 | |||
1546 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 1372 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
1547 | list_for_each_entry(port, &adapter->port_list_head, list) { | 1373 | list_for_each_entry(port, &adapter->port_list_head, list) { |
1548 | if (port->wwpn == (*(wwn_t *) & els_logi->nport_wwn)) | 1374 | if (port->wwpn == (*(wwn_t *) & els_logi->nport_wwn)) |
@@ -1556,8 +1382,6 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter, | |||
1556 | status_buffer->d_id, | 1382 | status_buffer->d_id, |
1557 | zfcp_get_busid_by_adapter(adapter)); | 1383 | zfcp_get_busid_by_adapter(adapter)); |
1558 | } else { | 1384 | } else { |
1559 | debug_text_event(adapter->erp_dbf, 1, "unsol_els_plogi:"); | ||
1560 | debug_event(adapter->erp_dbf, 1, &els_logi->nport_wwn, 8); | ||
1561 | zfcp_erp_port_forced_reopen(port, 0); | 1385 | zfcp_erp_port_forced_reopen(port, 0); |
1562 | } | 1386 | } |
1563 | } | 1387 | } |
@@ -1570,8 +1394,6 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter, | |||
1570 | struct zfcp_port *port; | 1394 | struct zfcp_port *port; |
1571 | unsigned long flags; | 1395 | unsigned long flags; |
1572 | 1396 | ||
1573 | zfcp_in_els_dbf_event(adapter, "##logo", status_buffer, 16); | ||
1574 | |||
1575 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 1397 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
1576 | list_for_each_entry(port, &adapter->port_list_head, list) { | 1398 | list_for_each_entry(port, &adapter->port_list_head, list) { |
1577 | if (port->wwpn == els_logo->nport_wwpn) | 1399 | if (port->wwpn == els_logo->nport_wwpn) |
@@ -1585,8 +1407,6 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter, | |||
1585 | status_buffer->d_id, | 1407 | status_buffer->d_id, |
1586 | zfcp_get_busid_by_adapter(adapter)); | 1408 | zfcp_get_busid_by_adapter(adapter)); |
1587 | } else { | 1409 | } else { |
1588 | debug_text_event(adapter->erp_dbf, 1, "unsol_els_logo:"); | ||
1589 | debug_event(adapter->erp_dbf, 1, &els_logo->nport_wwpn, 8); | ||
1590 | zfcp_erp_port_forced_reopen(port, 0); | 1410 | zfcp_erp_port_forced_reopen(port, 0); |
1591 | } | 1411 | } |
1592 | } | 1412 | } |
@@ -1595,7 +1415,6 @@ static void | |||
1595 | zfcp_fsf_incoming_els_unknown(struct zfcp_adapter *adapter, | 1415 | zfcp_fsf_incoming_els_unknown(struct zfcp_adapter *adapter, |
1596 | struct fsf_status_read_buffer *status_buffer) | 1416 | struct fsf_status_read_buffer *status_buffer) |
1597 | { | 1417 | { |
1598 | zfcp_in_els_dbf_event(adapter, "##undef", status_buffer, 24); | ||
1599 | ZFCP_LOG_NORMAL("warning: unknown incoming ELS 0x%08x " | 1418 | ZFCP_LOG_NORMAL("warning: unknown incoming ELS 0x%08x " |
1600 | "for adapter %s\n", *(u32 *) (status_buffer->payload), | 1419 | "for adapter %s\n", *(u32 *) (status_buffer->payload), |
1601 | zfcp_get_busid_by_adapter(adapter)); | 1420 | zfcp_get_busid_by_adapter(adapter)); |
@@ -1609,10 +1428,11 @@ zfcp_fsf_incoming_els(struct zfcp_fsf_req *fsf_req) | |||
1609 | u32 els_type; | 1428 | u32 els_type; |
1610 | struct zfcp_adapter *adapter; | 1429 | struct zfcp_adapter *adapter; |
1611 | 1430 | ||
1612 | status_buffer = fsf_req->data.status_read.buffer; | 1431 | status_buffer = (struct fsf_status_read_buffer *) fsf_req->data; |
1613 | els_type = *(u32 *) (status_buffer->payload); | 1432 | els_type = *(u32 *) (status_buffer->payload); |
1614 | adapter = fsf_req->adapter; | 1433 | adapter = fsf_req->adapter; |
1615 | 1434 | ||
1435 | zfcp_san_dbf_event_incoming_els(fsf_req); | ||
1616 | if (els_type == LS_PLOGI) | 1436 | if (els_type == LS_PLOGI) |
1617 | zfcp_fsf_incoming_els_plogi(adapter, status_buffer); | 1437 | zfcp_fsf_incoming_els_plogi(adapter, status_buffer); |
1618 | else if (els_type == LS_LOGO) | 1438 | else if (els_type == LS_LOGO) |
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index b30abab77da3..0fc46381fc22 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -202,19 +202,9 @@ static int | |||
202 | zfcp_ccw_set_offline(struct ccw_device *ccw_device) | 202 | zfcp_ccw_set_offline(struct ccw_device *ccw_device) |
203 | { | 203 | { |
204 | struct zfcp_adapter *adapter; | 204 | struct zfcp_adapter *adapter; |
205 | struct zfcp_port *port; | ||
206 | struct fc_rport *rport; | ||
207 | 205 | ||
208 | down(&zfcp_data.config_sema); | 206 | down(&zfcp_data.config_sema); |
209 | adapter = dev_get_drvdata(&ccw_device->dev); | 207 | adapter = dev_get_drvdata(&ccw_device->dev); |
210 | /* might be racy, but we cannot take config_lock due to the fact that | ||
211 | fc_remote_port_delete might sleep */ | ||
212 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
213 | if (port->rport) { | ||
214 | rport = port->rport; | ||
215 | port->rport = NULL; | ||
216 | fc_remote_port_delete(rport); | ||
217 | } | ||
218 | zfcp_erp_adapter_shutdown(adapter, 0); | 208 | zfcp_erp_adapter_shutdown(adapter, 0); |
219 | zfcp_erp_wait(adapter); | 209 | zfcp_erp_wait(adapter); |
220 | zfcp_adapter_scsi_unregister(adapter); | 210 | zfcp_adapter_scsi_unregister(adapter); |
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c new file mode 100644 index 000000000000..826fb3b00605 --- /dev/null +++ b/drivers/s390/scsi/zfcp_dbf.c | |||
@@ -0,0 +1,995 @@ | |||
1 | /* | ||
2 | * | ||
3 | * linux/drivers/s390/scsi/zfcp_dbf.c | ||
4 | * | ||
5 | * FCP adapter driver for IBM eServer zSeries | ||
6 | * | ||
7 | * Debugging facilities | ||
8 | * | ||
9 | * (C) Copyright IBM Corp. 2005 | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2, or (at your option) | ||
14 | * any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | #define ZFCP_DBF_REVISION "$Revision$" | ||
27 | |||
28 | #include <asm/debug.h> | ||
29 | #include <linux/ctype.h> | ||
30 | #include "zfcp_ext.h" | ||
31 | |||
32 | static u32 dbfsize = 4; | ||
33 | |||
34 | module_param(dbfsize, uint, 0400); | ||
35 | MODULE_PARM_DESC(dbfsize, | ||
36 | "number of pages for each debug feature area (default 4)"); | ||
37 | |||
38 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER | ||
39 | |||
40 | static inline int | ||
41 | zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck) | ||
42 | { | ||
43 | unsigned long long sec; | ||
44 | struct timespec xtime; | ||
45 | int len = 0; | ||
46 | |||
47 | stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096); | ||
48 | sec = stck >> 12; | ||
49 | do_div(sec, 1000000); | ||
50 | xtime.tv_sec = sec; | ||
51 | stck -= (sec * 1000000) << 12; | ||
52 | xtime.tv_nsec = ((stck * 1000) >> 12); | ||
53 | len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n", | ||
54 | label, xtime.tv_sec, xtime.tv_nsec); | ||
55 | |||
56 | return len; | ||
57 | } | ||
58 | |||
59 | static int zfcp_dbf_tag(char *out_buf, const char *label, const char *tag) | ||
60 | { | ||
61 | int len = 0, i; | ||
62 | |||
63 | len += sprintf(out_buf + len, "%-24s", label); | ||
64 | for (i = 0; i < ZFCP_DBF_TAG_SIZE; i++) | ||
65 | len += sprintf(out_buf + len, "%c", tag[i]); | ||
66 | len += sprintf(out_buf + len, "\n"); | ||
67 | |||
68 | return len; | ||
69 | } | ||
70 | |||
71 | static int | ||
72 | zfcp_dbf_view(char *out_buf, const char *label, const char *format, ...) | ||
73 | { | ||
74 | va_list arg; | ||
75 | int len = 0; | ||
76 | |||
77 | len += sprintf(out_buf + len, "%-24s", label); | ||
78 | va_start(arg, format); | ||
79 | len += vsprintf(out_buf + len, format, arg); | ||
80 | va_end(arg); | ||
81 | len += sprintf(out_buf + len, "\n"); | ||
82 | |||
83 | return len; | ||
84 | } | ||
85 | |||
86 | static int | ||
87 | zfcp_dbf_view_dump(char *out_buf, const char *label, | ||
88 | char *buffer, int buflen, int offset, int total_size) | ||
89 | { | ||
90 | int len = 0; | ||
91 | |||
92 | if (offset == 0) | ||
93 | len += sprintf(out_buf + len, "%-24s ", label); | ||
94 | |||
95 | while (buflen--) { | ||
96 | if (offset > 0) { | ||
97 | if ((offset % 32) == 0) | ||
98 | len += sprintf(out_buf + len, "\n%-24c ", ' '); | ||
99 | else if ((offset % 4) == 0) | ||
100 | len += sprintf(out_buf + len, " "); | ||
101 | } | ||
102 | len += sprintf(out_buf + len, "%02x", *buffer++); | ||
103 | if (++offset == total_size) { | ||
104 | len += sprintf(out_buf + len, "\n"); | ||
105 | break; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | if (total_size == 0) | ||
110 | len += sprintf(out_buf + len, "\n"); | ||
111 | |||
112 | return len; | ||
113 | } | ||
114 | |||
115 | static inline int | ||
116 | zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area, | ||
117 | debug_entry_t * entry, char *out_buf) | ||
118 | { | ||
119 | struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)DEBUG_DATA(entry); | ||
120 | int len = 0; | ||
121 | |||
122 | if (strncmp(dump->tag, "dump", ZFCP_DBF_TAG_SIZE) != 0) { | ||
123 | len += zfcp_dbf_stck(out_buf + len, "timestamp", | ||
124 | entry->id.stck); | ||
125 | len += zfcp_dbf_view(out_buf + len, "cpu", "%02i", | ||
126 | entry->id.fields.cpuid); | ||
127 | } else { | ||
128 | len += zfcp_dbf_view_dump(out_buf + len, NULL, | ||
129 | dump->data, | ||
130 | dump->size, | ||
131 | dump->offset, dump->total_size); | ||
132 | if ((dump->offset + dump->size) == dump->total_size) | ||
133 | len += sprintf(out_buf + len, "\n"); | ||
134 | } | ||
135 | |||
136 | return len; | ||
137 | } | ||
138 | |||
139 | inline void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req) | ||
140 | { | ||
141 | struct zfcp_adapter *adapter = fsf_req->adapter; | ||
142 | struct fsf_qtcb *qtcb = fsf_req->qtcb; | ||
143 | union fsf_prot_status_qual *prot_status_qual = | ||
144 | &qtcb->prefix.prot_status_qual; | ||
145 | union fsf_status_qual *fsf_status_qual = &qtcb->header.fsf_status_qual; | ||
146 | struct scsi_cmnd *scsi_cmnd; | ||
147 | struct zfcp_port *port; | ||
148 | struct zfcp_unit *unit; | ||
149 | struct zfcp_send_els *send_els; | ||
150 | struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf; | ||
151 | struct zfcp_hba_dbf_record_response *response = &rec->type.response; | ||
152 | int level; | ||
153 | unsigned long flags; | ||
154 | |||
155 | spin_lock_irqsave(&adapter->hba_dbf_lock, flags); | ||
156 | memset(rec, 0, sizeof(struct zfcp_hba_dbf_record)); | ||
157 | strncpy(rec->tag, "resp", ZFCP_DBF_TAG_SIZE); | ||
158 | |||
159 | if ((qtcb->prefix.prot_status != FSF_PROT_GOOD) && | ||
160 | (qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) { | ||
161 | strncpy(rec->tag2, "perr", ZFCP_DBF_TAG_SIZE); | ||
162 | level = 1; | ||
163 | } else if (qtcb->header.fsf_status != FSF_GOOD) { | ||
164 | strncpy(rec->tag2, "ferr", ZFCP_DBF_TAG_SIZE); | ||
165 | level = 1; | ||
166 | } else if ((fsf_req->fsf_command == FSF_QTCB_OPEN_PORT_WITH_DID) || | ||
167 | (fsf_req->fsf_command == FSF_QTCB_OPEN_LUN)) { | ||
168 | strncpy(rec->tag2, "open", ZFCP_DBF_TAG_SIZE); | ||
169 | level = 4; | ||
170 | } else if ((prot_status_qual->doubleword[0] != 0) || | ||
171 | (prot_status_qual->doubleword[1] != 0) || | ||
172 | (fsf_status_qual->doubleword[0] != 0) || | ||
173 | (fsf_status_qual->doubleword[1] != 0)) { | ||
174 | strncpy(rec->tag2, "qual", ZFCP_DBF_TAG_SIZE); | ||
175 | level = 3; | ||
176 | } else { | ||
177 | strncpy(rec->tag2, "norm", ZFCP_DBF_TAG_SIZE); | ||
178 | level = 6; | ||
179 | } | ||
180 | |||
181 | response->fsf_command = fsf_req->fsf_command; | ||
182 | response->fsf_reqid = (unsigned long)fsf_req; | ||
183 | response->fsf_seqno = fsf_req->seq_no; | ||
184 | response->fsf_issued = fsf_req->issued; | ||
185 | response->fsf_prot_status = qtcb->prefix.prot_status; | ||
186 | response->fsf_status = qtcb->header.fsf_status; | ||
187 | memcpy(response->fsf_prot_status_qual, | ||
188 | prot_status_qual, FSF_PROT_STATUS_QUAL_SIZE); | ||
189 | memcpy(response->fsf_status_qual, | ||
190 | fsf_status_qual, FSF_STATUS_QUALIFIER_SIZE); | ||
191 | response->fsf_req_status = fsf_req->status; | ||
192 | response->sbal_first = fsf_req->sbal_first; | ||
193 | response->sbal_curr = fsf_req->sbal_curr; | ||
194 | response->sbal_last = fsf_req->sbal_last; | ||
195 | response->pool = fsf_req->pool != NULL; | ||
196 | response->erp_action = (unsigned long)fsf_req->erp_action; | ||
197 | |||
198 | switch (fsf_req->fsf_command) { | ||
199 | case FSF_QTCB_FCP_CMND: | ||
200 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) | ||
201 | break; | ||
202 | scsi_cmnd = (struct scsi_cmnd *)fsf_req->data; | ||
203 | if (scsi_cmnd != NULL) { | ||
204 | response->data.send_fcp.scsi_cmnd | ||
205 | = (unsigned long)scsi_cmnd; | ||
206 | response->data.send_fcp.scsi_serial | ||
207 | = scsi_cmnd->serial_number; | ||
208 | } | ||
209 | break; | ||
210 | |||
211 | case FSF_QTCB_OPEN_PORT_WITH_DID: | ||
212 | case FSF_QTCB_CLOSE_PORT: | ||
213 | case FSF_QTCB_CLOSE_PHYSICAL_PORT: | ||
214 | port = (struct zfcp_port *)fsf_req->data; | ||
215 | response->data.port.wwpn = port->wwpn; | ||
216 | response->data.port.d_id = port->d_id; | ||
217 | response->data.port.port_handle = qtcb->header.port_handle; | ||
218 | break; | ||
219 | |||
220 | case FSF_QTCB_OPEN_LUN: | ||
221 | case FSF_QTCB_CLOSE_LUN: | ||
222 | unit = (struct zfcp_unit *)fsf_req->data; | ||
223 | port = unit->port; | ||
224 | response->data.unit.wwpn = port->wwpn; | ||
225 | response->data.unit.fcp_lun = unit->fcp_lun; | ||
226 | response->data.unit.port_handle = qtcb->header.port_handle; | ||
227 | response->data.unit.lun_handle = qtcb->header.lun_handle; | ||
228 | break; | ||
229 | |||
230 | case FSF_QTCB_SEND_ELS: | ||
231 | send_els = (struct zfcp_send_els *)fsf_req->data; | ||
232 | response->data.send_els.d_id = qtcb->bottom.support.d_id; | ||
233 | response->data.send_els.ls_code = send_els->ls_code >> 24; | ||
234 | break; | ||
235 | |||
236 | case FSF_QTCB_ABORT_FCP_CMND: | ||
237 | case FSF_QTCB_SEND_GENERIC: | ||
238 | case FSF_QTCB_EXCHANGE_CONFIG_DATA: | ||
239 | case FSF_QTCB_EXCHANGE_PORT_DATA: | ||
240 | case FSF_QTCB_DOWNLOAD_CONTROL_FILE: | ||
241 | case FSF_QTCB_UPLOAD_CONTROL_FILE: | ||
242 | break; | ||
243 | } | ||
244 | |||
245 | debug_event(adapter->hba_dbf, level, | ||
246 | rec, sizeof(struct zfcp_hba_dbf_record)); | ||
247 | spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); | ||
248 | } | ||
249 | |||
250 | inline void | ||
251 | zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter, | ||
252 | struct fsf_status_read_buffer *status_buffer) | ||
253 | { | ||
254 | struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf; | ||
255 | unsigned long flags; | ||
256 | |||
257 | spin_lock_irqsave(&adapter->hba_dbf_lock, flags); | ||
258 | memset(rec, 0, sizeof(struct zfcp_hba_dbf_record)); | ||
259 | strncpy(rec->tag, "stat", ZFCP_DBF_TAG_SIZE); | ||
260 | strncpy(rec->tag2, tag, ZFCP_DBF_TAG_SIZE); | ||
261 | |||
262 | rec->type.status.failed = adapter->status_read_failed; | ||
263 | if (status_buffer != NULL) { | ||
264 | rec->type.status.status_type = status_buffer->status_type; | ||
265 | rec->type.status.status_subtype = status_buffer->status_subtype; | ||
266 | memcpy(&rec->type.status.queue_designator, | ||
267 | &status_buffer->queue_designator, | ||
268 | sizeof(struct fsf_queue_designator)); | ||
269 | |||
270 | switch (status_buffer->status_type) { | ||
271 | case FSF_STATUS_READ_SENSE_DATA_AVAIL: | ||
272 | rec->type.status.payload_size = | ||
273 | ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL; | ||
274 | break; | ||
275 | |||
276 | case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: | ||
277 | rec->type.status.payload_size = | ||
278 | ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD; | ||
279 | break; | ||
280 | |||
281 | case FSF_STATUS_READ_LINK_DOWN: | ||
282 | switch (status_buffer->status_subtype) { | ||
283 | case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: | ||
284 | case FSF_STATUS_READ_SUB_FDISC_FAILED: | ||
285 | rec->type.status.payload_size = | ||
286 | sizeof(struct fsf_link_down_info); | ||
287 | } | ||
288 | break; | ||
289 | |||
290 | case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: | ||
291 | rec->type.status.payload_size = | ||
292 | ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT; | ||
293 | break; | ||
294 | } | ||
295 | memcpy(&rec->type.status.payload, | ||
296 | &status_buffer->payload, rec->type.status.payload_size); | ||
297 | } | ||
298 | |||
299 | debug_event(adapter->hba_dbf, 2, | ||
300 | rec, sizeof(struct zfcp_hba_dbf_record)); | ||
301 | spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); | ||
302 | } | ||
303 | |||
304 | inline void | ||
305 | zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status, | ||
306 | unsigned int qdio_error, unsigned int siga_error, | ||
307 | int sbal_index, int sbal_count) | ||
308 | { | ||
309 | struct zfcp_hba_dbf_record *rec = &adapter->hba_dbf_buf; | ||
310 | unsigned long flags; | ||
311 | |||
312 | spin_lock_irqsave(&adapter->hba_dbf_lock, flags); | ||
313 | memset(rec, 0, sizeof(struct zfcp_hba_dbf_record)); | ||
314 | strncpy(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE); | ||
315 | rec->type.qdio.status = status; | ||
316 | rec->type.qdio.qdio_error = qdio_error; | ||
317 | rec->type.qdio.siga_error = siga_error; | ||
318 | rec->type.qdio.sbal_index = sbal_index; | ||
319 | rec->type.qdio.sbal_count = sbal_count; | ||
320 | debug_event(adapter->hba_dbf, 0, | ||
321 | rec, sizeof(struct zfcp_hba_dbf_record)); | ||
322 | spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); | ||
323 | } | ||
324 | |||
325 | static inline int | ||
326 | zfcp_hba_dbf_view_response(char *out_buf, | ||
327 | struct zfcp_hba_dbf_record_response *rec) | ||
328 | { | ||
329 | int len = 0; | ||
330 | |||
331 | len += zfcp_dbf_view(out_buf + len, "fsf_command", "0x%08x", | ||
332 | rec->fsf_command); | ||
333 | len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx", | ||
334 | rec->fsf_reqid); | ||
335 | len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x", | ||
336 | rec->fsf_seqno); | ||
337 | len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued); | ||
338 | len += zfcp_dbf_view(out_buf + len, "fsf_prot_status", "0x%08x", | ||
339 | rec->fsf_prot_status); | ||
340 | len += zfcp_dbf_view(out_buf + len, "fsf_status", "0x%08x", | ||
341 | rec->fsf_status); | ||
342 | len += zfcp_dbf_view_dump(out_buf + len, "fsf_prot_status_qual", | ||
343 | rec->fsf_prot_status_qual, | ||
344 | FSF_PROT_STATUS_QUAL_SIZE, | ||
345 | 0, FSF_PROT_STATUS_QUAL_SIZE); | ||
346 | len += zfcp_dbf_view_dump(out_buf + len, "fsf_status_qual", | ||
347 | rec->fsf_status_qual, | ||
348 | FSF_STATUS_QUALIFIER_SIZE, | ||
349 | 0, FSF_STATUS_QUALIFIER_SIZE); | ||
350 | len += zfcp_dbf_view(out_buf + len, "fsf_req_status", "0x%08x", | ||
351 | rec->fsf_req_status); | ||
352 | len += zfcp_dbf_view(out_buf + len, "sbal_first", "0x%02x", | ||
353 | rec->sbal_first); | ||
354 | len += zfcp_dbf_view(out_buf + len, "sbal_curr", "0x%02x", | ||
355 | rec->sbal_curr); | ||
356 | len += zfcp_dbf_view(out_buf + len, "sbal_last", "0x%02x", | ||
357 | rec->sbal_last); | ||
358 | len += zfcp_dbf_view(out_buf + len, "pool", "0x%02x", rec->pool); | ||
359 | |||
360 | switch (rec->fsf_command) { | ||
361 | case FSF_QTCB_FCP_CMND: | ||
362 | if (rec->fsf_req_status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT) | ||
363 | break; | ||
364 | len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx", | ||
365 | rec->data.send_fcp.scsi_cmnd); | ||
366 | len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx", | ||
367 | rec->data.send_fcp.scsi_serial); | ||
368 | break; | ||
369 | |||
370 | case FSF_QTCB_OPEN_PORT_WITH_DID: | ||
371 | case FSF_QTCB_CLOSE_PORT: | ||
372 | case FSF_QTCB_CLOSE_PHYSICAL_PORT: | ||
373 | len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx", | ||
374 | rec->data.port.wwpn); | ||
375 | len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x", | ||
376 | rec->data.port.d_id); | ||
377 | len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x", | ||
378 | rec->data.port.port_handle); | ||
379 | break; | ||
380 | |||
381 | case FSF_QTCB_OPEN_LUN: | ||
382 | case FSF_QTCB_CLOSE_LUN: | ||
383 | len += zfcp_dbf_view(out_buf + len, "wwpn", "0x%016Lx", | ||
384 | rec->data.unit.wwpn); | ||
385 | len += zfcp_dbf_view(out_buf + len, "fcp_lun", "0x%016Lx", | ||
386 | rec->data.unit.fcp_lun); | ||
387 | len += zfcp_dbf_view(out_buf + len, "port_handle", "0x%08x", | ||
388 | rec->data.unit.port_handle); | ||
389 | len += zfcp_dbf_view(out_buf + len, "lun_handle", "0x%08x", | ||
390 | rec->data.unit.lun_handle); | ||
391 | break; | ||
392 | |||
393 | case FSF_QTCB_SEND_ELS: | ||
394 | len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x", | ||
395 | rec->data.send_els.d_id); | ||
396 | len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x", | ||
397 | rec->data.send_els.ls_code); | ||
398 | break; | ||
399 | |||
400 | case FSF_QTCB_ABORT_FCP_CMND: | ||
401 | case FSF_QTCB_SEND_GENERIC: | ||
402 | case FSF_QTCB_EXCHANGE_CONFIG_DATA: | ||
403 | case FSF_QTCB_EXCHANGE_PORT_DATA: | ||
404 | case FSF_QTCB_DOWNLOAD_CONTROL_FILE: | ||
405 | case FSF_QTCB_UPLOAD_CONTROL_FILE: | ||
406 | break; | ||
407 | } | ||
408 | |||
409 | return len; | ||
410 | } | ||
411 | |||
412 | static inline int | ||
413 | zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec) | ||
414 | { | ||
415 | int len = 0; | ||
416 | |||
417 | len += zfcp_dbf_view(out_buf + len, "failed", "0x%02x", rec->failed); | ||
418 | len += zfcp_dbf_view(out_buf + len, "status_type", "0x%08x", | ||
419 | rec->status_type); | ||
420 | len += zfcp_dbf_view(out_buf + len, "status_subtype", "0x%08x", | ||
421 | rec->status_subtype); | ||
422 | len += zfcp_dbf_view_dump(out_buf + len, "queue_designator", | ||
423 | (char *)&rec->queue_designator, | ||
424 | sizeof(struct fsf_queue_designator), | ||
425 | 0, sizeof(struct fsf_queue_designator)); | ||
426 | len += zfcp_dbf_view_dump(out_buf + len, "payload", | ||
427 | (char *)&rec->payload, | ||
428 | rec->payload_size, 0, rec->payload_size); | ||
429 | |||
430 | return len; | ||
431 | } | ||
432 | |||
433 | static inline int | ||
434 | zfcp_hba_dbf_view_qdio(char *out_buf, struct zfcp_hba_dbf_record_qdio *rec) | ||
435 | { | ||
436 | int len = 0; | ||
437 | |||
438 | len += zfcp_dbf_view(out_buf + len, "status", "0x%08x", rec->status); | ||
439 | len += zfcp_dbf_view(out_buf + len, "qdio_error", "0x%08x", | ||
440 | rec->qdio_error); | ||
441 | len += zfcp_dbf_view(out_buf + len, "siga_error", "0x%08x", | ||
442 | rec->siga_error); | ||
443 | len += zfcp_dbf_view(out_buf + len, "sbal_index", "0x%02x", | ||
444 | rec->sbal_index); | ||
445 | len += zfcp_dbf_view(out_buf + len, "sbal_count", "0x%02x", | ||
446 | rec->sbal_count); | ||
447 | |||
448 | return len; | ||
449 | } | ||
450 | |||
451 | static int | ||
452 | zfcp_hba_dbf_view_format(debug_info_t * id, struct debug_view *view, | ||
453 | char *out_buf, const char *in_buf) | ||
454 | { | ||
455 | struct zfcp_hba_dbf_record *rec = (struct zfcp_hba_dbf_record *)in_buf; | ||
456 | int len = 0; | ||
457 | |||
458 | if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) | ||
459 | return 0; | ||
460 | |||
461 | len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag); | ||
462 | if (isalpha(rec->tag2[0])) | ||
463 | len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2); | ||
464 | if (strncmp(rec->tag, "resp", ZFCP_DBF_TAG_SIZE) == 0) | ||
465 | len += zfcp_hba_dbf_view_response(out_buf + len, | ||
466 | &rec->type.response); | ||
467 | else if (strncmp(rec->tag, "stat", ZFCP_DBF_TAG_SIZE) == 0) | ||
468 | len += zfcp_hba_dbf_view_status(out_buf + len, | ||
469 | &rec->type.status); | ||
470 | else if (strncmp(rec->tag, "qdio", ZFCP_DBF_TAG_SIZE) == 0) | ||
471 | len += zfcp_hba_dbf_view_qdio(out_buf + len, &rec->type.qdio); | ||
472 | |||
473 | len += sprintf(out_buf + len, "\n"); | ||
474 | |||
475 | return len; | ||
476 | } | ||
477 | |||
478 | struct debug_view zfcp_hba_dbf_view = { | ||
479 | "structured", | ||
480 | NULL, | ||
481 | &zfcp_dbf_view_header, | ||
482 | &zfcp_hba_dbf_view_format, | ||
483 | NULL, | ||
484 | NULL | ||
485 | }; | ||
486 | |||
487 | inline void | ||
488 | _zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req, | ||
489 | u32 s_id, u32 d_id, void *buffer, int buflen) | ||
490 | { | ||
491 | struct zfcp_send_ct *send_ct = (struct zfcp_send_ct *)fsf_req->data; | ||
492 | struct zfcp_port *port = send_ct->port; | ||
493 | struct zfcp_adapter *adapter = port->adapter; | ||
494 | struct ct_hdr *header = (struct ct_hdr *)buffer; | ||
495 | struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf; | ||
496 | struct zfcp_san_dbf_record_ct *ct = &rec->type.ct; | ||
497 | unsigned long flags; | ||
498 | |||
499 | spin_lock_irqsave(&adapter->san_dbf_lock, flags); | ||
500 | memset(rec, 0, sizeof(struct zfcp_san_dbf_record)); | ||
501 | strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE); | ||
502 | rec->fsf_reqid = (unsigned long)fsf_req; | ||
503 | rec->fsf_seqno = fsf_req->seq_no; | ||
504 | rec->s_id = s_id; | ||
505 | rec->d_id = d_id; | ||
506 | if (strncmp(tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) { | ||
507 | ct->type.request.cmd_req_code = header->cmd_rsp_code; | ||
508 | ct->type.request.revision = header->revision; | ||
509 | ct->type.request.gs_type = header->gs_type; | ||
510 | ct->type.request.gs_subtype = header->gs_subtype; | ||
511 | ct->type.request.options = header->options; | ||
512 | ct->type.request.max_res_size = header->max_res_size; | ||
513 | } else if (strncmp(tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) { | ||
514 | ct->type.response.cmd_rsp_code = header->cmd_rsp_code; | ||
515 | ct->type.response.revision = header->revision; | ||
516 | ct->type.response.reason_code = header->reason_code; | ||
517 | ct->type.response.reason_code_expl = header->reason_code_expl; | ||
518 | ct->type.response.vendor_unique = header->vendor_unique; | ||
519 | } | ||
520 | ct->payload_size = | ||
521 | min(buflen - (int)sizeof(struct ct_hdr), ZFCP_DBF_CT_PAYLOAD); | ||
522 | memcpy(ct->payload, buffer + sizeof(struct ct_hdr), ct->payload_size); | ||
523 | debug_event(adapter->san_dbf, 3, | ||
524 | rec, sizeof(struct zfcp_san_dbf_record)); | ||
525 | spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); | ||
526 | } | ||
527 | |||
528 | inline void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) | ||
529 | { | ||
530 | struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; | ||
531 | struct zfcp_port *port = ct->port; | ||
532 | struct zfcp_adapter *adapter = port->adapter; | ||
533 | |||
534 | _zfcp_san_dbf_event_common_ct("octc", fsf_req, | ||
535 | fc_host_port_id(adapter->scsi_host), | ||
536 | port->d_id, zfcp_sg_to_address(ct->req), | ||
537 | ct->req->length); | ||
538 | } | ||
539 | |||
540 | inline void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) | ||
541 | { | ||
542 | struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; | ||
543 | struct zfcp_port *port = ct->port; | ||
544 | struct zfcp_adapter *adapter = port->adapter; | ||
545 | |||
546 | _zfcp_san_dbf_event_common_ct("rctc", fsf_req, port->d_id, | ||
547 | fc_host_port_id(adapter->scsi_host), | ||
548 | zfcp_sg_to_address(ct->resp), | ||
549 | ct->resp->length); | ||
550 | } | ||
551 | |||
552 | static inline void | ||
553 | _zfcp_san_dbf_event_common_els(const char *tag, int level, | ||
554 | struct zfcp_fsf_req *fsf_req, u32 s_id, | ||
555 | u32 d_id, u8 ls_code, void *buffer, int buflen) | ||
556 | { | ||
557 | struct zfcp_adapter *adapter = fsf_req->adapter; | ||
558 | struct zfcp_san_dbf_record *rec = &adapter->san_dbf_buf; | ||
559 | struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec; | ||
560 | unsigned long flags; | ||
561 | int offset = 0; | ||
562 | |||
563 | spin_lock_irqsave(&adapter->san_dbf_lock, flags); | ||
564 | do { | ||
565 | memset(rec, 0, sizeof(struct zfcp_san_dbf_record)); | ||
566 | if (offset == 0) { | ||
567 | strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE); | ||
568 | rec->fsf_reqid = (unsigned long)fsf_req; | ||
569 | rec->fsf_seqno = fsf_req->seq_no; | ||
570 | rec->s_id = s_id; | ||
571 | rec->d_id = d_id; | ||
572 | rec->type.els.ls_code = ls_code; | ||
573 | buflen = min(buflen, ZFCP_DBF_ELS_MAX_PAYLOAD); | ||
574 | rec->type.els.payload_size = buflen; | ||
575 | memcpy(rec->type.els.payload, | ||
576 | buffer, min(buflen, ZFCP_DBF_ELS_PAYLOAD)); | ||
577 | offset += min(buflen, ZFCP_DBF_ELS_PAYLOAD); | ||
578 | } else { | ||
579 | strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE); | ||
580 | dump->total_size = buflen; | ||
581 | dump->offset = offset; | ||
582 | dump->size = min(buflen - offset, | ||
583 | (int)sizeof(struct zfcp_san_dbf_record) | ||
584 | - (int)sizeof(struct zfcp_dbf_dump)); | ||
585 | memcpy(dump->data, buffer + offset, dump->size); | ||
586 | offset += dump->size; | ||
587 | } | ||
588 | debug_event(adapter->san_dbf, level, | ||
589 | rec, sizeof(struct zfcp_san_dbf_record)); | ||
590 | } while (offset < buflen); | ||
591 | spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); | ||
592 | } | ||
593 | |||
594 | inline void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req) | ||
595 | { | ||
596 | struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data; | ||
597 | |||
598 | _zfcp_san_dbf_event_common_els("oels", 2, fsf_req, | ||
599 | fc_host_port_id(els->adapter->scsi_host), | ||
600 | els->d_id, | ||
601 | *(u8 *) zfcp_sg_to_address(els->req), | ||
602 | zfcp_sg_to_address(els->req), | ||
603 | els->req->length); | ||
604 | } | ||
605 | |||
606 | inline void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req) | ||
607 | { | ||
608 | struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data; | ||
609 | |||
610 | _zfcp_san_dbf_event_common_els("rels", 2, fsf_req, els->d_id, | ||
611 | fc_host_port_id(els->adapter->scsi_host), | ||
612 | *(u8 *) zfcp_sg_to_address(els->req), | ||
613 | zfcp_sg_to_address(els->resp), | ||
614 | els->resp->length); | ||
615 | } | ||
616 | |||
617 | inline void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req) | ||
618 | { | ||
619 | struct zfcp_adapter *adapter = fsf_req->adapter; | ||
620 | struct fsf_status_read_buffer *status_buffer = | ||
621 | (struct fsf_status_read_buffer *)fsf_req->data; | ||
622 | int length = (int)status_buffer->length - | ||
623 | (int)((void *)&status_buffer->payload - (void *)status_buffer); | ||
624 | |||
625 | _zfcp_san_dbf_event_common_els("iels", 1, fsf_req, status_buffer->d_id, | ||
626 | fc_host_port_id(adapter->scsi_host), | ||
627 | *(u8 *) status_buffer->payload, | ||
628 | (void *)status_buffer->payload, length); | ||
629 | } | ||
630 | |||
631 | static int | ||
632 | zfcp_san_dbf_view_format(debug_info_t * id, struct debug_view *view, | ||
633 | char *out_buf, const char *in_buf) | ||
634 | { | ||
635 | struct zfcp_san_dbf_record *rec = (struct zfcp_san_dbf_record *)in_buf; | ||
636 | char *buffer = NULL; | ||
637 | int buflen = 0, total = 0; | ||
638 | int len = 0; | ||
639 | |||
640 | if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) | ||
641 | return 0; | ||
642 | |||
643 | len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag); | ||
644 | len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx", | ||
645 | rec->fsf_reqid); | ||
646 | len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x", | ||
647 | rec->fsf_seqno); | ||
648 | len += zfcp_dbf_view(out_buf + len, "s_id", "0x%06x", rec->s_id); | ||
649 | len += zfcp_dbf_view(out_buf + len, "d_id", "0x%06x", rec->d_id); | ||
650 | |||
651 | if (strncmp(rec->tag, "octc", ZFCP_DBF_TAG_SIZE) == 0) { | ||
652 | len += zfcp_dbf_view(out_buf + len, "cmd_req_code", "0x%04x", | ||
653 | rec->type.ct.type.request.cmd_req_code); | ||
654 | len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x", | ||
655 | rec->type.ct.type.request.revision); | ||
656 | len += zfcp_dbf_view(out_buf + len, "gs_type", "0x%02x", | ||
657 | rec->type.ct.type.request.gs_type); | ||
658 | len += zfcp_dbf_view(out_buf + len, "gs_subtype", "0x%02x", | ||
659 | rec->type.ct.type.request.gs_subtype); | ||
660 | len += zfcp_dbf_view(out_buf + len, "options", "0x%02x", | ||
661 | rec->type.ct.type.request.options); | ||
662 | len += zfcp_dbf_view(out_buf + len, "max_res_size", "0x%04x", | ||
663 | rec->type.ct.type.request.max_res_size); | ||
664 | total = rec->type.ct.payload_size; | ||
665 | buffer = rec->type.ct.payload; | ||
666 | buflen = min(total, ZFCP_DBF_CT_PAYLOAD); | ||
667 | } else if (strncmp(rec->tag, "rctc", ZFCP_DBF_TAG_SIZE) == 0) { | ||
668 | len += zfcp_dbf_view(out_buf + len, "cmd_rsp_code", "0x%04x", | ||
669 | rec->type.ct.type.response.cmd_rsp_code); | ||
670 | len += zfcp_dbf_view(out_buf + len, "revision", "0x%02x", | ||
671 | rec->type.ct.type.response.revision); | ||
672 | len += zfcp_dbf_view(out_buf + len, "reason_code", "0x%02x", | ||
673 | rec->type.ct.type.response.reason_code); | ||
674 | len += | ||
675 | zfcp_dbf_view(out_buf + len, "reason_code_expl", "0x%02x", | ||
676 | rec->type.ct.type.response.reason_code_expl); | ||
677 | len += | ||
678 | zfcp_dbf_view(out_buf + len, "vendor_unique", "0x%02x", | ||
679 | rec->type.ct.type.response.vendor_unique); | ||
680 | total = rec->type.ct.payload_size; | ||
681 | buffer = rec->type.ct.payload; | ||
682 | buflen = min(total, ZFCP_DBF_CT_PAYLOAD); | ||
683 | } else if (strncmp(rec->tag, "oels", ZFCP_DBF_TAG_SIZE) == 0 || | ||
684 | strncmp(rec->tag, "rels", ZFCP_DBF_TAG_SIZE) == 0 || | ||
685 | strncmp(rec->tag, "iels", ZFCP_DBF_TAG_SIZE) == 0) { | ||
686 | len += zfcp_dbf_view(out_buf + len, "ls_code", "0x%02x", | ||
687 | rec->type.els.ls_code); | ||
688 | total = rec->type.els.payload_size; | ||
689 | buffer = rec->type.els.payload; | ||
690 | buflen = min(total, ZFCP_DBF_ELS_PAYLOAD); | ||
691 | } | ||
692 | |||
693 | len += zfcp_dbf_view_dump(out_buf + len, "payload", | ||
694 | buffer, buflen, 0, total); | ||
695 | |||
696 | if (buflen == total) | ||
697 | len += sprintf(out_buf + len, "\n"); | ||
698 | |||
699 | return len; | ||
700 | } | ||
701 | |||
702 | struct debug_view zfcp_san_dbf_view = { | ||
703 | "structured", | ||
704 | NULL, | ||
705 | &zfcp_dbf_view_header, | ||
706 | &zfcp_san_dbf_view_format, | ||
707 | NULL, | ||
708 | NULL | ||
709 | }; | ||
710 | |||
711 | static inline void | ||
712 | _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, | ||
713 | struct zfcp_adapter *adapter, | ||
714 | struct scsi_cmnd *scsi_cmnd, | ||
715 | struct zfcp_fsf_req *new_fsf_req) | ||
716 | { | ||
717 | struct zfcp_fsf_req *fsf_req = | ||
718 | (struct zfcp_fsf_req *)scsi_cmnd->host_scribble; | ||
719 | struct zfcp_scsi_dbf_record *rec = &adapter->scsi_dbf_buf; | ||
720 | struct zfcp_dbf_dump *dump = (struct zfcp_dbf_dump *)rec; | ||
721 | unsigned long flags; | ||
722 | struct fcp_rsp_iu *fcp_rsp; | ||
723 | char *fcp_rsp_info = NULL, *fcp_sns_info = NULL; | ||
724 | int offset = 0, buflen = 0; | ||
725 | |||
726 | spin_lock_irqsave(&adapter->scsi_dbf_lock, flags); | ||
727 | do { | ||
728 | memset(rec, 0, sizeof(struct zfcp_scsi_dbf_record)); | ||
729 | if (offset == 0) { | ||
730 | strncpy(rec->tag, tag, ZFCP_DBF_TAG_SIZE); | ||
731 | strncpy(rec->tag2, tag2, ZFCP_DBF_TAG_SIZE); | ||
732 | if (scsi_cmnd->device) { | ||
733 | rec->scsi_id = scsi_cmnd->device->id; | ||
734 | rec->scsi_lun = scsi_cmnd->device->lun; | ||
735 | } | ||
736 | rec->scsi_result = scsi_cmnd->result; | ||
737 | rec->scsi_cmnd = (unsigned long)scsi_cmnd; | ||
738 | rec->scsi_serial = scsi_cmnd->serial_number; | ||
739 | memcpy(rec->scsi_opcode, | ||
740 | &scsi_cmnd->cmnd, | ||
741 | min((int)scsi_cmnd->cmd_len, | ||
742 | ZFCP_DBF_SCSI_OPCODE)); | ||
743 | rec->scsi_retries = scsi_cmnd->retries; | ||
744 | rec->scsi_allowed = scsi_cmnd->allowed; | ||
745 | if (fsf_req != NULL) { | ||
746 | fcp_rsp = (struct fcp_rsp_iu *) | ||
747 | &(fsf_req->qtcb->bottom.io.fcp_rsp); | ||
748 | fcp_rsp_info = | ||
749 | zfcp_get_fcp_rsp_info_ptr(fcp_rsp); | ||
750 | fcp_sns_info = | ||
751 | zfcp_get_fcp_sns_info_ptr(fcp_rsp); | ||
752 | |||
753 | rec->type.fcp.rsp_validity = | ||
754 | fcp_rsp->validity.value; | ||
755 | rec->type.fcp.rsp_scsi_status = | ||
756 | fcp_rsp->scsi_status; | ||
757 | rec->type.fcp.rsp_resid = fcp_rsp->fcp_resid; | ||
758 | if (fcp_rsp->validity.bits.fcp_rsp_len_valid) | ||
759 | rec->type.fcp.rsp_code = | ||
760 | *(fcp_rsp_info + 3); | ||
761 | if (fcp_rsp->validity.bits.fcp_sns_len_valid) { | ||
762 | buflen = min((int)fcp_rsp->fcp_sns_len, | ||
763 | ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO); | ||
764 | rec->type.fcp.sns_info_len = buflen; | ||
765 | memcpy(rec->type.fcp.sns_info, | ||
766 | fcp_sns_info, | ||
767 | min(buflen, | ||
768 | ZFCP_DBF_SCSI_FCP_SNS_INFO)); | ||
769 | offset += min(buflen, | ||
770 | ZFCP_DBF_SCSI_FCP_SNS_INFO); | ||
771 | } | ||
772 | |||
773 | rec->fsf_reqid = (unsigned long)fsf_req; | ||
774 | rec->fsf_seqno = fsf_req->seq_no; | ||
775 | rec->fsf_issued = fsf_req->issued; | ||
776 | } | ||
777 | if (new_fsf_req != NULL) { | ||
778 | rec->type.new_fsf_req.fsf_reqid = | ||
779 | (unsigned long) | ||
780 | new_fsf_req; | ||
781 | rec->type.new_fsf_req.fsf_seqno = | ||
782 | new_fsf_req->seq_no; | ||
783 | rec->type.new_fsf_req.fsf_issued = | ||
784 | new_fsf_req->issued; | ||
785 | } | ||
786 | } else { | ||
787 | strncpy(dump->tag, "dump", ZFCP_DBF_TAG_SIZE); | ||
788 | dump->total_size = buflen; | ||
789 | dump->offset = offset; | ||
790 | dump->size = min(buflen - offset, | ||
791 | (int)sizeof(struct | ||
792 | zfcp_scsi_dbf_record) - | ||
793 | (int)sizeof(struct zfcp_dbf_dump)); | ||
794 | memcpy(dump->data, fcp_sns_info + offset, dump->size); | ||
795 | offset += dump->size; | ||
796 | } | ||
797 | debug_event(adapter->scsi_dbf, level, | ||
798 | rec, sizeof(struct zfcp_scsi_dbf_record)); | ||
799 | } while (offset < buflen); | ||
800 | spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags); | ||
801 | } | ||
802 | |||
803 | inline void | ||
804 | zfcp_scsi_dbf_event_result(const char *tag, int level, | ||
805 | struct zfcp_adapter *adapter, | ||
806 | struct scsi_cmnd *scsi_cmnd) | ||
807 | { | ||
808 | _zfcp_scsi_dbf_event_common("rslt", | ||
809 | tag, level, adapter, scsi_cmnd, NULL); | ||
810 | } | ||
811 | |||
812 | inline void | ||
813 | zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter, | ||
814 | struct scsi_cmnd *scsi_cmnd, | ||
815 | struct zfcp_fsf_req *new_fsf_req) | ||
816 | { | ||
817 | _zfcp_scsi_dbf_event_common("abrt", | ||
818 | tag, 1, adapter, scsi_cmnd, new_fsf_req); | ||
819 | } | ||
820 | |||
821 | inline void | ||
822 | zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit, | ||
823 | struct scsi_cmnd *scsi_cmnd) | ||
824 | { | ||
825 | struct zfcp_adapter *adapter = unit->port->adapter; | ||
826 | |||
827 | _zfcp_scsi_dbf_event_common(flag == FCP_TARGET_RESET ? "trst" : "lrst", | ||
828 | tag, 1, adapter, scsi_cmnd, NULL); | ||
829 | } | ||
830 | |||
831 | static int | ||
832 | zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view, | ||
833 | char *out_buf, const char *in_buf) | ||
834 | { | ||
835 | struct zfcp_scsi_dbf_record *rec = | ||
836 | (struct zfcp_scsi_dbf_record *)in_buf; | ||
837 | int len = 0; | ||
838 | |||
839 | if (strncmp(rec->tag, "dump", ZFCP_DBF_TAG_SIZE) == 0) | ||
840 | return 0; | ||
841 | |||
842 | len += zfcp_dbf_tag(out_buf + len, "tag", rec->tag); | ||
843 | len += zfcp_dbf_tag(out_buf + len, "tag2", rec->tag2); | ||
844 | len += zfcp_dbf_view(out_buf + len, "scsi_id", "0x%08x", rec->scsi_id); | ||
845 | len += zfcp_dbf_view(out_buf + len, "scsi_lun", "0x%08x", | ||
846 | rec->scsi_lun); | ||
847 | len += zfcp_dbf_view(out_buf + len, "scsi_result", "0x%08x", | ||
848 | rec->scsi_result); | ||
849 | len += zfcp_dbf_view(out_buf + len, "scsi_cmnd", "0x%0Lx", | ||
850 | rec->scsi_cmnd); | ||
851 | len += zfcp_dbf_view(out_buf + len, "scsi_serial", "0x%016Lx", | ||
852 | rec->scsi_serial); | ||
853 | len += zfcp_dbf_view_dump(out_buf + len, "scsi_opcode", | ||
854 | rec->scsi_opcode, | ||
855 | ZFCP_DBF_SCSI_OPCODE, | ||
856 | 0, ZFCP_DBF_SCSI_OPCODE); | ||
857 | len += zfcp_dbf_view(out_buf + len, "scsi_retries", "0x%02x", | ||
858 | rec->scsi_retries); | ||
859 | len += zfcp_dbf_view(out_buf + len, "scsi_allowed", "0x%02x", | ||
860 | rec->scsi_allowed); | ||
861 | len += zfcp_dbf_view(out_buf + len, "fsf_reqid", "0x%0Lx", | ||
862 | rec->fsf_reqid); | ||
863 | len += zfcp_dbf_view(out_buf + len, "fsf_seqno", "0x%08x", | ||
864 | rec->fsf_seqno); | ||
865 | len += zfcp_dbf_stck(out_buf + len, "fsf_issued", rec->fsf_issued); | ||
866 | if (strncmp(rec->tag, "rslt", ZFCP_DBF_TAG_SIZE) == 0) { | ||
867 | len += | ||
868 | zfcp_dbf_view(out_buf + len, "fcp_rsp_validity", "0x%02x", | ||
869 | rec->type.fcp.rsp_validity); | ||
870 | len += | ||
871 | zfcp_dbf_view(out_buf + len, "fcp_rsp_scsi_status", | ||
872 | "0x%02x", rec->type.fcp.rsp_scsi_status); | ||
873 | len += | ||
874 | zfcp_dbf_view(out_buf + len, "fcp_rsp_resid", "0x%08x", | ||
875 | rec->type.fcp.rsp_resid); | ||
876 | len += | ||
877 | zfcp_dbf_view(out_buf + len, "fcp_rsp_code", "0x%08x", | ||
878 | rec->type.fcp.rsp_code); | ||
879 | len += | ||
880 | zfcp_dbf_view(out_buf + len, "fcp_sns_info_len", "0x%08x", | ||
881 | rec->type.fcp.sns_info_len); | ||
882 | len += | ||
883 | zfcp_dbf_view_dump(out_buf + len, "fcp_sns_info", | ||
884 | rec->type.fcp.sns_info, | ||
885 | min((int)rec->type.fcp.sns_info_len, | ||
886 | ZFCP_DBF_SCSI_FCP_SNS_INFO), 0, | ||
887 | rec->type.fcp.sns_info_len); | ||
888 | } else if (strncmp(rec->tag, "abrt", ZFCP_DBF_TAG_SIZE) == 0) { | ||
889 | len += zfcp_dbf_view(out_buf + len, "fsf_reqid_abort", "0x%0Lx", | ||
890 | rec->type.new_fsf_req.fsf_reqid); | ||
891 | len += zfcp_dbf_view(out_buf + len, "fsf_seqno_abort", "0x%08x", | ||
892 | rec->type.new_fsf_req.fsf_seqno); | ||
893 | len += zfcp_dbf_stck(out_buf + len, "fsf_issued", | ||
894 | rec->type.new_fsf_req.fsf_issued); | ||
895 | } else if ((strncmp(rec->tag, "trst", ZFCP_DBF_TAG_SIZE) == 0) || | ||
896 | (strncmp(rec->tag, "lrst", ZFCP_DBF_TAG_SIZE) == 0)) { | ||
897 | len += zfcp_dbf_view(out_buf + len, "fsf_reqid_reset", "0x%0Lx", | ||
898 | rec->type.new_fsf_req.fsf_reqid); | ||
899 | len += zfcp_dbf_view(out_buf + len, "fsf_seqno_reset", "0x%08x", | ||
900 | rec->type.new_fsf_req.fsf_seqno); | ||
901 | len += zfcp_dbf_stck(out_buf + len, "fsf_issued", | ||
902 | rec->type.new_fsf_req.fsf_issued); | ||
903 | } | ||
904 | |||
905 | len += sprintf(out_buf + len, "\n"); | ||
906 | |||
907 | return len; | ||
908 | } | ||
909 | |||
910 | struct debug_view zfcp_scsi_dbf_view = { | ||
911 | "structured", | ||
912 | NULL, | ||
913 | &zfcp_dbf_view_header, | ||
914 | &zfcp_scsi_dbf_view_format, | ||
915 | NULL, | ||
916 | NULL | ||
917 | }; | ||
918 | |||
919 | /** | ||
920 | * zfcp_adapter_debug_register - registers debug feature for an adapter | ||
921 | * @adapter: pointer to adapter for which debug features should be registered | ||
922 | * return: -ENOMEM on error, 0 otherwise | ||
923 | */ | ||
924 | int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) | ||
925 | { | ||
926 | char dbf_name[DEBUG_MAX_NAME_LEN]; | ||
927 | |||
928 | /* debug feature area which records recovery activity */ | ||
929 | spin_lock_init(&adapter->erp_dbf_lock); | ||
930 | sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter)); | ||
931 | adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2, | ||
932 | sizeof(struct zfcp_erp_dbf_record)); | ||
933 | if (!adapter->erp_dbf) | ||
934 | goto failed; | ||
935 | debug_register_view(adapter->erp_dbf, &debug_hex_ascii_view); | ||
936 | debug_set_level(adapter->erp_dbf, 3); | ||
937 | |||
938 | /* debug feature area which records HBA (FSF and QDIO) conditions */ | ||
939 | spin_lock_init(&adapter->hba_dbf_lock); | ||
940 | sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter)); | ||
941 | adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1, | ||
942 | sizeof(struct zfcp_hba_dbf_record)); | ||
943 | if (!adapter->hba_dbf) | ||
944 | goto failed; | ||
945 | debug_register_view(adapter->hba_dbf, &debug_hex_ascii_view); | ||
946 | debug_register_view(adapter->hba_dbf, &zfcp_hba_dbf_view); | ||
947 | debug_set_level(adapter->hba_dbf, 3); | ||
948 | |||
949 | /* debug feature area which records SAN command failures and recovery */ | ||
950 | spin_lock_init(&adapter->san_dbf_lock); | ||
951 | sprintf(dbf_name, "zfcp_%s_san", zfcp_get_busid_by_adapter(adapter)); | ||
952 | adapter->san_dbf = debug_register(dbf_name, dbfsize, 1, | ||
953 | sizeof(struct zfcp_san_dbf_record)); | ||
954 | if (!adapter->san_dbf) | ||
955 | goto failed; | ||
956 | debug_register_view(adapter->san_dbf, &debug_hex_ascii_view); | ||
957 | debug_register_view(adapter->san_dbf, &zfcp_san_dbf_view); | ||
958 | debug_set_level(adapter->san_dbf, 6); | ||
959 | |||
960 | /* debug feature area which records SCSI command failures and recovery */ | ||
961 | spin_lock_init(&adapter->scsi_dbf_lock); | ||
962 | sprintf(dbf_name, "zfcp_%s_scsi", zfcp_get_busid_by_adapter(adapter)); | ||
963 | adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1, | ||
964 | sizeof(struct zfcp_scsi_dbf_record)); | ||
965 | if (!adapter->scsi_dbf) | ||
966 | goto failed; | ||
967 | debug_register_view(adapter->scsi_dbf, &debug_hex_ascii_view); | ||
968 | debug_register_view(adapter->scsi_dbf, &zfcp_scsi_dbf_view); | ||
969 | debug_set_level(adapter->scsi_dbf, 3); | ||
970 | |||
971 | return 0; | ||
972 | |||
973 | failed: | ||
974 | zfcp_adapter_debug_unregister(adapter); | ||
975 | |||
976 | return -ENOMEM; | ||
977 | } | ||
978 | |||
979 | /** | ||
980 | * zfcp_adapter_debug_unregister - unregisters debug feature for an adapter | ||
981 | * @adapter: pointer to adapter for which debug features should be unregistered | ||
982 | */ | ||
983 | void zfcp_adapter_debug_unregister(struct zfcp_adapter *adapter) | ||
984 | { | ||
985 | debug_unregister(adapter->scsi_dbf); | ||
986 | debug_unregister(adapter->san_dbf); | ||
987 | debug_unregister(adapter->hba_dbf); | ||
988 | debug_unregister(adapter->erp_dbf); | ||
989 | adapter->scsi_dbf = NULL; | ||
990 | adapter->san_dbf = NULL; | ||
991 | adapter->hba_dbf = NULL; | ||
992 | adapter->erp_dbf = NULL; | ||
993 | } | ||
994 | |||
995 | #undef ZFCP_LOG_AREA | ||
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 455e902533a9..d81b737d68cc 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h | |||
@@ -66,7 +66,7 @@ | |||
66 | /********************* GENERAL DEFINES *********************************/ | 66 | /********************* GENERAL DEFINES *********************************/ |
67 | 67 | ||
68 | /* zfcp version number, it consists of major, minor, and patch-level number */ | 68 | /* zfcp version number, it consists of major, minor, and patch-level number */ |
69 | #define ZFCP_VERSION "4.3.0" | 69 | #define ZFCP_VERSION "4.5.0" |
70 | 70 | ||
71 | /** | 71 | /** |
72 | * zfcp_sg_to_address - determine kernel address from struct scatterlist | 72 | * zfcp_sg_to_address - determine kernel address from struct scatterlist |
@@ -154,13 +154,17 @@ typedef u32 scsi_lun_t; | |||
154 | #define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100 | 154 | #define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100 |
155 | #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7 | 155 | #define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7 |
156 | 156 | ||
157 | /* Retry 5 times every 2 second, then every minute */ | ||
158 | #define ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES 5 | ||
159 | #define ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP 200 | ||
160 | #define ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP 6000 | ||
161 | |||
157 | /* timeout value for "default timer" for fsf requests */ | 162 | /* timeout value for "default timer" for fsf requests */ |
158 | #define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ); | 163 | #define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ); |
159 | 164 | ||
160 | /*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/ | 165 | /*************** FIBRE CHANNEL PROTOCOL SPECIFIC DEFINES ********************/ |
161 | 166 | ||
162 | typedef unsigned long long wwn_t; | 167 | typedef unsigned long long wwn_t; |
163 | typedef unsigned int fc_id_t; | ||
164 | typedef unsigned long long fcp_lun_t; | 168 | typedef unsigned long long fcp_lun_t; |
165 | /* data length field may be at variable position in FCP-2 FCP_CMND IU */ | 169 | /* data length field may be at variable position in FCP-2 FCP_CMND IU */ |
166 | typedef unsigned int fcp_dl_t; | 170 | typedef unsigned int fcp_dl_t; |
@@ -281,6 +285,171 @@ struct fcp_logo { | |||
281 | } __attribute__((packed)); | 285 | } __attribute__((packed)); |
282 | 286 | ||
283 | /* | 287 | /* |
288 | * DBF stuff | ||
289 | */ | ||
290 | #define ZFCP_DBF_TAG_SIZE 4 | ||
291 | |||
292 | struct zfcp_dbf_dump { | ||
293 | u8 tag[ZFCP_DBF_TAG_SIZE]; | ||
294 | u32 total_size; /* size of total dump data */ | ||
295 | u32 offset; /* how much data has being already dumped */ | ||
296 | u32 size; /* how much data comes with this record */ | ||
297 | u8 data[]; /* dump data */ | ||
298 | } __attribute__ ((packed)); | ||
299 | |||
300 | /* FIXME: to be inflated when reworking the erp dbf */ | ||
301 | struct zfcp_erp_dbf_record { | ||
302 | u8 dummy[16]; | ||
303 | } __attribute__ ((packed)); | ||
304 | |||
305 | struct zfcp_hba_dbf_record_response { | ||
306 | u32 fsf_command; | ||
307 | u64 fsf_reqid; | ||
308 | u32 fsf_seqno; | ||
309 | u64 fsf_issued; | ||
310 | u32 fsf_prot_status; | ||
311 | u32 fsf_status; | ||
312 | u8 fsf_prot_status_qual[FSF_PROT_STATUS_QUAL_SIZE]; | ||
313 | u8 fsf_status_qual[FSF_STATUS_QUALIFIER_SIZE]; | ||
314 | u32 fsf_req_status; | ||
315 | u8 sbal_first; | ||
316 | u8 sbal_curr; | ||
317 | u8 sbal_last; | ||
318 | u8 pool; | ||
319 | u64 erp_action; | ||
320 | union { | ||
321 | struct { | ||
322 | u64 scsi_cmnd; | ||
323 | u64 scsi_serial; | ||
324 | } send_fcp; | ||
325 | struct { | ||
326 | u64 wwpn; | ||
327 | u32 d_id; | ||
328 | u32 port_handle; | ||
329 | } port; | ||
330 | struct { | ||
331 | u64 wwpn; | ||
332 | u64 fcp_lun; | ||
333 | u32 port_handle; | ||
334 | u32 lun_handle; | ||
335 | } unit; | ||
336 | struct { | ||
337 | u32 d_id; | ||
338 | u8 ls_code; | ||
339 | } send_els; | ||
340 | } data; | ||
341 | } __attribute__ ((packed)); | ||
342 | |||
343 | struct zfcp_hba_dbf_record_status { | ||
344 | u8 failed; | ||
345 | u32 status_type; | ||
346 | u32 status_subtype; | ||
347 | struct fsf_queue_designator | ||
348 | queue_designator; | ||
349 | u32 payload_size; | ||
350 | #define ZFCP_DBF_UNSOL_PAYLOAD 80 | ||
351 | #define ZFCP_DBF_UNSOL_PAYLOAD_SENSE_DATA_AVAIL 32 | ||
352 | #define ZFCP_DBF_UNSOL_PAYLOAD_BIT_ERROR_THRESHOLD 56 | ||
353 | #define ZFCP_DBF_UNSOL_PAYLOAD_FEATURE_UPDATE_ALERT 2 * sizeof(u32) | ||
354 | u8 payload[ZFCP_DBF_UNSOL_PAYLOAD]; | ||
355 | } __attribute__ ((packed)); | ||
356 | |||
357 | struct zfcp_hba_dbf_record_qdio { | ||
358 | u32 status; | ||
359 | u32 qdio_error; | ||
360 | u32 siga_error; | ||
361 | u8 sbal_index; | ||
362 | u8 sbal_count; | ||
363 | } __attribute__ ((packed)); | ||
364 | |||
365 | struct zfcp_hba_dbf_record { | ||
366 | u8 tag[ZFCP_DBF_TAG_SIZE]; | ||
367 | u8 tag2[ZFCP_DBF_TAG_SIZE]; | ||
368 | union { | ||
369 | struct zfcp_hba_dbf_record_response response; | ||
370 | struct zfcp_hba_dbf_record_status status; | ||
371 | struct zfcp_hba_dbf_record_qdio qdio; | ||
372 | } type; | ||
373 | } __attribute__ ((packed)); | ||
374 | |||
375 | struct zfcp_san_dbf_record_ct { | ||
376 | union { | ||
377 | struct { | ||
378 | u16 cmd_req_code; | ||
379 | u8 revision; | ||
380 | u8 gs_type; | ||
381 | u8 gs_subtype; | ||
382 | u8 options; | ||
383 | u16 max_res_size; | ||
384 | } request; | ||
385 | struct { | ||
386 | u16 cmd_rsp_code; | ||
387 | u8 revision; | ||
388 | u8 reason_code; | ||
389 | u8 reason_code_expl; | ||
390 | u8 vendor_unique; | ||
391 | } response; | ||
392 | } type; | ||
393 | u32 payload_size; | ||
394 | #define ZFCP_DBF_CT_PAYLOAD 24 | ||
395 | u8 payload[ZFCP_DBF_CT_PAYLOAD]; | ||
396 | } __attribute__ ((packed)); | ||
397 | |||
398 | struct zfcp_san_dbf_record_els { | ||
399 | u8 ls_code; | ||
400 | u32 payload_size; | ||
401 | #define ZFCP_DBF_ELS_PAYLOAD 32 | ||
402 | #define ZFCP_DBF_ELS_MAX_PAYLOAD 1024 | ||
403 | u8 payload[ZFCP_DBF_ELS_PAYLOAD]; | ||
404 | } __attribute__ ((packed)); | ||
405 | |||
406 | struct zfcp_san_dbf_record { | ||
407 | u8 tag[ZFCP_DBF_TAG_SIZE]; | ||
408 | u64 fsf_reqid; | ||
409 | u32 fsf_seqno; | ||
410 | u32 s_id; | ||
411 | u32 d_id; | ||
412 | union { | ||
413 | struct zfcp_san_dbf_record_ct ct; | ||
414 | struct zfcp_san_dbf_record_els els; | ||
415 | } type; | ||
416 | } __attribute__ ((packed)); | ||
417 | |||
418 | struct zfcp_scsi_dbf_record { | ||
419 | u8 tag[ZFCP_DBF_TAG_SIZE]; | ||
420 | u8 tag2[ZFCP_DBF_TAG_SIZE]; | ||
421 | u32 scsi_id; | ||
422 | u32 scsi_lun; | ||
423 | u32 scsi_result; | ||
424 | u64 scsi_cmnd; | ||
425 | u64 scsi_serial; | ||
426 | #define ZFCP_DBF_SCSI_OPCODE 16 | ||
427 | u8 scsi_opcode[ZFCP_DBF_SCSI_OPCODE]; | ||
428 | u8 scsi_retries; | ||
429 | u8 scsi_allowed; | ||
430 | u64 fsf_reqid; | ||
431 | u32 fsf_seqno; | ||
432 | u64 fsf_issued; | ||
433 | union { | ||
434 | struct { | ||
435 | u64 fsf_reqid; | ||
436 | u32 fsf_seqno; | ||
437 | u64 fsf_issued; | ||
438 | } new_fsf_req; | ||
439 | struct { | ||
440 | u8 rsp_validity; | ||
441 | u8 rsp_scsi_status; | ||
442 | u32 rsp_resid; | ||
443 | u8 rsp_code; | ||
444 | #define ZFCP_DBF_SCSI_FCP_SNS_INFO 16 | ||
445 | #define ZFCP_DBF_SCSI_MAX_FCP_SNS_INFO 256 | ||
446 | u32 sns_info_len; | ||
447 | u8 sns_info[ZFCP_DBF_SCSI_FCP_SNS_INFO]; | ||
448 | } fcp; | ||
449 | } type; | ||
450 | } __attribute__ ((packed)); | ||
451 | |||
452 | /* | ||
284 | * FC-FS stuff | 453 | * FC-FS stuff |
285 | */ | 454 | */ |
286 | #define R_A_TOV 10 /* seconds */ | 455 | #define R_A_TOV 10 /* seconds */ |
@@ -339,34 +508,6 @@ struct zfcp_rc_entry { | |||
339 | */ | 508 | */ |
340 | #define ZFCP_CT_TIMEOUT (3 * R_A_TOV) | 509 | #define ZFCP_CT_TIMEOUT (3 * R_A_TOV) |
341 | 510 | ||
342 | |||
343 | /***************** S390 DEBUG FEATURE SPECIFIC DEFINES ***********************/ | ||
344 | |||
345 | /* debug feature entries per adapter */ | ||
346 | #define ZFCP_ERP_DBF_INDEX 1 | ||
347 | #define ZFCP_ERP_DBF_AREAS 2 | ||
348 | #define ZFCP_ERP_DBF_LENGTH 16 | ||
349 | #define ZFCP_ERP_DBF_LEVEL 3 | ||
350 | #define ZFCP_ERP_DBF_NAME "zfcperp" | ||
351 | |||
352 | #define ZFCP_CMD_DBF_INDEX 2 | ||
353 | #define ZFCP_CMD_DBF_AREAS 1 | ||
354 | #define ZFCP_CMD_DBF_LENGTH 8 | ||
355 | #define ZFCP_CMD_DBF_LEVEL 3 | ||
356 | #define ZFCP_CMD_DBF_NAME "zfcpcmd" | ||
357 | |||
358 | #define ZFCP_ABORT_DBF_INDEX 2 | ||
359 | #define ZFCP_ABORT_DBF_AREAS 1 | ||
360 | #define ZFCP_ABORT_DBF_LENGTH 8 | ||
361 | #define ZFCP_ABORT_DBF_LEVEL 6 | ||
362 | #define ZFCP_ABORT_DBF_NAME "zfcpabt" | ||
363 | |||
364 | #define ZFCP_IN_ELS_DBF_INDEX 2 | ||
365 | #define ZFCP_IN_ELS_DBF_AREAS 1 | ||
366 | #define ZFCP_IN_ELS_DBF_LENGTH 8 | ||
367 | #define ZFCP_IN_ELS_DBF_LEVEL 6 | ||
368 | #define ZFCP_IN_ELS_DBF_NAME "zfcpels" | ||
369 | |||
370 | /******************** LOGGING MACROS AND DEFINES *****************************/ | 511 | /******************** LOGGING MACROS AND DEFINES *****************************/ |
371 | 512 | ||
372 | /* | 513 | /* |
@@ -501,6 +642,7 @@ do { \ | |||
501 | #define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL 0x00000080 | 642 | #define ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL 0x00000080 |
502 | #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 | 643 | #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 |
503 | #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 | 644 | #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 |
645 | #define ZFCP_STATUS_ADAPTER_XPORT_OK 0x00000800 | ||
504 | 646 | ||
505 | #define ZFCP_STATUS_ADAPTER_SCSI_UP \ | 647 | #define ZFCP_STATUS_ADAPTER_SCSI_UP \ |
506 | (ZFCP_STATUS_COMMON_UNBLOCKED | \ | 648 | (ZFCP_STATUS_COMMON_UNBLOCKED | \ |
@@ -635,45 +777,6 @@ struct zfcp_adapter_mempool { | |||
635 | mempool_t *data_gid_pn; | 777 | mempool_t *data_gid_pn; |
636 | }; | 778 | }; |
637 | 779 | ||
638 | struct zfcp_exchange_config_data{ | ||
639 | }; | ||
640 | |||
641 | struct zfcp_open_port { | ||
642 | struct zfcp_port *port; | ||
643 | }; | ||
644 | |||
645 | struct zfcp_close_port { | ||
646 | struct zfcp_port *port; | ||
647 | }; | ||
648 | |||
649 | struct zfcp_open_unit { | ||
650 | struct zfcp_unit *unit; | ||
651 | }; | ||
652 | |||
653 | struct zfcp_close_unit { | ||
654 | struct zfcp_unit *unit; | ||
655 | }; | ||
656 | |||
657 | struct zfcp_close_physical_port { | ||
658 | struct zfcp_port *port; | ||
659 | }; | ||
660 | |||
661 | struct zfcp_send_fcp_command_task { | ||
662 | struct zfcp_fsf_req *fsf_req; | ||
663 | struct zfcp_unit *unit; | ||
664 | struct scsi_cmnd *scsi_cmnd; | ||
665 | unsigned long start_jiffies; | ||
666 | }; | ||
667 | |||
668 | struct zfcp_send_fcp_command_task_management { | ||
669 | struct zfcp_unit *unit; | ||
670 | }; | ||
671 | |||
672 | struct zfcp_abort_fcp_command { | ||
673 | struct zfcp_fsf_req *fsf_req; | ||
674 | struct zfcp_unit *unit; | ||
675 | }; | ||
676 | |||
677 | /* | 780 | /* |
678 | * header for CT_IU | 781 | * header for CT_IU |
679 | */ | 782 | */ |
@@ -702,7 +805,7 @@ struct ct_iu_gid_pn_req { | |||
702 | /* FS_ACC IU and data unit for GID_PN nameserver request */ | 805 | /* FS_ACC IU and data unit for GID_PN nameserver request */ |
703 | struct ct_iu_gid_pn_resp { | 806 | struct ct_iu_gid_pn_resp { |
704 | struct ct_hdr header; | 807 | struct ct_hdr header; |
705 | fc_id_t d_id; | 808 | u32 d_id; |
706 | } __attribute__ ((packed)); | 809 | } __attribute__ ((packed)); |
707 | 810 | ||
708 | typedef void (*zfcp_send_ct_handler_t)(unsigned long); | 811 | typedef void (*zfcp_send_ct_handler_t)(unsigned long); |
@@ -768,7 +871,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long); | |||
768 | struct zfcp_send_els { | 871 | struct zfcp_send_els { |
769 | struct zfcp_adapter *adapter; | 872 | struct zfcp_adapter *adapter; |
770 | struct zfcp_port *port; | 873 | struct zfcp_port *port; |
771 | fc_id_t d_id; | 874 | u32 d_id; |
772 | struct scatterlist *req; | 875 | struct scatterlist *req; |
773 | struct scatterlist *resp; | 876 | struct scatterlist *resp; |
774 | unsigned int req_count; | 877 | unsigned int req_count; |
@@ -781,33 +884,6 @@ struct zfcp_send_els { | |||
781 | int status; | 884 | int status; |
782 | }; | 885 | }; |
783 | 886 | ||
784 | struct zfcp_status_read { | ||
785 | struct fsf_status_read_buffer *buffer; | ||
786 | }; | ||
787 | |||
788 | struct zfcp_fsf_done { | ||
789 | struct completion *complete; | ||
790 | int status; | ||
791 | }; | ||
792 | |||
793 | /* request specific data */ | ||
794 | union zfcp_req_data { | ||
795 | struct zfcp_exchange_config_data exchange_config_data; | ||
796 | struct zfcp_open_port open_port; | ||
797 | struct zfcp_close_port close_port; | ||
798 | struct zfcp_open_unit open_unit; | ||
799 | struct zfcp_close_unit close_unit; | ||
800 | struct zfcp_close_physical_port close_physical_port; | ||
801 | struct zfcp_send_fcp_command_task send_fcp_command_task; | ||
802 | struct zfcp_send_fcp_command_task_management | ||
803 | send_fcp_command_task_management; | ||
804 | struct zfcp_abort_fcp_command abort_fcp_command; | ||
805 | struct zfcp_send_ct *send_ct; | ||
806 | struct zfcp_send_els *send_els; | ||
807 | struct zfcp_status_read status_read; | ||
808 | struct fsf_qtcb_bottom_port *port_data; | ||
809 | }; | ||
810 | |||
811 | struct zfcp_qdio_queue { | 887 | struct zfcp_qdio_queue { |
812 | struct qdio_buffer *buffer[QDIO_MAX_BUFFERS_PER_Q]; /* SBALs */ | 888 | struct qdio_buffer *buffer[QDIO_MAX_BUFFERS_PER_Q]; /* SBALs */ |
813 | u8 free_index; /* index of next free bfr | 889 | u8 free_index; /* index of next free bfr |
@@ -838,21 +914,19 @@ struct zfcp_adapter { | |||
838 | atomic_t refcount; /* reference count */ | 914 | atomic_t refcount; /* reference count */ |
839 | wait_queue_head_t remove_wq; /* can be used to wait for | 915 | wait_queue_head_t remove_wq; /* can be used to wait for |
840 | refcount drop to zero */ | 916 | refcount drop to zero */ |
841 | wwn_t wwnn; /* WWNN */ | ||
842 | wwn_t wwpn; /* WWPN */ | ||
843 | fc_id_t s_id; /* N_Port ID */ | ||
844 | wwn_t peer_wwnn; /* P2P peer WWNN */ | 917 | wwn_t peer_wwnn; /* P2P peer WWNN */ |
845 | wwn_t peer_wwpn; /* P2P peer WWPN */ | 918 | wwn_t peer_wwpn; /* P2P peer WWPN */ |
846 | fc_id_t peer_d_id; /* P2P peer D_ID */ | 919 | u32 peer_d_id; /* P2P peer D_ID */ |
920 | wwn_t physical_wwpn; /* WWPN of physical port */ | ||
921 | u32 physical_s_id; /* local FC port ID */ | ||
847 | struct ccw_device *ccw_device; /* S/390 ccw device */ | 922 | struct ccw_device *ccw_device; /* S/390 ccw device */ |
848 | u8 fc_service_class; | 923 | u8 fc_service_class; |
849 | u32 fc_topology; /* FC topology */ | 924 | u32 fc_topology; /* FC topology */ |
850 | u32 fc_link_speed; /* FC interface speed */ | ||
851 | u32 hydra_version; /* Hydra version */ | 925 | u32 hydra_version; /* Hydra version */ |
852 | u32 fsf_lic_version; | 926 | u32 fsf_lic_version; |
853 | u32 supported_features;/* of FCP channel */ | 927 | u32 adapter_features; /* FCP channel features */ |
928 | u32 connection_features; /* host connection features */ | ||
854 | u32 hardware_version; /* of FCP channel */ | 929 | u32 hardware_version; /* of FCP channel */ |
855 | u8 serial_number[32]; /* of hardware */ | ||
856 | struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ | 930 | struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ |
857 | unsigned short scsi_host_no; /* Assigned host number */ | 931 | unsigned short scsi_host_no; /* Assigned host number */ |
858 | unsigned char name[9]; | 932 | unsigned char name[9]; |
@@ -889,11 +963,18 @@ struct zfcp_adapter { | |||
889 | u32 erp_low_mem_count; /* nr of erp actions waiting | 963 | u32 erp_low_mem_count; /* nr of erp actions waiting |
890 | for memory */ | 964 | for memory */ |
891 | struct zfcp_port *nameserver_port; /* adapter's nameserver */ | 965 | struct zfcp_port *nameserver_port; /* adapter's nameserver */ |
892 | debug_info_t *erp_dbf; /* S/390 debug features */ | 966 | debug_info_t *erp_dbf; |
893 | debug_info_t *abort_dbf; | 967 | debug_info_t *hba_dbf; |
894 | debug_info_t *in_els_dbf; | 968 | debug_info_t *san_dbf; /* debug feature areas */ |
895 | debug_info_t *cmd_dbf; | 969 | debug_info_t *scsi_dbf; |
896 | spinlock_t dbf_lock; | 970 | spinlock_t erp_dbf_lock; |
971 | spinlock_t hba_dbf_lock; | ||
972 | spinlock_t san_dbf_lock; | ||
973 | spinlock_t scsi_dbf_lock; | ||
974 | struct zfcp_erp_dbf_record erp_dbf_buf; | ||
975 | struct zfcp_hba_dbf_record hba_dbf_buf; | ||
976 | struct zfcp_san_dbf_record san_dbf_buf; | ||
977 | struct zfcp_scsi_dbf_record scsi_dbf_buf; | ||
897 | struct zfcp_adapter_mempool pool; /* Adapter memory pools */ | 978 | struct zfcp_adapter_mempool pool; /* Adapter memory pools */ |
898 | struct qdio_initialize qdio_init_data; /* for qdio_establish */ | 979 | struct qdio_initialize qdio_init_data; /* for qdio_establish */ |
899 | struct device generic_services; /* directory for WKA ports */ | 980 | struct device generic_services; /* directory for WKA ports */ |
@@ -919,7 +1000,7 @@ struct zfcp_port { | |||
919 | atomic_t status; /* status of this remote port */ | 1000 | atomic_t status; /* status of this remote port */ |
920 | wwn_t wwnn; /* WWNN if known */ | 1001 | wwn_t wwnn; /* WWNN if known */ |
921 | wwn_t wwpn; /* WWPN */ | 1002 | wwn_t wwpn; /* WWPN */ |
922 | fc_id_t d_id; /* D_ID */ | 1003 | u32 d_id; /* D_ID */ |
923 | u32 handle; /* handle assigned by FSF */ | 1004 | u32 handle; /* handle assigned by FSF */ |
924 | struct zfcp_erp_action erp_action; /* pending error recovery */ | 1005 | struct zfcp_erp_action erp_action; /* pending error recovery */ |
925 | atomic_t erp_counter; | 1006 | atomic_t erp_counter; |
@@ -963,11 +1044,13 @@ struct zfcp_fsf_req { | |||
963 | u32 fsf_command; /* FSF Command copy */ | 1044 | u32 fsf_command; /* FSF Command copy */ |
964 | struct fsf_qtcb *qtcb; /* address of associated QTCB */ | 1045 | struct fsf_qtcb *qtcb; /* address of associated QTCB */ |
965 | u32 seq_no; /* Sequence number of request */ | 1046 | u32 seq_no; /* Sequence number of request */ |
966 | union zfcp_req_data data; /* Info fields of request */ | 1047 | unsigned long data; /* private data of request */ |
967 | struct zfcp_erp_action *erp_action; /* used if this request is | 1048 | struct zfcp_erp_action *erp_action; /* used if this request is |
968 | issued on behalf of erp */ | 1049 | issued on behalf of erp */ |
969 | mempool_t *pool; /* used if request was alloacted | 1050 | mempool_t *pool; /* used if request was alloacted |
970 | from emergency pool */ | 1051 | from emergency pool */ |
1052 | unsigned long long issued; /* request sent time (STCK) */ | ||
1053 | struct zfcp_unit *unit; | ||
971 | }; | 1054 | }; |
972 | 1055 | ||
973 | typedef void zfcp_fsf_req_handler_t(struct zfcp_fsf_req*); | 1056 | typedef void zfcp_fsf_req_handler_t(struct zfcp_fsf_req*); |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index cb4f612550ba..023f4e558ae4 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -82,6 +82,7 @@ static int zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *); | |||
82 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *); | 82 | static int zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *); |
83 | static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *); | 83 | static int zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *); |
84 | static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *); | 84 | static int zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *); |
85 | static int zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *); | ||
85 | static int zfcp_erp_adapter_strategy_open_fsf_statusread( | 86 | static int zfcp_erp_adapter_strategy_open_fsf_statusread( |
86 | struct zfcp_erp_action *); | 87 | struct zfcp_erp_action *); |
87 | 88 | ||
@@ -345,13 +346,13 @@ zfcp_erp_adisc(struct zfcp_port *port) | |||
345 | 346 | ||
346 | /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports | 347 | /* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports |
347 | without FC-AL-2 capability, so we don't set it */ | 348 | without FC-AL-2 capability, so we don't set it */ |
348 | adisc->wwpn = adapter->wwpn; | 349 | adisc->wwpn = fc_host_port_name(adapter->scsi_host); |
349 | adisc->wwnn = adapter->wwnn; | 350 | adisc->wwnn = fc_host_node_name(adapter->scsi_host); |
350 | adisc->nport_id = adapter->s_id; | 351 | adisc->nport_id = fc_host_port_id(adapter->scsi_host); |
351 | ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x " | 352 | ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x " |
352 | "(wwpn=0x%016Lx, wwnn=0x%016Lx, " | 353 | "(wwpn=0x%016Lx, wwnn=0x%016Lx, " |
353 | "hard_nport_id=0x%08x, nport_id=0x%08x)\n", | 354 | "hard_nport_id=0x%08x, nport_id=0x%08x)\n", |
354 | adapter->s_id, send_els->d_id, (wwn_t) adisc->wwpn, | 355 | adisc->nport_id, send_els->d_id, (wwn_t) adisc->wwpn, |
355 | (wwn_t) adisc->wwnn, adisc->hard_nport_id, | 356 | (wwn_t) adisc->wwnn, adisc->hard_nport_id, |
356 | adisc->nport_id); | 357 | adisc->nport_id); |
357 | 358 | ||
@@ -404,7 +405,7 @@ zfcp_erp_adisc_handler(unsigned long data) | |||
404 | struct zfcp_send_els *send_els; | 405 | struct zfcp_send_els *send_els; |
405 | struct zfcp_port *port; | 406 | struct zfcp_port *port; |
406 | struct zfcp_adapter *adapter; | 407 | struct zfcp_adapter *adapter; |
407 | fc_id_t d_id; | 408 | u32 d_id; |
408 | struct zfcp_ls_adisc_acc *adisc; | 409 | struct zfcp_ls_adisc_acc *adisc; |
409 | 410 | ||
410 | send_els = (struct zfcp_send_els *) data; | 411 | send_els = (struct zfcp_send_els *) data; |
@@ -435,9 +436,9 @@ zfcp_erp_adisc_handler(unsigned long data) | |||
435 | ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id " | 436 | ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id " |
436 | "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " | 437 | "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " |
437 | "hard_nport_id=0x%08x, nport_id=0x%08x)\n", | 438 | "hard_nport_id=0x%08x, nport_id=0x%08x)\n", |
438 | d_id, adapter->s_id, (wwn_t) adisc->wwpn, | 439 | d_id, fc_host_port_id(adapter->scsi_host), |
439 | (wwn_t) adisc->wwnn, adisc->hard_nport_id, | 440 | (wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn, |
440 | adisc->nport_id); | 441 | adisc->hard_nport_id, adisc->nport_id); |
441 | 442 | ||
442 | /* set wwnn for port */ | 443 | /* set wwnn for port */ |
443 | if (port->wwnn == 0) | 444 | if (port->wwnn == 0) |
@@ -886,7 +887,7 @@ static int | |||
886 | zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) | 887 | zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) |
887 | { | 888 | { |
888 | int retval = 0; | 889 | int retval = 0; |
889 | struct zfcp_fsf_req *fsf_req; | 890 | struct zfcp_fsf_req *fsf_req = NULL; |
890 | struct zfcp_adapter *adapter = erp_action->adapter; | 891 | struct zfcp_adapter *adapter = erp_action->adapter; |
891 | 892 | ||
892 | if (erp_action->fsf_req) { | 893 | if (erp_action->fsf_req) { |
@@ -896,7 +897,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) | |||
896 | list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list) | 897 | list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list) |
897 | if (fsf_req == erp_action->fsf_req) | 898 | if (fsf_req == erp_action->fsf_req) |
898 | break; | 899 | break; |
899 | if (fsf_req == erp_action->fsf_req) { | 900 | if (fsf_req && (fsf_req->erp_action == erp_action)) { |
900 | /* fsf_req still exists */ | 901 | /* fsf_req still exists */ |
901 | debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); | 902 | debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); |
902 | debug_event(adapter->erp_dbf, 3, &fsf_req, | 903 | debug_event(adapter->erp_dbf, 3, &fsf_req, |
@@ -2258,16 +2259,21 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) | |||
2258 | static int | 2259 | static int |
2259 | zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) | 2260 | zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) |
2260 | { | 2261 | { |
2261 | int retval; | 2262 | int xconfig, xport; |
2263 | |||
2264 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
2265 | &erp_action->adapter->status)) { | ||
2266 | zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); | ||
2267 | atomic_set(&erp_action->adapter->erp_counter, 0); | ||
2268 | return ZFCP_ERP_FAILED; | ||
2269 | } | ||
2262 | 2270 | ||
2263 | /* do 'exchange configuration data' */ | 2271 | xconfig = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); |
2264 | retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); | 2272 | xport = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); |
2265 | if (retval == ZFCP_ERP_FAILED) | 2273 | if ((xconfig == ZFCP_ERP_FAILED) || (xport == ZFCP_ERP_FAILED)) |
2266 | return retval; | 2274 | return ZFCP_ERP_FAILED; |
2267 | 2275 | ||
2268 | /* start the desired number of Status Reads */ | 2276 | return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); |
2269 | retval = zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); | ||
2270 | return retval; | ||
2271 | } | 2277 | } |
2272 | 2278 | ||
2273 | /* | 2279 | /* |
@@ -2291,7 +2297,9 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) | |||
2291 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, | 2297 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, |
2292 | &adapter->status); | 2298 | &adapter->status); |
2293 | ZFCP_LOG_DEBUG("Doing exchange config data\n"); | 2299 | ZFCP_LOG_DEBUG("Doing exchange config data\n"); |
2300 | write_lock(&adapter->erp_lock); | ||
2294 | zfcp_erp_action_to_running(erp_action); | 2301 | zfcp_erp_action_to_running(erp_action); |
2302 | write_unlock(&adapter->erp_lock); | ||
2295 | zfcp_erp_timeout_init(erp_action); | 2303 | zfcp_erp_timeout_init(erp_action); |
2296 | if (zfcp_fsf_exchange_config_data(erp_action)) { | 2304 | if (zfcp_fsf_exchange_config_data(erp_action)) { |
2297 | retval = ZFCP_ERP_FAILED; | 2305 | retval = ZFCP_ERP_FAILED; |
@@ -2348,6 +2356,76 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) | |||
2348 | return retval; | 2356 | return retval; |
2349 | } | 2357 | } |
2350 | 2358 | ||
2359 | static int | ||
2360 | zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) | ||
2361 | { | ||
2362 | int retval = ZFCP_ERP_SUCCEEDED; | ||
2363 | int retries; | ||
2364 | int sleep; | ||
2365 | struct zfcp_adapter *adapter = erp_action->adapter; | ||
2366 | |||
2367 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); | ||
2368 | |||
2369 | for (retries = 0; ; retries++) { | ||
2370 | ZFCP_LOG_DEBUG("Doing exchange port data\n"); | ||
2371 | zfcp_erp_action_to_running(erp_action); | ||
2372 | zfcp_erp_timeout_init(erp_action); | ||
2373 | if (zfcp_fsf_exchange_port_data(erp_action, adapter, NULL)) { | ||
2374 | retval = ZFCP_ERP_FAILED; | ||
2375 | debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf"); | ||
2376 | ZFCP_LOG_INFO("error: initiation of exchange of " | ||
2377 | "port data failed for adapter %s\n", | ||
2378 | zfcp_get_busid_by_adapter(adapter)); | ||
2379 | break; | ||
2380 | } | ||
2381 | debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok"); | ||
2382 | ZFCP_LOG_DEBUG("Xchange underway\n"); | ||
2383 | |||
2384 | /* | ||
2385 | * Why this works: | ||
2386 | * Both the normal completion handler as well as the timeout | ||
2387 | * handler will do an 'up' when the 'exchange port data' | ||
2388 | * request completes or times out. Thus, the signal to go on | ||
2389 | * won't be lost utilizing this semaphore. | ||
2390 | * Furthermore, this 'adapter_reopen' action is | ||
2391 | * guaranteed to be the only action being there (highest action | ||
2392 | * which prevents other actions from being created). | ||
2393 | * Resulting from that, the wake signal recognized here | ||
2394 | * _must_ be the one belonging to the 'exchange port | ||
2395 | * data' request. | ||
2396 | */ | ||
2397 | down(&adapter->erp_ready_sem); | ||
2398 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { | ||
2399 | ZFCP_LOG_INFO("error: exchange of port data " | ||
2400 | "for adapter %s timed out\n", | ||
2401 | zfcp_get_busid_by_adapter(adapter)); | ||
2402 | break; | ||
2403 | } | ||
2404 | |||
2405 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
2406 | &adapter->status)) | ||
2407 | break; | ||
2408 | |||
2409 | ZFCP_LOG_DEBUG("host connection still initialising... " | ||
2410 | "waiting and retrying...\n"); | ||
2411 | /* sleep a little bit before retry */ | ||
2412 | sleep = retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES ? | ||
2413 | ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP : | ||
2414 | ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP; | ||
2415 | msleep(jiffies_to_msecs(sleep)); | ||
2416 | } | ||
2417 | |||
2418 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
2419 | &adapter->status)) { | ||
2420 | ZFCP_LOG_INFO("error: exchange of port data for " | ||
2421 | "adapter %s failed\n", | ||
2422 | zfcp_get_busid_by_adapter(adapter)); | ||
2423 | retval = ZFCP_ERP_FAILED; | ||
2424 | } | ||
2425 | |||
2426 | return retval; | ||
2427 | } | ||
2428 | |||
2351 | /* | 2429 | /* |
2352 | * function: | 2430 | * function: |
2353 | * | 2431 | * |
@@ -3194,11 +3272,19 @@ zfcp_erp_action_enqueue(int action, | |||
3194 | /* fall through !!! */ | 3272 | /* fall through !!! */ |
3195 | 3273 | ||
3196 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: | 3274 | case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: |
3197 | if (atomic_test_mask | 3275 | if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, |
3198 | (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status) | 3276 | &port->status)) { |
3199 | && port->erp_action.action == | 3277 | if (port->erp_action.action != |
3200 | ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) { | 3278 | ZFCP_ERP_ACTION_REOPEN_PORT_FORCED) { |
3201 | debug_text_event(adapter->erp_dbf, 4, "pf_actenq_drp"); | 3279 | ZFCP_LOG_INFO("dropped erp action %i (port " |
3280 | "0x%016Lx, action in use: %i)\n", | ||
3281 | action, port->wwpn, | ||
3282 | port->erp_action.action); | ||
3283 | debug_text_event(adapter->erp_dbf, 4, | ||
3284 | "pf_actenq_drp"); | ||
3285 | } else | ||
3286 | debug_text_event(adapter->erp_dbf, 4, | ||
3287 | "pf_actenq_drpcp"); | ||
3202 | debug_event(adapter->erp_dbf, 4, &port->wwpn, | 3288 | debug_event(adapter->erp_dbf, 4, &port->wwpn, |
3203 | sizeof (wwn_t)); | 3289 | sizeof (wwn_t)); |
3204 | goto out; | 3290 | goto out; |
@@ -3589,6 +3675,9 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter) | |||
3589 | struct zfcp_port *port; | 3675 | struct zfcp_port *port; |
3590 | unsigned long flags; | 3676 | unsigned long flags; |
3591 | 3677 | ||
3678 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) | ||
3679 | return; | ||
3680 | |||
3592 | debug_text_event(adapter->erp_dbf, 3, "a_access_recover"); | 3681 | debug_text_event(adapter->erp_dbf, 3, "a_access_recover"); |
3593 | debug_event(adapter->erp_dbf, 3, &adapter->name, 8); | 3682 | debug_event(adapter->erp_dbf, 3, &adapter->name, 8); |
3594 | 3683 | ||
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index cd98a2de9f8f..c3782261cb5c 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -96,7 +96,8 @@ extern int zfcp_fsf_open_unit(struct zfcp_erp_action *); | |||
96 | extern int zfcp_fsf_close_unit(struct zfcp_erp_action *); | 96 | extern int zfcp_fsf_close_unit(struct zfcp_erp_action *); |
97 | 97 | ||
98 | extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *); | 98 | extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *); |
99 | extern int zfcp_fsf_exchange_port_data(struct zfcp_adapter *, | 99 | extern int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *, |
100 | struct zfcp_adapter *, | ||
100 | struct fsf_qtcb_bottom_port *); | 101 | struct fsf_qtcb_bottom_port *); |
101 | extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **, | 102 | extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **, |
102 | u32, u32, struct zfcp_sg_list *); | 103 | u32, u32, struct zfcp_sg_list *); |
@@ -109,7 +110,6 @@ extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *, | |||
109 | extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *, | 110 | extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *, |
110 | struct zfcp_erp_action *); | 111 | struct zfcp_erp_action *); |
111 | extern int zfcp_fsf_send_els(struct zfcp_send_els *); | 112 | extern int zfcp_fsf_send_els(struct zfcp_send_els *); |
112 | extern int zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *, int, u32 *); | ||
113 | extern int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *, | 113 | extern int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *, |
114 | struct zfcp_unit *, | 114 | struct zfcp_unit *, |
115 | struct scsi_cmnd *, | 115 | struct scsi_cmnd *, |
@@ -182,9 +182,25 @@ extern void zfcp_erp_port_access_changed(struct zfcp_port *); | |||
182 | extern void zfcp_erp_unit_access_changed(struct zfcp_unit *); | 182 | extern void zfcp_erp_unit_access_changed(struct zfcp_unit *); |
183 | 183 | ||
184 | /******************************** AUX ****************************************/ | 184 | /******************************** AUX ****************************************/ |
185 | extern void zfcp_cmd_dbf_event_fsf(const char *, struct zfcp_fsf_req *, | 185 | extern void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *); |
186 | void *, int); | 186 | extern void zfcp_hba_dbf_event_fsf_unsol(const char *, struct zfcp_adapter *, |
187 | extern void zfcp_cmd_dbf_event_scsi(const char *, struct scsi_cmnd *); | 187 | struct fsf_status_read_buffer *); |
188 | extern void zfcp_in_els_dbf_event(struct zfcp_adapter *, const char *, | 188 | extern void zfcp_hba_dbf_event_qdio(struct zfcp_adapter *, |
189 | struct fsf_status_read_buffer *, int); | 189 | unsigned int, unsigned int, unsigned int, |
190 | int, int); | ||
191 | |||
192 | extern void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *); | ||
193 | extern void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *); | ||
194 | extern void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *); | ||
195 | extern void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *); | ||
196 | extern void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *); | ||
197 | |||
198 | extern void zfcp_scsi_dbf_event_result(const char *, int, struct zfcp_adapter *, | ||
199 | struct scsi_cmnd *); | ||
200 | extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *, | ||
201 | struct scsi_cmnd *, | ||
202 | struct zfcp_fsf_req *); | ||
203 | extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, | ||
204 | struct scsi_cmnd *); | ||
205 | |||
190 | #endif /* ZFCP_EXT_H */ | 206 | #endif /* ZFCP_EXT_H */ |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index c007b6424e74..3b0fc1163f5f 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -59,6 +59,8 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *, struct timer_list *); | |||
59 | static int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *); | 59 | static int zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *); |
60 | static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *); | 60 | static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *); |
61 | static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *); | 61 | static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *); |
62 | static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *, | ||
63 | struct fsf_link_down_info *); | ||
62 | static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); | 64 | static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); |
63 | static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *); | 65 | static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *); |
64 | 66 | ||
@@ -285,51 +287,51 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) | |||
285 | { | 287 | { |
286 | int retval = 0; | 288 | int retval = 0; |
287 | struct zfcp_adapter *adapter = fsf_req->adapter; | 289 | struct zfcp_adapter *adapter = fsf_req->adapter; |
290 | struct fsf_qtcb *qtcb = fsf_req->qtcb; | ||
291 | union fsf_prot_status_qual *prot_status_qual = | ||
292 | &qtcb->prefix.prot_status_qual; | ||
288 | 293 | ||
289 | ZFCP_LOG_DEBUG("QTCB is at %p\n", fsf_req->qtcb); | 294 | zfcp_hba_dbf_event_fsf_response(fsf_req); |
290 | 295 | ||
291 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { | 296 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { |
292 | ZFCP_LOG_DEBUG("fsf_req 0x%lx has been dismissed\n", | 297 | ZFCP_LOG_DEBUG("fsf_req 0x%lx has been dismissed\n", |
293 | (unsigned long) fsf_req); | 298 | (unsigned long) fsf_req); |
294 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | | 299 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR | |
295 | ZFCP_STATUS_FSFREQ_RETRY; /* only for SCSI cmnds. */ | 300 | ZFCP_STATUS_FSFREQ_RETRY; /* only for SCSI cmnds. */ |
296 | zfcp_cmd_dbf_event_fsf("dismiss", fsf_req, NULL, 0); | ||
297 | goto skip_protstatus; | 301 | goto skip_protstatus; |
298 | } | 302 | } |
299 | 303 | ||
300 | /* log additional information provided by FSF (if any) */ | 304 | /* log additional information provided by FSF (if any) */ |
301 | if (unlikely(fsf_req->qtcb->header.log_length)) { | 305 | if (unlikely(qtcb->header.log_length)) { |
302 | /* do not trust them ;-) */ | 306 | /* do not trust them ;-) */ |
303 | if (fsf_req->qtcb->header.log_start > sizeof(struct fsf_qtcb)) { | 307 | if (qtcb->header.log_start > sizeof(struct fsf_qtcb)) { |
304 | ZFCP_LOG_NORMAL | 308 | ZFCP_LOG_NORMAL |
305 | ("bug: ULP (FSF logging) log data starts " | 309 | ("bug: ULP (FSF logging) log data starts " |
306 | "beyond end of packet header. Ignored. " | 310 | "beyond end of packet header. Ignored. " |
307 | "(start=%i, size=%li)\n", | 311 | "(start=%i, size=%li)\n", |
308 | fsf_req->qtcb->header.log_start, | 312 | qtcb->header.log_start, |
309 | sizeof(struct fsf_qtcb)); | 313 | sizeof(struct fsf_qtcb)); |
310 | goto forget_log; | 314 | goto forget_log; |
311 | } | 315 | } |
312 | if ((size_t) (fsf_req->qtcb->header.log_start + | 316 | if ((size_t) (qtcb->header.log_start + qtcb->header.log_length) |
313 | fsf_req->qtcb->header.log_length) | ||
314 | > sizeof(struct fsf_qtcb)) { | 317 | > sizeof(struct fsf_qtcb)) { |
315 | ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends " | 318 | ZFCP_LOG_NORMAL("bug: ULP (FSF logging) log data ends " |
316 | "beyond end of packet header. Ignored. " | 319 | "beyond end of packet header. Ignored. " |
317 | "(start=%i, length=%i, size=%li)\n", | 320 | "(start=%i, length=%i, size=%li)\n", |
318 | fsf_req->qtcb->header.log_start, | 321 | qtcb->header.log_start, |
319 | fsf_req->qtcb->header.log_length, | 322 | qtcb->header.log_length, |
320 | sizeof(struct fsf_qtcb)); | 323 | sizeof(struct fsf_qtcb)); |
321 | goto forget_log; | 324 | goto forget_log; |
322 | } | 325 | } |
323 | ZFCP_LOG_TRACE("ULP log data: \n"); | 326 | ZFCP_LOG_TRACE("ULP log data: \n"); |
324 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, | 327 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, |
325 | (char *) fsf_req->qtcb + | 328 | (char *) qtcb + qtcb->header.log_start, |
326 | fsf_req->qtcb->header.log_start, | 329 | qtcb->header.log_length); |
327 | fsf_req->qtcb->header.log_length); | ||
328 | } | 330 | } |
329 | forget_log: | 331 | forget_log: |
330 | 332 | ||
331 | /* evaluate FSF Protocol Status */ | 333 | /* evaluate FSF Protocol Status */ |
332 | switch (fsf_req->qtcb->prefix.prot_status) { | 334 | switch (qtcb->prefix.prot_status) { |
333 | 335 | ||
334 | case FSF_PROT_GOOD: | 336 | case FSF_PROT_GOOD: |
335 | case FSF_PROT_FSF_STATUS_PRESENTED: | 337 | case FSF_PROT_FSF_STATUS_PRESENTED: |
@@ -340,14 +342,9 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) | |||
340 | "microcode of version 0x%x, the device driver " | 342 | "microcode of version 0x%x, the device driver " |
341 | "only supports 0x%x. Aborting.\n", | 343 | "only supports 0x%x. Aborting.\n", |
342 | zfcp_get_busid_by_adapter(adapter), | 344 | zfcp_get_busid_by_adapter(adapter), |
343 | fsf_req->qtcb->prefix.prot_status_qual. | 345 | prot_status_qual->version_error.fsf_version, |
344 | version_error.fsf_version, ZFCP_QTCB_VERSION); | 346 | ZFCP_QTCB_VERSION); |
345 | /* stop operation for this adapter */ | ||
346 | debug_text_exception(adapter->erp_dbf, 0, "prot_ver_err"); | ||
347 | zfcp_erp_adapter_shutdown(adapter, 0); | 347 | zfcp_erp_adapter_shutdown(adapter, 0); |
348 | zfcp_cmd_dbf_event_fsf("qverserr", fsf_req, | ||
349 | &fsf_req->qtcb->prefix.prot_status_qual, | ||
350 | sizeof (union fsf_prot_status_qual)); | ||
351 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 348 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
352 | break; | 349 | break; |
353 | 350 | ||
@@ -355,16 +352,10 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) | |||
355 | ZFCP_LOG_NORMAL("bug: Sequence number mismatch between " | 352 | ZFCP_LOG_NORMAL("bug: Sequence number mismatch between " |
356 | "driver (0x%x) and adapter %s (0x%x). " | 353 | "driver (0x%x) and adapter %s (0x%x). " |
357 | "Restarting all operations on this adapter.\n", | 354 | "Restarting all operations on this adapter.\n", |
358 | fsf_req->qtcb->prefix.req_seq_no, | 355 | qtcb->prefix.req_seq_no, |
359 | zfcp_get_busid_by_adapter(adapter), | 356 | zfcp_get_busid_by_adapter(adapter), |
360 | fsf_req->qtcb->prefix.prot_status_qual. | 357 | prot_status_qual->sequence_error.exp_req_seq_no); |
361 | sequence_error.exp_req_seq_no); | ||
362 | debug_text_exception(adapter->erp_dbf, 0, "prot_seq_err"); | ||
363 | /* restart operation on this adapter */ | ||
364 | zfcp_erp_adapter_reopen(adapter, 0); | 358 | zfcp_erp_adapter_reopen(adapter, 0); |
365 | zfcp_cmd_dbf_event_fsf("seqnoerr", fsf_req, | ||
366 | &fsf_req->qtcb->prefix.prot_status_qual, | ||
367 | sizeof (union fsf_prot_status_qual)); | ||
368 | fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY; | 359 | fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY; |
369 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 360 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
370 | break; | 361 | break; |
@@ -375,116 +366,35 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) | |||
375 | "that used on adapter %s. " | 366 | "that used on adapter %s. " |
376 | "Stopping all operations on this adapter.\n", | 367 | "Stopping all operations on this adapter.\n", |
377 | zfcp_get_busid_by_adapter(adapter)); | 368 | zfcp_get_busid_by_adapter(adapter)); |
378 | debug_text_exception(adapter->erp_dbf, 0, "prot_unsup_qtcb"); | ||
379 | zfcp_erp_adapter_shutdown(adapter, 0); | 369 | zfcp_erp_adapter_shutdown(adapter, 0); |
380 | zfcp_cmd_dbf_event_fsf("unsqtcbt", fsf_req, | ||
381 | &fsf_req->qtcb->prefix.prot_status_qual, | ||
382 | sizeof (union fsf_prot_status_qual)); | ||
383 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 370 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
384 | break; | 371 | break; |
385 | 372 | ||
386 | case FSF_PROT_HOST_CONNECTION_INITIALIZING: | 373 | case FSF_PROT_HOST_CONNECTION_INITIALIZING: |
387 | zfcp_cmd_dbf_event_fsf("hconinit", fsf_req, | ||
388 | &fsf_req->qtcb->prefix.prot_status_qual, | ||
389 | sizeof (union fsf_prot_status_qual)); | ||
390 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 374 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
391 | atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, | 375 | atomic_set_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT, |
392 | &(adapter->status)); | 376 | &(adapter->status)); |
393 | debug_text_event(adapter->erp_dbf, 3, "prot_con_init"); | ||
394 | break; | 377 | break; |
395 | 378 | ||
396 | case FSF_PROT_DUPLICATE_REQUEST_ID: | 379 | case FSF_PROT_DUPLICATE_REQUEST_ID: |
397 | if (fsf_req->qtcb) { | ||
398 | ZFCP_LOG_NORMAL("bug: The request identifier 0x%Lx " | 380 | ZFCP_LOG_NORMAL("bug: The request identifier 0x%Lx " |
399 | "to the adapter %s is ambiguous. " | 381 | "to the adapter %s is ambiguous. " |
400 | "Stopping all operations on this " | 382 | "Stopping all operations on this adapter.\n", |
401 | "adapter.\n", | 383 | *(unsigned long long*) |
402 | *(unsigned long long *) | 384 | (&qtcb->bottom.support.req_handle), |
403 | (&fsf_req->qtcb->bottom.support. | ||
404 | req_handle), | ||
405 | zfcp_get_busid_by_adapter(adapter)); | ||
406 | } else { | ||
407 | ZFCP_LOG_NORMAL("bug: The request identifier %p " | ||
408 | "to the adapter %s is ambiguous. " | ||
409 | "Stopping all operations on this " | ||
410 | "adapter. " | ||
411 | "(bug: got this for an unsolicited " | ||
412 | "status read request)\n", | ||
413 | fsf_req, | ||
414 | zfcp_get_busid_by_adapter(adapter)); | 385 | zfcp_get_busid_by_adapter(adapter)); |
415 | } | ||
416 | debug_text_exception(adapter->erp_dbf, 0, "prot_dup_id"); | ||
417 | zfcp_erp_adapter_shutdown(adapter, 0); | 386 | zfcp_erp_adapter_shutdown(adapter, 0); |
418 | zfcp_cmd_dbf_event_fsf("dupreqid", fsf_req, | ||
419 | &fsf_req->qtcb->prefix.prot_status_qual, | ||
420 | sizeof (union fsf_prot_status_qual)); | ||
421 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 387 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
422 | break; | 388 | break; |
423 | 389 | ||
424 | case FSF_PROT_LINK_DOWN: | 390 | case FSF_PROT_LINK_DOWN: |
425 | /* | 391 | zfcp_fsf_link_down_info_eval(adapter, |
426 | * 'test and set' is not atomic here - | 392 | &prot_status_qual->link_down_info); |
427 | * it's ok as long as calls to our response queue handler | ||
428 | * (and thus execution of this code here) are serialized | ||
429 | * by the qdio module | ||
430 | */ | ||
431 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
432 | &adapter->status)) { | ||
433 | switch (fsf_req->qtcb->prefix.prot_status_qual. | ||
434 | locallink_error.code) { | ||
435 | case FSF_PSQ_LINK_NOLIGHT: | ||
436 | ZFCP_LOG_INFO("The local link to adapter %s " | ||
437 | "is down (no light detected).\n", | ||
438 | zfcp_get_busid_by_adapter( | ||
439 | adapter)); | ||
440 | break; | ||
441 | case FSF_PSQ_LINK_WRAPPLUG: | ||
442 | ZFCP_LOG_INFO("The local link to adapter %s " | ||
443 | "is down (wrap plug detected).\n", | ||
444 | zfcp_get_busid_by_adapter( | ||
445 | adapter)); | ||
446 | break; | ||
447 | case FSF_PSQ_LINK_NOFCP: | ||
448 | ZFCP_LOG_INFO("The local link to adapter %s " | ||
449 | "is down (adjacent node on " | ||
450 | "link does not support FCP).\n", | ||
451 | zfcp_get_busid_by_adapter( | ||
452 | adapter)); | ||
453 | break; | ||
454 | default: | ||
455 | ZFCP_LOG_INFO("The local link to adapter %s " | ||
456 | "is down " | ||
457 | "(warning: unknown reason " | ||
458 | "code).\n", | ||
459 | zfcp_get_busid_by_adapter( | ||
460 | adapter)); | ||
461 | break; | ||
462 | |||
463 | } | ||
464 | /* | ||
465 | * Due to the 'erp failed' flag the adapter won't | ||
466 | * be recovered but will be just set to 'blocked' | ||
467 | * state. All subordinary devices will have state | ||
468 | * 'blocked' and 'erp failed', too. | ||
469 | * Thus the adapter is still able to provide | ||
470 | * 'link up' status without being flooded with | ||
471 | * requests. | ||
472 | * (note: even 'close port' is not permitted) | ||
473 | */ | ||
474 | ZFCP_LOG_INFO("Stopping all operations for adapter " | ||
475 | "%s.\n", | ||
476 | zfcp_get_busid_by_adapter(adapter)); | ||
477 | atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | | ||
478 | ZFCP_STATUS_COMMON_ERP_FAILED, | ||
479 | &adapter->status); | ||
480 | zfcp_erp_adapter_reopen(adapter, 0); | ||
481 | } | ||
482 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 393 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
483 | break; | 394 | break; |
484 | 395 | ||
485 | case FSF_PROT_REEST_QUEUE: | 396 | case FSF_PROT_REEST_QUEUE: |
486 | debug_text_event(adapter->erp_dbf, 1, "prot_reest_queue"); | 397 | ZFCP_LOG_NORMAL("The local link to adapter with " |
487 | ZFCP_LOG_INFO("The local link to adapter with " | ||
488 | "%s was re-plugged. " | 398 | "%s was re-plugged. " |
489 | "Re-starting operations on this adapter.\n", | 399 | "Re-starting operations on this adapter.\n", |
490 | zfcp_get_busid_by_adapter(adapter)); | 400 | zfcp_get_busid_by_adapter(adapter)); |
@@ -495,9 +405,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) | |||
495 | zfcp_erp_adapter_reopen(adapter, | 405 | zfcp_erp_adapter_reopen(adapter, |
496 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | 406 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
497 | | ZFCP_STATUS_COMMON_ERP_FAILED); | 407 | | ZFCP_STATUS_COMMON_ERP_FAILED); |
498 | zfcp_cmd_dbf_event_fsf("reestque", fsf_req, | ||
499 | &fsf_req->qtcb->prefix.prot_status_qual, | ||
500 | sizeof (union fsf_prot_status_qual)); | ||
501 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 408 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
502 | break; | 409 | break; |
503 | 410 | ||
@@ -507,12 +414,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) | |||
507 | "Restarting all operations on this " | 414 | "Restarting all operations on this " |
508 | "adapter.\n", | 415 | "adapter.\n", |
509 | zfcp_get_busid_by_adapter(adapter)); | 416 | zfcp_get_busid_by_adapter(adapter)); |
510 | debug_text_event(adapter->erp_dbf, 0, "prot_err_sta"); | ||
511 | /* restart operation on this adapter */ | ||
512 | zfcp_erp_adapter_reopen(adapter, 0); | 417 | zfcp_erp_adapter_reopen(adapter, 0); |
513 | zfcp_cmd_dbf_event_fsf("proterrs", fsf_req, | ||
514 | &fsf_req->qtcb->prefix.prot_status_qual, | ||
515 | sizeof (union fsf_prot_status_qual)); | ||
516 | fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY; | 418 | fsf_req->status |= ZFCP_STATUS_FSFREQ_RETRY; |
517 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 419 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
518 | break; | 420 | break; |
@@ -524,11 +426,7 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req) | |||
524 | "Stopping all operations on this adapter. " | 426 | "Stopping all operations on this adapter. " |
525 | "(debug info 0x%x).\n", | 427 | "(debug info 0x%x).\n", |
526 | zfcp_get_busid_by_adapter(adapter), | 428 | zfcp_get_busid_by_adapter(adapter), |
527 | fsf_req->qtcb->prefix.prot_status); | 429 | qtcb->prefix.prot_status); |
528 | debug_text_event(adapter->erp_dbf, 0, "prot_inval:"); | ||
529 | debug_exception(adapter->erp_dbf, 0, | ||
530 | &fsf_req->qtcb->prefix.prot_status, | ||
531 | sizeof (u32)); | ||
532 | zfcp_erp_adapter_shutdown(adapter, 0); | 430 | zfcp_erp_adapter_shutdown(adapter, 0); |
533 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 431 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
534 | } | 432 | } |
@@ -568,28 +466,18 @@ zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *fsf_req) | |||
568 | "(debug info 0x%x).\n", | 466 | "(debug info 0x%x).\n", |
569 | zfcp_get_busid_by_adapter(fsf_req->adapter), | 467 | zfcp_get_busid_by_adapter(fsf_req->adapter), |
570 | fsf_req->qtcb->header.fsf_command); | 468 | fsf_req->qtcb->header.fsf_command); |
571 | debug_text_exception(fsf_req->adapter->erp_dbf, 0, | ||
572 | "fsf_s_unknown"); | ||
573 | zfcp_erp_adapter_shutdown(fsf_req->adapter, 0); | 469 | zfcp_erp_adapter_shutdown(fsf_req->adapter, 0); |
574 | zfcp_cmd_dbf_event_fsf("unknownc", fsf_req, | ||
575 | &fsf_req->qtcb->header.fsf_status_qual, | ||
576 | sizeof (union fsf_status_qual)); | ||
577 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 470 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
578 | break; | 471 | break; |
579 | 472 | ||
580 | case FSF_FCP_RSP_AVAILABLE: | 473 | case FSF_FCP_RSP_AVAILABLE: |
581 | ZFCP_LOG_DEBUG("FCP Sense data will be presented to the " | 474 | ZFCP_LOG_DEBUG("FCP Sense data will be presented to the " |
582 | "SCSI stack.\n"); | 475 | "SCSI stack.\n"); |
583 | debug_text_event(fsf_req->adapter->erp_dbf, 3, "fsf_s_rsp"); | ||
584 | break; | 476 | break; |
585 | 477 | ||
586 | case FSF_ADAPTER_STATUS_AVAILABLE: | 478 | case FSF_ADAPTER_STATUS_AVAILABLE: |
587 | debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_astatus"); | ||
588 | zfcp_fsf_fsfstatus_qual_eval(fsf_req); | 479 | zfcp_fsf_fsfstatus_qual_eval(fsf_req); |
589 | break; | 480 | break; |
590 | |||
591 | default: | ||
592 | break; | ||
593 | } | 481 | } |
594 | 482 | ||
595 | skip_fsfstatus: | 483 | skip_fsfstatus: |
@@ -617,44 +505,28 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req) | |||
617 | 505 | ||
618 | switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) { | 506 | switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) { |
619 | case FSF_SQ_FCP_RSP_AVAILABLE: | 507 | case FSF_SQ_FCP_RSP_AVAILABLE: |
620 | debug_text_event(fsf_req->adapter->erp_dbf, 4, "fsf_sq_rsp"); | ||
621 | break; | 508 | break; |
622 | case FSF_SQ_RETRY_IF_POSSIBLE: | 509 | case FSF_SQ_RETRY_IF_POSSIBLE: |
623 | /* The SCSI-stack may now issue retries or escalate */ | 510 | /* The SCSI-stack may now issue retries or escalate */ |
624 | debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_sq_retry"); | ||
625 | zfcp_cmd_dbf_event_fsf("sqretry", fsf_req, | ||
626 | &fsf_req->qtcb->header.fsf_status_qual, | ||
627 | sizeof (union fsf_status_qual)); | ||
628 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 511 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
629 | break; | 512 | break; |
630 | case FSF_SQ_COMMAND_ABORTED: | 513 | case FSF_SQ_COMMAND_ABORTED: |
631 | /* Carry the aborted state on to upper layer */ | 514 | /* Carry the aborted state on to upper layer */ |
632 | debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_sq_abort"); | ||
633 | zfcp_cmd_dbf_event_fsf("sqabort", fsf_req, | ||
634 | &fsf_req->qtcb->header.fsf_status_qual, | ||
635 | sizeof (union fsf_status_qual)); | ||
636 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTED; | 515 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTED; |
637 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 516 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
638 | break; | 517 | break; |
639 | case FSF_SQ_NO_RECOM: | 518 | case FSF_SQ_NO_RECOM: |
640 | debug_text_exception(fsf_req->adapter->erp_dbf, 0, | ||
641 | "fsf_sq_no_rec"); | ||
642 | ZFCP_LOG_NORMAL("bug: No recommendation could be given for a" | 519 | ZFCP_LOG_NORMAL("bug: No recommendation could be given for a" |
643 | "problem on the adapter %s " | 520 | "problem on the adapter %s " |
644 | "Stopping all operations on this adapter. ", | 521 | "Stopping all operations on this adapter. ", |
645 | zfcp_get_busid_by_adapter(fsf_req->adapter)); | 522 | zfcp_get_busid_by_adapter(fsf_req->adapter)); |
646 | zfcp_erp_adapter_shutdown(fsf_req->adapter, 0); | 523 | zfcp_erp_adapter_shutdown(fsf_req->adapter, 0); |
647 | zfcp_cmd_dbf_event_fsf("sqnrecom", fsf_req, | ||
648 | &fsf_req->qtcb->header.fsf_status_qual, | ||
649 | sizeof (union fsf_status_qual)); | ||
650 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 524 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
651 | break; | 525 | break; |
652 | case FSF_SQ_ULP_PROGRAMMING_ERROR: | 526 | case FSF_SQ_ULP_PROGRAMMING_ERROR: |
653 | ZFCP_LOG_NORMAL("error: not enough SBALs for data transfer " | 527 | ZFCP_LOG_NORMAL("error: not enough SBALs for data transfer " |
654 | "(adapter %s)\n", | 528 | "(adapter %s)\n", |
655 | zfcp_get_busid_by_adapter(fsf_req->adapter)); | 529 | zfcp_get_busid_by_adapter(fsf_req->adapter)); |
656 | debug_text_exception(fsf_req->adapter->erp_dbf, 0, | ||
657 | "fsf_sq_ulp_err"); | ||
658 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 530 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
659 | break; | 531 | break; |
660 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: | 532 | case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE: |
@@ -668,13 +540,6 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req) | |||
668 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, | 540 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, |
669 | (char *) &fsf_req->qtcb->header.fsf_status_qual, | 541 | (char *) &fsf_req->qtcb->header.fsf_status_qual, |
670 | sizeof (union fsf_status_qual)); | 542 | sizeof (union fsf_status_qual)); |
671 | debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf_sq_inval:"); | ||
672 | debug_exception(fsf_req->adapter->erp_dbf, 0, | ||
673 | &fsf_req->qtcb->header.fsf_status_qual.word[0], | ||
674 | sizeof (u32)); | ||
675 | zfcp_cmd_dbf_event_fsf("squndef", fsf_req, | ||
676 | &fsf_req->qtcb->header.fsf_status_qual, | ||
677 | sizeof (union fsf_status_qual)); | ||
678 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 543 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
679 | break; | 544 | break; |
680 | } | 545 | } |
@@ -682,6 +547,110 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req) | |||
682 | return retval; | 547 | return retval; |
683 | } | 548 | } |
684 | 549 | ||
550 | /** | ||
551 | * zfcp_fsf_link_down_info_eval - evaluate link down information block | ||
552 | */ | ||
553 | static void | ||
554 | zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, | ||
555 | struct fsf_link_down_info *link_down) | ||
556 | { | ||
557 | switch (link_down->error_code) { | ||
558 | case FSF_PSQ_LINK_NO_LIGHT: | ||
559 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
560 | "(no light detected)\n", | ||
561 | zfcp_get_busid_by_adapter(adapter)); | ||
562 | break; | ||
563 | case FSF_PSQ_LINK_WRAP_PLUG: | ||
564 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
565 | "(wrap plug detected)\n", | ||
566 | zfcp_get_busid_by_adapter(adapter)); | ||
567 | break; | ||
568 | case FSF_PSQ_LINK_NO_FCP: | ||
569 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
570 | "(adjacent node on link does not support FCP)\n", | ||
571 | zfcp_get_busid_by_adapter(adapter)); | ||
572 | break; | ||
573 | case FSF_PSQ_LINK_FIRMWARE_UPDATE: | ||
574 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
575 | "(firmware update in progress)\n", | ||
576 | zfcp_get_busid_by_adapter(adapter)); | ||
577 | break; | ||
578 | case FSF_PSQ_LINK_INVALID_WWPN: | ||
579 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
580 | "(duplicate or invalid WWPN detected)\n", | ||
581 | zfcp_get_busid_by_adapter(adapter)); | ||
582 | break; | ||
583 | case FSF_PSQ_LINK_NO_NPIV_SUPPORT: | ||
584 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
585 | "(no support for NPIV by Fabric)\n", | ||
586 | zfcp_get_busid_by_adapter(adapter)); | ||
587 | break; | ||
588 | case FSF_PSQ_LINK_NO_FCP_RESOURCES: | ||
589 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
590 | "(out of resource in FCP daughtercard)\n", | ||
591 | zfcp_get_busid_by_adapter(adapter)); | ||
592 | break; | ||
593 | case FSF_PSQ_LINK_NO_FABRIC_RESOURCES: | ||
594 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
595 | "(out of resource in Fabric)\n", | ||
596 | zfcp_get_busid_by_adapter(adapter)); | ||
597 | break; | ||
598 | case FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE: | ||
599 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
600 | "(unable to Fabric login)\n", | ||
601 | zfcp_get_busid_by_adapter(adapter)); | ||
602 | break; | ||
603 | case FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED: | ||
604 | ZFCP_LOG_NORMAL("WWPN assignment file corrupted on adapter %s\n", | ||
605 | zfcp_get_busid_by_adapter(adapter)); | ||
606 | break; | ||
607 | case FSF_PSQ_LINK_MODE_TABLE_CURRUPTED: | ||
608 | ZFCP_LOG_NORMAL("Mode table corrupted on adapter %s\n", | ||
609 | zfcp_get_busid_by_adapter(adapter)); | ||
610 | break; | ||
611 | case FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT: | ||
612 | ZFCP_LOG_NORMAL("No WWPN for assignment table on adapter %s\n", | ||
613 | zfcp_get_busid_by_adapter(adapter)); | ||
614 | break; | ||
615 | default: | ||
616 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | ||
617 | "(warning: unknown reason code %d)\n", | ||
618 | zfcp_get_busid_by_adapter(adapter), | ||
619 | link_down->error_code); | ||
620 | } | ||
621 | |||
622 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) | ||
623 | ZFCP_LOG_DEBUG("Debug information to link down: " | ||
624 | "primary_status=0x%02x " | ||
625 | "ioerr_code=0x%02x " | ||
626 | "action_code=0x%02x " | ||
627 | "reason_code=0x%02x " | ||
628 | "explanation_code=0x%02x " | ||
629 | "vendor_specific_code=0x%02x\n", | ||
630 | link_down->primary_status, | ||
631 | link_down->ioerr_code, | ||
632 | link_down->action_code, | ||
633 | link_down->reason_code, | ||
634 | link_down->explanation_code, | ||
635 | link_down->vendor_specific_code); | ||
636 | |||
637 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
638 | &adapter->status)) { | ||
639 | atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
640 | &adapter->status); | ||
641 | switch (link_down->error_code) { | ||
642 | case FSF_PSQ_LINK_NO_LIGHT: | ||
643 | case FSF_PSQ_LINK_WRAP_PLUG: | ||
644 | case FSF_PSQ_LINK_NO_FCP: | ||
645 | case FSF_PSQ_LINK_FIRMWARE_UPDATE: | ||
646 | zfcp_erp_adapter_reopen(adapter, 0); | ||
647 | break; | ||
648 | default: | ||
649 | zfcp_erp_adapter_failed(adapter); | ||
650 | } | ||
651 | } | ||
652 | } | ||
653 | |||
685 | /* | 654 | /* |
686 | * function: zfcp_fsf_req_dispatch | 655 | * function: zfcp_fsf_req_dispatch |
687 | * | 656 | * |
@@ -696,11 +665,6 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req) | |||
696 | struct zfcp_adapter *adapter = fsf_req->adapter; | 665 | struct zfcp_adapter *adapter = fsf_req->adapter; |
697 | int retval = 0; | 666 | int retval = 0; |
698 | 667 | ||
699 | if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { | ||
700 | ZFCP_LOG_TRACE("fsf_req=%p, QTCB=%p\n", fsf_req, fsf_req->qtcb); | ||
701 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, | ||
702 | (char *) fsf_req->qtcb, sizeof(struct fsf_qtcb)); | ||
703 | } | ||
704 | 668 | ||
705 | switch (fsf_req->fsf_command) { | 669 | switch (fsf_req->fsf_command) { |
706 | 670 | ||
@@ -760,13 +724,13 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req) | |||
760 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 724 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
761 | ZFCP_LOG_NORMAL("bug: Command issued by the device driver is " | 725 | ZFCP_LOG_NORMAL("bug: Command issued by the device driver is " |
762 | "not supported by the adapter %s\n", | 726 | "not supported by the adapter %s\n", |
763 | zfcp_get_busid_by_adapter(fsf_req->adapter)); | 727 | zfcp_get_busid_by_adapter(adapter)); |
764 | if (fsf_req->fsf_command != fsf_req->qtcb->header.fsf_command) | 728 | if (fsf_req->fsf_command != fsf_req->qtcb->header.fsf_command) |
765 | ZFCP_LOG_NORMAL | 729 | ZFCP_LOG_NORMAL |
766 | ("bug: Command issued by the device driver differs " | 730 | ("bug: Command issued by the device driver differs " |
767 | "from the command returned by the adapter %s " | 731 | "from the command returned by the adapter %s " |
768 | "(debug info 0x%x, 0x%x).\n", | 732 | "(debug info 0x%x, 0x%x).\n", |
769 | zfcp_get_busid_by_adapter(fsf_req->adapter), | 733 | zfcp_get_busid_by_adapter(adapter), |
770 | fsf_req->fsf_command, | 734 | fsf_req->fsf_command, |
771 | fsf_req->qtcb->header.fsf_command); | 735 | fsf_req->qtcb->header.fsf_command); |
772 | } | 736 | } |
@@ -774,8 +738,6 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req) | |||
774 | if (!erp_action) | 738 | if (!erp_action) |
775 | return retval; | 739 | return retval; |
776 | 740 | ||
777 | debug_text_event(adapter->erp_dbf, 3, "a_frh"); | ||
778 | debug_event(adapter->erp_dbf, 3, &erp_action->action, sizeof (int)); | ||
779 | zfcp_erp_async_handler(erp_action, 0); | 741 | zfcp_erp_async_handler(erp_action, 0); |
780 | 742 | ||
781 | return retval; | 743 | return retval; |
@@ -821,7 +783,7 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags) | |||
821 | goto failed_buf; | 783 | goto failed_buf; |
822 | } | 784 | } |
823 | memset(status_buffer, 0, sizeof (struct fsf_status_read_buffer)); | 785 | memset(status_buffer, 0, sizeof (struct fsf_status_read_buffer)); |
824 | fsf_req->data.status_read.buffer = status_buffer; | 786 | fsf_req->data = (unsigned long) status_buffer; |
825 | 787 | ||
826 | /* insert pointer to respective buffer */ | 788 | /* insert pointer to respective buffer */ |
827 | sbale = zfcp_qdio_sbale_curr(fsf_req); | 789 | sbale = zfcp_qdio_sbale_curr(fsf_req); |
@@ -846,6 +808,7 @@ zfcp_fsf_status_read(struct zfcp_adapter *adapter, int req_flags) | |||
846 | failed_buf: | 808 | failed_buf: |
847 | zfcp_fsf_req_free(fsf_req); | 809 | zfcp_fsf_req_free(fsf_req); |
848 | failed_req_create: | 810 | failed_req_create: |
811 | zfcp_hba_dbf_event_fsf_unsol("fail", adapter, NULL); | ||
849 | out: | 812 | out: |
850 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); | 813 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); |
851 | return retval; | 814 | return retval; |
@@ -859,7 +822,7 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req) | |||
859 | struct zfcp_port *port; | 822 | struct zfcp_port *port; |
860 | unsigned long flags; | 823 | unsigned long flags; |
861 | 824 | ||
862 | status_buffer = fsf_req->data.status_read.buffer; | 825 | status_buffer = (struct fsf_status_read_buffer *) fsf_req->data; |
863 | adapter = fsf_req->adapter; | 826 | adapter = fsf_req->adapter; |
864 | 827 | ||
865 | read_lock_irqsave(&zfcp_data.config_lock, flags); | 828 | read_lock_irqsave(&zfcp_data.config_lock, flags); |
@@ -918,38 +881,33 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) | |||
918 | int retval = 0; | 881 | int retval = 0; |
919 | struct zfcp_adapter *adapter = fsf_req->adapter; | 882 | struct zfcp_adapter *adapter = fsf_req->adapter; |
920 | struct fsf_status_read_buffer *status_buffer = | 883 | struct fsf_status_read_buffer *status_buffer = |
921 | fsf_req->data.status_read.buffer; | 884 | (struct fsf_status_read_buffer *) fsf_req->data; |
922 | 885 | ||
923 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { | 886 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) { |
887 | zfcp_hba_dbf_event_fsf_unsol("dism", adapter, status_buffer); | ||
924 | mempool_free(status_buffer, adapter->pool.data_status_read); | 888 | mempool_free(status_buffer, adapter->pool.data_status_read); |
925 | zfcp_fsf_req_free(fsf_req); | 889 | zfcp_fsf_req_free(fsf_req); |
926 | goto out; | 890 | goto out; |
927 | } | 891 | } |
928 | 892 | ||
893 | zfcp_hba_dbf_event_fsf_unsol("read", adapter, status_buffer); | ||
894 | |||
929 | switch (status_buffer->status_type) { | 895 | switch (status_buffer->status_type) { |
930 | 896 | ||
931 | case FSF_STATUS_READ_PORT_CLOSED: | 897 | case FSF_STATUS_READ_PORT_CLOSED: |
932 | debug_text_event(adapter->erp_dbf, 3, "unsol_pclosed:"); | ||
933 | debug_event(adapter->erp_dbf, 3, | ||
934 | &status_buffer->d_id, sizeof (u32)); | ||
935 | zfcp_fsf_status_read_port_closed(fsf_req); | 898 | zfcp_fsf_status_read_port_closed(fsf_req); |
936 | break; | 899 | break; |
937 | 900 | ||
938 | case FSF_STATUS_READ_INCOMING_ELS: | 901 | case FSF_STATUS_READ_INCOMING_ELS: |
939 | debug_text_event(adapter->erp_dbf, 3, "unsol_els:"); | ||
940 | zfcp_fsf_incoming_els(fsf_req); | 902 | zfcp_fsf_incoming_els(fsf_req); |
941 | break; | 903 | break; |
942 | 904 | ||
943 | case FSF_STATUS_READ_SENSE_DATA_AVAIL: | 905 | case FSF_STATUS_READ_SENSE_DATA_AVAIL: |
944 | debug_text_event(adapter->erp_dbf, 3, "unsol_sense:"); | ||
945 | ZFCP_LOG_INFO("unsolicited sense data received (adapter %s)\n", | 906 | ZFCP_LOG_INFO("unsolicited sense data received (adapter %s)\n", |
946 | zfcp_get_busid_by_adapter(adapter)); | 907 | zfcp_get_busid_by_adapter(adapter)); |
947 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, (char *) status_buffer, | ||
948 | sizeof(struct fsf_status_read_buffer)); | ||
949 | break; | 908 | break; |
950 | 909 | ||
951 | case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: | 910 | case FSF_STATUS_READ_BIT_ERROR_THRESHOLD: |
952 | debug_text_event(adapter->erp_dbf, 3, "unsol_bit_err:"); | ||
953 | ZFCP_LOG_NORMAL("Bit error threshold data received:\n"); | 911 | ZFCP_LOG_NORMAL("Bit error threshold data received:\n"); |
954 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, | 912 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, |
955 | (char *) status_buffer, | 913 | (char *) status_buffer, |
@@ -957,17 +915,32 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) | |||
957 | break; | 915 | break; |
958 | 916 | ||
959 | case FSF_STATUS_READ_LINK_DOWN: | 917 | case FSF_STATUS_READ_LINK_DOWN: |
960 | debug_text_event(adapter->erp_dbf, 0, "unsol_link_down:"); | 918 | switch (status_buffer->status_subtype) { |
961 | ZFCP_LOG_INFO("Local link to adapter %s is down\n", | 919 | case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: |
920 | ZFCP_LOG_INFO("Physical link to adapter %s is down\n", | ||
921 | zfcp_get_busid_by_adapter(adapter)); | ||
922 | break; | ||
923 | case FSF_STATUS_READ_SUB_FDISC_FAILED: | ||
924 | ZFCP_LOG_INFO("Local link to adapter %s is down " | ||
925 | "due to failed FDISC login\n", | ||
962 | zfcp_get_busid_by_adapter(adapter)); | 926 | zfcp_get_busid_by_adapter(adapter)); |
963 | atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 927 | break; |
964 | &adapter->status); | 928 | case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: |
965 | zfcp_erp_adapter_failed(adapter); | 929 | ZFCP_LOG_INFO("Local link to adapter %s is down " |
930 | "due to firmware update on adapter\n", | ||
931 | zfcp_get_busid_by_adapter(adapter)); | ||
932 | break; | ||
933 | default: | ||
934 | ZFCP_LOG_INFO("Local link to adapter %s is down " | ||
935 | "due to unknown reason\n", | ||
936 | zfcp_get_busid_by_adapter(adapter)); | ||
937 | }; | ||
938 | zfcp_fsf_link_down_info_eval(adapter, | ||
939 | (struct fsf_link_down_info *) &status_buffer->payload); | ||
966 | break; | 940 | break; |
967 | 941 | ||
968 | case FSF_STATUS_READ_LINK_UP: | 942 | case FSF_STATUS_READ_LINK_UP: |
969 | debug_text_event(adapter->erp_dbf, 2, "unsol_link_up:"); | 943 | ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. " |
970 | ZFCP_LOG_INFO("Local link to adapter %s was replugged. " | ||
971 | "Restarting operations on this adapter\n", | 944 | "Restarting operations on this adapter\n", |
972 | zfcp_get_busid_by_adapter(adapter)); | 945 | zfcp_get_busid_by_adapter(adapter)); |
973 | /* All ports should be marked as ready to run again */ | 946 | /* All ports should be marked as ready to run again */ |
@@ -980,35 +953,40 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) | |||
980 | break; | 953 | break; |
981 | 954 | ||
982 | case FSF_STATUS_READ_CFDC_UPDATED: | 955 | case FSF_STATUS_READ_CFDC_UPDATED: |
983 | debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_update:"); | 956 | ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n", |
984 | ZFCP_LOG_INFO("CFDC has been updated on the adapter %s\n", | ||
985 | zfcp_get_busid_by_adapter(adapter)); | 957 | zfcp_get_busid_by_adapter(adapter)); |
986 | zfcp_erp_adapter_access_changed(adapter); | 958 | zfcp_erp_adapter_access_changed(adapter); |
987 | break; | 959 | break; |
988 | 960 | ||
989 | case FSF_STATUS_READ_CFDC_HARDENED: | 961 | case FSF_STATUS_READ_CFDC_HARDENED: |
990 | debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_harden:"); | ||
991 | switch (status_buffer->status_subtype) { | 962 | switch (status_buffer->status_subtype) { |
992 | case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE: | 963 | case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE: |
993 | ZFCP_LOG_INFO("CFDC of adapter %s saved on SE\n", | 964 | ZFCP_LOG_NORMAL("CFDC of adapter %s saved on SE\n", |
994 | zfcp_get_busid_by_adapter(adapter)); | 965 | zfcp_get_busid_by_adapter(adapter)); |
995 | break; | 966 | break; |
996 | case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2: | 967 | case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2: |
997 | ZFCP_LOG_INFO("CFDC of adapter %s has been copied " | 968 | ZFCP_LOG_NORMAL("CFDC of adapter %s has been copied " |
998 | "to the secondary SE\n", | 969 | "to the secondary SE\n", |
999 | zfcp_get_busid_by_adapter(adapter)); | 970 | zfcp_get_busid_by_adapter(adapter)); |
1000 | break; | 971 | break; |
1001 | default: | 972 | default: |
1002 | ZFCP_LOG_INFO("CFDC of adapter %s has been hardened\n", | 973 | ZFCP_LOG_NORMAL("CFDC of adapter %s has been hardened\n", |
1003 | zfcp_get_busid_by_adapter(adapter)); | 974 | zfcp_get_busid_by_adapter(adapter)); |
1004 | } | 975 | } |
1005 | break; | 976 | break; |
1006 | 977 | ||
978 | case FSF_STATUS_READ_FEATURE_UPDATE_ALERT: | ||
979 | debug_text_event(adapter->erp_dbf, 2, "unsol_features:"); | ||
980 | ZFCP_LOG_INFO("List of supported features on adapter %s has " | ||
981 | "been changed from 0x%08X to 0x%08X\n", | ||
982 | zfcp_get_busid_by_adapter(adapter), | ||
983 | *(u32*) (status_buffer->payload + 4), | ||
984 | *(u32*) (status_buffer->payload)); | ||
985 | adapter->adapter_features = *(u32*) status_buffer->payload; | ||
986 | break; | ||
987 | |||
1007 | default: | 988 | default: |
1008 | debug_text_event(adapter->erp_dbf, 0, "unsol_unknown:"); | 989 | ZFCP_LOG_NORMAL("warning: An unsolicited status packet of unknown " |
1009 | debug_exception(adapter->erp_dbf, 0, | ||
1010 | &status_buffer->status_type, sizeof (u32)); | ||
1011 | ZFCP_LOG_NORMAL("bug: An unsolicited status packet of unknown " | ||
1012 | "type was received (debug info 0x%x)\n", | 990 | "type was received (debug info 0x%x)\n", |
1013 | status_buffer->status_type); | 991 | status_buffer->status_type); |
1014 | ZFCP_LOG_DEBUG("Dump of status_read_buffer %p:\n", | 992 | ZFCP_LOG_DEBUG("Dump of status_read_buffer %p:\n", |
@@ -1093,7 +1071,7 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id, | |||
1093 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 1071 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
1094 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 1072 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
1095 | 1073 | ||
1096 | fsf_req->data.abort_fcp_command.unit = unit; | 1074 | fsf_req->data = (unsigned long) unit; |
1097 | 1075 | ||
1098 | /* set handles of unit and its parent port in QTCB */ | 1076 | /* set handles of unit and its parent port in QTCB */ |
1099 | fsf_req->qtcb->header.lun_handle = unit->handle; | 1077 | fsf_req->qtcb->header.lun_handle = unit->handle; |
@@ -1139,7 +1117,7 @@ static int | |||
1139 | zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) | 1117 | zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) |
1140 | { | 1118 | { |
1141 | int retval = -EINVAL; | 1119 | int retval = -EINVAL; |
1142 | struct zfcp_unit *unit = new_fsf_req->data.abort_fcp_command.unit; | 1120 | struct zfcp_unit *unit; |
1143 | unsigned char status_qual = | 1121 | unsigned char status_qual = |
1144 | new_fsf_req->qtcb->header.fsf_status_qual.word[0]; | 1122 | new_fsf_req->qtcb->header.fsf_status_qual.word[0]; |
1145 | 1123 | ||
@@ -1150,6 +1128,8 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) | |||
1150 | goto skip_fsfstatus; | 1128 | goto skip_fsfstatus; |
1151 | } | 1129 | } |
1152 | 1130 | ||
1131 | unit = (struct zfcp_unit *) new_fsf_req->data; | ||
1132 | |||
1153 | /* evaluate FSF status in QTCB */ | 1133 | /* evaluate FSF status in QTCB */ |
1154 | switch (new_fsf_req->qtcb->header.fsf_status) { | 1134 | switch (new_fsf_req->qtcb->header.fsf_status) { |
1155 | 1135 | ||
@@ -1364,7 +1344,7 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, | |||
1364 | sbale[3].addr = zfcp_sg_to_address(&ct->resp[0]); | 1344 | sbale[3].addr = zfcp_sg_to_address(&ct->resp[0]); |
1365 | sbale[3].length = ct->resp[0].length; | 1345 | sbale[3].length = ct->resp[0].length; |
1366 | sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; | 1346 | sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; |
1367 | } else if (adapter->supported_features & | 1347 | } else if (adapter->adapter_features & |
1368 | FSF_FEATURE_ELS_CT_CHAINED_SBALS) { | 1348 | FSF_FEATURE_ELS_CT_CHAINED_SBALS) { |
1369 | /* try to use chained SBALs */ | 1349 | /* try to use chained SBALs */ |
1370 | bytes = zfcp_qdio_sbals_from_sg(fsf_req, | 1350 | bytes = zfcp_qdio_sbals_from_sg(fsf_req, |
@@ -1414,7 +1394,9 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, | |||
1414 | fsf_req->qtcb->header.port_handle = port->handle; | 1394 | fsf_req->qtcb->header.port_handle = port->handle; |
1415 | fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; | 1395 | fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; |
1416 | fsf_req->qtcb->bottom.support.timeout = ct->timeout; | 1396 | fsf_req->qtcb->bottom.support.timeout = ct->timeout; |
1417 | fsf_req->data.send_ct = ct; | 1397 | fsf_req->data = (unsigned long) ct; |
1398 | |||
1399 | zfcp_san_dbf_event_ct_request(fsf_req); | ||
1418 | 1400 | ||
1419 | /* start QDIO request for this FSF request */ | 1401 | /* start QDIO request for this FSF request */ |
1420 | ret = zfcp_fsf_req_send(fsf_req, ct->timer); | 1402 | ret = zfcp_fsf_req_send(fsf_req, ct->timer); |
@@ -1445,10 +1427,10 @@ zfcp_fsf_send_ct(struct zfcp_send_ct *ct, mempool_t *pool, | |||
1445 | * zfcp_fsf_send_ct_handler - handler for Generic Service requests | 1427 | * zfcp_fsf_send_ct_handler - handler for Generic Service requests |
1446 | * @fsf_req: pointer to struct zfcp_fsf_req | 1428 | * @fsf_req: pointer to struct zfcp_fsf_req |
1447 | * | 1429 | * |
1448 | * Data specific for the Generic Service request is passed by | 1430 | * Data specific for the Generic Service request is passed using |
1449 | * fsf_req->data.send_ct | 1431 | * fsf_req->data. There we find the pointer to struct zfcp_send_ct. |
1450 | * Usually a specific handler for the request is called via | 1432 | * Usually a specific handler for the CT request is called which is |
1451 | * fsf_req->data.send_ct->handler at end of this function. | 1433 | * found in this structure. |
1452 | */ | 1434 | */ |
1453 | static int | 1435 | static int |
1454 | zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) | 1436 | zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) |
@@ -1462,7 +1444,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) | |||
1462 | u16 subtable, rule, counter; | 1444 | u16 subtable, rule, counter; |
1463 | 1445 | ||
1464 | adapter = fsf_req->adapter; | 1446 | adapter = fsf_req->adapter; |
1465 | send_ct = fsf_req->data.send_ct; | 1447 | send_ct = (struct zfcp_send_ct *) fsf_req->data; |
1466 | port = send_ct->port; | 1448 | port = send_ct->port; |
1467 | header = &fsf_req->qtcb->header; | 1449 | header = &fsf_req->qtcb->header; |
1468 | bottom = &fsf_req->qtcb->bottom.support; | 1450 | bottom = &fsf_req->qtcb->bottom.support; |
@@ -1474,6 +1456,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req) | |||
1474 | switch (header->fsf_status) { | 1456 | switch (header->fsf_status) { |
1475 | 1457 | ||
1476 | case FSF_GOOD: | 1458 | case FSF_GOOD: |
1459 | zfcp_san_dbf_event_ct_response(fsf_req); | ||
1477 | retval = 0; | 1460 | retval = 0; |
1478 | break; | 1461 | break; |
1479 | 1462 | ||
@@ -1634,7 +1617,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) | |||
1634 | { | 1617 | { |
1635 | volatile struct qdio_buffer_element *sbale; | 1618 | volatile struct qdio_buffer_element *sbale; |
1636 | struct zfcp_fsf_req *fsf_req; | 1619 | struct zfcp_fsf_req *fsf_req; |
1637 | fc_id_t d_id; | 1620 | u32 d_id; |
1638 | struct zfcp_adapter *adapter; | 1621 | struct zfcp_adapter *adapter; |
1639 | unsigned long lock_flags; | 1622 | unsigned long lock_flags; |
1640 | int bytes; | 1623 | int bytes; |
@@ -1664,7 +1647,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) | |||
1664 | sbale[3].addr = zfcp_sg_to_address(&els->resp[0]); | 1647 | sbale[3].addr = zfcp_sg_to_address(&els->resp[0]); |
1665 | sbale[3].length = els->resp[0].length; | 1648 | sbale[3].length = els->resp[0].length; |
1666 | sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; | 1649 | sbale[3].flags |= SBAL_FLAGS_LAST_ENTRY; |
1667 | } else if (adapter->supported_features & | 1650 | } else if (adapter->adapter_features & |
1668 | FSF_FEATURE_ELS_CT_CHAINED_SBALS) { | 1651 | FSF_FEATURE_ELS_CT_CHAINED_SBALS) { |
1669 | /* try to use chained SBALs */ | 1652 | /* try to use chained SBALs */ |
1670 | bytes = zfcp_qdio_sbals_from_sg(fsf_req, | 1653 | bytes = zfcp_qdio_sbals_from_sg(fsf_req, |
@@ -1714,10 +1697,12 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) | |||
1714 | fsf_req->qtcb->bottom.support.d_id = d_id; | 1697 | fsf_req->qtcb->bottom.support.d_id = d_id; |
1715 | fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; | 1698 | fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class; |
1716 | fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT; | 1699 | fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT; |
1717 | fsf_req->data.send_els = els; | 1700 | fsf_req->data = (unsigned long) els; |
1718 | 1701 | ||
1719 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); | 1702 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); |
1720 | 1703 | ||
1704 | zfcp_san_dbf_event_els_request(fsf_req); | ||
1705 | |||
1721 | /* start QDIO request for this FSF request */ | 1706 | /* start QDIO request for this FSF request */ |
1722 | ret = zfcp_fsf_req_send(fsf_req, els->timer); | 1707 | ret = zfcp_fsf_req_send(fsf_req, els->timer); |
1723 | if (ret) { | 1708 | if (ret) { |
@@ -1746,23 +1731,23 @@ zfcp_fsf_send_els(struct zfcp_send_els *els) | |||
1746 | * zfcp_fsf_send_els_handler - handler for ELS commands | 1731 | * zfcp_fsf_send_els_handler - handler for ELS commands |
1747 | * @fsf_req: pointer to struct zfcp_fsf_req | 1732 | * @fsf_req: pointer to struct zfcp_fsf_req |
1748 | * | 1733 | * |
1749 | * Data specific for the ELS command is passed by | 1734 | * Data specific for the ELS command is passed using |
1750 | * fsf_req->data.send_els | 1735 | * fsf_req->data. There we find the pointer to struct zfcp_send_els. |
1751 | * Usually a specific handler for the command is called via | 1736 | * Usually a specific handler for the ELS command is called which is |
1752 | * fsf_req->data.send_els->handler at end of this function. | 1737 | * found in this structure. |
1753 | */ | 1738 | */ |
1754 | static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) | 1739 | static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) |
1755 | { | 1740 | { |
1756 | struct zfcp_adapter *adapter; | 1741 | struct zfcp_adapter *adapter; |
1757 | struct zfcp_port *port; | 1742 | struct zfcp_port *port; |
1758 | fc_id_t d_id; | 1743 | u32 d_id; |
1759 | struct fsf_qtcb_header *header; | 1744 | struct fsf_qtcb_header *header; |
1760 | struct fsf_qtcb_bottom_support *bottom; | 1745 | struct fsf_qtcb_bottom_support *bottom; |
1761 | struct zfcp_send_els *send_els; | 1746 | struct zfcp_send_els *send_els; |
1762 | int retval = -EINVAL; | 1747 | int retval = -EINVAL; |
1763 | u16 subtable, rule, counter; | 1748 | u16 subtable, rule, counter; |
1764 | 1749 | ||
1765 | send_els = fsf_req->data.send_els; | 1750 | send_els = (struct zfcp_send_els *) fsf_req->data; |
1766 | adapter = send_els->adapter; | 1751 | adapter = send_els->adapter; |
1767 | port = send_els->port; | 1752 | port = send_els->port; |
1768 | d_id = send_els->d_id; | 1753 | d_id = send_els->d_id; |
@@ -1775,6 +1760,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req) | |||
1775 | switch (header->fsf_status) { | 1760 | switch (header->fsf_status) { |
1776 | 1761 | ||
1777 | case FSF_GOOD: | 1762 | case FSF_GOOD: |
1763 | zfcp_san_dbf_event_els_response(fsf_req); | ||
1778 | retval = 0; | 1764 | retval = 0; |
1779 | break; | 1765 | break; |
1780 | 1766 | ||
@@ -1954,7 +1940,9 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) | |||
1954 | 1940 | ||
1955 | erp_action->fsf_req->erp_action = erp_action; | 1941 | erp_action->fsf_req->erp_action = erp_action; |
1956 | erp_action->fsf_req->qtcb->bottom.config.feature_selection = | 1942 | erp_action->fsf_req->qtcb->bottom.config.feature_selection = |
1957 | (FSF_FEATURE_CFDC | FSF_FEATURE_LUN_SHARING); | 1943 | FSF_FEATURE_CFDC | |
1944 | FSF_FEATURE_LUN_SHARING | | ||
1945 | FSF_FEATURE_UPDATE_ALERT; | ||
1958 | 1946 | ||
1959 | /* start QDIO request for this FSF request */ | 1947 | /* start QDIO request for this FSF request */ |
1960 | retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); | 1948 | retval = zfcp_fsf_req_send(erp_action->fsf_req, &erp_action->timer); |
@@ -1990,29 +1978,36 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) | |||
1990 | { | 1978 | { |
1991 | struct fsf_qtcb_bottom_config *bottom; | 1979 | struct fsf_qtcb_bottom_config *bottom; |
1992 | struct zfcp_adapter *adapter = fsf_req->adapter; | 1980 | struct zfcp_adapter *adapter = fsf_req->adapter; |
1981 | struct Scsi_Host *shost = adapter->scsi_host; | ||
1993 | 1982 | ||
1994 | bottom = &fsf_req->qtcb->bottom.config; | 1983 | bottom = &fsf_req->qtcb->bottom.config; |
1995 | ZFCP_LOG_DEBUG("low/high QTCB version 0x%x/0x%x of FSF\n", | 1984 | ZFCP_LOG_DEBUG("low/high QTCB version 0x%x/0x%x of FSF\n", |
1996 | bottom->low_qtcb_version, bottom->high_qtcb_version); | 1985 | bottom->low_qtcb_version, bottom->high_qtcb_version); |
1997 | adapter->fsf_lic_version = bottom->lic_version; | 1986 | adapter->fsf_lic_version = bottom->lic_version; |
1998 | adapter->supported_features = bottom->supported_features; | 1987 | adapter->adapter_features = bottom->adapter_features; |
1988 | adapter->connection_features = bottom->connection_features; | ||
1999 | adapter->peer_wwpn = 0; | 1989 | adapter->peer_wwpn = 0; |
2000 | adapter->peer_wwnn = 0; | 1990 | adapter->peer_wwnn = 0; |
2001 | adapter->peer_d_id = 0; | 1991 | adapter->peer_d_id = 0; |
2002 | 1992 | ||
2003 | if (xchg_ok) { | 1993 | if (xchg_ok) { |
2004 | adapter->wwnn = bottom->nport_serv_param.wwnn; | 1994 | fc_host_node_name(shost) = bottom->nport_serv_param.wwnn; |
2005 | adapter->wwpn = bottom->nport_serv_param.wwpn; | 1995 | fc_host_port_name(shost) = bottom->nport_serv_param.wwpn; |
2006 | adapter->s_id = bottom->s_id & ZFCP_DID_MASK; | 1996 | fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK; |
1997 | fc_host_speed(shost) = bottom->fc_link_speed; | ||
1998 | fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; | ||
2007 | adapter->fc_topology = bottom->fc_topology; | 1999 | adapter->fc_topology = bottom->fc_topology; |
2008 | adapter->fc_link_speed = bottom->fc_link_speed; | ||
2009 | adapter->hydra_version = bottom->adapter_type; | 2000 | adapter->hydra_version = bottom->adapter_type; |
2001 | if (adapter->physical_wwpn == 0) | ||
2002 | adapter->physical_wwpn = fc_host_port_name(shost); | ||
2003 | if (adapter->physical_s_id == 0) | ||
2004 | adapter->physical_s_id = fc_host_port_id(shost); | ||
2010 | } else { | 2005 | } else { |
2011 | adapter->wwnn = 0; | 2006 | fc_host_node_name(shost) = 0; |
2012 | adapter->wwpn = 0; | 2007 | fc_host_port_name(shost) = 0; |
2013 | adapter->s_id = 0; | 2008 | fc_host_port_id(shost) = 0; |
2009 | fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; | ||
2014 | adapter->fc_topology = 0; | 2010 | adapter->fc_topology = 0; |
2015 | adapter->fc_link_speed = 0; | ||
2016 | adapter->hydra_version = 0; | 2011 | adapter->hydra_version = 0; |
2017 | } | 2012 | } |
2018 | 2013 | ||
@@ -2022,26 +2017,28 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) | |||
2022 | adapter->peer_wwnn = bottom->plogi_payload.wwnn; | 2017 | adapter->peer_wwnn = bottom->plogi_payload.wwnn; |
2023 | } | 2018 | } |
2024 | 2019 | ||
2025 | if(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT){ | 2020 | if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) { |
2026 | adapter->hardware_version = bottom->hardware_version; | 2021 | adapter->hardware_version = bottom->hardware_version; |
2027 | memcpy(adapter->serial_number, bottom->serial_number, 17); | 2022 | memcpy(fc_host_serial_number(shost), bottom->serial_number, |
2028 | EBCASC(adapter->serial_number, sizeof(adapter->serial_number)); | 2023 | min(FC_SERIAL_NUMBER_SIZE, 17)); |
2024 | EBCASC(fc_host_serial_number(shost), | ||
2025 | min(FC_SERIAL_NUMBER_SIZE, 17)); | ||
2029 | } | 2026 | } |
2030 | 2027 | ||
2031 | ZFCP_LOG_NORMAL("The adapter %s reported the following characteristics:\n" | 2028 | ZFCP_LOG_NORMAL("The adapter %s reported the following characteristics:\n" |
2032 | "WWNN 0x%016Lx, " | 2029 | "WWNN 0x%016Lx, " |
2033 | "WWPN 0x%016Lx, " | 2030 | "WWPN 0x%016Lx, " |
2034 | "S_ID 0x%08x,\n" | 2031 | "S_ID 0x%08x,\n" |
2035 | "adapter version 0x%x, " | 2032 | "adapter version 0x%x, " |
2036 | "LIC version 0x%x, " | 2033 | "LIC version 0x%x, " |
2037 | "FC link speed %d Gb/s\n", | 2034 | "FC link speed %d Gb/s\n", |
2038 | zfcp_get_busid_by_adapter(adapter), | 2035 | zfcp_get_busid_by_adapter(adapter), |
2039 | adapter->wwnn, | 2036 | (wwn_t) fc_host_node_name(shost), |
2040 | adapter->wwpn, | 2037 | (wwn_t) fc_host_port_name(shost), |
2041 | (unsigned int) adapter->s_id, | 2038 | fc_host_port_id(shost), |
2042 | adapter->hydra_version, | 2039 | adapter->hydra_version, |
2043 | adapter->fsf_lic_version, | 2040 | adapter->fsf_lic_version, |
2044 | adapter->fc_link_speed); | 2041 | fc_host_speed(shost)); |
2045 | if (ZFCP_QTCB_VERSION < bottom->low_qtcb_version) { | 2042 | if (ZFCP_QTCB_VERSION < bottom->low_qtcb_version) { |
2046 | ZFCP_LOG_NORMAL("error: the adapter %s " | 2043 | ZFCP_LOG_NORMAL("error: the adapter %s " |
2047 | "only supports newer control block " | 2044 | "only supports newer control block " |
@@ -2062,7 +2059,6 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) | |||
2062 | zfcp_erp_adapter_shutdown(adapter, 0); | 2059 | zfcp_erp_adapter_shutdown(adapter, 0); |
2063 | return -EIO; | 2060 | return -EIO; |
2064 | } | 2061 | } |
2065 | zfcp_set_fc_host_attrs(adapter); | ||
2066 | return 0; | 2062 | return 0; |
2067 | } | 2063 | } |
2068 | 2064 | ||
@@ -2078,11 +2074,12 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) | |||
2078 | { | 2074 | { |
2079 | struct fsf_qtcb_bottom_config *bottom; | 2075 | struct fsf_qtcb_bottom_config *bottom; |
2080 | struct zfcp_adapter *adapter = fsf_req->adapter; | 2076 | struct zfcp_adapter *adapter = fsf_req->adapter; |
2077 | struct fsf_qtcb *qtcb = fsf_req->qtcb; | ||
2081 | 2078 | ||
2082 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) | 2079 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) |
2083 | return -EIO; | 2080 | return -EIO; |
2084 | 2081 | ||
2085 | switch (fsf_req->qtcb->header.fsf_status) { | 2082 | switch (qtcb->header.fsf_status) { |
2086 | 2083 | ||
2087 | case FSF_GOOD: | 2084 | case FSF_GOOD: |
2088 | if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1)) | 2085 | if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1)) |
@@ -2112,7 +2109,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) | |||
2112 | zfcp_erp_adapter_shutdown(adapter, 0); | 2109 | zfcp_erp_adapter_shutdown(adapter, 0); |
2113 | return -EIO; | 2110 | return -EIO; |
2114 | case FSF_TOPO_FABRIC: | 2111 | case FSF_TOPO_FABRIC: |
2115 | ZFCP_LOG_INFO("Switched fabric fibrechannel " | 2112 | ZFCP_LOG_NORMAL("Switched fabric fibrechannel " |
2116 | "network detected at adapter %s.\n", | 2113 | "network detected at adapter %s.\n", |
2117 | zfcp_get_busid_by_adapter(adapter)); | 2114 | zfcp_get_busid_by_adapter(adapter)); |
2118 | break; | 2115 | break; |
@@ -2130,7 +2127,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) | |||
2130 | zfcp_erp_adapter_shutdown(adapter, 0); | 2127 | zfcp_erp_adapter_shutdown(adapter, 0); |
2131 | return -EIO; | 2128 | return -EIO; |
2132 | } | 2129 | } |
2133 | bottom = &fsf_req->qtcb->bottom.config; | 2130 | bottom = &qtcb->bottom.config; |
2134 | if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) { | 2131 | if (bottom->max_qtcb_size < sizeof(struct fsf_qtcb)) { |
2135 | ZFCP_LOG_NORMAL("bug: Maximum QTCB size (%d bytes) " | 2132 | ZFCP_LOG_NORMAL("bug: Maximum QTCB size (%d bytes) " |
2136 | "allowed by the adapter %s " | 2133 | "allowed by the adapter %s " |
@@ -2155,12 +2152,10 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) | |||
2155 | if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0)) | 2152 | if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0)) |
2156 | return -EIO; | 2153 | return -EIO; |
2157 | 2154 | ||
2158 | ZFCP_LOG_INFO("Local link to adapter %s is down\n", | 2155 | atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status); |
2159 | zfcp_get_busid_by_adapter(adapter)); | 2156 | |
2160 | atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK | | 2157 | zfcp_fsf_link_down_info_eval(adapter, |
2161 | ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 2158 | &qtcb->header.fsf_status_qual.link_down_info); |
2162 | &adapter->status); | ||
2163 | zfcp_erp_adapter_failed(adapter); | ||
2164 | break; | 2159 | break; |
2165 | default: | 2160 | default: |
2166 | debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng"); | 2161 | debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng"); |
@@ -2174,11 +2169,13 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) | |||
2174 | 2169 | ||
2175 | /** | 2170 | /** |
2176 | * zfcp_fsf_exchange_port_data - request information about local port | 2171 | * zfcp_fsf_exchange_port_data - request information about local port |
2172 | * @erp_action: ERP action for the adapter for which port data is requested | ||
2177 | * @adapter: for which port data is requested | 2173 | * @adapter: for which port data is requested |
2178 | * @data: response to exchange port data request | 2174 | * @data: response to exchange port data request |
2179 | */ | 2175 | */ |
2180 | int | 2176 | int |
2181 | zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, | 2177 | zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, |
2178 | struct zfcp_adapter *adapter, | ||
2182 | struct fsf_qtcb_bottom_port *data) | 2179 | struct fsf_qtcb_bottom_port *data) |
2183 | { | 2180 | { |
2184 | volatile struct qdio_buffer_element *sbale; | 2181 | volatile struct qdio_buffer_element *sbale; |
@@ -2187,7 +2184,7 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, | |||
2187 | struct zfcp_fsf_req *fsf_req; | 2184 | struct zfcp_fsf_req *fsf_req; |
2188 | struct timer_list *timer; | 2185 | struct timer_list *timer; |
2189 | 2186 | ||
2190 | if(!(adapter->supported_features & FSF_FEATURE_HBAAPI_MANAGEMENT)){ | 2187 | if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) { |
2191 | ZFCP_LOG_INFO("error: exchange port data " | 2188 | ZFCP_LOG_INFO("error: exchange port data " |
2192 | "command not supported by adapter %s\n", | 2189 | "command not supported by adapter %s\n", |
2193 | zfcp_get_busid_by_adapter(adapter)); | 2190 | zfcp_get_busid_by_adapter(adapter)); |
@@ -2211,12 +2208,18 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, | |||
2211 | goto out; | 2208 | goto out; |
2212 | } | 2209 | } |
2213 | 2210 | ||
2211 | if (erp_action) { | ||
2212 | erp_action->fsf_req = fsf_req; | ||
2213 | fsf_req->erp_action = erp_action; | ||
2214 | } | ||
2215 | |||
2216 | if (data) | ||
2217 | fsf_req->data = (unsigned long) data; | ||
2218 | |||
2214 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); | 2219 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); |
2215 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 2220 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
2216 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 2221 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
2217 | 2222 | ||
2218 | fsf_req->data.port_data = data; | ||
2219 | |||
2220 | init_timer(timer); | 2223 | init_timer(timer); |
2221 | timer->function = zfcp_fsf_request_timeout_handler; | 2224 | timer->function = zfcp_fsf_request_timeout_handler; |
2222 | timer->data = (unsigned long) adapter; | 2225 | timer->data = (unsigned long) adapter; |
@@ -2228,6 +2231,8 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, | |||
2228 | "command on the adapter %s\n", | 2231 | "command on the adapter %s\n", |
2229 | zfcp_get_busid_by_adapter(adapter)); | 2232 | zfcp_get_busid_by_adapter(adapter)); |
2230 | zfcp_fsf_req_free(fsf_req); | 2233 | zfcp_fsf_req_free(fsf_req); |
2234 | if (erp_action) | ||
2235 | erp_action->fsf_req = NULL; | ||
2231 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, | 2236 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, |
2232 | lock_flags); | 2237 | lock_flags); |
2233 | goto out; | 2238 | goto out; |
@@ -2256,21 +2261,42 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter, | |||
2256 | static void | 2261 | static void |
2257 | zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) | 2262 | zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) |
2258 | { | 2263 | { |
2259 | struct fsf_qtcb_bottom_port *bottom; | 2264 | struct zfcp_adapter *adapter = fsf_req->adapter; |
2260 | struct fsf_qtcb_bottom_port *data = fsf_req->data.port_data; | 2265 | struct Scsi_Host *shost = adapter->scsi_host; |
2266 | struct fsf_qtcb *qtcb = fsf_req->qtcb; | ||
2267 | struct fsf_qtcb_bottom_port *bottom, *data; | ||
2261 | 2268 | ||
2262 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) | 2269 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) |
2263 | return; | 2270 | return; |
2264 | 2271 | ||
2265 | switch (fsf_req->qtcb->header.fsf_status) { | 2272 | switch (qtcb->header.fsf_status) { |
2266 | case FSF_GOOD: | 2273 | case FSF_GOOD: |
2267 | bottom = &fsf_req->qtcb->bottom.port; | 2274 | atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); |
2268 | memcpy(data, bottom, sizeof(*data)); | 2275 | |
2276 | bottom = &qtcb->bottom.port; | ||
2277 | data = (struct fsf_qtcb_bottom_port*) fsf_req->data; | ||
2278 | if (data) | ||
2279 | memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port)); | ||
2280 | if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) { | ||
2281 | adapter->physical_wwpn = bottom->wwpn; | ||
2282 | adapter->physical_s_id = bottom->fc_port_id; | ||
2283 | } else { | ||
2284 | adapter->physical_wwpn = fc_host_port_name(shost); | ||
2285 | adapter->physical_s_id = fc_host_port_id(shost); | ||
2286 | } | ||
2287 | fc_host_maxframe_size(shost) = bottom->maximum_frame_size; | ||
2288 | break; | ||
2289 | |||
2290 | case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE: | ||
2291 | atomic_set_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); | ||
2292 | |||
2293 | zfcp_fsf_link_down_info_eval(adapter, | ||
2294 | &qtcb->header.fsf_status_qual.link_down_info); | ||
2269 | break; | 2295 | break; |
2270 | 2296 | ||
2271 | default: | 2297 | default: |
2272 | debug_text_event(fsf_req->adapter->erp_dbf, 0, "xchg-port-ng"); | 2298 | debug_text_event(adapter->erp_dbf, 0, "xchg-port-ng"); |
2273 | debug_event(fsf_req->adapter->erp_dbf, 0, | 2299 | debug_event(adapter->erp_dbf, 0, |
2274 | &fsf_req->qtcb->header.fsf_status, sizeof(u32)); | 2300 | &fsf_req->qtcb->header.fsf_status, sizeof(u32)); |
2275 | } | 2301 | } |
2276 | } | 2302 | } |
@@ -2312,7 +2338,7 @@ zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) | |||
2312 | 2338 | ||
2313 | erp_action->fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id; | 2339 | erp_action->fsf_req->qtcb->bottom.support.d_id = erp_action->port->d_id; |
2314 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); | 2340 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->port->status); |
2315 | erp_action->fsf_req->data.open_port.port = erp_action->port; | 2341 | erp_action->fsf_req->data = (unsigned long) erp_action->port; |
2316 | erp_action->fsf_req->erp_action = erp_action; | 2342 | erp_action->fsf_req->erp_action = erp_action; |
2317 | 2343 | ||
2318 | /* start QDIO request for this FSF request */ | 2344 | /* start QDIO request for this FSF request */ |
@@ -2353,7 +2379,7 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req) | |||
2353 | struct fsf_qtcb_header *header; | 2379 | struct fsf_qtcb_header *header; |
2354 | u16 subtable, rule, counter; | 2380 | u16 subtable, rule, counter; |
2355 | 2381 | ||
2356 | port = fsf_req->data.open_port.port; | 2382 | port = (struct zfcp_port *) fsf_req->data; |
2357 | header = &fsf_req->qtcb->header; | 2383 | header = &fsf_req->qtcb->header; |
2358 | 2384 | ||
2359 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { | 2385 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { |
@@ -2566,7 +2592,7 @@ zfcp_fsf_close_port(struct zfcp_erp_action *erp_action) | |||
2566 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 2592 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
2567 | 2593 | ||
2568 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); | 2594 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->port->status); |
2569 | erp_action->fsf_req->data.close_port.port = erp_action->port; | 2595 | erp_action->fsf_req->data = (unsigned long) erp_action->port; |
2570 | erp_action->fsf_req->erp_action = erp_action; | 2596 | erp_action->fsf_req->erp_action = erp_action; |
2571 | erp_action->fsf_req->qtcb->header.port_handle = | 2597 | erp_action->fsf_req->qtcb->header.port_handle = |
2572 | erp_action->port->handle; | 2598 | erp_action->port->handle; |
@@ -2606,7 +2632,7 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req) | |||
2606 | int retval = -EINVAL; | 2632 | int retval = -EINVAL; |
2607 | struct zfcp_port *port; | 2633 | struct zfcp_port *port; |
2608 | 2634 | ||
2609 | port = fsf_req->data.close_port.port; | 2635 | port = (struct zfcp_port *) fsf_req->data; |
2610 | 2636 | ||
2611 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { | 2637 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { |
2612 | /* don't change port status in our bookkeeping */ | 2638 | /* don't change port status in our bookkeeping */ |
@@ -2703,8 +2729,8 @@ zfcp_fsf_close_physical_port(struct zfcp_erp_action *erp_action) | |||
2703 | atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, | 2729 | atomic_set_mask(ZFCP_STATUS_PORT_PHYS_CLOSING, |
2704 | &erp_action->port->status); | 2730 | &erp_action->port->status); |
2705 | /* save a pointer to this port */ | 2731 | /* save a pointer to this port */ |
2706 | erp_action->fsf_req->data.close_physical_port.port = erp_action->port; | 2732 | erp_action->fsf_req->data = (unsigned long) erp_action->port; |
2707 | /* port to be closeed */ | 2733 | /* port to be closed */ |
2708 | erp_action->fsf_req->qtcb->header.port_handle = | 2734 | erp_action->fsf_req->qtcb->header.port_handle = |
2709 | erp_action->port->handle; | 2735 | erp_action->port->handle; |
2710 | erp_action->fsf_req->erp_action = erp_action; | 2736 | erp_action->fsf_req->erp_action = erp_action; |
@@ -2747,7 +2773,7 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req) | |||
2747 | struct fsf_qtcb_header *header; | 2773 | struct fsf_qtcb_header *header; |
2748 | u16 subtable, rule, counter; | 2774 | u16 subtable, rule, counter; |
2749 | 2775 | ||
2750 | port = fsf_req->data.close_physical_port.port; | 2776 | port = (struct zfcp_port *) fsf_req->data; |
2751 | header = &fsf_req->qtcb->header; | 2777 | header = &fsf_req->qtcb->header; |
2752 | 2778 | ||
2753 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { | 2779 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { |
@@ -2908,10 +2934,11 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) | |||
2908 | erp_action->port->handle; | 2934 | erp_action->port->handle; |
2909 | erp_action->fsf_req->qtcb->bottom.support.fcp_lun = | 2935 | erp_action->fsf_req->qtcb->bottom.support.fcp_lun = |
2910 | erp_action->unit->fcp_lun; | 2936 | erp_action->unit->fcp_lun; |
2937 | if (!(erp_action->adapter->connection_features & FSF_FEATURE_NPIV_MODE)) | ||
2911 | erp_action->fsf_req->qtcb->bottom.support.option = | 2938 | erp_action->fsf_req->qtcb->bottom.support.option = |
2912 | FSF_OPEN_LUN_SUPPRESS_BOXING; | 2939 | FSF_OPEN_LUN_SUPPRESS_BOXING; |
2913 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); | 2940 | atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status); |
2914 | erp_action->fsf_req->data.open_unit.unit = erp_action->unit; | 2941 | erp_action->fsf_req->data = (unsigned long) erp_action->unit; |
2915 | erp_action->fsf_req->erp_action = erp_action; | 2942 | erp_action->fsf_req->erp_action = erp_action; |
2916 | 2943 | ||
2917 | /* start QDIO request for this FSF request */ | 2944 | /* start QDIO request for this FSF request */ |
@@ -2955,9 +2982,9 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) | |||
2955 | struct fsf_qtcb_bottom_support *bottom; | 2982 | struct fsf_qtcb_bottom_support *bottom; |
2956 | struct fsf_queue_designator *queue_designator; | 2983 | struct fsf_queue_designator *queue_designator; |
2957 | u16 subtable, rule, counter; | 2984 | u16 subtable, rule, counter; |
2958 | u32 allowed, exclusive, readwrite; | 2985 | int exclusive, readwrite; |
2959 | 2986 | ||
2960 | unit = fsf_req->data.open_unit.unit; | 2987 | unit = (struct zfcp_unit *) fsf_req->data; |
2961 | 2988 | ||
2962 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { | 2989 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { |
2963 | /* don't change unit status in our bookkeeping */ | 2990 | /* don't change unit status in our bookkeeping */ |
@@ -2969,10 +2996,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) | |||
2969 | bottom = &fsf_req->qtcb->bottom.support; | 2996 | bottom = &fsf_req->qtcb->bottom.support; |
2970 | queue_designator = &header->fsf_status_qual.fsf_queue_designator; | 2997 | queue_designator = &header->fsf_status_qual.fsf_queue_designator; |
2971 | 2998 | ||
2972 | allowed = bottom->lun_access_info & FSF_UNIT_ACCESS_OPEN_LUN_ALLOWED; | ||
2973 | exclusive = bottom->lun_access_info & FSF_UNIT_ACCESS_EXCLUSIVE; | ||
2974 | readwrite = bottom->lun_access_info & FSF_UNIT_ACCESS_OUTBOUND_TRANSFER; | ||
2975 | |||
2976 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | | 2999 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | |
2977 | ZFCP_STATUS_UNIT_SHARED | | 3000 | ZFCP_STATUS_UNIT_SHARED | |
2978 | ZFCP_STATUS_UNIT_READONLY, | 3001 | ZFCP_STATUS_UNIT_READONLY, |
@@ -3146,10 +3169,15 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) | |||
3146 | unit->handle); | 3169 | unit->handle); |
3147 | /* mark unit as open */ | 3170 | /* mark unit as open */ |
3148 | atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); | 3171 | atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status); |
3149 | atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | | 3172 | |
3150 | ZFCP_STATUS_COMMON_ACCESS_BOXED, | 3173 | if (!(adapter->connection_features & FSF_FEATURE_NPIV_MODE) && |
3151 | &unit->status); | 3174 | (adapter->adapter_features & FSF_FEATURE_LUN_SHARING) && |
3152 | if (adapter->supported_features & FSF_FEATURE_LUN_SHARING){ | 3175 | (adapter->ccw_device->id.dev_model != ZFCP_DEVICE_MODEL_PRIV)) { |
3176 | exclusive = (bottom->lun_access_info & | ||
3177 | FSF_UNIT_ACCESS_EXCLUSIVE); | ||
3178 | readwrite = (bottom->lun_access_info & | ||
3179 | FSF_UNIT_ACCESS_OUTBOUND_TRANSFER); | ||
3180 | |||
3153 | if (!exclusive) | 3181 | if (!exclusive) |
3154 | atomic_set_mask(ZFCP_STATUS_UNIT_SHARED, | 3182 | atomic_set_mask(ZFCP_STATUS_UNIT_SHARED, |
3155 | &unit->status); | 3183 | &unit->status); |
@@ -3242,7 +3270,7 @@ zfcp_fsf_close_unit(struct zfcp_erp_action *erp_action) | |||
3242 | erp_action->port->handle; | 3270 | erp_action->port->handle; |
3243 | erp_action->fsf_req->qtcb->header.lun_handle = erp_action->unit->handle; | 3271 | erp_action->fsf_req->qtcb->header.lun_handle = erp_action->unit->handle; |
3244 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status); | 3272 | atomic_set_mask(ZFCP_STATUS_COMMON_CLOSING, &erp_action->unit->status); |
3245 | erp_action->fsf_req->data.close_unit.unit = erp_action->unit; | 3273 | erp_action->fsf_req->data = (unsigned long) erp_action->unit; |
3246 | erp_action->fsf_req->erp_action = erp_action; | 3274 | erp_action->fsf_req->erp_action = erp_action; |
3247 | 3275 | ||
3248 | /* start QDIO request for this FSF request */ | 3276 | /* start QDIO request for this FSF request */ |
@@ -3281,7 +3309,7 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req) | |||
3281 | int retval = -EINVAL; | 3309 | int retval = -EINVAL; |
3282 | struct zfcp_unit *unit; | 3310 | struct zfcp_unit *unit; |
3283 | 3311 | ||
3284 | unit = fsf_req->data.close_unit.unit; /* restore unit */ | 3312 | unit = (struct zfcp_unit *) fsf_req->data; |
3285 | 3313 | ||
3286 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { | 3314 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { |
3287 | /* don't change unit status in our bookkeeping */ | 3315 | /* don't change unit status in our bookkeeping */ |
@@ -3305,9 +3333,6 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req) | |||
3305 | debug_text_event(fsf_req->adapter->erp_dbf, 1, | 3333 | debug_text_event(fsf_req->adapter->erp_dbf, 1, |
3306 | "fsf_s_phand_nv"); | 3334 | "fsf_s_phand_nv"); |
3307 | zfcp_erp_adapter_reopen(unit->port->adapter, 0); | 3335 | zfcp_erp_adapter_reopen(unit->port->adapter, 0); |
3308 | zfcp_cmd_dbf_event_fsf("porthinv", fsf_req, | ||
3309 | &fsf_req->qtcb->header.fsf_status_qual, | ||
3310 | sizeof (union fsf_status_qual)); | ||
3311 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 3336 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
3312 | break; | 3337 | break; |
3313 | 3338 | ||
@@ -3326,9 +3351,6 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req) | |||
3326 | debug_text_event(fsf_req->adapter->erp_dbf, 1, | 3351 | debug_text_event(fsf_req->adapter->erp_dbf, 1, |
3327 | "fsf_s_lhand_nv"); | 3352 | "fsf_s_lhand_nv"); |
3328 | zfcp_erp_port_reopen(unit->port, 0); | 3353 | zfcp_erp_port_reopen(unit->port, 0); |
3329 | zfcp_cmd_dbf_event_fsf("lunhinv", fsf_req, | ||
3330 | &fsf_req->qtcb->header.fsf_status_qual, | ||
3331 | sizeof (union fsf_status_qual)); | ||
3332 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 3354 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
3333 | break; | 3355 | break; |
3334 | 3356 | ||
@@ -3436,21 +3458,14 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, | |||
3436 | goto failed_req_create; | 3458 | goto failed_req_create; |
3437 | } | 3459 | } |
3438 | 3460 | ||
3439 | /* | 3461 | zfcp_unit_get(unit); |
3440 | * associate FSF request with SCSI request | 3462 | fsf_req->unit = unit; |
3441 | * (need this for look up on abort) | ||
3442 | */ | ||
3443 | fsf_req->data.send_fcp_command_task.fsf_req = fsf_req; | ||
3444 | scsi_cmnd->host_scribble = (char *) &(fsf_req->data); | ||
3445 | 3463 | ||
3446 | /* | 3464 | /* associate FSF request with SCSI request (for look up on abort) */ |
3447 | * associate SCSI command with FSF request | 3465 | scsi_cmnd->host_scribble = (char *) fsf_req; |
3448 | * (need this for look up on normal command completion) | 3466 | |
3449 | */ | 3467 | /* associate SCSI command with FSF request */ |
3450 | fsf_req->data.send_fcp_command_task.scsi_cmnd = scsi_cmnd; | 3468 | fsf_req->data = (unsigned long) scsi_cmnd; |
3451 | fsf_req->data.send_fcp_command_task.start_jiffies = jiffies; | ||
3452 | fsf_req->data.send_fcp_command_task.unit = unit; | ||
3453 | ZFCP_LOG_DEBUG("unit=%p, fcp_lun=0x%016Lx\n", unit, unit->fcp_lun); | ||
3454 | 3469 | ||
3455 | /* set handles of unit and its parent port in QTCB */ | 3470 | /* set handles of unit and its parent port in QTCB */ |
3456 | fsf_req->qtcb->header.lun_handle = unit->handle; | 3471 | fsf_req->qtcb->header.lun_handle = unit->handle; |
@@ -3584,6 +3599,7 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, | |||
3584 | send_failed: | 3599 | send_failed: |
3585 | no_fit: | 3600 | no_fit: |
3586 | failed_scsi_cmnd: | 3601 | failed_scsi_cmnd: |
3602 | zfcp_unit_put(unit); | ||
3587 | zfcp_fsf_req_free(fsf_req); | 3603 | zfcp_fsf_req_free(fsf_req); |
3588 | fsf_req = NULL; | 3604 | fsf_req = NULL; |
3589 | scsi_cmnd->host_scribble = NULL; | 3605 | scsi_cmnd->host_scribble = NULL; |
@@ -3640,7 +3656,7 @@ zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter, | |||
3640 | * hold a pointer to the unit being target of this | 3656 | * hold a pointer to the unit being target of this |
3641 | * task management request | 3657 | * task management request |
3642 | */ | 3658 | */ |
3643 | fsf_req->data.send_fcp_command_task_management.unit = unit; | 3659 | fsf_req->data = (unsigned long) unit; |
3644 | 3660 | ||
3645 | /* set FSF related fields in QTCB */ | 3661 | /* set FSF related fields in QTCB */ |
3646 | fsf_req->qtcb->header.lun_handle = unit->handle; | 3662 | fsf_req->qtcb->header.lun_handle = unit->handle; |
@@ -3706,9 +3722,9 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) | |||
3706 | header = &fsf_req->qtcb->header; | 3722 | header = &fsf_req->qtcb->header; |
3707 | 3723 | ||
3708 | if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)) | 3724 | if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT)) |
3709 | unit = fsf_req->data.send_fcp_command_task_management.unit; | 3725 | unit = (struct zfcp_unit *) fsf_req->data; |
3710 | else | 3726 | else |
3711 | unit = fsf_req->data.send_fcp_command_task.unit; | 3727 | unit = fsf_req->unit; |
3712 | 3728 | ||
3713 | if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { | 3729 | if (unlikely(fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)) { |
3714 | /* go directly to calls of special handlers */ | 3730 | /* go directly to calls of special handlers */ |
@@ -3765,10 +3781,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) | |||
3765 | debug_text_event(fsf_req->adapter->erp_dbf, 1, | 3781 | debug_text_event(fsf_req->adapter->erp_dbf, 1, |
3766 | "fsf_s_hand_mis"); | 3782 | "fsf_s_hand_mis"); |
3767 | zfcp_erp_adapter_reopen(unit->port->adapter, 0); | 3783 | zfcp_erp_adapter_reopen(unit->port->adapter, 0); |
3768 | zfcp_cmd_dbf_event_fsf("handmism", | ||
3769 | fsf_req, | ||
3770 | &header->fsf_status_qual, | ||
3771 | sizeof (union fsf_status_qual)); | ||
3772 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 3784 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
3773 | break; | 3785 | break; |
3774 | 3786 | ||
@@ -3789,10 +3801,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) | |||
3789 | debug_text_exception(fsf_req->adapter->erp_dbf, 0, | 3801 | debug_text_exception(fsf_req->adapter->erp_dbf, 0, |
3790 | "fsf_s_class_nsup"); | 3802 | "fsf_s_class_nsup"); |
3791 | zfcp_erp_adapter_shutdown(unit->port->adapter, 0); | 3803 | zfcp_erp_adapter_shutdown(unit->port->adapter, 0); |
3792 | zfcp_cmd_dbf_event_fsf("unsclass", | ||
3793 | fsf_req, | ||
3794 | &header->fsf_status_qual, | ||
3795 | sizeof (union fsf_status_qual)); | ||
3796 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 3804 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
3797 | break; | 3805 | break; |
3798 | 3806 | ||
@@ -3811,10 +3819,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) | |||
3811 | debug_text_event(fsf_req->adapter->erp_dbf, 1, | 3819 | debug_text_event(fsf_req->adapter->erp_dbf, 1, |
3812 | "fsf_s_fcp_lun_nv"); | 3820 | "fsf_s_fcp_lun_nv"); |
3813 | zfcp_erp_port_reopen(unit->port, 0); | 3821 | zfcp_erp_port_reopen(unit->port, 0); |
3814 | zfcp_cmd_dbf_event_fsf("fluninv", | ||
3815 | fsf_req, | ||
3816 | &header->fsf_status_qual, | ||
3817 | sizeof (union fsf_status_qual)); | ||
3818 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 3822 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
3819 | break; | 3823 | break; |
3820 | 3824 | ||
@@ -3853,10 +3857,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) | |||
3853 | debug_text_event(fsf_req->adapter->erp_dbf, 0, | 3857 | debug_text_event(fsf_req->adapter->erp_dbf, 0, |
3854 | "fsf_s_dir_ind_nv"); | 3858 | "fsf_s_dir_ind_nv"); |
3855 | zfcp_erp_adapter_shutdown(unit->port->adapter, 0); | 3859 | zfcp_erp_adapter_shutdown(unit->port->adapter, 0); |
3856 | zfcp_cmd_dbf_event_fsf("dirinv", | ||
3857 | fsf_req, | ||
3858 | &header->fsf_status_qual, | ||
3859 | sizeof (union fsf_status_qual)); | ||
3860 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 3860 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
3861 | break; | 3861 | break; |
3862 | 3862 | ||
@@ -3872,10 +3872,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) | |||
3872 | debug_text_event(fsf_req->adapter->erp_dbf, 0, | 3872 | debug_text_event(fsf_req->adapter->erp_dbf, 0, |
3873 | "fsf_s_cmd_len_nv"); | 3873 | "fsf_s_cmd_len_nv"); |
3874 | zfcp_erp_adapter_shutdown(unit->port->adapter, 0); | 3874 | zfcp_erp_adapter_shutdown(unit->port->adapter, 0); |
3875 | zfcp_cmd_dbf_event_fsf("cleninv", | ||
3876 | fsf_req, | ||
3877 | &header->fsf_status_qual, | ||
3878 | sizeof (union fsf_status_qual)); | ||
3879 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; | 3875 | fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; |
3880 | break; | 3876 | break; |
3881 | 3877 | ||
@@ -3947,6 +3943,8 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) | |||
3947 | zfcp_fsf_send_fcp_command_task_management_handler(fsf_req); | 3943 | zfcp_fsf_send_fcp_command_task_management_handler(fsf_req); |
3948 | } else { | 3944 | } else { |
3949 | retval = zfcp_fsf_send_fcp_command_task_handler(fsf_req); | 3945 | retval = zfcp_fsf_send_fcp_command_task_handler(fsf_req); |
3946 | fsf_req->unit = NULL; | ||
3947 | zfcp_unit_put(unit); | ||
3950 | } | 3948 | } |
3951 | return retval; | 3949 | return retval; |
3952 | } | 3950 | } |
@@ -3970,10 +3968,10 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) | |||
3970 | u32 sns_len; | 3968 | u32 sns_len; |
3971 | char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); | 3969 | char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); |
3972 | unsigned long flags; | 3970 | unsigned long flags; |
3973 | struct zfcp_unit *unit = fsf_req->data.send_fcp_command_task.unit; | 3971 | struct zfcp_unit *unit = fsf_req->unit; |
3974 | 3972 | ||
3975 | read_lock_irqsave(&fsf_req->adapter->abort_lock, flags); | 3973 | read_lock_irqsave(&fsf_req->adapter->abort_lock, flags); |
3976 | scpnt = fsf_req->data.send_fcp_command_task.scsi_cmnd; | 3974 | scpnt = (struct scsi_cmnd *) fsf_req->data; |
3977 | if (unlikely(!scpnt)) { | 3975 | if (unlikely(!scpnt)) { |
3978 | ZFCP_LOG_DEBUG | 3976 | ZFCP_LOG_DEBUG |
3979 | ("Command with fsf_req %p is not associated to " | 3977 | ("Command with fsf_req %p is not associated to " |
@@ -4043,7 +4041,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) | |||
4043 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, | 4041 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, |
4044 | (char *) &fsf_req->qtcb-> | 4042 | (char *) &fsf_req->qtcb-> |
4045 | bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); | 4043 | bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); |
4046 | zfcp_cmd_dbf_event_fsf("clenmis", fsf_req, NULL, 0); | ||
4047 | set_host_byte(&scpnt->result, DID_ERROR); | 4044 | set_host_byte(&scpnt->result, DID_ERROR); |
4048 | goto skip_fsfstatus; | 4045 | goto skip_fsfstatus; |
4049 | case RSP_CODE_FIELD_INVALID: | 4046 | case RSP_CODE_FIELD_INVALID: |
@@ -4062,7 +4059,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) | |||
4062 | (char *) &fsf_req->qtcb-> | 4059 | (char *) &fsf_req->qtcb-> |
4063 | bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); | 4060 | bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); |
4064 | set_host_byte(&scpnt->result, DID_ERROR); | 4061 | set_host_byte(&scpnt->result, DID_ERROR); |
4065 | zfcp_cmd_dbf_event_fsf("codeinv", fsf_req, NULL, 0); | ||
4066 | goto skip_fsfstatus; | 4062 | goto skip_fsfstatus; |
4067 | case RSP_CODE_RO_MISMATCH: | 4063 | case RSP_CODE_RO_MISMATCH: |
4068 | /* hardware bug */ | 4064 | /* hardware bug */ |
@@ -4079,7 +4075,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) | |||
4079 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, | 4075 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, |
4080 | (char *) &fsf_req->qtcb-> | 4076 | (char *) &fsf_req->qtcb-> |
4081 | bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); | 4077 | bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); |
4082 | zfcp_cmd_dbf_event_fsf("codemism", fsf_req, NULL, 0); | ||
4083 | set_host_byte(&scpnt->result, DID_ERROR); | 4078 | set_host_byte(&scpnt->result, DID_ERROR); |
4084 | goto skip_fsfstatus; | 4079 | goto skip_fsfstatus; |
4085 | default: | 4080 | default: |
@@ -4096,7 +4091,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) | |||
4096 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, | 4091 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_DEBUG, |
4097 | (char *) &fsf_req->qtcb-> | 4092 | (char *) &fsf_req->qtcb-> |
4098 | bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); | 4093 | bottom.io.fcp_cmnd, FSF_FCP_CMND_SIZE); |
4099 | zfcp_cmd_dbf_event_fsf("undeffcp", fsf_req, NULL, 0); | ||
4100 | set_host_byte(&scpnt->result, DID_ERROR); | 4094 | set_host_byte(&scpnt->result, DID_ERROR); |
4101 | goto skip_fsfstatus; | 4095 | goto skip_fsfstatus; |
4102 | } | 4096 | } |
@@ -4158,19 +4152,17 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) | |||
4158 | skip_fsfstatus: | 4152 | skip_fsfstatus: |
4159 | ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result); | 4153 | ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result); |
4160 | 4154 | ||
4161 | zfcp_cmd_dbf_event_scsi("response", scpnt); | 4155 | if (scpnt->result != 0) |
4156 | zfcp_scsi_dbf_event_result("erro", 3, fsf_req->adapter, scpnt); | ||
4157 | else if (scpnt->retries > 0) | ||
4158 | zfcp_scsi_dbf_event_result("retr", 4, fsf_req->adapter, scpnt); | ||
4159 | else | ||
4160 | zfcp_scsi_dbf_event_result("norm", 6, fsf_req->adapter, scpnt); | ||
4162 | 4161 | ||
4163 | /* cleanup pointer (need this especially for abort) */ | 4162 | /* cleanup pointer (need this especially for abort) */ |
4164 | scpnt->host_scribble = NULL; | 4163 | scpnt->host_scribble = NULL; |
4165 | 4164 | ||
4166 | /* | ||
4167 | * NOTE: | ||
4168 | * according to the outcome of a discussion on linux-scsi we | ||
4169 | * don't need to grab the io_request_lock here since we use | ||
4170 | * the new eh | ||
4171 | */ | ||
4172 | /* always call back */ | 4165 | /* always call back */ |
4173 | |||
4174 | (scpnt->scsi_done) (scpnt); | 4166 | (scpnt->scsi_done) (scpnt); |
4175 | 4167 | ||
4176 | /* | 4168 | /* |
@@ -4198,8 +4190,7 @@ zfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req) | |||
4198 | struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *) | 4190 | struct fcp_rsp_iu *fcp_rsp_iu = (struct fcp_rsp_iu *) |
4199 | &(fsf_req->qtcb->bottom.io.fcp_rsp); | 4191 | &(fsf_req->qtcb->bottom.io.fcp_rsp); |
4200 | char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); | 4192 | char *fcp_rsp_info = zfcp_get_fcp_rsp_info_ptr(fcp_rsp_iu); |
4201 | struct zfcp_unit *unit = | 4193 | struct zfcp_unit *unit = (struct zfcp_unit *) fsf_req->data; |
4202 | fsf_req->data.send_fcp_command_task_management.unit; | ||
4203 | 4194 | ||
4204 | del_timer(&fsf_req->adapter->scsi_er_timer); | 4195 | del_timer(&fsf_req->adapter->scsi_er_timer); |
4205 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { | 4196 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR) { |
@@ -4276,7 +4267,7 @@ zfcp_fsf_control_file(struct zfcp_adapter *adapter, | |||
4276 | int direction; | 4267 | int direction; |
4277 | int retval = 0; | 4268 | int retval = 0; |
4278 | 4269 | ||
4279 | if (!(adapter->supported_features & FSF_FEATURE_CFDC)) { | 4270 | if (!(adapter->adapter_features & FSF_FEATURE_CFDC)) { |
4280 | ZFCP_LOG_INFO("cfdc not supported (adapter %s)\n", | 4271 | ZFCP_LOG_INFO("cfdc not supported (adapter %s)\n", |
4281 | zfcp_get_busid_by_adapter(adapter)); | 4272 | zfcp_get_busid_by_adapter(adapter)); |
4282 | retval = -EOPNOTSUPP; | 4273 | retval = -EOPNOTSUPP; |
@@ -4549,52 +4540,6 @@ skip_fsfstatus: | |||
4549 | return retval; | 4540 | return retval; |
4550 | } | 4541 | } |
4551 | 4542 | ||
4552 | |||
4553 | /* | ||
4554 | * function: zfcp_fsf_req_wait_and_cleanup | ||
4555 | * | ||
4556 | * purpose: | ||
4557 | * | ||
4558 | * FIXME(design): signal seems to be <0 !!! | ||
4559 | * returns: 0 - request completed (*status is valid), cleanup succ. | ||
4560 | * <0 - request completed (*status is valid), cleanup failed | ||
4561 | * >0 - signal which interrupted waiting (*status invalid), | ||
4562 | * request not completed, no cleanup | ||
4563 | * | ||
4564 | * *status is a copy of status of completed fsf_req | ||
4565 | */ | ||
4566 | int | ||
4567 | zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *fsf_req, | ||
4568 | int interruptible, u32 * status) | ||
4569 | { | ||
4570 | int retval = 0; | ||
4571 | int signal = 0; | ||
4572 | |||
4573 | if (interruptible) { | ||
4574 | __wait_event_interruptible(fsf_req->completion_wq, | ||
4575 | fsf_req->status & | ||
4576 | ZFCP_STATUS_FSFREQ_COMPLETED, | ||
4577 | signal); | ||
4578 | if (signal) { | ||
4579 | ZFCP_LOG_DEBUG("Caught signal %i while waiting for the " | ||
4580 | "completion of the request at %p\n", | ||
4581 | signal, fsf_req); | ||
4582 | retval = signal; | ||
4583 | goto out; | ||
4584 | } | ||
4585 | } else { | ||
4586 | __wait_event(fsf_req->completion_wq, | ||
4587 | fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | ||
4588 | } | ||
4589 | |||
4590 | *status = fsf_req->status; | ||
4591 | |||
4592 | /* cleanup request */ | ||
4593 | zfcp_fsf_req_free(fsf_req); | ||
4594 | out: | ||
4595 | return retval; | ||
4596 | } | ||
4597 | |||
4598 | static inline int | 4543 | static inline int |
4599 | zfcp_fsf_req_sbal_check(unsigned long *flags, | 4544 | zfcp_fsf_req_sbal_check(unsigned long *flags, |
4600 | struct zfcp_qdio_queue *queue, int needed) | 4545 | struct zfcp_qdio_queue *queue, int needed) |
@@ -4610,15 +4555,16 @@ zfcp_fsf_req_sbal_check(unsigned long *flags, | |||
4610 | * set qtcb pointer in fsf_req and initialize QTCB | 4555 | * set qtcb pointer in fsf_req and initialize QTCB |
4611 | */ | 4556 | */ |
4612 | static inline void | 4557 | static inline void |
4613 | zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req, u32 fsf_cmd) | 4558 | zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req) |
4614 | { | 4559 | { |
4615 | if (likely(fsf_req->qtcb != NULL)) { | 4560 | if (likely(fsf_req->qtcb != NULL)) { |
4561 | fsf_req->qtcb->prefix.req_seq_no = fsf_req->adapter->fsf_req_seq_no; | ||
4616 | fsf_req->qtcb->prefix.req_id = (unsigned long)fsf_req; | 4562 | fsf_req->qtcb->prefix.req_id = (unsigned long)fsf_req; |
4617 | fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION; | 4563 | fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION; |
4618 | fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_cmd]; | 4564 | fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_req->fsf_command]; |
4619 | fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION; | 4565 | fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION; |
4620 | fsf_req->qtcb->header.req_handle = (unsigned long)fsf_req; | 4566 | fsf_req->qtcb->header.req_handle = (unsigned long)fsf_req; |
4621 | fsf_req->qtcb->header.fsf_command = fsf_cmd; | 4567 | fsf_req->qtcb->header.fsf_command = fsf_req->fsf_command; |
4622 | } | 4568 | } |
4623 | } | 4569 | } |
4624 | 4570 | ||
@@ -4686,7 +4632,10 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, | |||
4686 | goto failed_fsf_req; | 4632 | goto failed_fsf_req; |
4687 | } | 4633 | } |
4688 | 4634 | ||
4689 | zfcp_fsf_req_qtcb_init(fsf_req, fsf_cmd); | 4635 | fsf_req->adapter = adapter; |
4636 | fsf_req->fsf_command = fsf_cmd; | ||
4637 | |||
4638 | zfcp_fsf_req_qtcb_init(fsf_req); | ||
4690 | 4639 | ||
4691 | /* initialize waitqueue which may be used to wait on | 4640 | /* initialize waitqueue which may be used to wait on |
4692 | this request completion */ | 4641 | this request completion */ |
@@ -4708,8 +4657,10 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, | |||
4708 | goto failed_sbals; | 4657 | goto failed_sbals; |
4709 | } | 4658 | } |
4710 | 4659 | ||
4711 | fsf_req->adapter = adapter; /* pointer to "parent" adapter */ | 4660 | if (fsf_req->qtcb) { |
4712 | fsf_req->fsf_command = fsf_cmd; | 4661 | fsf_req->seq_no = adapter->fsf_req_seq_no; |
4662 | fsf_req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no; | ||
4663 | } | ||
4713 | fsf_req->sbal_number = 1; | 4664 | fsf_req->sbal_number = 1; |
4714 | fsf_req->sbal_first = req_queue->free_index; | 4665 | fsf_req->sbal_first = req_queue->free_index; |
4715 | fsf_req->sbal_curr = req_queue->free_index; | 4666 | fsf_req->sbal_curr = req_queue->free_index; |
@@ -4760,9 +4711,9 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) | |||
4760 | struct zfcp_adapter *adapter; | 4711 | struct zfcp_adapter *adapter; |
4761 | struct zfcp_qdio_queue *req_queue; | 4712 | struct zfcp_qdio_queue *req_queue; |
4762 | volatile struct qdio_buffer_element *sbale; | 4713 | volatile struct qdio_buffer_element *sbale; |
4714 | int inc_seq_no; | ||
4763 | int new_distance_from_int; | 4715 | int new_distance_from_int; |
4764 | unsigned long flags; | 4716 | unsigned long flags; |
4765 | int inc_seq_no = 1; | ||
4766 | int retval = 0; | 4717 | int retval = 0; |
4767 | 4718 | ||
4768 | adapter = fsf_req->adapter; | 4719 | adapter = fsf_req->adapter; |
@@ -4776,23 +4727,13 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) | |||
4776 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr, | 4727 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr, |
4777 | sbale[1].length); | 4728 | sbale[1].length); |
4778 | 4729 | ||
4779 | /* set sequence counter in QTCB */ | ||
4780 | if (likely(fsf_req->qtcb)) { | ||
4781 | fsf_req->qtcb->prefix.req_seq_no = adapter->fsf_req_seq_no; | ||
4782 | fsf_req->seq_no = adapter->fsf_req_seq_no; | ||
4783 | ZFCP_LOG_TRACE("FSF request %p of adapter %s gets " | ||
4784 | "FSF sequence counter value of %i\n", | ||
4785 | fsf_req, | ||
4786 | zfcp_get_busid_by_adapter(adapter), | ||
4787 | fsf_req->qtcb->prefix.req_seq_no); | ||
4788 | } else | ||
4789 | inc_seq_no = 0; | ||
4790 | |||
4791 | /* put allocated FSF request at list tail */ | 4730 | /* put allocated FSF request at list tail */ |
4792 | spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); | 4731 | spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); |
4793 | list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head); | 4732 | list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head); |
4794 | spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); | 4733 | spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); |
4795 | 4734 | ||
4735 | inc_seq_no = (fsf_req->qtcb != NULL); | ||
4736 | |||
4796 | /* figure out expiration time of timeout and start timeout */ | 4737 | /* figure out expiration time of timeout and start timeout */ |
4797 | if (unlikely(timer)) { | 4738 | if (unlikely(timer)) { |
4798 | timer->expires += jiffies; | 4739 | timer->expires += jiffies; |
@@ -4822,6 +4763,8 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) | |||
4822 | req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap if needed */ | 4763 | req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap if needed */ |
4823 | new_distance_from_int = zfcp_qdio_determine_pci(req_queue, fsf_req); | 4764 | new_distance_from_int = zfcp_qdio_determine_pci(req_queue, fsf_req); |
4824 | 4765 | ||
4766 | fsf_req->issued = get_clock(); | ||
4767 | |||
4825 | retval = do_QDIO(adapter->ccw_device, | 4768 | retval = do_QDIO(adapter->ccw_device, |
4826 | QDIO_FLAG_SYNC_OUTPUT, | 4769 | QDIO_FLAG_SYNC_OUTPUT, |
4827 | 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL); | 4770 | 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL); |
@@ -4860,15 +4803,11 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) | |||
4860 | * routines resulting in missing sequence counter values | 4803 | * routines resulting in missing sequence counter values |
4861 | * otherwise, | 4804 | * otherwise, |
4862 | */ | 4805 | */ |
4806 | |||
4863 | /* Don't increase for unsolicited status */ | 4807 | /* Don't increase for unsolicited status */ |
4864 | if (likely(inc_seq_no)) { | 4808 | if (inc_seq_no) |
4865 | adapter->fsf_req_seq_no++; | 4809 | adapter->fsf_req_seq_no++; |
4866 | ZFCP_LOG_TRACE | 4810 | |
4867 | ("FSF sequence counter value of adapter %s " | ||
4868 | "increased to %i\n", | ||
4869 | zfcp_get_busid_by_adapter(adapter), | ||
4870 | adapter->fsf_req_seq_no); | ||
4871 | } | ||
4872 | /* count FSF requests pending */ | 4811 | /* count FSF requests pending */ |
4873 | atomic_inc(&adapter->fsf_reqs_active); | 4812 | atomic_inc(&adapter->fsf_reqs_active); |
4874 | } | 4813 | } |
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 07140dfda2a7..48719f055952 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h | |||
@@ -116,6 +116,7 @@ | |||
116 | #define FSF_INVALID_COMMAND_OPTION 0x000000E5 | 116 | #define FSF_INVALID_COMMAND_OPTION 0x000000E5 |
117 | /* #define FSF_ERROR 0x000000FF */ | 117 | /* #define FSF_ERROR 0x000000FF */ |
118 | 118 | ||
119 | #define FSF_PROT_STATUS_QUAL_SIZE 16 | ||
119 | #define FSF_STATUS_QUALIFIER_SIZE 16 | 120 | #define FSF_STATUS_QUALIFIER_SIZE 16 |
120 | 121 | ||
121 | /* FSF status qualifier, recommendations */ | 122 | /* FSF status qualifier, recommendations */ |
@@ -139,9 +140,18 @@ | |||
139 | #define FSF_SQ_CFDC_SUBTABLE_LUN 0x0004 | 140 | #define FSF_SQ_CFDC_SUBTABLE_LUN 0x0004 |
140 | 141 | ||
141 | /* FSF status qualifier (most significant 4 bytes), local link down */ | 142 | /* FSF status qualifier (most significant 4 bytes), local link down */ |
142 | #define FSF_PSQ_LINK_NOLIGHT 0x00000004 | 143 | #define FSF_PSQ_LINK_NO_LIGHT 0x00000004 |
143 | #define FSF_PSQ_LINK_WRAPPLUG 0x00000008 | 144 | #define FSF_PSQ_LINK_WRAP_PLUG 0x00000008 |
144 | #define FSF_PSQ_LINK_NOFCP 0x00000010 | 145 | #define FSF_PSQ_LINK_NO_FCP 0x00000010 |
146 | #define FSF_PSQ_LINK_FIRMWARE_UPDATE 0x00000020 | ||
147 | #define FSF_PSQ_LINK_INVALID_WWPN 0x00000100 | ||
148 | #define FSF_PSQ_LINK_NO_NPIV_SUPPORT 0x00000200 | ||
149 | #define FSF_PSQ_LINK_NO_FCP_RESOURCES 0x00000400 | ||
150 | #define FSF_PSQ_LINK_NO_FABRIC_RESOURCES 0x00000800 | ||
151 | #define FSF_PSQ_LINK_FABRIC_LOGIN_UNABLE 0x00001000 | ||
152 | #define FSF_PSQ_LINK_WWPN_ASSIGNMENT_CORRUPTED 0x00002000 | ||
153 | #define FSF_PSQ_LINK_MODE_TABLE_CURRUPTED 0x00004000 | ||
154 | #define FSF_PSQ_LINK_NO_WWPN_ASSIGNMENT 0x00008000 | ||
145 | 155 | ||
146 | /* payload size in status read buffer */ | 156 | /* payload size in status read buffer */ |
147 | #define FSF_STATUS_READ_PAYLOAD_SIZE 4032 | 157 | #define FSF_STATUS_READ_PAYLOAD_SIZE 4032 |
@@ -154,15 +164,21 @@ | |||
154 | #define FSF_STATUS_READ_INCOMING_ELS 0x00000002 | 164 | #define FSF_STATUS_READ_INCOMING_ELS 0x00000002 |
155 | #define FSF_STATUS_READ_SENSE_DATA_AVAIL 0x00000003 | 165 | #define FSF_STATUS_READ_SENSE_DATA_AVAIL 0x00000003 |
156 | #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004 | 166 | #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD 0x00000004 |
157 | #define FSF_STATUS_READ_LINK_DOWN 0x00000005 /* FIXME: really? */ | 167 | #define FSF_STATUS_READ_LINK_DOWN 0x00000005 |
158 | #define FSF_STATUS_READ_LINK_UP 0x00000006 | 168 | #define FSF_STATUS_READ_LINK_UP 0x00000006 |
159 | #define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A | 169 | #define FSF_STATUS_READ_CFDC_UPDATED 0x0000000A |
160 | #define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B | 170 | #define FSF_STATUS_READ_CFDC_HARDENED 0x0000000B |
171 | #define FSF_STATUS_READ_FEATURE_UPDATE_ALERT 0x0000000C | ||
161 | 172 | ||
162 | /* status subtypes in status read buffer */ | 173 | /* status subtypes in status read buffer */ |
163 | #define FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT 0x00000001 | 174 | #define FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT 0x00000001 |
164 | #define FSF_STATUS_READ_SUB_ERROR_PORT 0x00000002 | 175 | #define FSF_STATUS_READ_SUB_ERROR_PORT 0x00000002 |
165 | 176 | ||
177 | /* status subtypes for link down */ | ||
178 | #define FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK 0x00000000 | ||
179 | #define FSF_STATUS_READ_SUB_FDISC_FAILED 0x00000001 | ||
180 | #define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE 0x00000002 | ||
181 | |||
166 | /* status subtypes for CFDC */ | 182 | /* status subtypes for CFDC */ |
167 | #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002 | 183 | #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE 0x00000002 |
168 | #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F | 184 | #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F |
@@ -193,11 +209,15 @@ | |||
193 | #define FSF_QTCB_LOG_SIZE 1024 | 209 | #define FSF_QTCB_LOG_SIZE 1024 |
194 | 210 | ||
195 | /* channel features */ | 211 | /* channel features */ |
196 | #define FSF_FEATURE_QTCB_SUPPRESSION 0x00000001 | ||
197 | #define FSF_FEATURE_CFDC 0x00000002 | 212 | #define FSF_FEATURE_CFDC 0x00000002 |
198 | #define FSF_FEATURE_LUN_SHARING 0x00000004 | 213 | #define FSF_FEATURE_LUN_SHARING 0x00000004 |
199 | #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 | 214 | #define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 |
200 | #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 | 215 | #define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 |
216 | #define FSF_FEATURE_UPDATE_ALERT 0x00000100 | ||
217 | |||
218 | /* host connection features */ | ||
219 | #define FSF_FEATURE_NPIV_MODE 0x00000001 | ||
220 | #define FSF_FEATURE_VM_ASSIGNED_WWPN 0x00000002 | ||
201 | 221 | ||
202 | /* option */ | 222 | /* option */ |
203 | #define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001 | 223 | #define FSF_OPEN_LUN_SUPPRESS_BOXING 0x00000001 |
@@ -305,15 +325,23 @@ struct fsf_qual_sequence_error { | |||
305 | u32 res1[3]; | 325 | u32 res1[3]; |
306 | } __attribute__ ((packed)); | 326 | } __attribute__ ((packed)); |
307 | 327 | ||
308 | struct fsf_qual_locallink_error { | 328 | struct fsf_link_down_info { |
309 | u32 code; | 329 | u32 error_code; |
310 | u32 res1[3]; | 330 | u32 res1; |
331 | u8 res2[2]; | ||
332 | u8 primary_status; | ||
333 | u8 ioerr_code; | ||
334 | u8 action_code; | ||
335 | u8 reason_code; | ||
336 | u8 explanation_code; | ||
337 | u8 vendor_specific_code; | ||
311 | } __attribute__ ((packed)); | 338 | } __attribute__ ((packed)); |
312 | 339 | ||
313 | union fsf_prot_status_qual { | 340 | union fsf_prot_status_qual { |
341 | u64 doubleword[FSF_PROT_STATUS_QUAL_SIZE / sizeof(u64)]; | ||
314 | struct fsf_qual_version_error version_error; | 342 | struct fsf_qual_version_error version_error; |
315 | struct fsf_qual_sequence_error sequence_error; | 343 | struct fsf_qual_sequence_error sequence_error; |
316 | struct fsf_qual_locallink_error locallink_error; | 344 | struct fsf_link_down_info link_down_info; |
317 | } __attribute__ ((packed)); | 345 | } __attribute__ ((packed)); |
318 | 346 | ||
319 | struct fsf_qtcb_prefix { | 347 | struct fsf_qtcb_prefix { |
@@ -331,7 +359,9 @@ union fsf_status_qual { | |||
331 | u8 byte[FSF_STATUS_QUALIFIER_SIZE]; | 359 | u8 byte[FSF_STATUS_QUALIFIER_SIZE]; |
332 | u16 halfword[FSF_STATUS_QUALIFIER_SIZE / sizeof (u16)]; | 360 | u16 halfword[FSF_STATUS_QUALIFIER_SIZE / sizeof (u16)]; |
333 | u32 word[FSF_STATUS_QUALIFIER_SIZE / sizeof (u32)]; | 361 | u32 word[FSF_STATUS_QUALIFIER_SIZE / sizeof (u32)]; |
362 | u64 doubleword[FSF_STATUS_QUALIFIER_SIZE / sizeof(u64)]; | ||
334 | struct fsf_queue_designator fsf_queue_designator; | 363 | struct fsf_queue_designator fsf_queue_designator; |
364 | struct fsf_link_down_info link_down_info; | ||
335 | } __attribute__ ((packed)); | 365 | } __attribute__ ((packed)); |
336 | 366 | ||
337 | struct fsf_qtcb_header { | 367 | struct fsf_qtcb_header { |
@@ -406,8 +436,8 @@ struct fsf_qtcb_bottom_config { | |||
406 | u32 low_qtcb_version; | 436 | u32 low_qtcb_version; |
407 | u32 max_qtcb_size; | 437 | u32 max_qtcb_size; |
408 | u32 max_data_transfer_size; | 438 | u32 max_data_transfer_size; |
409 | u32 supported_features; | 439 | u32 adapter_features; |
410 | u8 res1[4]; | 440 | u32 connection_features; |
411 | u32 fc_topology; | 441 | u32 fc_topology; |
412 | u32 fc_link_speed; | 442 | u32 fc_link_speed; |
413 | u32 adapter_type; | 443 | u32 adapter_type; |
@@ -425,7 +455,7 @@ struct fsf_qtcb_bottom_config { | |||
425 | } __attribute__ ((packed)); | 455 | } __attribute__ ((packed)); |
426 | 456 | ||
427 | struct fsf_qtcb_bottom_port { | 457 | struct fsf_qtcb_bottom_port { |
428 | u8 res1[8]; | 458 | u64 wwpn; |
429 | u32 fc_port_id; | 459 | u32 fc_port_id; |
430 | u32 port_type; | 460 | u32 port_type; |
431 | u32 port_state; | 461 | u32 port_state; |
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index 24e16ec331d9..d719f66a29a4 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
@@ -54,8 +54,7 @@ static inline int zfcp_qdio_sbals_from_buffer | |||
54 | static qdio_handler_t zfcp_qdio_request_handler; | 54 | static qdio_handler_t zfcp_qdio_request_handler; |
55 | static qdio_handler_t zfcp_qdio_response_handler; | 55 | static qdio_handler_t zfcp_qdio_response_handler; |
56 | static int zfcp_qdio_handler_error_check(struct zfcp_adapter *, | 56 | static int zfcp_qdio_handler_error_check(struct zfcp_adapter *, |
57 | unsigned int, | 57 | unsigned int, unsigned int, unsigned int, int, int); |
58 | unsigned int, unsigned int); | ||
59 | 58 | ||
60 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_QDIO | 59 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_QDIO |
61 | 60 | ||
@@ -214,22 +213,12 @@ zfcp_qdio_allocate(struct zfcp_adapter *adapter) | |||
214 | * | 213 | * |
215 | */ | 214 | */ |
216 | static inline int | 215 | static inline int |
217 | zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, | 216 | zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status, |
218 | unsigned int status, | 217 | unsigned int qdio_error, unsigned int siga_error, |
219 | unsigned int qdio_error, unsigned int siga_error) | 218 | int first_element, int elements_processed) |
220 | { | 219 | { |
221 | int retval = 0; | 220 | int retval = 0; |
222 | 221 | ||
223 | if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_TRACE)) { | ||
224 | if (status & QDIO_STATUS_INBOUND_INT) { | ||
225 | ZFCP_LOG_TRACE("status is" | ||
226 | " QDIO_STATUS_INBOUND_INT \n"); | ||
227 | } | ||
228 | if (status & QDIO_STATUS_OUTBOUND_INT) { | ||
229 | ZFCP_LOG_TRACE("status is" | ||
230 | " QDIO_STATUS_OUTBOUND_INT \n"); | ||
231 | } | ||
232 | } | ||
233 | if (unlikely(status & QDIO_STATUS_LOOK_FOR_ERROR)) { | 222 | if (unlikely(status & QDIO_STATUS_LOOK_FOR_ERROR)) { |
234 | retval = -EIO; | 223 | retval = -EIO; |
235 | 224 | ||
@@ -237,9 +226,10 @@ zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, | |||
237 | "qdio_error=0x%x, siga_error=0x%x)\n", | 226 | "qdio_error=0x%x, siga_error=0x%x)\n", |
238 | status, qdio_error, siga_error); | 227 | status, qdio_error, siga_error); |
239 | 228 | ||
240 | /* Restarting IO on the failed adapter from scratch */ | 229 | zfcp_hba_dbf_event_qdio(adapter, status, qdio_error, siga_error, |
241 | debug_text_event(adapter->erp_dbf, 1, "qdio_err"); | 230 | first_element, elements_processed); |
242 | /* | 231 | /* |
232 | * Restarting IO on the failed adapter from scratch. | ||
243 | * Since we have been using this adapter, it is save to assume | 233 | * Since we have been using this adapter, it is save to assume |
244 | * that it is not failed but recoverable. The card seems to | 234 | * that it is not failed but recoverable. The card seems to |
245 | * report link-up events by self-initiated queue shutdown. | 235 | * report link-up events by self-initiated queue shutdown. |
@@ -282,7 +272,8 @@ zfcp_qdio_request_handler(struct ccw_device *ccw_device, | |||
282 | first_element, elements_processed); | 272 | first_element, elements_processed); |
283 | 273 | ||
284 | if (unlikely(zfcp_qdio_handler_error_check(adapter, status, qdio_error, | 274 | if (unlikely(zfcp_qdio_handler_error_check(adapter, status, qdio_error, |
285 | siga_error))) | 275 | siga_error, first_element, |
276 | elements_processed))) | ||
286 | goto out; | 277 | goto out; |
287 | /* | 278 | /* |
288 | * we stored address of struct zfcp_adapter data structure | 279 | * we stored address of struct zfcp_adapter data structure |
@@ -334,7 +325,8 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device, | |||
334 | queue = &adapter->response_queue; | 325 | queue = &adapter->response_queue; |
335 | 326 | ||
336 | if (unlikely(zfcp_qdio_handler_error_check(adapter, status, qdio_error, | 327 | if (unlikely(zfcp_qdio_handler_error_check(adapter, status, qdio_error, |
337 | siga_error))) | 328 | siga_error, first_element, |
329 | elements_processed))) | ||
338 | goto out; | 330 | goto out; |
339 | 331 | ||
340 | /* | 332 | /* |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 31a76065cf28..3dcd1bfba3b4 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -44,7 +44,8 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); | |||
44 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); | 44 | static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); |
45 | static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *); | 45 | static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *); |
46 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); | 46 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); |
47 | static int zfcp_task_management_function(struct zfcp_unit *, u8); | 47 | static int zfcp_task_management_function(struct zfcp_unit *, u8, |
48 | struct scsi_cmnd *); | ||
48 | 49 | ||
49 | static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, | 50 | static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, |
50 | scsi_lun_t); | 51 | scsi_lun_t); |
@@ -242,7 +243,10 @@ static void | |||
242 | zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) | 243 | zfcp_scsi_command_fail(struct scsi_cmnd *scpnt, int result) |
243 | { | 244 | { |
244 | set_host_byte(&scpnt->result, result); | 245 | set_host_byte(&scpnt->result, result); |
245 | zfcp_cmd_dbf_event_scsi("failing", scpnt); | 246 | if ((scpnt->device != NULL) && (scpnt->device->host != NULL)) |
247 | zfcp_scsi_dbf_event_result("fail", 4, | ||
248 | (struct zfcp_adapter*) scpnt->device->host->hostdata[0], | ||
249 | scpnt); | ||
246 | /* return directly */ | 250 | /* return directly */ |
247 | scpnt->scsi_done(scpnt); | 251 | scpnt->scsi_done(scpnt); |
248 | } | 252 | } |
@@ -414,67 +418,38 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id) | |||
414 | return (struct zfcp_port *) NULL; | 418 | return (struct zfcp_port *) NULL; |
415 | } | 419 | } |
416 | 420 | ||
417 | /* | 421 | /** |
418 | * function: zfcp_scsi_eh_abort_handler | 422 | * zfcp_scsi_eh_abort_handler - abort the specified SCSI command |
419 | * | 423 | * @scpnt: pointer to scsi_cmnd to be aborted |
420 | * purpose: tries to abort the specified (timed out) SCSI command | 424 | * Return: SUCCESS - command has been aborted and cleaned up in internal |
421 | * | 425 | * bookkeeping, SCSI stack won't be called for aborted command |
422 | * note: We do not need to care for a SCSI command which completes | 426 | * FAILED - otherwise |
423 | * normally but late during this abort routine runs. | ||
424 | * We are allowed to return late commands to the SCSI stack. | ||
425 | * It tracks the state of commands and will handle late commands. | ||
426 | * (Usually, the normal completion of late commands is ignored with | ||
427 | * respect to the running abort operation. Grep for 'done_late' | ||
428 | * in the SCSI stacks sources.) | ||
429 | * | 427 | * |
430 | * returns: SUCCESS - command has been aborted and cleaned up in internal | 428 | * We do not need to care for a SCSI command which completes normally |
431 | * bookkeeping, | 429 | * but late during this abort routine runs. We are allowed to return |
432 | * SCSI stack won't be called for aborted command | 430 | * late commands to the SCSI stack. It tracks the state of commands and |
433 | * FAILED - otherwise | 431 | * will handle late commands. (Usually, the normal completion of late |
432 | * commands is ignored with respect to the running abort operation.) | ||
434 | */ | 433 | */ |
435 | int | 434 | int |
436 | __zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | 435 | zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) |
437 | { | 436 | { |
437 | struct Scsi_Host *scsi_host; | ||
438 | struct zfcp_adapter *adapter; | ||
439 | struct zfcp_unit *unit; | ||
438 | int retval = SUCCESS; | 440 | int retval = SUCCESS; |
439 | struct zfcp_fsf_req *new_fsf_req, *old_fsf_req; | 441 | struct zfcp_fsf_req *new_fsf_req = NULL; |
440 | struct zfcp_adapter *adapter = (struct zfcp_adapter *) scpnt->device->host->hostdata[0]; | 442 | struct zfcp_fsf_req *old_fsf_req; |
441 | struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata; | ||
442 | struct zfcp_port *port = unit->port; | ||
443 | struct Scsi_Host *scsi_host = scpnt->device->host; | ||
444 | union zfcp_req_data *req_data = NULL; | ||
445 | unsigned long flags; | 443 | unsigned long flags; |
446 | u32 status = 0; | 444 | |
447 | 445 | scsi_host = scpnt->device->host; | |
448 | /* the components of a abort_dbf record (fixed size record) */ | 446 | adapter = (struct zfcp_adapter *) scsi_host->hostdata[0]; |
449 | u64 dbf_scsi_cmnd = (unsigned long) scpnt; | 447 | unit = (struct zfcp_unit *) scpnt->device->hostdata; |
450 | char dbf_opcode[ZFCP_ABORT_DBF_LENGTH]; | ||
451 | wwn_t dbf_wwn = port->wwpn; | ||
452 | fcp_lun_t dbf_fcp_lun = unit->fcp_lun; | ||
453 | u64 dbf_retries = scpnt->retries; | ||
454 | u64 dbf_allowed = scpnt->allowed; | ||
455 | u64 dbf_timeout = 0; | ||
456 | u64 dbf_fsf_req = 0; | ||
457 | u64 dbf_fsf_status = 0; | ||
458 | u64 dbf_fsf_qual[2] = { 0, 0 }; | ||
459 | char dbf_result[ZFCP_ABORT_DBF_LENGTH] = "##undef"; | ||
460 | |||
461 | memset(dbf_opcode, 0, ZFCP_ABORT_DBF_LENGTH); | ||
462 | memcpy(dbf_opcode, | ||
463 | scpnt->cmnd, | ||
464 | min(scpnt->cmd_len, (unsigned char) ZFCP_ABORT_DBF_LENGTH)); | ||
465 | 448 | ||
466 | ZFCP_LOG_INFO("aborting scsi_cmnd=%p on adapter %s\n", | 449 | ZFCP_LOG_INFO("aborting scsi_cmnd=%p on adapter %s\n", |
467 | scpnt, zfcp_get_busid_by_adapter(adapter)); | 450 | scpnt, zfcp_get_busid_by_adapter(adapter)); |
468 | 451 | ||
469 | spin_unlock_irq(scsi_host->host_lock); | 452 | /* avoid race condition between late normal completion and abort */ |
470 | |||
471 | /* | ||
472 | * Race condition between normal (late) completion and abort has | ||
473 | * to be avoided. | ||
474 | * The entirity of all accesses to scsi_req have to be atomic. | ||
475 | * scsi_req is usually part of the fsf_req and thus we block the | ||
476 | * release of fsf_req as long as we need to access scsi_req. | ||
477 | */ | ||
478 | write_lock_irqsave(&adapter->abort_lock, flags); | 453 | write_lock_irqsave(&adapter->abort_lock, flags); |
479 | 454 | ||
480 | /* | 455 | /* |
@@ -484,144 +459,47 @@ __zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
484 | * this routine returns. (scpnt is parameter passed to this routine | 459 | * this routine returns. (scpnt is parameter passed to this routine |
485 | * and must not disappear during abort even on late completion.) | 460 | * and must not disappear during abort even on late completion.) |
486 | */ | 461 | */ |
487 | req_data = (union zfcp_req_data *) scpnt->host_scribble; | 462 | old_fsf_req = (struct zfcp_fsf_req *) scpnt->host_scribble; |
488 | /* DEBUG */ | ||
489 | ZFCP_LOG_DEBUG("req_data=%p\n", req_data); | ||
490 | if (!req_data) { | ||
491 | ZFCP_LOG_DEBUG("late command completion overtook abort\n"); | ||
492 | /* | ||
493 | * That's it. | ||
494 | * Do not initiate abort but return SUCCESS. | ||
495 | */ | ||
496 | write_unlock_irqrestore(&adapter->abort_lock, flags); | ||
497 | retval = SUCCESS; | ||
498 | strncpy(dbf_result, "##late1", ZFCP_ABORT_DBF_LENGTH); | ||
499 | goto out; | ||
500 | } | ||
501 | |||
502 | /* Figure out which fsf_req needs to be aborted. */ | ||
503 | old_fsf_req = req_data->send_fcp_command_task.fsf_req; | ||
504 | |||
505 | dbf_fsf_req = (unsigned long) old_fsf_req; | ||
506 | dbf_timeout = | ||
507 | (jiffies - req_data->send_fcp_command_task.start_jiffies) / HZ; | ||
508 | |||
509 | ZFCP_LOG_DEBUG("old_fsf_req=%p\n", old_fsf_req); | ||
510 | if (!old_fsf_req) { | 463 | if (!old_fsf_req) { |
511 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 464 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
512 | ZFCP_LOG_NORMAL("bug: no old fsf request found\n"); | 465 | zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, new_fsf_req); |
513 | ZFCP_LOG_NORMAL("req_data:\n"); | 466 | retval = SUCCESS; |
514 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, | ||
515 | (char *) req_data, sizeof (union zfcp_req_data)); | ||
516 | ZFCP_LOG_NORMAL("scsi_cmnd:\n"); | ||
517 | ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL, | ||
518 | (char *) scpnt, sizeof (struct scsi_cmnd)); | ||
519 | retval = FAILED; | ||
520 | strncpy(dbf_result, "##bug:r", ZFCP_ABORT_DBF_LENGTH); | ||
521 | goto out; | 467 | goto out; |
522 | } | 468 | } |
523 | old_fsf_req->data.send_fcp_command_task.scsi_cmnd = NULL; | 469 | old_fsf_req->data = 0; |
524 | /* mark old request as being aborted */ | ||
525 | old_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING; | 470 | old_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTING; |
526 | /* | ||
527 | * We have to collect all information (e.g. unit) needed by | ||
528 | * zfcp_fsf_abort_fcp_command before calling that routine | ||
529 | * since that routine is not allowed to access | ||
530 | * fsf_req which it is going to abort. | ||
531 | * This is because of we need to release fsf_req_list_lock | ||
532 | * before calling zfcp_fsf_abort_fcp_command. | ||
533 | * Since this lock will not be held, fsf_req may complete | ||
534 | * late and may be released meanwhile. | ||
535 | */ | ||
536 | ZFCP_LOG_DEBUG("unit 0x%016Lx (%p)\n", unit->fcp_lun, unit); | ||
537 | 471 | ||
538 | /* | 472 | /* don't access old_fsf_req after releasing the abort_lock */ |
539 | * We block (call schedule) | ||
540 | * That's why we must release the lock and enable the | ||
541 | * interrupts before. | ||
542 | * On the other hand we do not need the lock anymore since | ||
543 | * all critical accesses to scsi_req are done. | ||
544 | */ | ||
545 | write_unlock_irqrestore(&adapter->abort_lock, flags); | 473 | write_unlock_irqrestore(&adapter->abort_lock, flags); |
546 | /* call FSF routine which does the abort */ | 474 | /* call FSF routine which does the abort */ |
547 | new_fsf_req = zfcp_fsf_abort_fcp_command((unsigned long) old_fsf_req, | 475 | new_fsf_req = zfcp_fsf_abort_fcp_command((unsigned long) old_fsf_req, |
548 | adapter, unit, 0); | 476 | adapter, unit, 0); |
549 | ZFCP_LOG_DEBUG("new_fsf_req=%p\n", new_fsf_req); | ||
550 | if (!new_fsf_req) { | 477 | if (!new_fsf_req) { |
478 | ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n"); | ||
551 | retval = FAILED; | 479 | retval = FAILED; |
552 | ZFCP_LOG_NORMAL("error: initiation of Abort FCP Cmnd " | ||
553 | "failed\n"); | ||
554 | strncpy(dbf_result, "##nores", ZFCP_ABORT_DBF_LENGTH); | ||
555 | goto out; | 480 | goto out; |
556 | } | 481 | } |
557 | 482 | ||
558 | /* wait for completion of abort */ | 483 | /* wait for completion of abort */ |
559 | ZFCP_LOG_DEBUG("waiting for cleanup...\n"); | ||
560 | #if 1 | ||
561 | /* | ||
562 | * FIXME: | ||
563 | * copying zfcp_fsf_req_wait_and_cleanup code is not really nice | ||
564 | */ | ||
565 | __wait_event(new_fsf_req->completion_wq, | 484 | __wait_event(new_fsf_req->completion_wq, |
566 | new_fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | 485 | new_fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); |
567 | status = new_fsf_req->status; | 486 | |
568 | dbf_fsf_status = new_fsf_req->qtcb->header.fsf_status; | ||
569 | /* | ||
570 | * Ralphs special debug load provides timestamps in the FSF | ||
571 | * status qualifier. This might be specified later if being | ||
572 | * useful for debugging aborts. | ||
573 | */ | ||
574 | dbf_fsf_qual[0] = | ||
575 | *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[0]; | ||
576 | dbf_fsf_qual[1] = | ||
577 | *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[2]; | ||
578 | zfcp_fsf_req_free(new_fsf_req); | ||
579 | #else | ||
580 | retval = zfcp_fsf_req_wait_and_cleanup(new_fsf_req, | ||
581 | ZFCP_UNINTERRUPTIBLE, &status); | ||
582 | #endif | ||
583 | ZFCP_LOG_DEBUG("Waiting for cleanup complete, status=0x%x\n", status); | ||
584 | /* status should be valid since signals were not permitted */ | 487 | /* status should be valid since signals were not permitted */ |
585 | if (status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { | 488 | if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) { |
489 | zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req); | ||
586 | retval = SUCCESS; | 490 | retval = SUCCESS; |
587 | strncpy(dbf_result, "##succ", ZFCP_ABORT_DBF_LENGTH); | 491 | } else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { |
588 | } else if (status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) { | 492 | zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req); |
589 | retval = SUCCESS; | 493 | retval = SUCCESS; |
590 | strncpy(dbf_result, "##late2", ZFCP_ABORT_DBF_LENGTH); | ||
591 | } else { | 494 | } else { |
495 | zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req); | ||
592 | retval = FAILED; | 496 | retval = FAILED; |
593 | strncpy(dbf_result, "##fail", ZFCP_ABORT_DBF_LENGTH); | ||
594 | } | 497 | } |
595 | 498 | zfcp_fsf_req_free(new_fsf_req); | |
596 | out: | 499 | out: |
597 | debug_event(adapter->abort_dbf, 1, &dbf_scsi_cmnd, sizeof (u64)); | ||
598 | debug_event(adapter->abort_dbf, 1, &dbf_opcode, ZFCP_ABORT_DBF_LENGTH); | ||
599 | debug_event(adapter->abort_dbf, 1, &dbf_wwn, sizeof (wwn_t)); | ||
600 | debug_event(adapter->abort_dbf, 1, &dbf_fcp_lun, sizeof (fcp_lun_t)); | ||
601 | debug_event(adapter->abort_dbf, 1, &dbf_retries, sizeof (u64)); | ||
602 | debug_event(adapter->abort_dbf, 1, &dbf_allowed, sizeof (u64)); | ||
603 | debug_event(adapter->abort_dbf, 1, &dbf_timeout, sizeof (u64)); | ||
604 | debug_event(adapter->abort_dbf, 1, &dbf_fsf_req, sizeof (u64)); | ||
605 | debug_event(adapter->abort_dbf, 1, &dbf_fsf_status, sizeof (u64)); | ||
606 | debug_event(adapter->abort_dbf, 1, &dbf_fsf_qual[0], sizeof (u64)); | ||
607 | debug_event(adapter->abort_dbf, 1, &dbf_fsf_qual[1], sizeof (u64)); | ||
608 | debug_text_event(adapter->abort_dbf, 1, dbf_result); | ||
609 | |||
610 | spin_lock_irq(scsi_host->host_lock); | ||
611 | return retval; | 500 | return retval; |
612 | } | 501 | } |
613 | 502 | ||
614 | int | ||
615 | zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | ||
616 | { | ||
617 | int rc; | ||
618 | struct Scsi_Host *scsi_host = scpnt->device->host; | ||
619 | spin_lock_irq(scsi_host->host_lock); | ||
620 | rc = __zfcp_scsi_eh_abort_handler(scpnt); | ||
621 | spin_unlock_irq(scsi_host->host_lock); | ||
622 | return rc; | ||
623 | } | ||
624 | |||
625 | /* | 503 | /* |
626 | * function: zfcp_scsi_eh_device_reset_handler | 504 | * function: zfcp_scsi_eh_device_reset_handler |
627 | * | 505 | * |
@@ -651,8 +529,9 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) | |||
651 | */ | 529 | */ |
652 | if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET, | 530 | if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET, |
653 | &unit->status)) { | 531 | &unit->status)) { |
654 | retval = | 532 | retval = zfcp_task_management_function(unit, |
655 | zfcp_task_management_function(unit, FCP_LOGICAL_UNIT_RESET); | 533 | FCP_LOGICAL_UNIT_RESET, |
534 | scpnt); | ||
656 | if (retval) { | 535 | if (retval) { |
657 | ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit); | 536 | ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit); |
658 | if (retval == -ENOTSUPP) | 537 | if (retval == -ENOTSUPP) |
@@ -668,7 +547,7 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) | |||
668 | goto out; | 547 | goto out; |
669 | } | 548 | } |
670 | } | 549 | } |
671 | retval = zfcp_task_management_function(unit, FCP_TARGET_RESET); | 550 | retval = zfcp_task_management_function(unit, FCP_TARGET_RESET, scpnt); |
672 | if (retval) { | 551 | if (retval) { |
673 | ZFCP_LOG_DEBUG("target reset failed (unit=%p)\n", unit); | 552 | ZFCP_LOG_DEBUG("target reset failed (unit=%p)\n", unit); |
674 | retval = FAILED; | 553 | retval = FAILED; |
@@ -681,12 +560,12 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) | |||
681 | } | 560 | } |
682 | 561 | ||
683 | static int | 562 | static int |
684 | zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags) | 563 | zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags, |
564 | struct scsi_cmnd *scpnt) | ||
685 | { | 565 | { |
686 | struct zfcp_adapter *adapter = unit->port->adapter; | 566 | struct zfcp_adapter *adapter = unit->port->adapter; |
687 | int retval; | ||
688 | int status; | ||
689 | struct zfcp_fsf_req *fsf_req; | 567 | struct zfcp_fsf_req *fsf_req; |
568 | int retval = 0; | ||
690 | 569 | ||
691 | /* issue task management function */ | 570 | /* issue task management function */ |
692 | fsf_req = zfcp_fsf_send_fcp_command_task_management | 571 | fsf_req = zfcp_fsf_send_fcp_command_task_management |
@@ -696,70 +575,63 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags) | |||
696 | "failed for unit 0x%016Lx on port 0x%016Lx on " | 575 | "failed for unit 0x%016Lx on port 0x%016Lx on " |
697 | "adapter %s\n", unit->fcp_lun, unit->port->wwpn, | 576 | "adapter %s\n", unit->fcp_lun, unit->port->wwpn, |
698 | zfcp_get_busid_by_adapter(adapter)); | 577 | zfcp_get_busid_by_adapter(adapter)); |
578 | zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit, scpnt); | ||
699 | retval = -ENOMEM; | 579 | retval = -ENOMEM; |
700 | goto out; | 580 | goto out; |
701 | } | 581 | } |
702 | 582 | ||
703 | retval = zfcp_fsf_req_wait_and_cleanup(fsf_req, | 583 | __wait_event(fsf_req->completion_wq, |
704 | ZFCP_UNINTERRUPTIBLE, &status); | 584 | fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); |
585 | |||
705 | /* | 586 | /* |
706 | * check completion status of task management function | 587 | * check completion status of task management function |
707 | * (status should always be valid since no signals permitted) | ||
708 | */ | 588 | */ |
709 | if (status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) | 589 | if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) { |
590 | zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt); | ||
710 | retval = -EIO; | 591 | retval = -EIO; |
711 | else if (status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP) | 592 | } else if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP) { |
593 | zfcp_scsi_dbf_event_devreset("nsup", tm_flags, unit, scpnt); | ||
712 | retval = -ENOTSUPP; | 594 | retval = -ENOTSUPP; |
713 | else | 595 | } else |
714 | retval = 0; | 596 | zfcp_scsi_dbf_event_devreset("okay", tm_flags, unit, scpnt); |
597 | |||
598 | zfcp_fsf_req_free(fsf_req); | ||
715 | out: | 599 | out: |
716 | return retval; | 600 | return retval; |
717 | } | 601 | } |
718 | 602 | ||
719 | /* | 603 | /** |
720 | * function: zfcp_scsi_eh_bus_reset_handler | 604 | * zfcp_scsi_eh_bus_reset_handler - reset bus (reopen adapter) |
721 | * | ||
722 | * purpose: | ||
723 | * | ||
724 | * returns: | ||
725 | */ | 605 | */ |
726 | int | 606 | int |
727 | zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt) | 607 | zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt) |
728 | { | 608 | { |
729 | int retval = 0; | 609 | struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata; |
730 | struct zfcp_unit *unit; | 610 | struct zfcp_adapter *adapter = unit->port->adapter; |
731 | 611 | ||
732 | unit = (struct zfcp_unit *) scpnt->device->hostdata; | ||
733 | ZFCP_LOG_NORMAL("bus reset because of problems with " | 612 | ZFCP_LOG_NORMAL("bus reset because of problems with " |
734 | "unit 0x%016Lx\n", unit->fcp_lun); | 613 | "unit 0x%016Lx\n", unit->fcp_lun); |
735 | zfcp_erp_adapter_reopen(unit->port->adapter, 0); | 614 | zfcp_erp_adapter_reopen(adapter, 0); |
736 | zfcp_erp_wait(unit->port->adapter); | 615 | zfcp_erp_wait(adapter); |
737 | retval = SUCCESS; | ||
738 | 616 | ||
739 | return retval; | 617 | return SUCCESS; |
740 | } | 618 | } |
741 | 619 | ||
742 | /* | 620 | /** |
743 | * function: zfcp_scsi_eh_host_reset_handler | 621 | * zfcp_scsi_eh_host_reset_handler - reset host (reopen adapter) |
744 | * | ||
745 | * purpose: | ||
746 | * | ||
747 | * returns: | ||
748 | */ | 622 | */ |
749 | int | 623 | int |
750 | zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) | 624 | zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) |
751 | { | 625 | { |
752 | int retval = 0; | 626 | struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata; |
753 | struct zfcp_unit *unit; | 627 | struct zfcp_adapter *adapter = unit->port->adapter; |
754 | 628 | ||
755 | unit = (struct zfcp_unit *) scpnt->device->hostdata; | ||
756 | ZFCP_LOG_NORMAL("host reset because of problems with " | 629 | ZFCP_LOG_NORMAL("host reset because of problems with " |
757 | "unit 0x%016Lx\n", unit->fcp_lun); | 630 | "unit 0x%016Lx\n", unit->fcp_lun); |
758 | zfcp_erp_adapter_reopen(unit->port->adapter, 0); | 631 | zfcp_erp_adapter_reopen(adapter, 0); |
759 | zfcp_erp_wait(unit->port->adapter); | 632 | zfcp_erp_wait(adapter); |
760 | retval = SUCCESS; | ||
761 | 633 | ||
762 | return retval; | 634 | return SUCCESS; |
763 | } | 635 | } |
764 | 636 | ||
765 | /* | 637 | /* |
@@ -826,10 +698,16 @@ void | |||
826 | zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) | 698 | zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) |
827 | { | 699 | { |
828 | struct Scsi_Host *shost; | 700 | struct Scsi_Host *shost; |
701 | struct zfcp_port *port; | ||
829 | 702 | ||
830 | shost = adapter->scsi_host; | 703 | shost = adapter->scsi_host; |
831 | if (!shost) | 704 | if (!shost) |
832 | return; | 705 | return; |
706 | read_lock_irq(&zfcp_data.config_lock); | ||
707 | list_for_each_entry(port, &adapter->port_list_head, list) | ||
708 | if (port->rport) | ||
709 | port->rport = NULL; | ||
710 | read_unlock_irq(&zfcp_data.config_lock); | ||
833 | fc_remove_host(shost); | 711 | fc_remove_host(shost); |
834 | scsi_remove_host(shost); | 712 | scsi_remove_host(shost); |
835 | scsi_host_put(shost); | 713 | scsi_host_put(shost); |
@@ -904,18 +782,6 @@ zfcp_get_node_name(struct scsi_target *starget) | |||
904 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); | 782 | read_unlock_irqrestore(&zfcp_data.config_lock, flags); |
905 | } | 783 | } |
906 | 784 | ||
907 | void | ||
908 | zfcp_set_fc_host_attrs(struct zfcp_adapter *adapter) | ||
909 | { | ||
910 | struct Scsi_Host *shost = adapter->scsi_host; | ||
911 | |||
912 | fc_host_node_name(shost) = adapter->wwnn; | ||
913 | fc_host_port_name(shost) = adapter->wwpn; | ||
914 | strncpy(fc_host_serial_number(shost), adapter->serial_number, | ||
915 | min(FC_SERIAL_NUMBER_SIZE, 32)); | ||
916 | fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; | ||
917 | } | ||
918 | |||
919 | struct fc_function_template zfcp_transport_functions = { | 785 | struct fc_function_template zfcp_transport_functions = { |
920 | .get_starget_port_id = zfcp_get_port_id, | 786 | .get_starget_port_id = zfcp_get_port_id, |
921 | .get_starget_port_name = zfcp_get_port_name, | 787 | .get_starget_port_name = zfcp_get_port_name, |
@@ -927,7 +793,10 @@ struct fc_function_template zfcp_transport_functions = { | |||
927 | .show_host_node_name = 1, | 793 | .show_host_node_name = 1, |
928 | .show_host_port_name = 1, | 794 | .show_host_port_name = 1, |
929 | .show_host_supported_classes = 1, | 795 | .show_host_supported_classes = 1, |
796 | .show_host_maxframe_size = 1, | ||
930 | .show_host_serial_number = 1, | 797 | .show_host_serial_number = 1, |
798 | .show_host_speed = 1, | ||
799 | .show_host_port_id = 1, | ||
931 | }; | 800 | }; |
932 | 801 | ||
933 | /** | 802 | /** |
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c index e7345a74800a..0cd435280e7d 100644 --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c | |||
@@ -62,21 +62,18 @@ static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, struct devi | |||
62 | static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_adapter_##_name##_show, NULL); | 62 | static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_adapter_##_name##_show, NULL); |
63 | 63 | ||
64 | ZFCP_DEFINE_ADAPTER_ATTR(status, "0x%08x\n", atomic_read(&adapter->status)); | 64 | ZFCP_DEFINE_ADAPTER_ATTR(status, "0x%08x\n", atomic_read(&adapter->status)); |
65 | ZFCP_DEFINE_ADAPTER_ATTR(wwnn, "0x%016llx\n", adapter->wwnn); | ||
66 | ZFCP_DEFINE_ADAPTER_ATTR(wwpn, "0x%016llx\n", adapter->wwpn); | ||
67 | ZFCP_DEFINE_ADAPTER_ATTR(s_id, "0x%06x\n", adapter->s_id); | ||
68 | ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn); | 65 | ZFCP_DEFINE_ADAPTER_ATTR(peer_wwnn, "0x%016llx\n", adapter->peer_wwnn); |
69 | ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn); | 66 | ZFCP_DEFINE_ADAPTER_ATTR(peer_wwpn, "0x%016llx\n", adapter->peer_wwpn); |
70 | ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id); | 67 | ZFCP_DEFINE_ADAPTER_ATTR(peer_d_id, "0x%06x\n", adapter->peer_d_id); |
68 | ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn); | ||
69 | ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id); | ||
71 | ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version); | 70 | ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version); |
72 | ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); | 71 | ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version); |
73 | ZFCP_DEFINE_ADAPTER_ATTR(fc_link_speed, "%d Gb/s\n", adapter->fc_link_speed); | ||
74 | ZFCP_DEFINE_ADAPTER_ATTR(fc_service_class, "%d\n", adapter->fc_service_class); | 72 | ZFCP_DEFINE_ADAPTER_ATTR(fc_service_class, "%d\n", adapter->fc_service_class); |
75 | ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n", | 73 | ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n", |
76 | fc_topologies[adapter->fc_topology]); | 74 | fc_topologies[adapter->fc_topology]); |
77 | ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n", | 75 | ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n", |
78 | adapter->hardware_version); | 76 | adapter->hardware_version); |
79 | ZFCP_DEFINE_ADAPTER_ATTR(serial_number, "%17s\n", adapter->serial_number); | ||
80 | ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no); | 77 | ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no); |
81 | ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask | 78 | ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask |
82 | (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)); | 79 | (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)); |
@@ -255,21 +252,18 @@ static struct attribute *zfcp_adapter_attrs[] = { | |||
255 | &dev_attr_in_recovery.attr, | 252 | &dev_attr_in_recovery.attr, |
256 | &dev_attr_port_remove.attr, | 253 | &dev_attr_port_remove.attr, |
257 | &dev_attr_port_add.attr, | 254 | &dev_attr_port_add.attr, |
258 | &dev_attr_wwnn.attr, | ||
259 | &dev_attr_wwpn.attr, | ||
260 | &dev_attr_s_id.attr, | ||
261 | &dev_attr_peer_wwnn.attr, | 255 | &dev_attr_peer_wwnn.attr, |
262 | &dev_attr_peer_wwpn.attr, | 256 | &dev_attr_peer_wwpn.attr, |
263 | &dev_attr_peer_d_id.attr, | 257 | &dev_attr_peer_d_id.attr, |
258 | &dev_attr_physical_wwpn.attr, | ||
259 | &dev_attr_physical_s_id.attr, | ||
264 | &dev_attr_card_version.attr, | 260 | &dev_attr_card_version.attr, |
265 | &dev_attr_lic_version.attr, | 261 | &dev_attr_lic_version.attr, |
266 | &dev_attr_fc_link_speed.attr, | ||
267 | &dev_attr_fc_service_class.attr, | 262 | &dev_attr_fc_service_class.attr, |
268 | &dev_attr_fc_topology.attr, | 263 | &dev_attr_fc_topology.attr, |
269 | &dev_attr_scsi_host_no.attr, | 264 | &dev_attr_scsi_host_no.attr, |
270 | &dev_attr_status.attr, | 265 | &dev_attr_status.attr, |
271 | &dev_attr_hardware_version.attr, | 266 | &dev_attr_hardware_version.attr, |
272 | &dev_attr_serial_number.attr, | ||
273 | NULL | 267 | NULL |
274 | }; | 268 | }; |
275 | 269 | ||
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index c932b3b94490..876d1de8480d 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
@@ -1109,15 +1109,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa | |||
1109 | return (0); | 1109 | return (0); |
1110 | } | 1110 | } |
1111 | 1111 | ||
1112 | uint64_t | ||
1113 | ahc_linux_get_memsize(void) | ||
1114 | { | ||
1115 | struct sysinfo si; | ||
1116 | |||
1117 | si_meminfo(&si); | ||
1118 | return ((uint64_t)si.totalram << PAGE_SHIFT); | ||
1119 | } | ||
1120 | |||
1121 | /* | 1112 | /* |
1122 | * Place the SCSI bus into a known state by either resetting it, | 1113 | * Place the SCSI bus into a known state by either resetting it, |
1123 | * or forcing transfer negotiations on the next command to any | 1114 | * or forcing transfer negotiations on the next command to any |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index c52996269240..be9edbe26dbe 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h | |||
@@ -494,8 +494,6 @@ ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count) | |||
494 | int ahc_linux_register_host(struct ahc_softc *, | 494 | int ahc_linux_register_host(struct ahc_softc *, |
495 | struct scsi_host_template *); | 495 | struct scsi_host_template *); |
496 | 496 | ||
497 | uint64_t ahc_linux_get_memsize(void); | ||
498 | |||
499 | /*************************** Pretty Printing **********************************/ | 497 | /*************************** Pretty Printing **********************************/ |
500 | struct info_str { | 498 | struct info_str { |
501 | char *buffer; | 499 | char *buffer; |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index 0d44a6907dd2..3ce77ddc889e 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | |||
@@ -180,6 +180,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
180 | struct ahc_pci_identity *entry; | 180 | struct ahc_pci_identity *entry; |
181 | char *name; | 181 | char *name; |
182 | int error; | 182 | int error; |
183 | struct device *dev = &pdev->dev; | ||
183 | 184 | ||
184 | pci = pdev; | 185 | pci = pdev; |
185 | entry = ahc_find_pci_device(pci); | 186 | entry = ahc_find_pci_device(pci); |
@@ -209,11 +210,12 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
209 | pci_set_master(pdev); | 210 | pci_set_master(pdev); |
210 | 211 | ||
211 | if (sizeof(dma_addr_t) > 4 | 212 | if (sizeof(dma_addr_t) > 4 |
212 | && ahc_linux_get_memsize() > 0x80000000 | 213 | && ahc->features & AHC_LARGE_SCBS |
213 | && pci_set_dma_mask(pdev, mask_39bit) == 0) { | 214 | && dma_set_mask(dev, mask_39bit) == 0 |
215 | && dma_get_required_mask(dev) > DMA_32BIT_MASK) { | ||
214 | ahc->flags |= AHC_39BIT_ADDRESSING; | 216 | ahc->flags |= AHC_39BIT_ADDRESSING; |
215 | } else { | 217 | } else { |
216 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { | 218 | if (dma_set_mask(dev, DMA_32BIT_MASK)) { |
217 | printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); | 219 | printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); |
218 | return (-ENODEV); | 220 | return (-ENODEV); |
219 | } | 221 | } |
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index e6153fe5842a..a8cfbef304b5 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c | |||
@@ -996,6 +996,7 @@ oktosend: | |||
996 | #ifdef ED_DBGP | 996 | #ifdef ED_DBGP |
997 | printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id); | 997 | printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id); |
998 | #endif | 998 | #endif |
999 | dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus; | ||
999 | outl(dev->id[c][target_id].prdaddr, tmpcip); | 1000 | outl(dev->id[c][target_id].prdaddr, tmpcip); |
1000 | tmpcip = tmpcip - 2; | 1001 | tmpcip = tmpcip - 2; |
1001 | outb(0x06, tmpcip); | 1002 | outb(0x06, tmpcip); |
@@ -2572,7 +2573,7 @@ static void atp870u_free_tables(struct Scsi_Host *host) | |||
2572 | for (k = 0; k < 16; k++) { | 2573 | for (k = 0; k < 16; k++) { |
2573 | if (!atp_dev->id[j][k].prd_table) | 2574 | if (!atp_dev->id[j][k].prd_table) |
2574 | continue; | 2575 | continue; |
2575 | pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prdaddr); | 2576 | pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prd_bus); |
2576 | atp_dev->id[j][k].prd_table = NULL; | 2577 | atp_dev->id[j][k].prd_table = NULL; |
2577 | } | 2578 | } |
2578 | } | 2579 | } |
@@ -2584,12 +2585,13 @@ static int atp870u_init_tables(struct Scsi_Host *host) | |||
2584 | int c,k; | 2585 | int c,k; |
2585 | for(c=0;c < 2;c++) { | 2586 | for(c=0;c < 2;c++) { |
2586 | for(k=0;k<16;k++) { | 2587 | for(k=0;k<16;k++) { |
2587 | atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prdaddr)); | 2588 | atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prd_bus)); |
2588 | if (!atp_dev->id[c][k].prd_table) { | 2589 | if (!atp_dev->id[c][k].prd_table) { |
2589 | printk("atp870u_init_tables fail\n"); | 2590 | printk("atp870u_init_tables fail\n"); |
2590 | atp870u_free_tables(host); | 2591 | atp870u_free_tables(host); |
2591 | return -ENOMEM; | 2592 | return -ENOMEM; |
2592 | } | 2593 | } |
2594 | atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus; | ||
2593 | atp_dev->id[c][k].devsp=0x20; | 2595 | atp_dev->id[c][k].devsp=0x20; |
2594 | atp_dev->id[c][k].devtype = 0x7f; | 2596 | atp_dev->id[c][k].devtype = 0x7f; |
2595 | atp_dev->id[c][k].curr_req = NULL; | 2597 | atp_dev->id[c][k].curr_req = NULL; |
diff --git a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h index 89f43af39cf2..62bae64a01c1 100644 --- a/drivers/scsi/atp870u.h +++ b/drivers/scsi/atp870u.h | |||
@@ -54,8 +54,9 @@ struct atp_unit | |||
54 | unsigned long tran_len; | 54 | unsigned long tran_len; |
55 | unsigned long last_len; | 55 | unsigned long last_len; |
56 | unsigned char *prd_pos; | 56 | unsigned char *prd_pos; |
57 | unsigned char *prd_table; | 57 | unsigned char *prd_table; /* Kernel address of PRD table */ |
58 | dma_addr_t prdaddr; | 58 | dma_addr_t prd_bus; /* Bus address of PRD */ |
59 | dma_addr_t prdaddr; /* Dynamically updated in driver */ | ||
59 | struct scsi_cmnd *curr_req; | 60 | struct scsi_cmnd *curr_req; |
60 | } id[2][16]; | 61 | } id[2][16]; |
61 | struct Scsi_Host *host; | 62 | struct Scsi_Host *host; |
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c index fa652f8aa643..d59d449a9e4d 100644 --- a/drivers/scsi/fd_mcs.c +++ b/drivers/scsi/fd_mcs.c | |||
@@ -1360,3 +1360,5 @@ static Scsi_Host_Template driver_template = { | |||
1360 | .use_clustering = DISABLE_CLUSTERING, | 1360 | .use_clustering = DISABLE_CLUSTERING, |
1361 | }; | 1361 | }; |
1362 | #include "scsi_module.c" | 1362 | #include "scsi_module.c" |
1363 | |||
1364 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 85503fad789a..f2a72d33132c 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
@@ -98,6 +98,7 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) | |||
98 | switch (oldstate) { | 98 | switch (oldstate) { |
99 | case SHOST_CREATED: | 99 | case SHOST_CREATED: |
100 | case SHOST_RUNNING: | 100 | case SHOST_RUNNING: |
101 | case SHOST_CANCEL_RECOVERY: | ||
101 | break; | 102 | break; |
102 | default: | 103 | default: |
103 | goto illegal; | 104 | goto illegal; |
@@ -107,12 +108,31 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) | |||
107 | case SHOST_DEL: | 108 | case SHOST_DEL: |
108 | switch (oldstate) { | 109 | switch (oldstate) { |
109 | case SHOST_CANCEL: | 110 | case SHOST_CANCEL: |
111 | case SHOST_DEL_RECOVERY: | ||
110 | break; | 112 | break; |
111 | default: | 113 | default: |
112 | goto illegal; | 114 | goto illegal; |
113 | } | 115 | } |
114 | break; | 116 | break; |
115 | 117 | ||
118 | case SHOST_CANCEL_RECOVERY: | ||
119 | switch (oldstate) { | ||
120 | case SHOST_CANCEL: | ||
121 | case SHOST_RECOVERY: | ||
122 | break; | ||
123 | default: | ||
124 | goto illegal; | ||
125 | } | ||
126 | break; | ||
127 | |||
128 | case SHOST_DEL_RECOVERY: | ||
129 | switch (oldstate) { | ||
130 | case SHOST_CANCEL_RECOVERY: | ||
131 | break; | ||
132 | default: | ||
133 | goto illegal; | ||
134 | } | ||
135 | break; | ||
116 | } | 136 | } |
117 | shost->shost_state = state; | 137 | shost->shost_state = state; |
118 | return 0; | 138 | return 0; |
@@ -134,13 +154,24 @@ EXPORT_SYMBOL(scsi_host_set_state); | |||
134 | **/ | 154 | **/ |
135 | void scsi_remove_host(struct Scsi_Host *shost) | 155 | void scsi_remove_host(struct Scsi_Host *shost) |
136 | { | 156 | { |
157 | unsigned long flags; | ||
137 | down(&shost->scan_mutex); | 158 | down(&shost->scan_mutex); |
138 | scsi_host_set_state(shost, SHOST_CANCEL); | 159 | spin_lock_irqsave(shost->host_lock, flags); |
160 | if (scsi_host_set_state(shost, SHOST_CANCEL)) | ||
161 | if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) { | ||
162 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
163 | up(&shost->scan_mutex); | ||
164 | return; | ||
165 | } | ||
166 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
139 | up(&shost->scan_mutex); | 167 | up(&shost->scan_mutex); |
140 | scsi_forget_host(shost); | 168 | scsi_forget_host(shost); |
141 | scsi_proc_host_rm(shost); | 169 | scsi_proc_host_rm(shost); |
142 | 170 | ||
143 | scsi_host_set_state(shost, SHOST_DEL); | 171 | spin_lock_irqsave(shost->host_lock, flags); |
172 | if (scsi_host_set_state(shost, SHOST_DEL)) | ||
173 | BUG_ON(scsi_host_set_state(shost, SHOST_DEL_RECOVERY)); | ||
174 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
144 | 175 | ||
145 | transport_unregister_device(&shost->shost_gendev); | 176 | transport_unregister_device(&shost->shost_gendev); |
146 | class_device_unregister(&shost->shost_classdev); | 177 | class_device_unregister(&shost->shost_classdev); |
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 6e54c7d9b33c..19392f651272 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c | |||
@@ -460,6 +460,8 @@ MODULE_PARM(adisplay, "1i"); | |||
460 | MODULE_PARM(normal, "1i"); | 460 | MODULE_PARM(normal, "1i"); |
461 | MODULE_PARM(ansi, "1i"); | 461 | MODULE_PARM(ansi, "1i"); |
462 | #endif | 462 | #endif |
463 | |||
464 | MODULE_LICENSE("GPL"); | ||
463 | #endif | 465 | #endif |
464 | /*counter of concurrent disk read/writes, to turn on/off disk led */ | 466 | /*counter of concurrent disk read/writes, to turn on/off disk led */ |
465 | static int disk_rw_in_progress = 0; | 467 | static int disk_rw_in_progress = 0; |
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 5b14934ba861..ff25210b00ba 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
@@ -727,6 +727,16 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct) | |||
727 | if (hostdata->madapter_info.port_max_txu[0]) | 727 | if (hostdata->madapter_info.port_max_txu[0]) |
728 | hostdata->host->max_sectors = | 728 | hostdata->host->max_sectors = |
729 | hostdata->madapter_info.port_max_txu[0] >> 9; | 729 | hostdata->madapter_info.port_max_txu[0] >> 9; |
730 | |||
731 | if (hostdata->madapter_info.os_type == 3 && | ||
732 | strcmp(hostdata->madapter_info.srp_version, "1.6a") <= 0) { | ||
733 | printk("ibmvscsi: host (Ver. %s) doesn't support large" | ||
734 | "transfers\n", | ||
735 | hostdata->madapter_info.srp_version); | ||
736 | printk("ibmvscsi: limiting scatterlists to %d\n", | ||
737 | MAX_INDIRECT_BUFS); | ||
738 | hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; | ||
739 | } | ||
730 | } | 740 | } |
731 | } | 741 | } |
732 | 742 | ||
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5cc53cd9323e..d92273cbe0de 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -2465,9 +2465,12 @@ static unsigned long ata_pio_poll(struct ata_port *ap) | |||
2465 | * | 2465 | * |
2466 | * LOCKING: | 2466 | * LOCKING: |
2467 | * None. (executing in kernel thread context) | 2467 | * None. (executing in kernel thread context) |
2468 | * | ||
2469 | * RETURNS: | ||
2470 | * Non-zero if qc completed, zero otherwise. | ||
2468 | */ | 2471 | */ |
2469 | 2472 | ||
2470 | static void ata_pio_complete (struct ata_port *ap) | 2473 | static int ata_pio_complete (struct ata_port *ap) |
2471 | { | 2474 | { |
2472 | struct ata_queued_cmd *qc; | 2475 | struct ata_queued_cmd *qc; |
2473 | u8 drv_stat; | 2476 | u8 drv_stat; |
@@ -2486,14 +2489,14 @@ static void ata_pio_complete (struct ata_port *ap) | |||
2486 | if (drv_stat & (ATA_BUSY | ATA_DRQ)) { | 2489 | if (drv_stat & (ATA_BUSY | ATA_DRQ)) { |
2487 | ap->pio_task_state = PIO_ST_LAST_POLL; | 2490 | ap->pio_task_state = PIO_ST_LAST_POLL; |
2488 | ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO; | 2491 | ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO; |
2489 | return; | 2492 | return 0; |
2490 | } | 2493 | } |
2491 | } | 2494 | } |
2492 | 2495 | ||
2493 | drv_stat = ata_wait_idle(ap); | 2496 | drv_stat = ata_wait_idle(ap); |
2494 | if (!ata_ok(drv_stat)) { | 2497 | if (!ata_ok(drv_stat)) { |
2495 | ap->pio_task_state = PIO_ST_ERR; | 2498 | ap->pio_task_state = PIO_ST_ERR; |
2496 | return; | 2499 | return 0; |
2497 | } | 2500 | } |
2498 | 2501 | ||
2499 | qc = ata_qc_from_tag(ap, ap->active_tag); | 2502 | qc = ata_qc_from_tag(ap, ap->active_tag); |
@@ -2502,6 +2505,10 @@ static void ata_pio_complete (struct ata_port *ap) | |||
2502 | ap->pio_task_state = PIO_ST_IDLE; | 2505 | ap->pio_task_state = PIO_ST_IDLE; |
2503 | 2506 | ||
2504 | ata_poll_qc_complete(qc, drv_stat); | 2507 | ata_poll_qc_complete(qc, drv_stat); |
2508 | |||
2509 | /* another command may start at this point */ | ||
2510 | |||
2511 | return 1; | ||
2505 | } | 2512 | } |
2506 | 2513 | ||
2507 | 2514 | ||
@@ -2709,7 +2716,7 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) | |||
2709 | 2716 | ||
2710 | next_sg: | 2717 | next_sg: |
2711 | if (unlikely(qc->cursg >= qc->n_elem)) { | 2718 | if (unlikely(qc->cursg >= qc->n_elem)) { |
2712 | /* | 2719 | /* |
2713 | * The end of qc->sg is reached and the device expects | 2720 | * The end of qc->sg is reached and the device expects |
2714 | * more data to transfer. In order not to overrun qc->sg | 2721 | * more data to transfer. In order not to overrun qc->sg |
2715 | * and fulfill length specified in the byte count register, | 2722 | * and fulfill length specified in the byte count register, |
@@ -2721,7 +2728,7 @@ next_sg: | |||
2721 | unsigned int i; | 2728 | unsigned int i; |
2722 | 2729 | ||
2723 | if (words) /* warning if bytes > 1 */ | 2730 | if (words) /* warning if bytes > 1 */ |
2724 | printk(KERN_WARNING "ata%u: %u bytes trailing data\n", | 2731 | printk(KERN_WARNING "ata%u: %u bytes trailing data\n", |
2725 | ap->id, bytes); | 2732 | ap->id, bytes); |
2726 | 2733 | ||
2727 | for (i = 0; i < words; i++) | 2734 | for (i = 0; i < words; i++) |
@@ -2849,9 +2856,7 @@ static void ata_pio_block(struct ata_port *ap) | |||
2849 | if (is_atapi_taskfile(&qc->tf)) { | 2856 | if (is_atapi_taskfile(&qc->tf)) { |
2850 | /* no more data to transfer or unsupported ATAPI command */ | 2857 | /* no more data to transfer or unsupported ATAPI command */ |
2851 | if ((status & ATA_DRQ) == 0) { | 2858 | if ((status & ATA_DRQ) == 0) { |
2852 | ap->pio_task_state = PIO_ST_IDLE; | 2859 | ap->pio_task_state = PIO_ST_LAST; |
2853 | |||
2854 | ata_poll_qc_complete(qc, status); | ||
2855 | return; | 2860 | return; |
2856 | } | 2861 | } |
2857 | 2862 | ||
@@ -2887,7 +2892,12 @@ static void ata_pio_error(struct ata_port *ap) | |||
2887 | static void ata_pio_task(void *_data) | 2892 | static void ata_pio_task(void *_data) |
2888 | { | 2893 | { |
2889 | struct ata_port *ap = _data; | 2894 | struct ata_port *ap = _data; |
2890 | unsigned long timeout = 0; | 2895 | unsigned long timeout; |
2896 | int qc_completed; | ||
2897 | |||
2898 | fsm_start: | ||
2899 | timeout = 0; | ||
2900 | qc_completed = 0; | ||
2891 | 2901 | ||
2892 | switch (ap->pio_task_state) { | 2902 | switch (ap->pio_task_state) { |
2893 | case PIO_ST_IDLE: | 2903 | case PIO_ST_IDLE: |
@@ -2898,7 +2908,7 @@ static void ata_pio_task(void *_data) | |||
2898 | break; | 2908 | break; |
2899 | 2909 | ||
2900 | case PIO_ST_LAST: | 2910 | case PIO_ST_LAST: |
2901 | ata_pio_complete(ap); | 2911 | qc_completed = ata_pio_complete(ap); |
2902 | break; | 2912 | break; |
2903 | 2913 | ||
2904 | case PIO_ST_POLL: | 2914 | case PIO_ST_POLL: |
@@ -2913,10 +2923,9 @@ static void ata_pio_task(void *_data) | |||
2913 | } | 2923 | } |
2914 | 2924 | ||
2915 | if (timeout) | 2925 | if (timeout) |
2916 | queue_delayed_work(ata_wq, &ap->pio_task, | 2926 | queue_delayed_work(ata_wq, &ap->pio_task, timeout); |
2917 | timeout); | 2927 | else if (!qc_completed) |
2918 | else | 2928 | goto fsm_start; |
2919 | queue_work(ata_wq, &ap->pio_task); | ||
2920 | } | 2929 | } |
2921 | 2930 | ||
2922 | static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev, | 2931 | static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev, |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 3e9b64137873..23d095d3817b 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -201,6 +201,7 @@ int | |||
201 | qla2100_pci_config(scsi_qla_host_t *ha) | 201 | qla2100_pci_config(scsi_qla_host_t *ha) |
202 | { | 202 | { |
203 | uint16_t w, mwi; | 203 | uint16_t w, mwi; |
204 | uint32_t d; | ||
204 | unsigned long flags; | 205 | unsigned long flags; |
205 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | 206 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
206 | 207 | ||
@@ -215,9 +216,9 @@ qla2100_pci_config(scsi_qla_host_t *ha) | |||
215 | pci_write_config_word(ha->pdev, PCI_COMMAND, w); | 216 | pci_write_config_word(ha->pdev, PCI_COMMAND, w); |
216 | 217 | ||
217 | /* Reset expansion ROM address decode enable */ | 218 | /* Reset expansion ROM address decode enable */ |
218 | pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); | 219 | pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); |
219 | w &= ~PCI_ROM_ADDRESS_ENABLE; | 220 | d &= ~PCI_ROM_ADDRESS_ENABLE; |
220 | pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); | 221 | pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); |
221 | 222 | ||
222 | /* Get PCI bus information. */ | 223 | /* Get PCI bus information. */ |
223 | spin_lock_irqsave(&ha->hardware_lock, flags); | 224 | spin_lock_irqsave(&ha->hardware_lock, flags); |
@@ -237,6 +238,7 @@ int | |||
237 | qla2300_pci_config(scsi_qla_host_t *ha) | 238 | qla2300_pci_config(scsi_qla_host_t *ha) |
238 | { | 239 | { |
239 | uint16_t w, mwi; | 240 | uint16_t w, mwi; |
241 | uint32_t d; | ||
240 | unsigned long flags = 0; | 242 | unsigned long flags = 0; |
241 | uint32_t cnt; | 243 | uint32_t cnt; |
242 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | 244 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
@@ -302,9 +304,9 @@ qla2300_pci_config(scsi_qla_host_t *ha) | |||
302 | pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); | 304 | pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); |
303 | 305 | ||
304 | /* Reset expansion ROM address decode enable */ | 306 | /* Reset expansion ROM address decode enable */ |
305 | pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); | 307 | pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); |
306 | w &= ~PCI_ROM_ADDRESS_ENABLE; | 308 | d &= ~PCI_ROM_ADDRESS_ENABLE; |
307 | pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); | 309 | pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); |
308 | 310 | ||
309 | /* Get PCI bus information. */ | 311 | /* Get PCI bus information. */ |
310 | spin_lock_irqsave(&ha->hardware_lock, flags); | 312 | spin_lock_irqsave(&ha->hardware_lock, flags); |
@@ -324,6 +326,7 @@ int | |||
324 | qla24xx_pci_config(scsi_qla_host_t *ha) | 326 | qla24xx_pci_config(scsi_qla_host_t *ha) |
325 | { | 327 | { |
326 | uint16_t w, mwi; | 328 | uint16_t w, mwi; |
329 | uint32_t d; | ||
327 | unsigned long flags = 0; | 330 | unsigned long flags = 0; |
328 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 331 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
329 | int pcix_cmd_reg, pcie_dctl_reg; | 332 | int pcix_cmd_reg, pcie_dctl_reg; |
@@ -366,9 +369,9 @@ qla24xx_pci_config(scsi_qla_host_t *ha) | |||
366 | } | 369 | } |
367 | 370 | ||
368 | /* Reset expansion ROM address decode enable */ | 371 | /* Reset expansion ROM address decode enable */ |
369 | pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); | 372 | pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); |
370 | w &= ~PCI_ROM_ADDRESS_ENABLE; | 373 | d &= ~PCI_ROM_ADDRESS_ENABLE; |
371 | pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); | 374 | pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); |
372 | 375 | ||
373 | /* Get PCI bus information. */ | 376 | /* Get PCI bus information. */ |
374 | spin_lock_irqsave(&ha->hardware_lock, flags); | 377 | spin_lock_irqsave(&ha->hardware_lock, flags); |
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index a63f93186e41..b227e51d12f4 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c | |||
@@ -161,7 +161,7 @@ static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) | |||
161 | { | 161 | { |
162 | struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); | 162 | struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); |
163 | unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device); | 163 | unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device); |
164 | u32 val, val2; | 164 | u32 val, val2 = 0; |
165 | u8 pmr; | 165 | u8 pmr; |
166 | 166 | ||
167 | if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */ | 167 | if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */ |
@@ -289,7 +289,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
289 | if (ent->device != 0x182) { | 289 | if (ent->device != 0x182) { |
290 | if ((pmr & SIS_PMR_COMBINED) == 0) { | 290 | if ((pmr & SIS_PMR_COMBINED) == 0) { |
291 | printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in SATA mode\n"); | 291 | printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in SATA mode\n"); |
292 | port2_start=0x64; | 292 | port2_start = 64; |
293 | } | 293 | } |
294 | else { | 294 | else { |
295 | printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in combined mode\n"); | 295 | printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in combined mode\n"); |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index a780546eda9c..1f0ebabf6d47 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -1265,9 +1265,8 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery) | |||
1265 | list_for_each_safe(lh, lh_sf, &active_list) { | 1265 | list_for_each_safe(lh, lh_sf, &active_list) { |
1266 | scmd = list_entry(lh, struct scsi_cmnd, eh_entry); | 1266 | scmd = list_entry(lh, struct scsi_cmnd, eh_entry); |
1267 | list_del_init(lh); | 1267 | list_del_init(lh); |
1268 | if (recovery) { | 1268 | if (recovery && |
1269 | scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD); | 1269 | !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD)) { |
1270 | } else { | ||
1271 | scmd->result = (DID_ABORT << 16); | 1270 | scmd->result = (DID_ABORT << 16); |
1272 | scsi_finish_command(scmd); | 1271 | scsi_finish_command(scmd); |
1273 | } | 1272 | } |
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 07b554affcf2..64fc9e21f35b 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c | |||
@@ -110,6 +110,7 @@ static struct { | |||
110 | {"RELISYS", "Scorpio", NULL, BLIST_NOLUN}, /* responds to all lun */ | 110 | {"RELISYS", "Scorpio", NULL, BLIST_NOLUN}, /* responds to all lun */ |
111 | {"SANKYO", "CP525", "6.64", BLIST_NOLUN}, /* causes failed REQ SENSE, extra reset */ | 111 | {"SANKYO", "CP525", "6.64", BLIST_NOLUN}, /* causes failed REQ SENSE, extra reset */ |
112 | {"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN}, | 112 | {"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN}, |
113 | {"transtec", "T5008", "0001", BLIST_NOREPORTLUN }, | ||
113 | {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* locks up */ | 114 | {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* locks up */ |
114 | {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* locks up */ | 115 | {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* locks up */ |
115 | {"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */ | 116 | {"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */ |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 895c9452be4c..ad5342165079 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -50,7 +50,7 @@ | |||
50 | void scsi_eh_wakeup(struct Scsi_Host *shost) | 50 | void scsi_eh_wakeup(struct Scsi_Host *shost) |
51 | { | 51 | { |
52 | if (shost->host_busy == shost->host_failed) { | 52 | if (shost->host_busy == shost->host_failed) { |
53 | up(shost->eh_wait); | 53 | wake_up_process(shost->ehandler); |
54 | SCSI_LOG_ERROR_RECOVERY(5, | 54 | SCSI_LOG_ERROR_RECOVERY(5, |
55 | printk("Waking error handler thread\n")); | 55 | printk("Waking error handler thread\n")); |
56 | } | 56 | } |
@@ -68,19 +68,24 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) | |||
68 | { | 68 | { |
69 | struct Scsi_Host *shost = scmd->device->host; | 69 | struct Scsi_Host *shost = scmd->device->host; |
70 | unsigned long flags; | 70 | unsigned long flags; |
71 | int ret = 0; | ||
71 | 72 | ||
72 | if (shost->eh_wait == NULL) | 73 | if (!shost->ehandler) |
73 | return 0; | 74 | return 0; |
74 | 75 | ||
75 | spin_lock_irqsave(shost->host_lock, flags); | 76 | spin_lock_irqsave(shost->host_lock, flags); |
77 | if (scsi_host_set_state(shost, SHOST_RECOVERY)) | ||
78 | if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) | ||
79 | goto out_unlock; | ||
76 | 80 | ||
81 | ret = 1; | ||
77 | scmd->eh_eflags |= eh_flag; | 82 | scmd->eh_eflags |= eh_flag; |
78 | list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); | 83 | list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); |
79 | scsi_host_set_state(shost, SHOST_RECOVERY); | ||
80 | shost->host_failed++; | 84 | shost->host_failed++; |
81 | scsi_eh_wakeup(shost); | 85 | scsi_eh_wakeup(shost); |
86 | out_unlock: | ||
82 | spin_unlock_irqrestore(shost->host_lock, flags); | 87 | spin_unlock_irqrestore(shost->host_lock, flags); |
83 | return 1; | 88 | return ret; |
84 | } | 89 | } |
85 | 90 | ||
86 | /** | 91 | /** |
@@ -176,8 +181,8 @@ void scsi_times_out(struct scsi_cmnd *scmd) | |||
176 | } | 181 | } |
177 | 182 | ||
178 | if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) { | 183 | if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) { |
179 | panic("Error handler thread not present at %p %p %s %d", | 184 | scmd->result |= DID_TIME_OUT << 16; |
180 | scmd, scmd->device->host, __FILE__, __LINE__); | 185 | __scsi_done(scmd); |
181 | } | 186 | } |
182 | } | 187 | } |
183 | 188 | ||
@@ -196,8 +201,7 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev) | |||
196 | { | 201 | { |
197 | int online; | 202 | int online; |
198 | 203 | ||
199 | wait_event(sdev->host->host_wait, (sdev->host->shost_state != | 204 | wait_event(sdev->host->host_wait, !scsi_host_in_recovery(sdev->host)); |
200 | SHOST_RECOVERY)); | ||
201 | 205 | ||
202 | online = scsi_device_online(sdev); | 206 | online = scsi_device_online(sdev); |
203 | 207 | ||
@@ -1441,6 +1445,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) | |||
1441 | static void scsi_restart_operations(struct Scsi_Host *shost) | 1445 | static void scsi_restart_operations(struct Scsi_Host *shost) |
1442 | { | 1446 | { |
1443 | struct scsi_device *sdev; | 1447 | struct scsi_device *sdev; |
1448 | unsigned long flags; | ||
1444 | 1449 | ||
1445 | /* | 1450 | /* |
1446 | * If the door was locked, we need to insert a door lock request | 1451 | * If the door was locked, we need to insert a door lock request |
@@ -1460,7 +1465,11 @@ static void scsi_restart_operations(struct Scsi_Host *shost) | |||
1460 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n", | 1465 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n", |
1461 | __FUNCTION__)); | 1466 | __FUNCTION__)); |
1462 | 1467 | ||
1463 | scsi_host_set_state(shost, SHOST_RUNNING); | 1468 | spin_lock_irqsave(shost->host_lock, flags); |
1469 | if (scsi_host_set_state(shost, SHOST_RUNNING)) | ||
1470 | if (scsi_host_set_state(shost, SHOST_CANCEL)) | ||
1471 | BUG_ON(scsi_host_set_state(shost, SHOST_DEL)); | ||
1472 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1464 | 1473 | ||
1465 | wake_up(&shost->host_wait); | 1474 | wake_up(&shost->host_wait); |
1466 | 1475 | ||
@@ -1582,40 +1591,31 @@ int scsi_error_handler(void *data) | |||
1582 | { | 1591 | { |
1583 | struct Scsi_Host *shost = (struct Scsi_Host *) data; | 1592 | struct Scsi_Host *shost = (struct Scsi_Host *) data; |
1584 | int rtn; | 1593 | int rtn; |
1585 | DECLARE_MUTEX_LOCKED(sem); | ||
1586 | 1594 | ||
1587 | current->flags |= PF_NOFREEZE; | 1595 | current->flags |= PF_NOFREEZE; |
1588 | shost->eh_wait = &sem; | ||
1589 | 1596 | ||
1597 | |||
1590 | /* | 1598 | /* |
1591 | * Wake up the thread that created us. | 1599 | * Note - we always use TASK_INTERRUPTIBLE even if the module |
1600 | * was loaded as part of the kernel. The reason is that | ||
1601 | * UNINTERRUPTIBLE would cause this thread to be counted in | ||
1602 | * the load average as a running process, and an interruptible | ||
1603 | * wait doesn't. | ||
1592 | */ | 1604 | */ |
1593 | SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of" | 1605 | set_current_state(TASK_INTERRUPTIBLE); |
1594 | " scsi_eh_%d\n",shost->host_no)); | 1606 | while (!kthread_should_stop()) { |
1595 | 1607 | if (shost->host_failed == 0 || | |
1596 | while (1) { | 1608 | shost->host_failed != shost->host_busy) { |
1597 | /* | 1609 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" |
1598 | * If we get a signal, it means we are supposed to go | 1610 | " scsi_eh_%d" |
1599 | * away and die. This typically happens if the user is | 1611 | " sleeping\n", |
1600 | * trying to unload a module. | 1612 | shost->host_no)); |
1601 | */ | 1613 | schedule(); |
1602 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" | 1614 | set_current_state(TASK_INTERRUPTIBLE); |
1603 | " scsi_eh_%d" | 1615 | continue; |
1604 | " sleeping\n",shost->host_no)); | 1616 | } |
1605 | |||
1606 | /* | ||
1607 | * Note - we always use down_interruptible with the semaphore | ||
1608 | * even if the module was loaded as part of the kernel. The | ||
1609 | * reason is that down() will cause this thread to be counted | ||
1610 | * in the load average as a running process, and down | ||
1611 | * interruptible doesn't. Given that we need to allow this | ||
1612 | * thread to die if the driver was loaded as a module, using | ||
1613 | * semaphores isn't unreasonable. | ||
1614 | */ | ||
1615 | down_interruptible(&sem); | ||
1616 | if (kthread_should_stop()) | ||
1617 | break; | ||
1618 | 1617 | ||
1618 | __set_current_state(TASK_RUNNING); | ||
1619 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" | 1619 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" |
1620 | " scsi_eh_%d waking" | 1620 | " scsi_eh_%d waking" |
1621 | " up\n",shost->host_no)); | 1621 | " up\n",shost->host_no)); |
@@ -1642,7 +1642,7 @@ int scsi_error_handler(void *data) | |||
1642 | * which are still online. | 1642 | * which are still online. |
1643 | */ | 1643 | */ |
1644 | scsi_restart_operations(shost); | 1644 | scsi_restart_operations(shost); |
1645 | 1645 | set_current_state(TASK_INTERRUPTIBLE); | |
1646 | } | 1646 | } |
1647 | 1647 | ||
1648 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d" | 1648 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d" |
@@ -1651,7 +1651,7 @@ int scsi_error_handler(void *data) | |||
1651 | /* | 1651 | /* |
1652 | * Make sure that nobody tries to wake us up again. | 1652 | * Make sure that nobody tries to wake us up again. |
1653 | */ | 1653 | */ |
1654 | shost->eh_wait = NULL; | 1654 | shost->ehandler = NULL; |
1655 | return 0; | 1655 | return 0; |
1656 | } | 1656 | } |
1657 | 1657 | ||
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index b7fddac81347..de7f98cc38fe 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c | |||
@@ -458,7 +458,7 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, | |||
458 | * error processing, as long as the device was opened | 458 | * error processing, as long as the device was opened |
459 | * non-blocking */ | 459 | * non-blocking */ |
460 | if (filp && filp->f_flags & O_NONBLOCK) { | 460 | if (filp && filp->f_flags & O_NONBLOCK) { |
461 | if (sdev->host->shost_state == SHOST_RECOVERY) | 461 | if (scsi_host_in_recovery(sdev->host)) |
462 | return -ENODEV; | 462 | return -ENODEV; |
463 | } else if (!scsi_block_when_processing_errors(sdev)) | 463 | } else if (!scsi_block_when_processing_errors(sdev)) |
464 | return -ENODEV; | 464 | return -ENODEV; |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 863bb6495daa..dc9c772bc874 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -118,7 +118,6 @@ static void scsi_unprep_request(struct request *req) | |||
118 | req->flags &= ~REQ_DONTPREP; | 118 | req->flags &= ~REQ_DONTPREP; |
119 | req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL; | 119 | req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL; |
120 | 120 | ||
121 | scsi_release_buffers(cmd); | ||
122 | scsi_put_command(cmd); | 121 | scsi_put_command(cmd); |
123 | } | 122 | } |
124 | 123 | ||
@@ -140,14 +139,12 @@ static void scsi_unprep_request(struct request *req) | |||
140 | * commands. | 139 | * commands. |
141 | * Notes: This could be called either from an interrupt context or a | 140 | * Notes: This could be called either from an interrupt context or a |
142 | * normal process context. | 141 | * normal process context. |
143 | * Notes: Upon return, cmd is a stale pointer. | ||
144 | */ | 142 | */ |
145 | int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) | 143 | int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) |
146 | { | 144 | { |
147 | struct Scsi_Host *host = cmd->device->host; | 145 | struct Scsi_Host *host = cmd->device->host; |
148 | struct scsi_device *device = cmd->device; | 146 | struct scsi_device *device = cmd->device; |
149 | struct request_queue *q = device->request_queue; | 147 | struct request_queue *q = device->request_queue; |
150 | struct request *req = cmd->request; | ||
151 | unsigned long flags; | 148 | unsigned long flags; |
152 | 149 | ||
153 | SCSI_LOG_MLQUEUE(1, | 150 | SCSI_LOG_MLQUEUE(1, |
@@ -188,9 +185,8 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) | |||
188 | * function. The SCSI request function detects the blocked condition | 185 | * function. The SCSI request function detects the blocked condition |
189 | * and plugs the queue appropriately. | 186 | * and plugs the queue appropriately. |
190 | */ | 187 | */ |
191 | scsi_unprep_request(req); | ||
192 | spin_lock_irqsave(q->queue_lock, flags); | 188 | spin_lock_irqsave(q->queue_lock, flags); |
193 | blk_requeue_request(q, req); | 189 | blk_requeue_request(q, cmd->request); |
194 | spin_unlock_irqrestore(q->queue_lock, flags); | 190 | spin_unlock_irqrestore(q->queue_lock, flags); |
195 | 191 | ||
196 | scsi_run_queue(q); | 192 | scsi_run_queue(q); |
@@ -451,7 +447,7 @@ void scsi_device_unbusy(struct scsi_device *sdev) | |||
451 | 447 | ||
452 | spin_lock_irqsave(shost->host_lock, flags); | 448 | spin_lock_irqsave(shost->host_lock, flags); |
453 | shost->host_busy--; | 449 | shost->host_busy--; |
454 | if (unlikely((shost->shost_state == SHOST_RECOVERY) && | 450 | if (unlikely(scsi_host_in_recovery(shost) && |
455 | shost->host_failed)) | 451 | shost->host_failed)) |
456 | scsi_eh_wakeup(shost); | 452 | scsi_eh_wakeup(shost); |
457 | spin_unlock(shost->host_lock); | 453 | spin_unlock(shost->host_lock); |
@@ -1268,6 +1264,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1268 | } | 1264 | } |
1269 | } else { | 1265 | } else { |
1270 | memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); | 1266 | memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); |
1267 | cmd->cmd_len = req->cmd_len; | ||
1271 | if (rq_data_dir(req) == WRITE) | 1268 | if (rq_data_dir(req) == WRITE) |
1272 | cmd->sc_data_direction = DMA_TO_DEVICE; | 1269 | cmd->sc_data_direction = DMA_TO_DEVICE; |
1273 | else if (req->data_len) | 1270 | else if (req->data_len) |
@@ -1342,7 +1339,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, | |||
1342 | struct Scsi_Host *shost, | 1339 | struct Scsi_Host *shost, |
1343 | struct scsi_device *sdev) | 1340 | struct scsi_device *sdev) |
1344 | { | 1341 | { |
1345 | if (shost->shost_state == SHOST_RECOVERY) | 1342 | if (scsi_host_in_recovery(shost)) |
1346 | return 0; | 1343 | return 0; |
1347 | if (shost->host_busy == 0 && shost->host_blocked) { | 1344 | if (shost->host_busy == 0 && shost->host_blocked) { |
1348 | /* | 1345 | /* |
@@ -1514,7 +1511,6 @@ static void scsi_request_fn(struct request_queue *q) | |||
1514 | * cases (host limits or settings) should run the queue at some | 1511 | * cases (host limits or settings) should run the queue at some |
1515 | * later time. | 1512 | * later time. |
1516 | */ | 1513 | */ |
1517 | scsi_unprep_request(req); | ||
1518 | spin_lock_irq(q->queue_lock); | 1514 | spin_lock_irq(q->queue_lock); |
1519 | blk_requeue_request(q, req); | 1515 | blk_requeue_request(q, req); |
1520 | sdev->device_busy--; | 1516 | sdev->device_busy--; |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index b86f170fa8ed..fcf9f6cbb142 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -1466,23 +1466,17 @@ EXPORT_SYMBOL(scsi_scan_single_target); | |||
1466 | 1466 | ||
1467 | void scsi_forget_host(struct Scsi_Host *shost) | 1467 | void scsi_forget_host(struct Scsi_Host *shost) |
1468 | { | 1468 | { |
1469 | struct scsi_target *starget, *tmp; | 1469 | struct scsi_device *sdev; |
1470 | unsigned long flags; | 1470 | unsigned long flags; |
1471 | 1471 | ||
1472 | /* | 1472 | restart: |
1473 | * Ok, this look a bit strange. We always look for the first device | ||
1474 | * on the list as scsi_remove_device removes them from it - thus we | ||
1475 | * also have to release the lock. | ||
1476 | * We don't need to get another reference to the device before | ||
1477 | * releasing the lock as we already own the reference from | ||
1478 | * scsi_register_device that's release in scsi_remove_device. And | ||
1479 | * after that we don't look at sdev anymore. | ||
1480 | */ | ||
1481 | spin_lock_irqsave(shost->host_lock, flags); | 1473 | spin_lock_irqsave(shost->host_lock, flags); |
1482 | list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) { | 1474 | list_for_each_entry(sdev, &shost->__devices, siblings) { |
1475 | if (sdev->sdev_state == SDEV_DEL) | ||
1476 | continue; | ||
1483 | spin_unlock_irqrestore(shost->host_lock, flags); | 1477 | spin_unlock_irqrestore(shost->host_lock, flags); |
1484 | scsi_remove_target(&starget->dev); | 1478 | __scsi_remove_device(sdev); |
1485 | spin_lock_irqsave(shost->host_lock, flags); | 1479 | goto restart; |
1486 | } | 1480 | } |
1487 | spin_unlock_irqrestore(shost->host_lock, flags); | 1481 | spin_unlock_irqrestore(shost->host_lock, flags); |
1488 | } | 1482 | } |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index b8052d5206cc..72a6550a056c 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -57,6 +57,8 @@ static struct { | |||
57 | { SHOST_CANCEL, "cancel" }, | 57 | { SHOST_CANCEL, "cancel" }, |
58 | { SHOST_DEL, "deleted" }, | 58 | { SHOST_DEL, "deleted" }, |
59 | { SHOST_RECOVERY, "recovery" }, | 59 | { SHOST_RECOVERY, "recovery" }, |
60 | { SHOST_CANCEL_RECOVERY, "cancel/recovery" }, | ||
61 | { SHOST_DEL_RECOVERY, "deleted/recovery", }, | ||
60 | }; | 62 | }; |
61 | const char *scsi_host_state_name(enum scsi_host_state state) | 63 | const char *scsi_host_state_name(enum scsi_host_state state) |
62 | { | 64 | { |
@@ -707,9 +709,11 @@ void __scsi_remove_device(struct scsi_device *sdev) | |||
707 | **/ | 709 | **/ |
708 | void scsi_remove_device(struct scsi_device *sdev) | 710 | void scsi_remove_device(struct scsi_device *sdev) |
709 | { | 711 | { |
710 | down(&sdev->host->scan_mutex); | 712 | struct Scsi_Host *shost = sdev->host; |
713 | |||
714 | down(&shost->scan_mutex); | ||
711 | __scsi_remove_device(sdev); | 715 | __scsi_remove_device(sdev); |
712 | up(&sdev->host->scan_mutex); | 716 | up(&shost->scan_mutex); |
713 | } | 717 | } |
714 | EXPORT_SYMBOL(scsi_remove_device); | 718 | EXPORT_SYMBOL(scsi_remove_device); |
715 | 719 | ||
@@ -717,17 +721,20 @@ void __scsi_remove_target(struct scsi_target *starget) | |||
717 | { | 721 | { |
718 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 722 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
719 | unsigned long flags; | 723 | unsigned long flags; |
720 | struct scsi_device *sdev, *tmp; | 724 | struct scsi_device *sdev; |
721 | 725 | ||
722 | spin_lock_irqsave(shost->host_lock, flags); | 726 | spin_lock_irqsave(shost->host_lock, flags); |
723 | starget->reap_ref++; | 727 | starget->reap_ref++; |
724 | list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) { | 728 | restart: |
729 | list_for_each_entry(sdev, &shost->__devices, siblings) { | ||
725 | if (sdev->channel != starget->channel || | 730 | if (sdev->channel != starget->channel || |
726 | sdev->id != starget->id) | 731 | sdev->id != starget->id || |
732 | sdev->sdev_state == SDEV_DEL) | ||
727 | continue; | 733 | continue; |
728 | spin_unlock_irqrestore(shost->host_lock, flags); | 734 | spin_unlock_irqrestore(shost->host_lock, flags); |
729 | scsi_remove_device(sdev); | 735 | scsi_remove_device(sdev); |
730 | spin_lock_irqsave(shost->host_lock, flags); | 736 | spin_lock_irqsave(shost->host_lock, flags); |
737 | goto restart; | ||
731 | } | 738 | } |
732 | spin_unlock_irqrestore(shost->host_lock, flags); | 739 | spin_unlock_irqrestore(shost->host_lock, flags); |
733 | scsi_target_reap(starget); | 740 | scsi_target_reap(starget); |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index de564b386052..9a1dc0cea03c 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -235,6 +235,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
235 | return 0; | 235 | return 0; |
236 | 236 | ||
237 | memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); | 237 | memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); |
238 | SCpnt->cmd_len = rq->cmd_len; | ||
238 | if (rq_data_dir(rq) == WRITE) | 239 | if (rq_data_dir(rq) == WRITE) |
239 | SCpnt->sc_data_direction = DMA_TO_DEVICE; | 240 | SCpnt->sc_data_direction = DMA_TO_DEVICE; |
240 | else if (rq->data_len) | 241 | else if (rq->data_len) |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 9ea4765d1d12..4d09a6e4dd2e 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -1027,7 +1027,7 @@ sg_ioctl(struct inode *inode, struct file *filp, | |||
1027 | if (sdp->detached) | 1027 | if (sdp->detached) |
1028 | return -ENODEV; | 1028 | return -ENODEV; |
1029 | if (filp->f_flags & O_NONBLOCK) { | 1029 | if (filp->f_flags & O_NONBLOCK) { |
1030 | if (sdp->device->host->shost_state == SHOST_RECOVERY) | 1030 | if (scsi_host_in_recovery(sdp->device->host)) |
1031 | return -EBUSY; | 1031 | return -EBUSY; |
1032 | } else if (!scsi_block_when_processing_errors(sdp->device)) | 1032 | } else if (!scsi_block_when_processing_errors(sdp->device)) |
1033 | return -EBUSY; | 1033 | return -EBUSY; |
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index ce63fc8312dc..561901b1cf11 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c | |||
@@ -326,6 +326,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) | |||
326 | return 0; | 326 | return 0; |
327 | 327 | ||
328 | memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); | 328 | memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); |
329 | SCpnt->cmd_len = rq->cmd_len; | ||
329 | if (!rq->data_len) | 330 | if (!rq->data_len) |
330 | SCpnt->sc_data_direction = DMA_NONE; | 331 | SCpnt->sc_data_direction = DMA_NONE; |
331 | else if (rq_data_dir(rq) == WRITE) | 332 | else if (rq_data_dir(rq) == WRITE) |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index a93308ae9736..d001c046551b 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -4206,6 +4206,7 @@ static int st_init_command(struct scsi_cmnd *SCpnt) | |||
4206 | return 0; | 4206 | return 0; |
4207 | 4207 | ||
4208 | memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); | 4208 | memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); |
4209 | SCpnt->cmd_len = rq->cmd_len; | ||
4209 | 4210 | ||
4210 | if (rq_data_dir(rq) == WRITE) | 4211 | if (rq_data_dir(rq) == WRITE) |
4211 | SCpnt->sc_data_direction = DMA_TO_DEVICE; | 4212 | SCpnt->sc_data_direction = DMA_TO_DEVICE; |
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index aec39fb261ca..b5cf39468d18 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c | |||
@@ -463,7 +463,7 @@ static int __init serial21285_console_setup(struct console *co, char *options) | |||
463 | return uart_set_options(port, co, baud, parity, bits, flow); | 463 | return uart_set_options(port, co, baud, parity, bits, flow); |
464 | } | 464 | } |
465 | 465 | ||
466 | extern struct uart_driver serial21285_reg; | 466 | static struct uart_driver serial21285_reg; |
467 | 467 | ||
468 | static struct console serial21285_console = | 468 | static struct console serial21285_console = |
469 | { | 469 | { |
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 978e12437e61..679e678c7e6a 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c | |||
@@ -689,7 +689,7 @@ static int __init pl010_console_setup(struct console *co, char *options) | |||
689 | return uart_set_options(port, co, baud, parity, bits, flow); | 689 | return uart_set_options(port, co, baud, parity, bits, flow); |
690 | } | 690 | } |
691 | 691 | ||
692 | extern struct uart_driver amba_reg; | 692 | static struct uart_driver amba_reg; |
693 | static struct console amba_console = { | 693 | static struct console amba_console = { |
694 | .name = "ttyAM", | 694 | .name = "ttyAM", |
695 | .write = pl010_console_write, | 695 | .write = pl010_console_write, |
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 56071309744c..1ff629c74750 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c | |||
@@ -701,7 +701,7 @@ static int __init pl011_console_setup(struct console *co, char *options) | |||
701 | return uart_set_options(&uap->port, co, baud, parity, bits, flow); | 701 | return uart_set_options(&uap->port, co, baud, parity, bits, flow); |
702 | } | 702 | } |
703 | 703 | ||
704 | extern struct uart_driver amba_reg; | 704 | static struct uart_driver amba_reg; |
705 | static struct console amba_console = { | 705 | static struct console amba_console = { |
706 | .name = "ttyAMA", | 706 | .name = "ttyAMA", |
707 | .write = pl011_console_write, | 707 | .write = pl011_console_write, |
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index d822896b488c..78c1f36ad9b7 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c | |||
@@ -525,7 +525,7 @@ static int __init clps711xuart_console_setup(struct console *co, char *options) | |||
525 | return uart_set_options(port, co, baud, parity, bits, flow); | 525 | return uart_set_options(port, co, baud, parity, bits, flow); |
526 | } | 526 | } |
527 | 527 | ||
528 | extern struct uart_driver clps711x_reg; | 528 | static struct uart_driver clps711x_reg; |
529 | static struct console clps711x_console = { | 529 | static struct console clps711x_console = { |
530 | .name = "ttyCL", | 530 | .name = "ttyCL", |
531 | .write = clps711xuart_console_write, | 531 | .write = clps711xuart_console_write, |
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index a3cd0ee8486d..0585ab27ffde 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -781,7 +781,7 @@ mpc52xx_uart_remove(struct device *dev) | |||
781 | 781 | ||
782 | #ifdef CONFIG_PM | 782 | #ifdef CONFIG_PM |
783 | static int | 783 | static int |
784 | mpc52xx_uart_suspend(struct device *dev, u32 state, u32 level) | 784 | mpc52xx_uart_suspend(struct device *dev, pm_message_t state, u32 level) |
785 | { | 785 | { |
786 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev); | 786 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev); |
787 | 787 | ||
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index eaa0af835290..672b359b07ce 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c | |||
@@ -589,8 +589,8 @@ serial_pxa_type(struct uart_port *port) | |||
589 | 589 | ||
590 | #ifdef CONFIG_SERIAL_PXA_CONSOLE | 590 | #ifdef CONFIG_SERIAL_PXA_CONSOLE |
591 | 591 | ||
592 | extern struct uart_pxa_port serial_pxa_ports[]; | 592 | static struct uart_pxa_port serial_pxa_ports[]; |
593 | extern struct uart_driver serial_pxa_reg; | 593 | static struct uart_driver serial_pxa_reg; |
594 | 594 | ||
595 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) | 595 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) |
596 | 596 | ||
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index 1225b14f6e9d..dd8aed242357 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c | |||
@@ -799,7 +799,7 @@ sa1100_console_setup(struct console *co, char *options) | |||
799 | return uart_set_options(&sport->port, co, baud, parity, bits, flow); | 799 | return uart_set_options(&sport->port, co, baud, parity, bits, flow); |
800 | } | 800 | } |
801 | 801 | ||
802 | extern struct uart_driver sa1100_reg; | 802 | static struct uart_driver sa1100_reg; |
803 | static struct console sa1100_console = { | 803 | static struct console sa1100_console = { |
804 | .name = "ttySA", | 804 | .name = "ttySA", |
805 | .write = sa1100_console_write, | 805 | .write = sa1100_console_write, |
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 8302376800c0..d01dbe5da3b9 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c | |||
@@ -632,7 +632,7 @@ static int __init lh7a40xuart_console_setup (struct console* co, char* options) | |||
632 | return uart_set_options (port, co, baud, parity, bits, flow); | 632 | return uart_set_options (port, co, baud, parity, bits, flow); |
633 | } | 633 | } |
634 | 634 | ||
635 | extern struct uart_driver lh7a40x_reg; | 635 | static struct uart_driver lh7a40x_reg; |
636 | static struct console lh7a40x_console = { | 636 | static struct console lh7a40x_console = { |
637 | .name = "ttyAM", | 637 | .name = "ttyAM", |
638 | .write = lh7a40xuart_console_write, | 638 | .write = lh7a40xuart_console_write, |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 31ee13eef7af..773ae11b4a19 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -650,6 +650,7 @@ config FB_NVIDIA | |||
650 | select FB_CFB_FILLRECT | 650 | select FB_CFB_FILLRECT |
651 | select FB_CFB_COPYAREA | 651 | select FB_CFB_COPYAREA |
652 | select FB_CFB_IMAGEBLIT | 652 | select FB_CFB_IMAGEBLIT |
653 | select FB_SOFT_CURSOR | ||
653 | help | 654 | help |
654 | This driver supports graphics boards with the nVidia chips, TNT | 655 | This driver supports graphics boards with the nVidia chips, TNT |
655 | and newer. For very old chipsets, such as the RIVA128, then use | 656 | and newer. For very old chipsets, such as the RIVA128, then use |
diff --git a/drivers/video/aty/xlinit.c b/drivers/video/aty/xlinit.c index 92643af12581..0bea0d8d7821 100644 --- a/drivers/video/aty/xlinit.c +++ b/drivers/video/aty/xlinit.c | |||
@@ -174,7 +174,7 @@ int atyfb_xl_init(struct fb_info *info) | |||
174 | const struct xl_card_cfg_t * card = &card_cfg[xl_card]; | 174 | const struct xl_card_cfg_t * card = &card_cfg[xl_card]; |
175 | struct atyfb_par *par = (struct atyfb_par *) info->par; | 175 | struct atyfb_par *par = (struct atyfb_par *) info->par; |
176 | union aty_pll pll; | 176 | union aty_pll pll; |
177 | int i, err; | 177 | int err; |
178 | u32 temp; | 178 | u32 temp; |
179 | 179 | ||
180 | aty_st_8(CONFIG_STAT0, 0x85, par); | 180 | aty_st_8(CONFIG_STAT0, 0x85, par); |
@@ -252,9 +252,12 @@ int atyfb_xl_init(struct fb_info *info) | |||
252 | aty_st_le32(0xEC, 0x00000000, par); | 252 | aty_st_le32(0xEC, 0x00000000, par); |
253 | aty_st_le32(0xFC, 0x00000000, par); | 253 | aty_st_le32(0xFC, 0x00000000, par); |
254 | 254 | ||
255 | #if defined (CONFIG_FB_ATY_GENERIC_LCD) | ||
256 | int i; | ||
255 | for (i=0; i<sizeof(lcd_tbl)/sizeof(lcd_tbl_t); i++) { | 257 | for (i=0; i<sizeof(lcd_tbl)/sizeof(lcd_tbl_t); i++) { |
256 | aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, par); | 258 | aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, par); |
257 | } | 259 | } |
260 | #endif | ||
258 | 261 | ||
259 | aty_st_le16(CONFIG_STAT0, 0x00A4, par); | 262 | aty_st_le16(CONFIG_STAT0, 0x00A4, par); |
260 | mdelay(10); | 263 | mdelay(10); |
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index a32817678552..630f2dfa9699 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c | |||
@@ -19,17 +19,18 @@ | |||
19 | #include <linux/fb.h> | 19 | #include <linux/fb.h> |
20 | #include <linux/backlight.h> | 20 | #include <linux/backlight.h> |
21 | 21 | ||
22 | #include <asm/arch-pxa/corgi.h> | 22 | #include <asm/mach-types.h> |
23 | #include <asm/hardware/scoop.h> | 23 | #include <asm/arch/sharpsl.h> |
24 | 24 | ||
25 | #define CORGI_MAX_INTENSITY 0x3e | ||
26 | #define CORGI_DEFAULT_INTENSITY 0x1f | 25 | #define CORGI_DEFAULT_INTENSITY 0x1f |
27 | #define CORGI_LIMIT_MASK 0x0b | 26 | #define CORGI_LIMIT_MASK 0x0b |
28 | 27 | ||
29 | static int corgibl_powermode = FB_BLANK_UNBLANK; | 28 | static int corgibl_powermode = FB_BLANK_UNBLANK; |
30 | static int current_intensity = 0; | 29 | static int current_intensity = 0; |
31 | static int corgibl_limit = 0; | 30 | static int corgibl_limit = 0; |
31 | static void (*corgibl_mach_set_intensity)(int intensity); | ||
32 | static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; | 32 | static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; |
33 | static struct backlight_properties corgibl_data; | ||
33 | 34 | ||
34 | static void corgibl_send_intensity(int intensity) | 35 | static void corgibl_send_intensity(int intensity) |
35 | { | 36 | { |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 0705cd741411..6ef6f7760e47 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
@@ -1020,7 +1020,9 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font) | |||
1020 | static int vgacon_resize(struct vc_data *c, unsigned int width, | 1020 | static int vgacon_resize(struct vc_data *c, unsigned int width, |
1021 | unsigned int height) | 1021 | unsigned int height) |
1022 | { | 1022 | { |
1023 | if (width % 2 || width > ORIG_VIDEO_COLS || height > ORIG_VIDEO_LINES) | 1023 | if (width % 2 || width > ORIG_VIDEO_COLS || |
1024 | height > (ORIG_VIDEO_LINES * vga_default_font_height)/ | ||
1025 | c->vc_font.height) | ||
1024 | return -EINVAL; | 1026 | return -EINVAL; |
1025 | 1027 | ||
1026 | if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */ | 1028 | if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */ |
diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c index cfa61b512de0..0b6af00d197e 100644 --- a/drivers/video/fbcvt.c +++ b/drivers/video/fbcvt.c | |||
@@ -272,11 +272,11 @@ static void fb_cvt_convert_to_mode(struct fb_cvt_data *cvt, | |||
272 | { | 272 | { |
273 | mode->refresh = cvt->f_refresh; | 273 | mode->refresh = cvt->f_refresh; |
274 | mode->pixclock = KHZ2PICOS(cvt->pixclock/1000); | 274 | mode->pixclock = KHZ2PICOS(cvt->pixclock/1000); |
275 | mode->left_margin = cvt->h_front_porch; | 275 | mode->left_margin = cvt->h_back_porch; |
276 | mode->right_margin = cvt->h_back_porch; | 276 | mode->right_margin = cvt->h_front_porch; |
277 | mode->hsync_len = cvt->hsync; | 277 | mode->hsync_len = cvt->hsync; |
278 | mode->upper_margin = cvt->v_front_porch; | 278 | mode->upper_margin = cvt->v_back_porch; |
279 | mode->lower_margin = cvt->v_back_porch; | 279 | mode->lower_margin = cvt->v_front_porch; |
280 | mode->vsync_len = cvt->vsync; | 280 | mode->vsync_len = cvt->vsync; |
281 | 281 | ||
282 | mode->sync &= ~(FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT); | 282 | mode->sync &= ~(FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT); |
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index cabd53cec991..6c2244cf0e74 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c | |||
@@ -425,7 +425,7 @@ static void imxfb_setup_gpio(struct imxfb_info *fbi) | |||
425 | * Power management hooks. Note that we won't be called from IRQ context, | 425 | * Power management hooks. Note that we won't be called from IRQ context, |
426 | * unlike the blank functions above, so we may sleep. | 426 | * unlike the blank functions above, so we may sleep. |
427 | */ | 427 | */ |
428 | static int imxfb_suspend(struct device *dev, u32 state, u32 level) | 428 | static int imxfb_suspend(struct device *dev, pm_message_t state, u32 level) |
429 | { | 429 | { |
430 | struct imxfb_info *fbi = dev_get_drvdata(dev); | 430 | struct imxfb_info *fbi = dev_get_drvdata(dev); |
431 | pr_debug("%s\n",__FUNCTION__); | 431 | pr_debug("%s\n",__FUNCTION__); |
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c index ace484fa61ce..12f2884d3f0b 100644 --- a/drivers/video/nvidia/nv_i2c.c +++ b/drivers/video/nvidia/nv_i2c.c | |||
@@ -209,10 +209,13 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) | |||
209 | 209 | ||
210 | if (!edid && conn == 1) { | 210 | if (!edid && conn == 1) { |
211 | /* try to get from firmware */ | 211 | /* try to get from firmware */ |
212 | edid = kmalloc(EDID_LENGTH, GFP_KERNEL); | 212 | const u8 *e = fb_firmware_edid(info->device); |
213 | if (edid) | 213 | |
214 | memcpy(edid, fb_firmware_edid(info->device), | 214 | if (e != NULL) { |
215 | EDID_LENGTH); | 215 | edid = kmalloc(EDID_LENGTH, GFP_KERNEL); |
216 | if (edid) | ||
217 | memcpy(edid, e, EDID_LENGTH); | ||
218 | } | ||
216 | } | 219 | } |
217 | 220 | ||
218 | if (out_edid) | 221 | if (out_edid) |
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 3620de0f252e..a7f020ada630 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
@@ -893,7 +893,7 @@ static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
893 | int i, set = cursor->set; | 893 | int i, set = cursor->set; |
894 | u16 fg, bg; | 894 | u16 fg, bg; |
895 | 895 | ||
896 | if (!hwcur || cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS) | 896 | if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS) |
897 | return -ENXIO; | 897 | return -ENXIO; |
898 | 898 | ||
899 | NVShowHideCursor(par, 0); | 899 | NVShowHideCursor(par, 0); |
@@ -1356,6 +1356,9 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info) | |||
1356 | info->pixmap.size = 8 * 1024; | 1356 | info->pixmap.size = 8 * 1024; |
1357 | info->pixmap.flags = FB_PIXMAP_SYSTEM; | 1357 | info->pixmap.flags = FB_PIXMAP_SYSTEM; |
1358 | 1358 | ||
1359 | if (!hwcur) | ||
1360 | info->fbops->fb_cursor = soft_cursor; | ||
1361 | |||
1359 | info->var.accel_flags = (!noaccel); | 1362 | info->var.accel_flags = (!noaccel); |
1360 | 1363 | ||
1361 | switch (par->Architecture) { | 1364 | switch (par->Architecture) { |
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index 959404ad68f4..3c98457783c4 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c | |||
@@ -274,10 +274,13 @@ int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid) | |||
274 | 274 | ||
275 | if (!edid) { | 275 | if (!edid) { |
276 | /* try to get from firmware */ | 276 | /* try to get from firmware */ |
277 | edid = kmalloc(EDID_LENGTH, GFP_KERNEL); | 277 | const u8 *e = fb_firmware_edid(info->device); |
278 | if (edid) | 278 | |
279 | memcpy(edid, fb_firmware_edid(info->device), | 279 | if (e) { |
280 | EDID_LENGTH); | 280 | edid = kmalloc(EDID_LENGTH, GFP_KERNEL); |
281 | if (edid) | ||
282 | memcpy(edid, e, EDID_LENGTH); | ||
283 | } | ||
281 | } | 284 | } |
282 | 285 | ||
283 | if (out_edid) | 286 | if (out_edid) |
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h index d6f94742c9f2..ea17f7e0482c 100644 --- a/drivers/video/savage/savagefb.h +++ b/drivers/video/savage/savagefb.h | |||
@@ -60,8 +60,6 @@ | |||
60 | 60 | ||
61 | #define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000)) | 61 | #define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000)) |
62 | 62 | ||
63 | #define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip == S3_PROSAVAGEDDR)) | ||
64 | |||
65 | /* Chip tags. These are used to group the adapters into | 63 | /* Chip tags. These are used to group the adapters into |
66 | * related families. | 64 | * related families. |
67 | */ | 65 | */ |
@@ -74,8 +72,6 @@ typedef enum { | |||
74 | S3_PROSAVAGE, | 72 | S3_PROSAVAGE, |
75 | S3_SUPERSAVAGE, | 73 | S3_SUPERSAVAGE, |
76 | S3_SAVAGE2000, | 74 | S3_SAVAGE2000, |
77 | S3_PROSAVAGEDDR, | ||
78 | S3_TWISTER, | ||
79 | S3_LAST | 75 | S3_LAST |
80 | } savage_chipset; | 76 | } savage_chipset; |
81 | 77 | ||
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index b5ca3ef8271f..7c285455c924 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c | |||
@@ -1773,8 +1773,7 @@ static int __devinit savage_init_hw (struct savagefb_par *par) | |||
1773 | } | 1773 | } |
1774 | } | 1774 | } |
1775 | 1775 | ||
1776 | if (S3_SAVAGE_MOBILE_SERIES(par->chip) || | 1776 | if (S3_SAVAGE_MOBILE_SERIES(par->chip) && !par->crtonly) |
1777 | (S3_MOBILE_TWISTER_SERIES(par->chip) && !par->crtonly)) | ||
1778 | par->display_type = DISP_LCD; | 1777 | par->display_type = DISP_LCD; |
1779 | else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi)) | 1778 | else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi)) |
1780 | par->display_type = DISP_DFP; | 1779 | par->display_type = DISP_DFP; |
@@ -1783,7 +1782,7 @@ static int __devinit savage_init_hw (struct savagefb_par *par) | |||
1783 | 1782 | ||
1784 | /* Check LCD panel parrmation */ | 1783 | /* Check LCD panel parrmation */ |
1785 | 1784 | ||
1786 | if (par->chip == S3_SAVAGE_MX) { | 1785 | if (par->display_type == DISP_LCD) { |
1787 | unsigned char cr6b = VGArCR( 0x6b ); | 1786 | unsigned char cr6b = VGArCR( 0x6b ); |
1788 | 1787 | ||
1789 | int panelX = (VGArSEQ (0x61) + | 1788 | int panelX = (VGArSEQ (0x61) + |
@@ -1922,15 +1921,15 @@ static int __devinit savage_init_fb_info (struct fb_info *info, | |||
1922 | snprintf (info->fix.id, 16, "ProSavageKM"); | 1921 | snprintf (info->fix.id, 16, "ProSavageKM"); |
1923 | break; | 1922 | break; |
1924 | case FB_ACCEL_S3TWISTER_P: | 1923 | case FB_ACCEL_S3TWISTER_P: |
1925 | par->chip = S3_TWISTER; | 1924 | par->chip = S3_PROSAVAGE; |
1926 | snprintf (info->fix.id, 16, "TwisterP"); | 1925 | snprintf (info->fix.id, 16, "TwisterP"); |
1927 | break; | 1926 | break; |
1928 | case FB_ACCEL_S3TWISTER_K: | 1927 | case FB_ACCEL_S3TWISTER_K: |
1929 | par->chip = S3_TWISTER; | 1928 | par->chip = S3_PROSAVAGE; |
1930 | snprintf (info->fix.id, 16, "TwisterK"); | 1929 | snprintf (info->fix.id, 16, "TwisterK"); |
1931 | break; | 1930 | break; |
1932 | case FB_ACCEL_PROSAVAGE_DDR: | 1931 | case FB_ACCEL_PROSAVAGE_DDR: |
1933 | par->chip = S3_PROSAVAGEDDR; | 1932 | par->chip = S3_PROSAVAGE; |
1934 | snprintf (info->fix.id, 16, "ProSavageDDR"); | 1933 | snprintf (info->fix.id, 16, "ProSavageDDR"); |
1935 | break; | 1934 | break; |
1936 | case FB_ACCEL_PROSAVAGE_DDRK: | 1935 | case FB_ACCEL_PROSAVAGE_DDRK: |
@@ -562,6 +562,7 @@ static inline void lock_kiocb(struct kiocb *iocb) | |||
562 | static inline void unlock_kiocb(struct kiocb *iocb) | 562 | static inline void unlock_kiocb(struct kiocb *iocb) |
563 | { | 563 | { |
564 | kiocbClearLocked(iocb); | 564 | kiocbClearLocked(iocb); |
565 | smp_mb__after_clear_bit(); | ||
565 | wake_up_bit(&iocb->ki_flags, KIF_LOCKED); | 566 | wake_up_bit(&iocb->ki_flags, KIF_LOCKED); |
566 | } | 567 | } |
567 | 568 | ||
diff --git a/fs/compat.c b/fs/compat.c index ac3fb9ed8eea..a719e158e002 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -44,6 +44,8 @@ | |||
44 | #include <linux/nfsd/syscall.h> | 44 | #include <linux/nfsd/syscall.h> |
45 | #include <linux/personality.h> | 45 | #include <linux/personality.h> |
46 | #include <linux/rwsem.h> | 46 | #include <linux/rwsem.h> |
47 | #include <linux/acct.h> | ||
48 | #include <linux/mm.h> | ||
47 | 49 | ||
48 | #include <net/sock.h> /* siocdevprivate_ioctl */ | 50 | #include <net/sock.h> /* siocdevprivate_ioctl */ |
49 | 51 | ||
@@ -1487,6 +1489,8 @@ int compat_do_execve(char * filename, | |||
1487 | 1489 | ||
1488 | /* execve success */ | 1490 | /* execve success */ |
1489 | security_bprm_free(bprm); | 1491 | security_bprm_free(bprm); |
1492 | acct_update_integrals(current); | ||
1493 | update_mem_hiwater(current); | ||
1490 | kfree(bprm); | 1494 | kfree(bprm); |
1491 | return retval; | 1495 | return retval; |
1492 | } | 1496 | } |
diff --git a/fs/dcache.c b/fs/dcache.c index 7376b61269fb..fb10386c59be 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -102,7 +102,8 @@ static inline void dentry_iput(struct dentry * dentry) | |||
102 | list_del_init(&dentry->d_alias); | 102 | list_del_init(&dentry->d_alias); |
103 | spin_unlock(&dentry->d_lock); | 103 | spin_unlock(&dentry->d_lock); |
104 | spin_unlock(&dcache_lock); | 104 | spin_unlock(&dcache_lock); |
105 | fsnotify_inoderemove(inode); | 105 | if (!inode->i_nlink) |
106 | fsnotify_inoderemove(inode); | ||
106 | if (dentry->d_op && dentry->d_op->d_iput) | 107 | if (dentry->d_op && dentry->d_op->d_iput) |
107 | dentry->d_op->d_iput(dentry, inode); | 108 | dentry->d_op->d_iput(dentry, inode); |
108 | else | 109 | else |
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 6ab1dd0ca904..403b90a1213d 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -231,8 +231,9 @@ struct ep_pqueue { | |||
231 | 231 | ||
232 | static void ep_poll_safewake_init(struct poll_safewake *psw); | 232 | static void ep_poll_safewake_init(struct poll_safewake *psw); |
233 | static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq); | 233 | static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq); |
234 | static int ep_getfd(int *efd, struct inode **einode, struct file **efile); | 234 | static int ep_getfd(int *efd, struct inode **einode, struct file **efile, |
235 | static int ep_file_init(struct file *file); | 235 | struct eventpoll *ep); |
236 | static int ep_alloc(struct eventpoll **pep); | ||
236 | static void ep_free(struct eventpoll *ep); | 237 | static void ep_free(struct eventpoll *ep); |
237 | static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd); | 238 | static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd); |
238 | static void ep_use_epitem(struct epitem *epi); | 239 | static void ep_use_epitem(struct epitem *epi); |
@@ -501,38 +502,37 @@ void eventpoll_release_file(struct file *file) | |||
501 | asmlinkage long sys_epoll_create(int size) | 502 | asmlinkage long sys_epoll_create(int size) |
502 | { | 503 | { |
503 | int error, fd; | 504 | int error, fd; |
505 | struct eventpoll *ep; | ||
504 | struct inode *inode; | 506 | struct inode *inode; |
505 | struct file *file; | 507 | struct file *file; |
506 | 508 | ||
507 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n", | 509 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n", |
508 | current, size)); | 510 | current, size)); |
509 | 511 | ||
510 | /* Sanity check on the size parameter */ | 512 | /* |
513 | * Sanity check on the size parameter, and create the internal data | ||
514 | * structure ( "struct eventpoll" ). | ||
515 | */ | ||
511 | error = -EINVAL; | 516 | error = -EINVAL; |
512 | if (size <= 0) | 517 | if (size <= 0 || (error = ep_alloc(&ep)) != 0) |
513 | goto eexit_1; | 518 | goto eexit_1; |
514 | 519 | ||
515 | /* | 520 | /* |
516 | * Creates all the items needed to setup an eventpoll file. That is, | 521 | * Creates all the items needed to setup an eventpoll file. That is, |
517 | * a file structure, and inode and a free file descriptor. | 522 | * a file structure, and inode and a free file descriptor. |
518 | */ | 523 | */ |
519 | error = ep_getfd(&fd, &inode, &file); | 524 | error = ep_getfd(&fd, &inode, &file, ep); |
520 | if (error) | ||
521 | goto eexit_1; | ||
522 | |||
523 | /* Setup the file internal data structure ( "struct eventpoll" ) */ | ||
524 | error = ep_file_init(file); | ||
525 | if (error) | 525 | if (error) |
526 | goto eexit_2; | 526 | goto eexit_2; |
527 | 527 | ||
528 | |||
529 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", | 528 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", |
530 | current, size, fd)); | 529 | current, size, fd)); |
531 | 530 | ||
532 | return fd; | 531 | return fd; |
533 | 532 | ||
534 | eexit_2: | 533 | eexit_2: |
535 | sys_close(fd); | 534 | ep_free(ep); |
535 | kfree(ep); | ||
536 | eexit_1: | 536 | eexit_1: |
537 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", | 537 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n", |
538 | current, size, error)); | 538 | current, size, error)); |
@@ -706,7 +706,8 @@ eexit_1: | |||
706 | /* | 706 | /* |
707 | * Creates the file descriptor to be used by the epoll interface. | 707 | * Creates the file descriptor to be used by the epoll interface. |
708 | */ | 708 | */ |
709 | static int ep_getfd(int *efd, struct inode **einode, struct file **efile) | 709 | static int ep_getfd(int *efd, struct inode **einode, struct file **efile, |
710 | struct eventpoll *ep) | ||
710 | { | 711 | { |
711 | struct qstr this; | 712 | struct qstr this; |
712 | char name[32]; | 713 | char name[32]; |
@@ -756,7 +757,7 @@ static int ep_getfd(int *efd, struct inode **einode, struct file **efile) | |||
756 | file->f_op = &eventpoll_fops; | 757 | file->f_op = &eventpoll_fops; |
757 | file->f_mode = FMODE_READ; | 758 | file->f_mode = FMODE_READ; |
758 | file->f_version = 0; | 759 | file->f_version = 0; |
759 | file->private_data = NULL; | 760 | file->private_data = ep; |
760 | 761 | ||
761 | /* Install the new setup file into the allocated fd. */ | 762 | /* Install the new setup file into the allocated fd. */ |
762 | fd_install(fd, file); | 763 | fd_install(fd, file); |
@@ -777,14 +778,13 @@ eexit_1: | |||
777 | } | 778 | } |
778 | 779 | ||
779 | 780 | ||
780 | static int ep_file_init(struct file *file) | 781 | static int ep_alloc(struct eventpoll **pep) |
781 | { | 782 | { |
782 | struct eventpoll *ep; | 783 | struct eventpoll *ep = kzalloc(sizeof(*ep), GFP_KERNEL); |
783 | 784 | ||
784 | if (!(ep = kmalloc(sizeof(struct eventpoll), GFP_KERNEL))) | 785 | if (!ep) |
785 | return -ENOMEM; | 786 | return -ENOMEM; |
786 | 787 | ||
787 | memset(ep, 0, sizeof(*ep)); | ||
788 | rwlock_init(&ep->lock); | 788 | rwlock_init(&ep->lock); |
789 | init_rwsem(&ep->sem); | 789 | init_rwsem(&ep->sem); |
790 | init_waitqueue_head(&ep->wq); | 790 | init_waitqueue_head(&ep->wq); |
@@ -792,9 +792,9 @@ static int ep_file_init(struct file *file) | |||
792 | INIT_LIST_HEAD(&ep->rdllist); | 792 | INIT_LIST_HEAD(&ep->rdllist); |
793 | ep->rbr = RB_ROOT; | 793 | ep->rbr = RB_ROOT; |
794 | 794 | ||
795 | file->private_data = ep; | 795 | *pep = ep; |
796 | 796 | ||
797 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_file_init() ep=%p\n", | 797 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_alloc() ep=%p\n", |
798 | current, ep)); | 798 | current, ep)); |
799 | return 0; | 799 | return 0; |
800 | } | 800 | } |
@@ -421,11 +421,6 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
421 | if (!mpnt) | 421 | if (!mpnt) |
422 | return -ENOMEM; | 422 | return -ENOMEM; |
423 | 423 | ||
424 | if (security_vm_enough_memory(arg_size >> PAGE_SHIFT)) { | ||
425 | kmem_cache_free(vm_area_cachep, mpnt); | ||
426 | return -ENOMEM; | ||
427 | } | ||
428 | |||
429 | memset(mpnt, 0, sizeof(*mpnt)); | 424 | memset(mpnt, 0, sizeof(*mpnt)); |
430 | 425 | ||
431 | down_write(&mm->mmap_sem); | 426 | down_write(&mm->mmap_sem); |
@@ -745,8 +740,8 @@ static inline int de_thread(struct task_struct *tsk) | |||
745 | } | 740 | } |
746 | 741 | ||
747 | /* | 742 | /* |
748 | * Now there are really no other threads at all, | 743 | * There may be one thread left which is just exiting, |
749 | * so it's safe to stop telling them to kill themselves. | 744 | * but it's safe to stop telling the group to kill themselves. |
750 | */ | 745 | */ |
751 | sig->flags = 0; | 746 | sig->flags = 0; |
752 | 747 | ||
@@ -785,7 +780,6 @@ no_thread_group: | |||
785 | kmem_cache_free(sighand_cachep, oldsighand); | 780 | kmem_cache_free(sighand_cachep, oldsighand); |
786 | } | 781 | } |
787 | 782 | ||
788 | BUG_ON(!thread_group_empty(current)); | ||
789 | BUG_ON(!thread_group_leader(current)); | 783 | BUG_ON(!thread_group_leader(current)); |
790 | return 0; | 784 | return 0; |
791 | } | 785 | } |
diff --git a/fs/fat/file.c b/fs/fat/file.c index 62ffa9139400..7134403d5be2 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
@@ -12,39 +12,6 @@ | |||
12 | #include <linux/smp_lock.h> | 12 | #include <linux/smp_lock.h> |
13 | #include <linux/buffer_head.h> | 13 | #include <linux/buffer_head.h> |
14 | 14 | ||
15 | static ssize_t fat_file_aio_write(struct kiocb *iocb, const char __user *buf, | ||
16 | size_t count, loff_t pos) | ||
17 | { | ||
18 | struct inode *inode = iocb->ki_filp->f_dentry->d_inode; | ||
19 | int retval; | ||
20 | |||
21 | retval = generic_file_aio_write(iocb, buf, count, pos); | ||
22 | if (retval > 0) { | ||
23 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; | ||
24 | MSDOS_I(inode)->i_attrs |= ATTR_ARCH; | ||
25 | mark_inode_dirty(inode); | ||
26 | // check the locking rules | ||
27 | // if (IS_SYNC(inode)) | ||
28 | // fat_sync_inode(inode); | ||
29 | } | ||
30 | return retval; | ||
31 | } | ||
32 | |||
33 | static ssize_t fat_file_writev(struct file *filp, const struct iovec *iov, | ||
34 | unsigned long nr_segs, loff_t *ppos) | ||
35 | { | ||
36 | struct inode *inode = filp->f_dentry->d_inode; | ||
37 | int retval; | ||
38 | |||
39 | retval = generic_file_writev(filp, iov, nr_segs, ppos); | ||
40 | if (retval > 0) { | ||
41 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; | ||
42 | MSDOS_I(inode)->i_attrs |= ATTR_ARCH; | ||
43 | mark_inode_dirty(inode); | ||
44 | } | ||
45 | return retval; | ||
46 | } | ||
47 | |||
48 | int fat_generic_ioctl(struct inode *inode, struct file *filp, | 15 | int fat_generic_ioctl(struct inode *inode, struct file *filp, |
49 | unsigned int cmd, unsigned long arg) | 16 | unsigned int cmd, unsigned long arg) |
50 | { | 17 | { |
@@ -148,9 +115,9 @@ struct file_operations fat_file_operations = { | |||
148 | .read = do_sync_read, | 115 | .read = do_sync_read, |
149 | .write = do_sync_write, | 116 | .write = do_sync_write, |
150 | .readv = generic_file_readv, | 117 | .readv = generic_file_readv, |
151 | .writev = fat_file_writev, | 118 | .writev = generic_file_writev, |
152 | .aio_read = generic_file_aio_read, | 119 | .aio_read = generic_file_aio_read, |
153 | .aio_write = fat_file_aio_write, | 120 | .aio_write = generic_file_aio_write, |
154 | .mmap = generic_file_mmap, | 121 | .mmap = generic_file_mmap, |
155 | .ioctl = fat_generic_ioctl, | 122 | .ioctl = fat_generic_ioctl, |
156 | .fsync = file_fsync, | 123 | .fsync = file_fsync, |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index a7cbe68e2259..e2effe2dc9b2 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -102,6 +102,19 @@ static int fat_prepare_write(struct file *file, struct page *page, | |||
102 | &MSDOS_I(page->mapping->host)->mmu_private); | 102 | &MSDOS_I(page->mapping->host)->mmu_private); |
103 | } | 103 | } |
104 | 104 | ||
105 | static int fat_commit_write(struct file *file, struct page *page, | ||
106 | unsigned from, unsigned to) | ||
107 | { | ||
108 | struct inode *inode = page->mapping->host; | ||
109 | int err = generic_commit_write(file, page, from, to); | ||
110 | if (!err && !(MSDOS_I(inode)->i_attrs & ATTR_ARCH)) { | ||
111 | inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; | ||
112 | MSDOS_I(inode)->i_attrs |= ATTR_ARCH; | ||
113 | mark_inode_dirty(inode); | ||
114 | } | ||
115 | return err; | ||
116 | } | ||
117 | |||
105 | static sector_t _fat_bmap(struct address_space *mapping, sector_t block) | 118 | static sector_t _fat_bmap(struct address_space *mapping, sector_t block) |
106 | { | 119 | { |
107 | return generic_block_bmap(mapping, block, fat_get_block); | 120 | return generic_block_bmap(mapping, block, fat_get_block); |
@@ -112,7 +125,7 @@ static struct address_space_operations fat_aops = { | |||
112 | .writepage = fat_writepage, | 125 | .writepage = fat_writepage, |
113 | .sync_page = block_sync_page, | 126 | .sync_page = block_sync_page, |
114 | .prepare_write = fat_prepare_write, | 127 | .prepare_write = fat_prepare_write, |
115 | .commit_write = generic_commit_write, | 128 | .commit_write = fat_commit_write, |
116 | .bmap = _fat_bmap | 129 | .bmap = _fat_bmap |
117 | }; | 130 | }; |
118 | 131 | ||
@@ -287,9 +300,9 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
287 | inode->i_blksize = sbi->cluster_size; | 300 | inode->i_blksize = sbi->cluster_size; |
288 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) | 301 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) |
289 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; | 302 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; |
290 | inode->i_mtime.tv_sec = inode->i_atime.tv_sec = | 303 | inode->i_mtime.tv_sec = |
291 | date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date)); | 304 | date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date)); |
292 | inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = 0; | 305 | inode->i_mtime.tv_nsec = 0; |
293 | if (sbi->options.isvfat) { | 306 | if (sbi->options.isvfat) { |
294 | int secs = de->ctime_cs / 100; | 307 | int secs = de->ctime_cs / 100; |
295 | int csecs = de->ctime_cs % 100; | 308 | int csecs = de->ctime_cs % 100; |
@@ -297,8 +310,11 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
297 | date_dos2unix(le16_to_cpu(de->ctime), | 310 | date_dos2unix(le16_to_cpu(de->ctime), |
298 | le16_to_cpu(de->cdate)) + secs; | 311 | le16_to_cpu(de->cdate)) + secs; |
299 | inode->i_ctime.tv_nsec = csecs * 10000000; | 312 | inode->i_ctime.tv_nsec = csecs * 10000000; |
313 | inode->i_atime.tv_sec = | ||
314 | date_dos2unix(le16_to_cpu(0), le16_to_cpu(de->adate)); | ||
315 | inode->i_atime.tv_nsec = 0; | ||
300 | } else | 316 | } else |
301 | inode->i_ctime = inode->i_mtime; | 317 | inode->i_ctime = inode->i_atime = inode->i_mtime; |
302 | 318 | ||
303 | return 0; | 319 | return 0; |
304 | } | 320 | } |
@@ -500,7 +516,9 @@ retry: | |||
500 | raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); | 516 | raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); |
501 | fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date); | 517 | fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date); |
502 | if (sbi->options.isvfat) { | 518 | if (sbi->options.isvfat) { |
519 | __le16 atime; | ||
503 | fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate); | 520 | fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate); |
521 | fat_date_unix2dos(inode->i_atime.tv_sec,&atime,&raw_entry->adate); | ||
504 | raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 + | 522 | raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 + |
505 | inode->i_ctime.tv_nsec / 10000000; | 523 | inode->i_ctime.tv_nsec / 10000000; |
506 | } | 524 | } |
@@ -69,13 +69,9 @@ void free_fd_array(struct file **array, int num) | |||
69 | 69 | ||
70 | static void __free_fdtable(struct fdtable *fdt) | 70 | static void __free_fdtable(struct fdtable *fdt) |
71 | { | 71 | { |
72 | int fdset_size, fdarray_size; | 72 | free_fdset(fdt->open_fds, fdt->max_fdset); |
73 | 73 | free_fdset(fdt->close_on_exec, fdt->max_fdset); | |
74 | fdset_size = fdt->max_fdset / 8; | 74 | free_fd_array(fdt->fd, fdt->max_fds); |
75 | fdarray_size = fdt->max_fds * sizeof(struct file *); | ||
76 | free_fdset(fdt->open_fds, fdset_size); | ||
77 | free_fdset(fdt->close_on_exec, fdset_size); | ||
78 | free_fd_array(fdt->fd, fdarray_size); | ||
79 | kfree(fdt); | 75 | kfree(fdt); |
80 | } | 76 | } |
81 | 77 | ||
diff --git a/fs/locks.c b/fs/locks.c index c2c09b4798d6..f7daa5f48949 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -124,6 +124,7 @@ | |||
124 | #include <linux/smp_lock.h> | 124 | #include <linux/smp_lock.h> |
125 | #include <linux/syscalls.h> | 125 | #include <linux/syscalls.h> |
126 | #include <linux/time.h> | 126 | #include <linux/time.h> |
127 | #include <linux/rcupdate.h> | ||
127 | 128 | ||
128 | #include <asm/semaphore.h> | 129 | #include <asm/semaphore.h> |
129 | #include <asm/uaccess.h> | 130 | #include <asm/uaccess.h> |
@@ -2205,6 +2206,7 @@ void steal_locks(fl_owner_t from) | |||
2205 | 2206 | ||
2206 | lock_kernel(); | 2207 | lock_kernel(); |
2207 | j = 0; | 2208 | j = 0; |
2209 | rcu_read_lock(); | ||
2208 | fdt = files_fdtable(files); | 2210 | fdt = files_fdtable(files); |
2209 | for (;;) { | 2211 | for (;;) { |
2210 | unsigned long set; | 2212 | unsigned long set; |
@@ -2222,6 +2224,7 @@ void steal_locks(fl_owner_t from) | |||
2222 | set >>= 1; | 2224 | set >>= 1; |
2223 | } | 2225 | } |
2224 | } | 2226 | } |
2227 | rcu_read_unlock(); | ||
2225 | unlock_kernel(); | 2228 | unlock_kernel(); |
2226 | } | 2229 | } |
2227 | EXPORT_SYMBOL(steal_locks); | 2230 | EXPORT_SYMBOL(steal_locks); |
diff --git a/fs/ntfs/ChangeLog b/fs/ntfs/ChangeLog index 49eafbdb15c1..c7e9237379c2 100644 --- a/fs/ntfs/ChangeLog +++ b/fs/ntfs/ChangeLog | |||
@@ -92,6 +92,8 @@ ToDo/Notes: | |||
92 | an octal number to conform to how chmod(1) works, too. Thanks to | 92 | an octal number to conform to how chmod(1) works, too. Thanks to |
93 | Giuseppe Bilotta and Horst von Brand for pointing out the errors of | 93 | Giuseppe Bilotta and Horst von Brand for pointing out the errors of |
94 | my ways. | 94 | my ways. |
95 | - Fix various bugs in the runlist merging code. (Based on libntfs | ||
96 | changes by Richard Russon.) | ||
95 | 97 | ||
96 | 2.1.23 - Implement extension of resident files and make writing safe as well as | 98 | 2.1.23 - Implement extension of resident files and make writing safe as well as |
97 | many bug fixes, cleanups, and enhancements... | 99 | many bug fixes, cleanups, and enhancements... |
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index b6cc8cf24626..5e80c07c6a4d 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c | |||
@@ -59,39 +59,49 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate) | |||
59 | unsigned long flags; | 59 | unsigned long flags; |
60 | struct buffer_head *first, *tmp; | 60 | struct buffer_head *first, *tmp; |
61 | struct page *page; | 61 | struct page *page; |
62 | struct inode *vi; | ||
62 | ntfs_inode *ni; | 63 | ntfs_inode *ni; |
63 | int page_uptodate = 1; | 64 | int page_uptodate = 1; |
64 | 65 | ||
65 | page = bh->b_page; | 66 | page = bh->b_page; |
66 | ni = NTFS_I(page->mapping->host); | 67 | vi = page->mapping->host; |
68 | ni = NTFS_I(vi); | ||
67 | 69 | ||
68 | if (likely(uptodate)) { | 70 | if (likely(uptodate)) { |
69 | s64 file_ofs, initialized_size; | 71 | loff_t i_size; |
72 | s64 file_ofs, init_size; | ||
70 | 73 | ||
71 | set_buffer_uptodate(bh); | 74 | set_buffer_uptodate(bh); |
72 | 75 | ||
73 | file_ofs = ((s64)page->index << PAGE_CACHE_SHIFT) + | 76 | file_ofs = ((s64)page->index << PAGE_CACHE_SHIFT) + |
74 | bh_offset(bh); | 77 | bh_offset(bh); |
75 | read_lock_irqsave(&ni->size_lock, flags); | 78 | read_lock_irqsave(&ni->size_lock, flags); |
76 | initialized_size = ni->initialized_size; | 79 | init_size = ni->initialized_size; |
80 | i_size = i_size_read(vi); | ||
77 | read_unlock_irqrestore(&ni->size_lock, flags); | 81 | read_unlock_irqrestore(&ni->size_lock, flags); |
82 | if (unlikely(init_size > i_size)) { | ||
83 | /* Race with shrinking truncate. */ | ||
84 | init_size = i_size; | ||
85 | } | ||
78 | /* Check for the current buffer head overflowing. */ | 86 | /* Check for the current buffer head overflowing. */ |
79 | if (file_ofs + bh->b_size > initialized_size) { | 87 | if (unlikely(file_ofs + bh->b_size > init_size)) { |
80 | char *addr; | 88 | u8 *kaddr; |
81 | int ofs = 0; | 89 | int ofs; |
82 | 90 | ||
83 | if (file_ofs < initialized_size) | 91 | ofs = 0; |
84 | ofs = initialized_size - file_ofs; | 92 | if (file_ofs < init_size) |
85 | addr = kmap_atomic(page, KM_BIO_SRC_IRQ); | 93 | ofs = init_size - file_ofs; |
86 | memset(addr + bh_offset(bh) + ofs, 0, bh->b_size - ofs); | 94 | kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ); |
95 | memset(kaddr + bh_offset(bh) + ofs, 0, | ||
96 | bh->b_size - ofs); | ||
97 | kunmap_atomic(kaddr, KM_BIO_SRC_IRQ); | ||
87 | flush_dcache_page(page); | 98 | flush_dcache_page(page); |
88 | kunmap_atomic(addr, KM_BIO_SRC_IRQ); | ||
89 | } | 99 | } |
90 | } else { | 100 | } else { |
91 | clear_buffer_uptodate(bh); | 101 | clear_buffer_uptodate(bh); |
92 | SetPageError(page); | 102 | SetPageError(page); |
93 | ntfs_error(ni->vol->sb, "Buffer I/O error, logical block %llu.", | 103 | ntfs_error(ni->vol->sb, "Buffer I/O error, logical block " |
94 | (unsigned long long)bh->b_blocknr); | 104 | "0x%llx.", (unsigned long long)bh->b_blocknr); |
95 | } | 105 | } |
96 | first = page_buffers(page); | 106 | first = page_buffers(page); |
97 | local_irq_save(flags); | 107 | local_irq_save(flags); |
@@ -124,7 +134,7 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate) | |||
124 | if (likely(page_uptodate && !PageError(page))) | 134 | if (likely(page_uptodate && !PageError(page))) |
125 | SetPageUptodate(page); | 135 | SetPageUptodate(page); |
126 | } else { | 136 | } else { |
127 | char *addr; | 137 | u8 *kaddr; |
128 | unsigned int i, recs; | 138 | unsigned int i, recs; |
129 | u32 rec_size; | 139 | u32 rec_size; |
130 | 140 | ||
@@ -132,12 +142,12 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate) | |||
132 | recs = PAGE_CACHE_SIZE / rec_size; | 142 | recs = PAGE_CACHE_SIZE / rec_size; |
133 | /* Should have been verified before we got here... */ | 143 | /* Should have been verified before we got here... */ |
134 | BUG_ON(!recs); | 144 | BUG_ON(!recs); |
135 | addr = kmap_atomic(page, KM_BIO_SRC_IRQ); | 145 | kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ); |
136 | for (i = 0; i < recs; i++) | 146 | for (i = 0; i < recs; i++) |
137 | post_read_mst_fixup((NTFS_RECORD*)(addr + | 147 | post_read_mst_fixup((NTFS_RECORD*)(kaddr + |
138 | i * rec_size), rec_size); | 148 | i * rec_size), rec_size); |
149 | kunmap_atomic(kaddr, KM_BIO_SRC_IRQ); | ||
139 | flush_dcache_page(page); | 150 | flush_dcache_page(page); |
140 | kunmap_atomic(addr, KM_BIO_SRC_IRQ); | ||
141 | if (likely(page_uptodate && !PageError(page))) | 151 | if (likely(page_uptodate && !PageError(page))) |
142 | SetPageUptodate(page); | 152 | SetPageUptodate(page); |
143 | } | 153 | } |
@@ -168,8 +178,11 @@ still_busy: | |||
168 | */ | 178 | */ |
169 | static int ntfs_read_block(struct page *page) | 179 | static int ntfs_read_block(struct page *page) |
170 | { | 180 | { |
181 | loff_t i_size; | ||
171 | VCN vcn; | 182 | VCN vcn; |
172 | LCN lcn; | 183 | LCN lcn; |
184 | s64 init_size; | ||
185 | struct inode *vi; | ||
173 | ntfs_inode *ni; | 186 | ntfs_inode *ni; |
174 | ntfs_volume *vol; | 187 | ntfs_volume *vol; |
175 | runlist_element *rl; | 188 | runlist_element *rl; |
@@ -180,7 +193,8 @@ static int ntfs_read_block(struct page *page) | |||
180 | int i, nr; | 193 | int i, nr; |
181 | unsigned char blocksize_bits; | 194 | unsigned char blocksize_bits; |
182 | 195 | ||
183 | ni = NTFS_I(page->mapping->host); | 196 | vi = page->mapping->host; |
197 | ni = NTFS_I(vi); | ||
184 | vol = ni->vol; | 198 | vol = ni->vol; |
185 | 199 | ||
186 | /* $MFT/$DATA must have its complete runlist in memory at all times. */ | 200 | /* $MFT/$DATA must have its complete runlist in memory at all times. */ |
@@ -199,11 +213,28 @@ static int ntfs_read_block(struct page *page) | |||
199 | bh = head = page_buffers(page); | 213 | bh = head = page_buffers(page); |
200 | BUG_ON(!bh); | 214 | BUG_ON(!bh); |
201 | 215 | ||
216 | /* | ||
217 | * We may be racing with truncate. To avoid some of the problems we | ||
218 | * now take a snapshot of the various sizes and use those for the whole | ||
219 | * of the function. In case of an extending truncate it just means we | ||
220 | * may leave some buffers unmapped which are now allocated. This is | ||
221 | * not a problem since these buffers will just get mapped when a write | ||
222 | * occurs. In case of a shrinking truncate, we will detect this later | ||
223 | * on due to the runlist being incomplete and if the page is being | ||
224 | * fully truncated, truncate will throw it away as soon as we unlock | ||
225 | * it so no need to worry what we do with it. | ||
226 | */ | ||
202 | iblock = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits); | 227 | iblock = (s64)page->index << (PAGE_CACHE_SHIFT - blocksize_bits); |
203 | read_lock_irqsave(&ni->size_lock, flags); | 228 | read_lock_irqsave(&ni->size_lock, flags); |
204 | lblock = (ni->allocated_size + blocksize - 1) >> blocksize_bits; | 229 | lblock = (ni->allocated_size + blocksize - 1) >> blocksize_bits; |
205 | zblock = (ni->initialized_size + blocksize - 1) >> blocksize_bits; | 230 | init_size = ni->initialized_size; |
231 | i_size = i_size_read(vi); | ||
206 | read_unlock_irqrestore(&ni->size_lock, flags); | 232 | read_unlock_irqrestore(&ni->size_lock, flags); |
233 | if (unlikely(init_size > i_size)) { | ||
234 | /* Race with shrinking truncate. */ | ||
235 | init_size = i_size; | ||
236 | } | ||
237 | zblock = (init_size + blocksize - 1) >> blocksize_bits; | ||
207 | 238 | ||
208 | /* Loop through all the buffers in the page. */ | 239 | /* Loop through all the buffers in the page. */ |
209 | rl = NULL; | 240 | rl = NULL; |
@@ -366,6 +397,8 @@ handle_zblock: | |||
366 | */ | 397 | */ |
367 | static int ntfs_readpage(struct file *file, struct page *page) | 398 | static int ntfs_readpage(struct file *file, struct page *page) |
368 | { | 399 | { |
400 | loff_t i_size; | ||
401 | struct inode *vi; | ||
369 | ntfs_inode *ni, *base_ni; | 402 | ntfs_inode *ni, *base_ni; |
370 | u8 *kaddr; | 403 | u8 *kaddr; |
371 | ntfs_attr_search_ctx *ctx; | 404 | ntfs_attr_search_ctx *ctx; |
@@ -384,14 +417,17 @@ retry_readpage: | |||
384 | unlock_page(page); | 417 | unlock_page(page); |
385 | return 0; | 418 | return 0; |
386 | } | 419 | } |
387 | ni = NTFS_I(page->mapping->host); | 420 | vi = page->mapping->host; |
421 | ni = NTFS_I(vi); | ||
388 | /* | 422 | /* |
389 | * Only $DATA attributes can be encrypted and only unnamed $DATA | 423 | * Only $DATA attributes can be encrypted and only unnamed $DATA |
390 | * attributes can be compressed. Index root can have the flags set but | 424 | * attributes can be compressed. Index root can have the flags set but |
391 | * this means to create compressed/encrypted files, not that the | 425 | * this means to create compressed/encrypted files, not that the |
392 | * attribute is compressed/encrypted. | 426 | * attribute is compressed/encrypted. Note we need to check for |
427 | * AT_INDEX_ALLOCATION since this is the type of both directory and | ||
428 | * index inodes. | ||
393 | */ | 429 | */ |
394 | if (ni->type != AT_INDEX_ROOT) { | 430 | if (ni->type != AT_INDEX_ALLOCATION) { |
395 | /* If attribute is encrypted, deny access, just like NT4. */ | 431 | /* If attribute is encrypted, deny access, just like NT4. */ |
396 | if (NInoEncrypted(ni)) { | 432 | if (NInoEncrypted(ni)) { |
397 | BUG_ON(ni->type != AT_DATA); | 433 | BUG_ON(ni->type != AT_DATA); |
@@ -456,7 +492,12 @@ retry_readpage: | |||
456 | read_lock_irqsave(&ni->size_lock, flags); | 492 | read_lock_irqsave(&ni->size_lock, flags); |
457 | if (unlikely(attr_len > ni->initialized_size)) | 493 | if (unlikely(attr_len > ni->initialized_size)) |
458 | attr_len = ni->initialized_size; | 494 | attr_len = ni->initialized_size; |
495 | i_size = i_size_read(vi); | ||
459 | read_unlock_irqrestore(&ni->size_lock, flags); | 496 | read_unlock_irqrestore(&ni->size_lock, flags); |
497 | if (unlikely(attr_len > i_size)) { | ||
498 | /* Race with shrinking truncate. */ | ||
499 | attr_len = i_size; | ||
500 | } | ||
460 | kaddr = kmap_atomic(page, KM_USER0); | 501 | kaddr = kmap_atomic(page, KM_USER0); |
461 | /* Copy the data to the page. */ | 502 | /* Copy the data to the page. */ |
462 | memcpy(kaddr, (u8*)ctx->attr + | 503 | memcpy(kaddr, (u8*)ctx->attr + |
@@ -1341,9 +1382,11 @@ retry_writepage: | |||
1341 | * Only $DATA attributes can be encrypted and only unnamed $DATA | 1382 | * Only $DATA attributes can be encrypted and only unnamed $DATA |
1342 | * attributes can be compressed. Index root can have the flags set but | 1383 | * attributes can be compressed. Index root can have the flags set but |
1343 | * this means to create compressed/encrypted files, not that the | 1384 | * this means to create compressed/encrypted files, not that the |
1344 | * attribute is compressed/encrypted. | 1385 | * attribute is compressed/encrypted. Note we need to check for |
1386 | * AT_INDEX_ALLOCATION since this is the type of both directory and | ||
1387 | * index inodes. | ||
1345 | */ | 1388 | */ |
1346 | if (ni->type != AT_INDEX_ROOT) { | 1389 | if (ni->type != AT_INDEX_ALLOCATION) { |
1347 | /* If file is encrypted, deny access, just like NT4. */ | 1390 | /* If file is encrypted, deny access, just like NT4. */ |
1348 | if (NInoEncrypted(ni)) { | 1391 | if (NInoEncrypted(ni)) { |
1349 | unlock_page(page); | 1392 | unlock_page(page); |
@@ -1379,8 +1422,8 @@ retry_writepage: | |||
1379 | unsigned int ofs = i_size & ~PAGE_CACHE_MASK; | 1422 | unsigned int ofs = i_size & ~PAGE_CACHE_MASK; |
1380 | kaddr = kmap_atomic(page, KM_USER0); | 1423 | kaddr = kmap_atomic(page, KM_USER0); |
1381 | memset(kaddr + ofs, 0, PAGE_CACHE_SIZE - ofs); | 1424 | memset(kaddr + ofs, 0, PAGE_CACHE_SIZE - ofs); |
1382 | flush_dcache_page(page); | ||
1383 | kunmap_atomic(kaddr, KM_USER0); | 1425 | kunmap_atomic(kaddr, KM_USER0); |
1426 | flush_dcache_page(page); | ||
1384 | } | 1427 | } |
1385 | /* Handle mst protected attributes. */ | 1428 | /* Handle mst protected attributes. */ |
1386 | if (NInoMstProtected(ni)) | 1429 | if (NInoMstProtected(ni)) |
@@ -1443,34 +1486,33 @@ retry_writepage: | |||
1443 | BUG_ON(PageWriteback(page)); | 1486 | BUG_ON(PageWriteback(page)); |
1444 | set_page_writeback(page); | 1487 | set_page_writeback(page); |
1445 | unlock_page(page); | 1488 | unlock_page(page); |
1446 | /* | ||
1447 | * Here, we do not need to zero the out of bounds area everytime | ||
1448 | * because the below memcpy() already takes care of the | ||
1449 | * mmap-at-end-of-file requirements. If the file is converted to a | ||
1450 | * non-resident one, then the code path use is switched to the | ||
1451 | * non-resident one where the zeroing happens on each ntfs_writepage() | ||
1452 | * invocation. | ||
1453 | */ | ||
1454 | attr_len = le32_to_cpu(ctx->attr->data.resident.value_length); | 1489 | attr_len = le32_to_cpu(ctx->attr->data.resident.value_length); |
1455 | i_size = i_size_read(vi); | 1490 | i_size = i_size_read(vi); |
1456 | if (unlikely(attr_len > i_size)) { | 1491 | if (unlikely(attr_len > i_size)) { |
1492 | /* Race with shrinking truncate or a failed truncate. */ | ||
1457 | attr_len = i_size; | 1493 | attr_len = i_size; |
1458 | ctx->attr->data.resident.value_length = cpu_to_le32(attr_len); | 1494 | /* |
1495 | * If the truncate failed, fix it up now. If a concurrent | ||
1496 | * truncate, we do its job, so it does not have to do anything. | ||
1497 | */ | ||
1498 | err = ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr, | ||
1499 | attr_len); | ||
1500 | /* Shrinking cannot fail. */ | ||
1501 | BUG_ON(err); | ||
1459 | } | 1502 | } |
1460 | kaddr = kmap_atomic(page, KM_USER0); | 1503 | kaddr = kmap_atomic(page, KM_USER0); |
1461 | /* Copy the data from the page to the mft record. */ | 1504 | /* Copy the data from the page to the mft record. */ |
1462 | memcpy((u8*)ctx->attr + | 1505 | memcpy((u8*)ctx->attr + |
1463 | le16_to_cpu(ctx->attr->data.resident.value_offset), | 1506 | le16_to_cpu(ctx->attr->data.resident.value_offset), |
1464 | kaddr, attr_len); | 1507 | kaddr, attr_len); |
1465 | flush_dcache_mft_record_page(ctx->ntfs_ino); | ||
1466 | /* Zero out of bounds area in the page cache page. */ | 1508 | /* Zero out of bounds area in the page cache page. */ |
1467 | memset(kaddr + attr_len, 0, PAGE_CACHE_SIZE - attr_len); | 1509 | memset(kaddr + attr_len, 0, PAGE_CACHE_SIZE - attr_len); |
1468 | flush_dcache_page(page); | ||
1469 | kunmap_atomic(kaddr, KM_USER0); | 1510 | kunmap_atomic(kaddr, KM_USER0); |
1470 | 1511 | flush_dcache_mft_record_page(ctx->ntfs_ino); | |
1512 | flush_dcache_page(page); | ||
1513 | /* We are done with the page. */ | ||
1471 | end_page_writeback(page); | 1514 | end_page_writeback(page); |
1472 | 1515 | /* Finally, mark the mft record dirty, so it gets written back. */ | |
1473 | /* Mark the mft record dirty, so it gets written back. */ | ||
1474 | mark_mft_record_dirty(ctx->ntfs_ino); | 1516 | mark_mft_record_dirty(ctx->ntfs_ino); |
1475 | ntfs_attr_put_search_ctx(ctx); | 1517 | ntfs_attr_put_search_ctx(ctx); |
1476 | unmap_mft_record(base_ni); | 1518 | unmap_mft_record(base_ni); |
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index dc4bbe3acf5c..7ec045131808 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c | |||
@@ -1166,6 +1166,8 @@ err_out: | |||
1166 | * | 1166 | * |
1167 | * Return 0 on success and -errno on error. In the error case, the inode will | 1167 | * Return 0 on success and -errno on error. In the error case, the inode will |
1168 | * have had make_bad_inode() executed on it. | 1168 | * have had make_bad_inode() executed on it. |
1169 | * | ||
1170 | * Note this cannot be called for AT_INDEX_ALLOCATION. | ||
1169 | */ | 1171 | */ |
1170 | static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | 1172 | static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) |
1171 | { | 1173 | { |
@@ -1242,8 +1244,8 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | |||
1242 | } | 1244 | } |
1243 | } | 1245 | } |
1244 | /* | 1246 | /* |
1245 | * The encryption flag set in an index root just means to | 1247 | * The compressed/sparse flag set in an index root just means |
1246 | * compress all files. | 1248 | * to compress all files. |
1247 | */ | 1249 | */ |
1248 | if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) { | 1250 | if (NInoMstProtected(ni) && ni->type != AT_INDEX_ROOT) { |
1249 | ntfs_error(vi->i_sb, "Found mst protected attribute " | 1251 | ntfs_error(vi->i_sb, "Found mst protected attribute " |
@@ -1319,8 +1321,7 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi) | |||
1319 | "the mapping pairs array."); | 1321 | "the mapping pairs array."); |
1320 | goto unm_err_out; | 1322 | goto unm_err_out; |
1321 | } | 1323 | } |
1322 | if ((NInoCompressed(ni) || NInoSparse(ni)) && | 1324 | if (NInoCompressed(ni) || NInoSparse(ni)) { |
1323 | ni->type != AT_INDEX_ROOT) { | ||
1324 | if (a->data.non_resident.compression_unit != 4) { | 1325 | if (a->data.non_resident.compression_unit != 4) { |
1325 | ntfs_error(vi->i_sb, "Found nonstandard " | 1326 | ntfs_error(vi->i_sb, "Found nonstandard " |
1326 | "compression unit (%u instead " | 1327 | "compression unit (%u instead " |
diff --git a/fs/ntfs/malloc.h b/fs/ntfs/malloc.h index 3288bcc2c4aa..006946efca8c 100644 --- a/fs/ntfs/malloc.h +++ b/fs/ntfs/malloc.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * malloc.h - NTFS kernel memory handling. Part of the Linux-NTFS project. | 2 | * malloc.h - NTFS kernel memory handling. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2004 Anton Altaparmakov | 4 | * Copyright (c) 2001-2005 Anton Altaparmakov |
5 | * | 5 | * |
6 | * This program/include file is free software; you can redistribute it and/or | 6 | * This program/include file is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as published | 7 | * modify it under the terms of the GNU General Public License as published |
diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index f5b2ac929081..061b5ff6b73c 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * runlist.c - NTFS runlist handling code. Part of the Linux-NTFS project. | 2 | * runlist.c - NTFS runlist handling code. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2005 Anton Altaparmakov | 4 | * Copyright (c) 2001-2005 Anton Altaparmakov |
5 | * Copyright (c) 2002 Richard Russon | 5 | * Copyright (c) 2002-2005 Richard Russon |
6 | * | 6 | * |
7 | * This program/include file is free software; you can redistribute it and/or | 7 | * This program/include file is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License as published | 8 | * modify it under the terms of the GNU General Public License as published |
@@ -158,17 +158,21 @@ static inline BOOL ntfs_are_rl_mergeable(runlist_element *dst, | |||
158 | BUG_ON(!dst); | 158 | BUG_ON(!dst); |
159 | BUG_ON(!src); | 159 | BUG_ON(!src); |
160 | 160 | ||
161 | if ((dst->lcn < 0) || (src->lcn < 0)) { /* Are we merging holes? */ | 161 | /* We can merge unmapped regions even if they are misaligned. */ |
162 | if (dst->lcn == LCN_HOLE && src->lcn == LCN_HOLE) | 162 | if ((dst->lcn == LCN_RL_NOT_MAPPED) && (src->lcn == LCN_RL_NOT_MAPPED)) |
163 | return TRUE; | 163 | return TRUE; |
164 | /* If the runs are misaligned, we cannot merge them. */ | ||
165 | if ((dst->vcn + dst->length) != src->vcn) | ||
164 | return FALSE; | 166 | return FALSE; |
165 | } | 167 | /* If both runs are non-sparse and contiguous, we can merge them. */ |
166 | if ((dst->lcn + dst->length) != src->lcn) /* Are the runs contiguous? */ | 168 | if ((dst->lcn >= 0) && (src->lcn >= 0) && |
167 | return FALSE; | 169 | ((dst->lcn + dst->length) == src->lcn)) |
168 | if ((dst->vcn + dst->length) != src->vcn) /* Are the runs misaligned? */ | 170 | return TRUE; |
169 | return FALSE; | 171 | /* If we are merging two holes, we can merge them. */ |
170 | 172 | if ((dst->lcn == LCN_HOLE) && (src->lcn == LCN_HOLE)) | |
171 | return TRUE; | 173 | return TRUE; |
174 | /* Cannot merge. */ | ||
175 | return FALSE; | ||
172 | } | 176 | } |
173 | 177 | ||
174 | /** | 178 | /** |
@@ -214,14 +218,15 @@ static inline void __ntfs_rl_merge(runlist_element *dst, runlist_element *src) | |||
214 | static inline runlist_element *ntfs_rl_append(runlist_element *dst, | 218 | static inline runlist_element *ntfs_rl_append(runlist_element *dst, |
215 | int dsize, runlist_element *src, int ssize, int loc) | 219 | int dsize, runlist_element *src, int ssize, int loc) |
216 | { | 220 | { |
217 | BOOL right; | 221 | BOOL right = FALSE; /* Right end of @src needs merging. */ |
218 | int magic; | 222 | int marker; /* End of the inserted runs. */ |
219 | 223 | ||
220 | BUG_ON(!dst); | 224 | BUG_ON(!dst); |
221 | BUG_ON(!src); | 225 | BUG_ON(!src); |
222 | 226 | ||
223 | /* First, check if the right hand end needs merging. */ | 227 | /* First, check if the right hand end needs merging. */ |
224 | right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1); | 228 | if ((loc + 1) < dsize) |
229 | right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1); | ||
225 | 230 | ||
226 | /* Space required: @dst size + @src size, less one if we merged. */ | 231 | /* Space required: @dst size + @src size, less one if we merged. */ |
227 | dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - right); | 232 | dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - right); |
@@ -236,18 +241,19 @@ static inline runlist_element *ntfs_rl_append(runlist_element *dst, | |||
236 | if (right) | 241 | if (right) |
237 | __ntfs_rl_merge(src + ssize - 1, dst + loc + 1); | 242 | __ntfs_rl_merge(src + ssize - 1, dst + loc + 1); |
238 | 243 | ||
239 | magic = loc + ssize; | 244 | /* First run after the @src runs that have been inserted. */ |
245 | marker = loc + ssize + 1; | ||
240 | 246 | ||
241 | /* Move the tail of @dst out of the way, then copy in @src. */ | 247 | /* Move the tail of @dst out of the way, then copy in @src. */ |
242 | ntfs_rl_mm(dst, magic + 1, loc + 1 + right, dsize - loc - 1 - right); | 248 | ntfs_rl_mm(dst, marker, loc + 1 + right, dsize - (loc + 1 + right)); |
243 | ntfs_rl_mc(dst, loc + 1, src, 0, ssize); | 249 | ntfs_rl_mc(dst, loc + 1, src, 0, ssize); |
244 | 250 | ||
245 | /* Adjust the size of the preceding hole. */ | 251 | /* Adjust the size of the preceding hole. */ |
246 | dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn; | 252 | dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn; |
247 | 253 | ||
248 | /* We may have changed the length of the file, so fix the end marker */ | 254 | /* We may have changed the length of the file, so fix the end marker */ |
249 | if (dst[magic + 1].lcn == LCN_ENOENT) | 255 | if (dst[marker].lcn == LCN_ENOENT) |
250 | dst[magic + 1].vcn = dst[magic].vcn + dst[magic].length; | 256 | dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length; |
251 | 257 | ||
252 | return dst; | 258 | return dst; |
253 | } | 259 | } |
@@ -279,18 +285,17 @@ static inline runlist_element *ntfs_rl_append(runlist_element *dst, | |||
279 | static inline runlist_element *ntfs_rl_insert(runlist_element *dst, | 285 | static inline runlist_element *ntfs_rl_insert(runlist_element *dst, |
280 | int dsize, runlist_element *src, int ssize, int loc) | 286 | int dsize, runlist_element *src, int ssize, int loc) |
281 | { | 287 | { |
282 | BOOL left = FALSE; | 288 | BOOL left = FALSE; /* Left end of @src needs merging. */ |
283 | BOOL disc = FALSE; /* Discontinuity */ | 289 | BOOL disc = FALSE; /* Discontinuity between @dst and @src. */ |
284 | BOOL hole = FALSE; /* Following a hole */ | 290 | int marker; /* End of the inserted runs. */ |
285 | int magic; | ||
286 | 291 | ||
287 | BUG_ON(!dst); | 292 | BUG_ON(!dst); |
288 | BUG_ON(!src); | 293 | BUG_ON(!src); |
289 | 294 | ||
290 | /* disc => Discontinuity between the end of @dst and the start of @src. | 295 | /* |
291 | * This means we might need to insert a hole. | 296 | * disc => Discontinuity between the end of @dst and the start of @src. |
292 | * hole => @dst ends with a hole or an unmapped region which we can | 297 | * This means we might need to insert a "not mapped" run. |
293 | * extend to match the discontinuity. */ | 298 | */ |
294 | if (loc == 0) | 299 | if (loc == 0) |
295 | disc = (src[0].vcn > 0); | 300 | disc = (src[0].vcn > 0); |
296 | else { | 301 | else { |
@@ -303,58 +308,49 @@ static inline runlist_element *ntfs_rl_insert(runlist_element *dst, | |||
303 | merged_length += src->length; | 308 | merged_length += src->length; |
304 | 309 | ||
305 | disc = (src[0].vcn > dst[loc - 1].vcn + merged_length); | 310 | disc = (src[0].vcn > dst[loc - 1].vcn + merged_length); |
306 | if (disc) | ||
307 | hole = (dst[loc - 1].lcn == LCN_HOLE); | ||
308 | } | 311 | } |
309 | 312 | /* | |
310 | /* Space required: @dst size + @src size, less one if we merged, plus | 313 | * Space required: @dst size + @src size, less one if we merged, plus |
311 | * one if there was a discontinuity, less one for a trailing hole. */ | 314 | * one if there was a discontinuity. |
312 | dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc - hole); | 315 | */ |
316 | dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc); | ||
313 | if (IS_ERR(dst)) | 317 | if (IS_ERR(dst)) |
314 | return dst; | 318 | return dst; |
315 | /* | 319 | /* |
316 | * We are guaranteed to succeed from here so can start modifying the | 320 | * We are guaranteed to succeed from here so can start modifying the |
317 | * original runlist. | 321 | * original runlist. |
318 | */ | 322 | */ |
319 | |||
320 | if (left) | 323 | if (left) |
321 | __ntfs_rl_merge(dst + loc - 1, src); | 324 | __ntfs_rl_merge(dst + loc - 1, src); |
322 | 325 | /* | |
323 | magic = loc + ssize - left + disc - hole; | 326 | * First run after the @src runs that have been inserted. |
327 | * Nominally, @marker equals @loc + @ssize, i.e. location + number of | ||
328 | * runs in @src. However, if @left, then the first run in @src has | ||
329 | * been merged with one in @dst. And if @disc, then @dst and @src do | ||
330 | * not meet and we need an extra run to fill the gap. | ||
331 | */ | ||
332 | marker = loc + ssize - left + disc; | ||
324 | 333 | ||
325 | /* Move the tail of @dst out of the way, then copy in @src. */ | 334 | /* Move the tail of @dst out of the way, then copy in @src. */ |
326 | ntfs_rl_mm(dst, magic, loc, dsize - loc); | 335 | ntfs_rl_mm(dst, marker, loc, dsize - loc); |
327 | ntfs_rl_mc(dst, loc + disc - hole, src, left, ssize - left); | 336 | ntfs_rl_mc(dst, loc + disc, src, left, ssize - left); |
328 | 337 | ||
329 | /* Adjust the VCN of the last run ... */ | 338 | /* Adjust the VCN of the first run after the insertion... */ |
330 | if (dst[magic].lcn <= LCN_HOLE) | 339 | dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length; |
331 | dst[magic].vcn = dst[magic - 1].vcn + dst[magic - 1].length; | ||
332 | /* ... and the length. */ | 340 | /* ... and the length. */ |
333 | if (dst[magic].lcn == LCN_HOLE || dst[magic].lcn == LCN_RL_NOT_MAPPED) | 341 | if (dst[marker].lcn == LCN_HOLE || dst[marker].lcn == LCN_RL_NOT_MAPPED) |
334 | dst[magic].length = dst[magic + 1].vcn - dst[magic].vcn; | 342 | dst[marker].length = dst[marker + 1].vcn - dst[marker].vcn; |
335 | 343 | ||
336 | /* Writing beyond the end of the file and there's a discontinuity. */ | 344 | /* Writing beyond the end of the file and there is a discontinuity. */ |
337 | if (disc) { | 345 | if (disc) { |
338 | if (hole) | 346 | if (loc > 0) { |
339 | dst[loc - 1].length = dst[loc].vcn - dst[loc - 1].vcn; | 347 | dst[loc].vcn = dst[loc - 1].vcn + dst[loc - 1].length; |
340 | else { | 348 | dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn; |
341 | if (loc > 0) { | 349 | } else { |
342 | dst[loc].vcn = dst[loc - 1].vcn + | 350 | dst[loc].vcn = 0; |
343 | dst[loc - 1].length; | 351 | dst[loc].length = dst[loc + 1].vcn; |
344 | dst[loc].length = dst[loc + 1].vcn - | ||
345 | dst[loc].vcn; | ||
346 | } else { | ||
347 | dst[loc].vcn = 0; | ||
348 | dst[loc].length = dst[loc + 1].vcn; | ||
349 | } | ||
350 | dst[loc].lcn = LCN_RL_NOT_MAPPED; | ||
351 | } | 352 | } |
352 | 353 | dst[loc].lcn = LCN_RL_NOT_MAPPED; | |
353 | magic += hole; | ||
354 | |||
355 | if (dst[magic].lcn == LCN_ENOENT) | ||
356 | dst[magic].vcn = dst[magic - 1].vcn + | ||
357 | dst[magic - 1].length; | ||
358 | } | 354 | } |
359 | return dst; | 355 | return dst; |
360 | } | 356 | } |
@@ -385,20 +381,23 @@ static inline runlist_element *ntfs_rl_insert(runlist_element *dst, | |||
385 | static inline runlist_element *ntfs_rl_replace(runlist_element *dst, | 381 | static inline runlist_element *ntfs_rl_replace(runlist_element *dst, |
386 | int dsize, runlist_element *src, int ssize, int loc) | 382 | int dsize, runlist_element *src, int ssize, int loc) |
387 | { | 383 | { |
388 | BOOL left = FALSE; | 384 | BOOL left = FALSE; /* Left end of @src needs merging. */ |
389 | BOOL right; | 385 | BOOL right = FALSE; /* Right end of @src needs merging. */ |
390 | int magic; | 386 | int tail; /* Start of tail of @dst. */ |
387 | int marker; /* End of the inserted runs. */ | ||
391 | 388 | ||
392 | BUG_ON(!dst); | 389 | BUG_ON(!dst); |
393 | BUG_ON(!src); | 390 | BUG_ON(!src); |
394 | 391 | ||
395 | /* First, merge the left and right ends, if necessary. */ | 392 | /* First, see if the left and right ends need merging. */ |
396 | right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1); | 393 | if ((loc + 1) < dsize) |
394 | right = ntfs_are_rl_mergeable(src + ssize - 1, dst + loc + 1); | ||
397 | if (loc > 0) | 395 | if (loc > 0) |
398 | left = ntfs_are_rl_mergeable(dst + loc - 1, src); | 396 | left = ntfs_are_rl_mergeable(dst + loc - 1, src); |
399 | 397 | /* | |
400 | /* Allocate some space. We'll need less if the left, right, or both | 398 | * Allocate some space. We will need less if the left, right, or both |
401 | * ends were merged. */ | 399 | * ends get merged. |
400 | */ | ||
402 | dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left - right); | 401 | dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left - right); |
403 | if (IS_ERR(dst)) | 402 | if (IS_ERR(dst)) |
404 | return dst; | 403 | return dst; |
@@ -406,21 +405,37 @@ static inline runlist_element *ntfs_rl_replace(runlist_element *dst, | |||
406 | * We are guaranteed to succeed from here so can start modifying the | 405 | * We are guaranteed to succeed from here so can start modifying the |
407 | * original runlists. | 406 | * original runlists. |
408 | */ | 407 | */ |
408 | |||
409 | /* First, merge the left and right ends, if necessary. */ | ||
409 | if (right) | 410 | if (right) |
410 | __ntfs_rl_merge(src + ssize - 1, dst + loc + 1); | 411 | __ntfs_rl_merge(src + ssize - 1, dst + loc + 1); |
411 | if (left) | 412 | if (left) |
412 | __ntfs_rl_merge(dst + loc - 1, src); | 413 | __ntfs_rl_merge(dst + loc - 1, src); |
413 | 414 | /* | |
414 | /* FIXME: What does this mean? (AIA) */ | 415 | * Offset of the tail of @dst. This needs to be moved out of the way |
415 | magic = loc + ssize - left; | 416 | * to make space for the runs to be copied from @src, i.e. the first |
417 | * run of the tail of @dst. | ||
418 | * Nominally, @tail equals @loc + 1, i.e. location, skipping the | ||
419 | * replaced run. However, if @right, then one of @dst's runs is | ||
420 | * already merged into @src. | ||
421 | */ | ||
422 | tail = loc + right + 1; | ||
423 | /* | ||
424 | * First run after the @src runs that have been inserted, i.e. where | ||
425 | * the tail of @dst needs to be moved to. | ||
426 | * Nominally, @marker equals @loc + @ssize, i.e. location + number of | ||
427 | * runs in @src. However, if @left, then the first run in @src has | ||
428 | * been merged with one in @dst. | ||
429 | */ | ||
430 | marker = loc + ssize - left; | ||
416 | 431 | ||
417 | /* Move the tail of @dst out of the way, then copy in @src. */ | 432 | /* Move the tail of @dst out of the way, then copy in @src. */ |
418 | ntfs_rl_mm(dst, magic, loc + right + 1, dsize - loc - right - 1); | 433 | ntfs_rl_mm(dst, marker, tail, dsize - tail); |
419 | ntfs_rl_mc(dst, loc, src, left, ssize - left); | 434 | ntfs_rl_mc(dst, loc, src, left, ssize - left); |
420 | 435 | ||
421 | /* We may have changed the length of the file, so fix the end marker */ | 436 | /* We may have changed the length of the file, so fix the end marker. */ |
422 | if (dst[magic].lcn == LCN_ENOENT) | 437 | if (dsize - tail > 0 && dst[marker].lcn == LCN_ENOENT) |
423 | dst[magic].vcn = dst[magic - 1].vcn + dst[magic - 1].length; | 438 | dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length; |
424 | return dst; | 439 | return dst; |
425 | } | 440 | } |
426 | 441 | ||
diff --git a/fs/proc/array.c b/fs/proc/array.c index d88d518d30f6..d84eecacbeaf 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -74,6 +74,7 @@ | |||
74 | #include <linux/file.h> | 74 | #include <linux/file.h> |
75 | #include <linux/times.h> | 75 | #include <linux/times.h> |
76 | #include <linux/cpuset.h> | 76 | #include <linux/cpuset.h> |
77 | #include <linux/rcupdate.h> | ||
77 | 78 | ||
78 | #include <asm/uaccess.h> | 79 | #include <asm/uaccess.h> |
79 | #include <asm/pgtable.h> | 80 | #include <asm/pgtable.h> |
@@ -180,12 +181,14 @@ static inline char * task_state(struct task_struct *p, char *buffer) | |||
180 | p->gid, p->egid, p->sgid, p->fsgid); | 181 | p->gid, p->egid, p->sgid, p->fsgid); |
181 | read_unlock(&tasklist_lock); | 182 | read_unlock(&tasklist_lock); |
182 | task_lock(p); | 183 | task_lock(p); |
184 | rcu_read_lock(); | ||
183 | if (p->files) | 185 | if (p->files) |
184 | fdt = files_fdtable(p->files); | 186 | fdt = files_fdtable(p->files); |
185 | buffer += sprintf(buffer, | 187 | buffer += sprintf(buffer, |
186 | "FDSize:\t%d\n" | 188 | "FDSize:\t%d\n" |
187 | "Groups:\t", | 189 | "Groups:\t", |
188 | fdt ? fdt->max_fds : 0); | 190 | fdt ? fdt->max_fds : 0); |
191 | rcu_read_unlock(); | ||
189 | 192 | ||
190 | group_info = p->group_info; | 193 | group_info = p->group_info; |
191 | get_group_info(group_info); | 194 | get_group_info(group_info); |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 23db452ab428..fb34f88a4a74 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -340,6 +340,52 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf | |||
340 | return result; | 340 | return result; |
341 | } | 341 | } |
342 | 342 | ||
343 | |||
344 | /* Same as proc_root_link, but this addionally tries to get fs from other | ||
345 | * threads in the group */ | ||
346 | static int proc_task_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) | ||
347 | { | ||
348 | struct fs_struct *fs; | ||
349 | int result = -ENOENT; | ||
350 | struct task_struct *leader = proc_task(inode); | ||
351 | |||
352 | task_lock(leader); | ||
353 | fs = leader->fs; | ||
354 | if (fs) { | ||
355 | atomic_inc(&fs->count); | ||
356 | task_unlock(leader); | ||
357 | } else { | ||
358 | /* Try to get fs from other threads */ | ||
359 | task_unlock(leader); | ||
360 | struct task_struct *task = leader; | ||
361 | read_lock(&tasklist_lock); | ||
362 | if (pid_alive(task)) { | ||
363 | while ((task = next_thread(task)) != leader) { | ||
364 | task_lock(task); | ||
365 | fs = task->fs; | ||
366 | if (fs) { | ||
367 | atomic_inc(&fs->count); | ||
368 | task_unlock(task); | ||
369 | break; | ||
370 | } | ||
371 | task_unlock(task); | ||
372 | } | ||
373 | } | ||
374 | read_unlock(&tasklist_lock); | ||
375 | } | ||
376 | |||
377 | if (fs) { | ||
378 | read_lock(&fs->lock); | ||
379 | *mnt = mntget(fs->rootmnt); | ||
380 | *dentry = dget(fs->root); | ||
381 | read_unlock(&fs->lock); | ||
382 | result = 0; | ||
383 | put_fs_struct(fs); | ||
384 | } | ||
385 | return result; | ||
386 | } | ||
387 | |||
388 | |||
343 | #define MAY_PTRACE(task) \ | 389 | #define MAY_PTRACE(task) \ |
344 | (task == current || \ | 390 | (task == current || \ |
345 | (task->parent == current && \ | 391 | (task->parent == current && \ |
@@ -471,14 +517,14 @@ static int proc_oom_score(struct task_struct *task, char *buffer) | |||
471 | 517 | ||
472 | /* permission checks */ | 518 | /* permission checks */ |
473 | 519 | ||
474 | static int proc_check_root(struct inode *inode) | 520 | /* If the process being read is separated by chroot from the reading process, |
521 | * don't let the reader access the threads. | ||
522 | */ | ||
523 | static int proc_check_chroot(struct dentry *root, struct vfsmount *vfsmnt) | ||
475 | { | 524 | { |
476 | struct dentry *de, *base, *root; | 525 | struct dentry *de, *base; |
477 | struct vfsmount *our_vfsmnt, *vfsmnt, *mnt; | 526 | struct vfsmount *our_vfsmnt, *mnt; |
478 | int res = 0; | 527 | int res = 0; |
479 | |||
480 | if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */ | ||
481 | return -ENOENT; | ||
482 | read_lock(¤t->fs->lock); | 528 | read_lock(¤t->fs->lock); |
483 | our_vfsmnt = mntget(current->fs->rootmnt); | 529 | our_vfsmnt = mntget(current->fs->rootmnt); |
484 | base = dget(current->fs->root); | 530 | base = dget(current->fs->root); |
@@ -511,6 +557,16 @@ out: | |||
511 | goto exit; | 557 | goto exit; |
512 | } | 558 | } |
513 | 559 | ||
560 | static int proc_check_root(struct inode *inode) | ||
561 | { | ||
562 | struct dentry *root; | ||
563 | struct vfsmount *vfsmnt; | ||
564 | |||
565 | if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */ | ||
566 | return -ENOENT; | ||
567 | return proc_check_chroot(root, vfsmnt); | ||
568 | } | ||
569 | |||
514 | static int proc_permission(struct inode *inode, int mask, struct nameidata *nd) | 570 | static int proc_permission(struct inode *inode, int mask, struct nameidata *nd) |
515 | { | 571 | { |
516 | if (generic_permission(inode, mask, NULL) != 0) | 572 | if (generic_permission(inode, mask, NULL) != 0) |
@@ -518,6 +574,20 @@ static int proc_permission(struct inode *inode, int mask, struct nameidata *nd) | |||
518 | return proc_check_root(inode); | 574 | return proc_check_root(inode); |
519 | } | 575 | } |
520 | 576 | ||
577 | static int proc_task_permission(struct inode *inode, int mask, struct nameidata *nd) | ||
578 | { | ||
579 | struct dentry *root; | ||
580 | struct vfsmount *vfsmnt; | ||
581 | |||
582 | if (generic_permission(inode, mask, NULL) != 0) | ||
583 | return -EACCES; | ||
584 | |||
585 | if (proc_task_root_link(inode, &root, &vfsmnt)) | ||
586 | return -ENOENT; | ||
587 | |||
588 | return proc_check_chroot(root, vfsmnt); | ||
589 | } | ||
590 | |||
521 | extern struct seq_operations proc_pid_maps_op; | 591 | extern struct seq_operations proc_pid_maps_op; |
522 | static int maps_open(struct inode *inode, struct file *file) | 592 | static int maps_open(struct inode *inode, struct file *file) |
523 | { | 593 | { |
@@ -1419,7 +1489,7 @@ static struct inode_operations proc_fd_inode_operations = { | |||
1419 | 1489 | ||
1420 | static struct inode_operations proc_task_inode_operations = { | 1490 | static struct inode_operations proc_task_inode_operations = { |
1421 | .lookup = proc_task_lookup, | 1491 | .lookup = proc_task_lookup, |
1422 | .permission = proc_permission, | 1492 | .permission = proc_task_permission, |
1423 | }; | 1493 | }; |
1424 | 1494 | ||
1425 | #ifdef CONFIG_SECURITY | 1495 | #ifdef CONFIG_SECURITY |
diff --git a/include/asm-alpha/futex.h b/include/asm-alpha/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-alpha/futex.h +++ b/include/asm-alpha/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-arm/arch-aaec2000/memory.h b/include/asm-arm/arch-aaec2000/memory.h index 681b6a6171a1..79c90813bc3e 100644 --- a/include/asm-arm/arch-aaec2000/memory.h +++ b/include/asm-arm/arch-aaec2000/memory.h | |||
@@ -64,10 +64,6 @@ | |||
64 | #define NODE_MAX_MEM_SHIFT 26 | 64 | #define NODE_MAX_MEM_SHIFT 26 |
65 | #define NODE_MAX_MEM_SIZE (1 << NODE_MAX_MEM_SHIFT) | 65 | #define NODE_MAX_MEM_SIZE (1 << NODE_MAX_MEM_SHIFT) |
66 | 66 | ||
67 | #else | ||
68 | |||
69 | #define PFN_TO_NID(addr) (0) | ||
70 | |||
71 | #endif /* CONFIG_DISCONTIGMEM */ | 67 | #endif /* CONFIG_DISCONTIGMEM */ |
72 | 68 | ||
73 | #endif /* __ASM_ARCH_MEMORY_H */ | 69 | #endif /* __ASM_ARCH_MEMORY_H */ |
diff --git a/include/asm-arm/arch-iop3xx/memory.h b/include/asm-arm/arch-iop3xx/memory.h index dc4735cb0c10..45351f5cd904 100644 --- a/include/asm-arm/arch-iop3xx/memory.h +++ b/include/asm-arm/arch-iop3xx/memory.h | |||
@@ -36,6 +36,4 @@ | |||
36 | 36 | ||
37 | #endif | 37 | #endif |
38 | 38 | ||
39 | #define PFN_TO_NID(addr) (0) | ||
40 | |||
41 | #endif | 39 | #endif |
diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h index 75623f81ef75..32aece069869 100644 --- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h +++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h | |||
@@ -370,8 +370,6 @@ | |||
370 | #define GLOBAL_REG_BASE (IXP2000_GLOBAL_REG_VIRT_BASE + 0x0a00) | 370 | #define GLOBAL_REG_BASE (IXP2000_GLOBAL_REG_VIRT_BASE + 0x0a00) |
371 | #define GLOBAL_REG(x) (volatile unsigned long*)(GLOBAL_REG_BASE | (x)) | 371 | #define GLOBAL_REG(x) (volatile unsigned long*)(GLOBAL_REG_BASE | (x)) |
372 | 372 | ||
373 | #define IXP2000_PROD_ID GLOBAL_REG(0x00) | ||
374 | |||
375 | #define IXP2000_MAJ_PROD_TYPE_MASK 0x001F0000 | 373 | #define IXP2000_MAJ_PROD_TYPE_MASK 0x001F0000 |
376 | #define IXP2000_MAJ_PROD_TYPE_IXP2000 0x00000000 | 374 | #define IXP2000_MAJ_PROD_TYPE_IXP2000 0x00000000 |
377 | #define IXP2000_MIN_PROD_TYPE_MASK 0x0000FF00 | 375 | #define IXP2000_MIN_PROD_TYPE_MASK 0x0000FF00 |
diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h index c0caf3e3e6fd..abdcf51bd283 100644 --- a/include/asm-arm/arch-ixp2000/platform.h +++ b/include/asm-arm/arch-ixp2000/platform.h | |||
@@ -31,20 +31,24 @@ | |||
31 | 31 | ||
32 | #include <asm/system.h> /* Pickup local_irq_ functions */ | 32 | #include <asm/system.h> /* Pickup local_irq_ functions */ |
33 | 33 | ||
34 | static inline void ixp2000_reg_write(volatile unsigned long *reg, unsigned long val) | 34 | static inline void ixp2000_reg_write(volatile void *reg, unsigned long val) |
35 | { | 35 | { |
36 | volatile unsigned long dummy; | 36 | unsigned long dummy; |
37 | unsigned long flags; | 37 | unsigned long flags; |
38 | 38 | ||
39 | local_irq_save(flags); | 39 | local_irq_save(flags); |
40 | *reg = val; | 40 | *((volatile unsigned long *)reg) = val; |
41 | barrier(); | 41 | barrier(); |
42 | dummy = *reg; | 42 | dummy = *((volatile unsigned long *)reg); |
43 | local_irq_restore(flags); | 43 | local_irq_restore(flags); |
44 | } | 44 | } |
45 | #else | 45 | #else |
46 | #define ixp2000_reg_write(reg, val) (*reg = val) | 46 | static inline void ixp2000_reg_write(volatile void *reg, unsigned long val) |
47 | { | ||
48 | *((volatile unsigned long *)reg) = val; | ||
49 | } | ||
47 | #endif /* IXDP2400 || IXDP2401 */ | 50 | #endif /* IXDP2400 || IXDP2401 */ |
51 | #define ixp2000_reg_read(reg) (*((volatile unsigned long *)reg)) | ||
48 | 52 | ||
49 | /* | 53 | /* |
50 | * Boards may multiplex different devices on the 2nd channel of | 54 | * Boards may multiplex different devices on the 2nd channel of |
@@ -84,7 +88,7 @@ void ixp2000_release_slowport(struct slowport_cfg *); | |||
84 | */ | 88 | */ |
85 | static inline unsigned ixp2000_has_broken_slowport(void) | 89 | static inline unsigned ixp2000_has_broken_slowport(void) |
86 | { | 90 | { |
87 | unsigned long id = *IXP2000_PROD_ID; | 91 | unsigned long id = *IXP2000_PRODUCT_ID; |
88 | unsigned long id_prod = id & (IXP2000_MAJ_PROD_TYPE_MASK | | 92 | unsigned long id_prod = id & (IXP2000_MAJ_PROD_TYPE_MASK | |
89 | IXP2000_MIN_PROD_TYPE_MASK); | 93 | IXP2000_MIN_PROD_TYPE_MASK); |
90 | return (((id_prod == | 94 | return (((id_prod == |
diff --git a/include/asm-arm/arch-lh7a40x/memory.h b/include/asm-arm/arch-lh7a40x/memory.h index 7e2fea372663..c650e6feb9d5 100644 --- a/include/asm-arm/arch-lh7a40x/memory.h +++ b/include/asm-arm/arch-lh7a40x/memory.h | |||
@@ -85,10 +85,6 @@ | |||
85 | (((unsigned long)(addr) & 0x01ffffff) >> PAGE_SHIFT) | 85 | (((unsigned long)(addr) & 0x01ffffff) >> PAGE_SHIFT) |
86 | # endif | 86 | # endif |
87 | 87 | ||
88 | #else | ||
89 | |||
90 | # define PFN_TO_NID(addr) (0) | ||
91 | |||
92 | #endif | 88 | #endif |
93 | 89 | ||
94 | #endif | 90 | #endif |
diff --git a/include/asm-arm/arch-omap/memory.h b/include/asm-arm/arch-omap/memory.h index 84f81e315a25..ef32d61eec7a 100644 --- a/include/asm-arm/arch-omap/memory.h +++ b/include/asm-arm/arch-omap/memory.h | |||
@@ -86,6 +86,5 @@ | |||
86 | 86 | ||
87 | #endif /* CONFIG_ARCH_OMAP1510 */ | 87 | #endif /* CONFIG_ARCH_OMAP1510 */ |
88 | 88 | ||
89 | #define PHYS_TO_NID(addr) (0) | ||
90 | #endif | 89 | #endif |
91 | 90 | ||
diff --git a/include/asm-arm/arch-pxa/memory.h b/include/asm-arm/arch-pxa/memory.h index 217a80b820ff..58bad9748b5c 100644 --- a/include/asm-arm/arch-pxa/memory.h +++ b/include/asm-arm/arch-pxa/memory.h | |||
@@ -67,10 +67,6 @@ | |||
67 | #define LOCAL_MAP_NR(addr) \ | 67 | #define LOCAL_MAP_NR(addr) \ |
68 | (((unsigned long)(addr) & 0x03ffffff) >> PAGE_SHIFT) | 68 | (((unsigned long)(addr) & 0x03ffffff) >> PAGE_SHIFT) |
69 | 69 | ||
70 | #else | ||
71 | |||
72 | #define PFN_TO_NID(addr) (0) | ||
73 | |||
74 | #endif | 70 | #endif |
75 | 71 | ||
76 | #endif | 72 | #endif |
diff --git a/include/asm-arm/arch-pxa/poodle.h b/include/asm-arm/arch-pxa/poodle.h index 58bda9d571a5..6b5ac5144e70 100644 --- a/include/asm-arm/arch-pxa/poodle.h +++ b/include/asm-arm/arch-pxa/poodle.h | |||
@@ -37,24 +37,25 @@ | |||
37 | #define POODLE_GPIO_nSD_DETECT (9) | 37 | #define POODLE_GPIO_nSD_DETECT (9) |
38 | #define POODLE_GPIO_MAIN_BAT_LOW (13) | 38 | #define POODLE_GPIO_MAIN_BAT_LOW (13) |
39 | #define POODLE_GPIO_BAT_COVER (13) | 39 | #define POODLE_GPIO_BAT_COVER (13) |
40 | #define POODLE_GPIO_USB_PULLUP (20) | ||
40 | #define POODLE_GPIO_ADC_TEMP_ON (21) | 41 | #define POODLE_GPIO_ADC_TEMP_ON (21) |
41 | #define POODLE_GPIO_BYPASS_ON (36) | 42 | #define POODLE_GPIO_BYPASS_ON (36) |
42 | #define POODLE_GPIO_CHRG_ON (38) | 43 | #define POODLE_GPIO_CHRG_ON (38) |
43 | #define POODLE_GPIO_CHRG_FULL (16) | 44 | #define POODLE_GPIO_CHRG_FULL (16) |
44 | 45 | ||
45 | /* PXA GPIOs */ | 46 | /* PXA GPIOs */ |
46 | #define POODLE_IRQ_GPIO_ON_KEY IRQ_GPIO0 | 47 | #define POODLE_IRQ_GPIO_ON_KEY IRQ_GPIO(0) |
47 | #define POODLE_IRQ_GPIO_AC_IN IRQ_GPIO1 | 48 | #define POODLE_IRQ_GPIO_AC_IN IRQ_GPIO(1) |
48 | #define POODLE_IRQ_GPIO_HP_IN IRQ_GPIO4 | 49 | #define POODLE_IRQ_GPIO_HP_IN IRQ_GPIO(4) |
49 | #define POODLE_IRQ_GPIO_CO IRQ_GPIO16 | 50 | #define POODLE_IRQ_GPIO_CO IRQ_GPIO(16) |
50 | #define POODLE_IRQ_GPIO_TP_INT IRQ_GPIO5 | 51 | #define POODLE_IRQ_GPIO_TP_INT IRQ_GPIO(5) |
51 | #define POODLE_IRQ_GPIO_WAKEUP IRQ_GPIO11 | 52 | #define POODLE_IRQ_GPIO_WAKEUP IRQ_GPIO(11) |
52 | #define POODLE_IRQ_GPIO_GA_INT IRQ_GPIO10 | 53 | #define POODLE_IRQ_GPIO_GA_INT IRQ_GPIO(10) |
53 | #define POODLE_IRQ_GPIO_CF_IRQ IRQ_GPIO17 | 54 | #define POODLE_IRQ_GPIO_CF_IRQ IRQ_GPIO(17) |
54 | #define POODLE_IRQ_GPIO_CF_CD IRQ_GPIO14 | 55 | #define POODLE_IRQ_GPIO_CF_CD IRQ_GPIO(14) |
55 | #define POODLE_IRQ_GPIO_nSD_INT IRQ_GPIO8 | 56 | #define POODLE_IRQ_GPIO_nSD_INT IRQ_GPIO(8) |
56 | #define POODLE_IRQ_GPIO_nSD_DETECT IRQ_GPIO9 | 57 | #define POODLE_IRQ_GPIO_nSD_DETECT IRQ_GPIO(9) |
57 | #define POODLE_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO13 | 58 | #define POODLE_IRQ_GPIO_MAIN_BAT_LOW IRQ_GPIO(13) |
58 | 59 | ||
59 | /* SCOOP GPIOs */ | 60 | /* SCOOP GPIOs */ |
60 | #define POODLE_SCOOP_CHARGE_ON SCOOP_GPCR_PA11 | 61 | #define POODLE_SCOOP_CHARGE_ON SCOOP_GPCR_PA11 |
diff --git a/include/asm-arm/arch-sa1100/memory.h b/include/asm-arm/arch-sa1100/memory.h index 32d3d5bde34d..8743ff5c1b23 100644 --- a/include/asm-arm/arch-sa1100/memory.h +++ b/include/asm-arm/arch-sa1100/memory.h | |||
@@ -99,10 +99,6 @@ __arch_adjust_zones(int node, unsigned long *size, unsigned long *holes) | |||
99 | #define LOCAL_MAP_NR(addr) \ | 99 | #define LOCAL_MAP_NR(addr) \ |
100 | (((unsigned long)(addr) & 0x07ffffff) >> PAGE_SHIFT) | 100 | (((unsigned long)(addr) & 0x07ffffff) >> PAGE_SHIFT) |
101 | 101 | ||
102 | #else | ||
103 | |||
104 | #define PFN_TO_NID(addr) (0) | ||
105 | |||
106 | #endif | 102 | #endif |
107 | 103 | ||
108 | #endif | 104 | #endif |
diff --git a/include/asm-arm/futex.h b/include/asm-arm/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-arm/futex.h +++ b/include/asm-arm/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-arm/hardware/arm_twd.h b/include/asm-arm/hardware/arm_twd.h new file mode 100644 index 000000000000..131d5b40e072 --- /dev/null +++ b/include/asm-arm/hardware/arm_twd.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef __ASM_HARDWARE_TWD_H | ||
2 | #define __ASM_HARDWARE_TWD_H | ||
3 | |||
4 | #define TWD_TIMER_LOAD 0x00 | ||
5 | #define TWD_TIMER_COUNTER 0x04 | ||
6 | #define TWD_TIMER_CONTROL 0x08 | ||
7 | #define TWD_TIMER_INTSTAT 0x0C | ||
8 | |||
9 | #define TWD_WDOG_LOAD 0x20 | ||
10 | #define TWD_WDOG_COUNTER 0x24 | ||
11 | #define TWD_WDOG_CONTROL 0x28 | ||
12 | #define TWD_WDOG_INTSTAT 0x2C | ||
13 | #define TWD_WDOG_RESETSTAT 0x30 | ||
14 | #define TWD_WDOG_DISABLE 0x34 | ||
15 | |||
16 | #endif | ||
diff --git a/include/asm-arm/mach/arch.h b/include/asm-arm/mach/arch.h index 56c6bf4ab0c3..4fa95084a8c0 100644 --- a/include/asm-arm/mach/arch.h +++ b/include/asm-arm/mach/arch.h | |||
@@ -50,7 +50,7 @@ struct machine_desc { | |||
50 | */ | 50 | */ |
51 | #define MACHINE_START(_type,_name) \ | 51 | #define MACHINE_START(_type,_name) \ |
52 | const struct machine_desc __mach_desc_##_type \ | 52 | const struct machine_desc __mach_desc_##_type \ |
53 | __attribute__((__section__(".arch.info"))) = { \ | 53 | __attribute__((__section__(".arch.info.init"))) = { \ |
54 | .nr = MACH_TYPE_##_type, \ | 54 | .nr = MACH_TYPE_##_type, \ |
55 | .name = _name, | 55 | .name = _name, |
56 | 56 | ||
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h index e47bea7d1723..a8a933a775db 100644 --- a/include/asm-arm/memory.h +++ b/include/asm-arm/memory.h | |||
@@ -160,12 +160,25 @@ static inline __deprecated void *bus_to_virt(unsigned long x) | |||
160 | #define page_to_pfn(page) \ | 160 | #define page_to_pfn(page) \ |
161 | (( (page) - page_zone(page)->zone_mem_map) \ | 161 | (( (page) - page_zone(page)->zone_mem_map) \ |
162 | + page_zone(page)->zone_start_pfn) | 162 | + page_zone(page)->zone_start_pfn) |
163 | |||
163 | #define pfn_to_page(pfn) \ | 164 | #define pfn_to_page(pfn) \ |
164 | (PFN_TO_MAPBASE(pfn) + LOCAL_MAP_NR((pfn) << PAGE_SHIFT)) | 165 | (PFN_TO_MAPBASE(pfn) + LOCAL_MAP_NR((pfn) << PAGE_SHIFT)) |
165 | #define pfn_valid(pfn) (PFN_TO_NID(pfn) < MAX_NUMNODES) | 166 | |
167 | #define pfn_valid(pfn) \ | ||
168 | ({ \ | ||
169 | unsigned int nid = PFN_TO_NID(pfn); \ | ||
170 | int valid = nid < MAX_NUMNODES; \ | ||
171 | if (valid) { \ | ||
172 | pg_data_t *node = NODE_DATA(nid); \ | ||
173 | valid = (pfn - node->node_start_pfn) < \ | ||
174 | node->node_spanned_pages; \ | ||
175 | } \ | ||
176 | valid; \ | ||
177 | }) | ||
166 | 178 | ||
167 | #define virt_to_page(kaddr) \ | 179 | #define virt_to_page(kaddr) \ |
168 | (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr)) | 180 | (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr)) |
181 | |||
169 | #define virt_addr_valid(kaddr) (KVADDR_TO_NID(kaddr) < MAX_NUMNODES) | 182 | #define virt_addr_valid(kaddr) (KVADDR_TO_NID(kaddr) < MAX_NUMNODES) |
170 | 183 | ||
171 | /* | 184 | /* |
diff --git a/include/asm-arm/setup.h b/include/asm-arm/setup.h index adcbd79762bf..ea3ed2465233 100644 --- a/include/asm-arm/setup.h +++ b/include/asm-arm/setup.h | |||
@@ -171,7 +171,7 @@ struct tagtable { | |||
171 | int (*parse)(const struct tag *); | 171 | int (*parse)(const struct tag *); |
172 | }; | 172 | }; |
173 | 173 | ||
174 | #define __tag __attribute_used__ __attribute__((__section__(".taglist"))) | 174 | #define __tag __attribute_used__ __attribute__((__section__(".taglist.init"))) |
175 | #define __tagtable(tag, fn) \ | 175 | #define __tagtable(tag, fn) \ |
176 | static struct tagtable __tagtable_##fn __tag = { tag, fn } | 176 | static struct tagtable __tagtable_##fn __tag = { tag, fn } |
177 | 177 | ||
@@ -213,6 +213,6 @@ struct early_params { | |||
213 | 213 | ||
214 | #define __early_param(name,fn) \ | 214 | #define __early_param(name,fn) \ |
215 | static struct early_params __early_##fn __attribute_used__ \ | 215 | static struct early_params __early_##fn __attribute_used__ \ |
216 | __attribute__((__section__("__early_param"))) = { name, fn } | 216 | __attribute__((__section__(".early_param.init"))) = { name, fn } |
217 | 217 | ||
218 | #endif | 218 | #endif |
diff --git a/include/asm-arm26/futex.h b/include/asm-arm26/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-arm26/futex.h +++ b/include/asm-arm26/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-cris/futex.h b/include/asm-cris/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-cris/futex.h +++ b/include/asm-cris/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-frv/futex.h b/include/asm-frv/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-frv/futex.h +++ b/include/asm-frv/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-h8300/futex.h b/include/asm-h8300/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-h8300/futex.h +++ b/include/asm-h8300/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-i386/futex.h b/include/asm-i386/futex.h index 44b9db806474..e7a271d39309 100644 --- a/include/asm-i386/futex.h +++ b/include/asm-i386/futex.h | |||
@@ -61,7 +61,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
61 | if (op == FUTEX_OP_SET) | 61 | if (op == FUTEX_OP_SET) |
62 | __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg); | 62 | __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg); |
63 | else { | 63 | else { |
64 | #ifndef CONFIG_X86_BSWAP | 64 | #if !defined(CONFIG_X86_BSWAP) && !defined(CONFIG_UML) |
65 | if (boot_cpu_data.x86 == 3) | 65 | if (boot_cpu_data.x86 == 3) |
66 | ret = -ENOSYS; | 66 | ret = -ENOSYS; |
67 | else | 67 | else |
diff --git a/include/asm-ia64/futex.h b/include/asm-ia64/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-ia64/futex.h +++ b/include/asm-ia64/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h index fc544929ac34..a79d1a7ecc77 100644 --- a/include/asm-ia64/ptrace.h +++ b/include/asm-ia64/ptrace.h | |||
@@ -57,7 +57,9 @@ | |||
57 | #include <linux/config.h> | 57 | #include <linux/config.h> |
58 | 58 | ||
59 | #include <asm/fpu.h> | 59 | #include <asm/fpu.h> |
60 | #ifndef ASM_OFFSETS_C | ||
60 | #include <asm/asm-offsets.h> | 61 | #include <asm/asm-offsets.h> |
62 | #endif | ||
61 | 63 | ||
62 | /* | 64 | /* |
63 | * Base-2 logarithm of number of pages to allocate per task structure | 65 | * Base-2 logarithm of number of pages to allocate per task structure |
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h index cf4a950a0f4f..171b2207bde4 100644 --- a/include/asm-ia64/thread_info.h +++ b/include/asm-ia64/thread_info.h | |||
@@ -5,7 +5,9 @@ | |||
5 | #ifndef _ASM_IA64_THREAD_INFO_H | 5 | #ifndef _ASM_IA64_THREAD_INFO_H |
6 | #define _ASM_IA64_THREAD_INFO_H | 6 | #define _ASM_IA64_THREAD_INFO_H |
7 | 7 | ||
8 | #ifndef ASM_OFFSETS_C | ||
8 | #include <asm/asm-offsets.h> | 9 | #include <asm/asm-offsets.h> |
10 | #endif | ||
9 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
10 | #include <asm/ptrace.h> | 12 | #include <asm/ptrace.h> |
11 | 13 | ||
@@ -51,9 +53,14 @@ struct thread_info { | |||
51 | }, \ | 53 | }, \ |
52 | } | 54 | } |
53 | 55 | ||
56 | #ifndef ASM_OFFSETS_C | ||
54 | /* how to get the thread information struct from C */ | 57 | /* how to get the thread information struct from C */ |
55 | #define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE)) | 58 | #define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE)) |
56 | #define alloc_thread_info(tsk) ((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE)) | 59 | #define alloc_thread_info(tsk) ((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE)) |
60 | #else | ||
61 | #define current_thread_info() ((struct thread_info *) 0) | ||
62 | #define alloc_thread_info(tsk) ((struct thread_info *) 0) | ||
63 | #endif | ||
57 | #define free_thread_info(ti) /* nothing */ | 64 | #define free_thread_info(ti) /* nothing */ |
58 | 65 | ||
59 | #define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR | 66 | #define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR |
diff --git a/include/asm-m32r/futex.h b/include/asm-m32r/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-m32r/futex.h +++ b/include/asm-m32r/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-m68k/futex.h b/include/asm-m68k/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-m68k/futex.h +++ b/include/asm-m68k/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-m68knommu/futex.h b/include/asm-m68knommu/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-m68knommu/futex.h +++ b/include/asm-m68knommu/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-parisc/futex.h b/include/asm-parisc/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-parisc/futex.h +++ b/include/asm-parisc/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-ppc/futex.h b/include/asm-ppc/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-ppc/futex.h +++ b/include/asm-ppc/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h index 55752474d0d9..bd9674807f05 100644 --- a/include/asm-ppc/irq.h +++ b/include/asm-ppc/irq.h | |||
@@ -138,6 +138,16 @@ irq_canonicalize(int irq) | |||
138 | #define SIU_IRQ7 (14) | 138 | #define SIU_IRQ7 (14) |
139 | #define SIU_LEVEL7 (15) | 139 | #define SIU_LEVEL7 (15) |
140 | 140 | ||
141 | #define MPC8xx_INT_FEC1 SIU_LEVEL1 | ||
142 | #define MPC8xx_INT_FEC2 SIU_LEVEL3 | ||
143 | |||
144 | #define MPC8xx_INT_SCC1 (CPM_IRQ_OFFSET + CPMVEC_SCC1) | ||
145 | #define MPC8xx_INT_SCC2 (CPM_IRQ_OFFSET + CPMVEC_SCC2) | ||
146 | #define MPC8xx_INT_SCC3 (CPM_IRQ_OFFSET + CPMVEC_SCC3) | ||
147 | #define MPC8xx_INT_SCC4 (CPM_IRQ_OFFSET + CPMVEC_SCC4) | ||
148 | #define MPC8xx_INT_SMC1 (CPM_IRQ_OFFSET + CPMVEC_SMC1) | ||
149 | #define MPC8xx_INT_SMC2 (CPM_IRQ_OFFSET + CPMVEC_SMC2) | ||
150 | |||
141 | /* The internal interrupts we can configure as we see fit. | 151 | /* The internal interrupts we can configure as we see fit. |
142 | * My personal preference is CPM at level 2, which puts it above the | 152 | * My personal preference is CPM at level 2, which puts it above the |
143 | * MBX PCI/ISA/IDE interrupts. | 153 | * MBX PCI/ISA/IDE interrupts. |
diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h index dc8e59896050..208a2e11daee 100644 --- a/include/asm-ppc/mpc8xx.h +++ b/include/asm-ppc/mpc8xx.h | |||
@@ -97,6 +97,22 @@ extern unsigned char __res[]; | |||
97 | 97 | ||
98 | struct pt_regs; | 98 | struct pt_regs; |
99 | 99 | ||
100 | enum ppc_sys_devices { | ||
101 | MPC8xx_CPM_FEC1, | ||
102 | MPC8xx_CPM_FEC2, | ||
103 | MPC8xx_CPM_I2C, | ||
104 | MPC8xx_CPM_SCC1, | ||
105 | MPC8xx_CPM_SCC2, | ||
106 | MPC8xx_CPM_SCC3, | ||
107 | MPC8xx_CPM_SCC4, | ||
108 | MPC8xx_CPM_SPI, | ||
109 | MPC8xx_CPM_MCC1, | ||
110 | MPC8xx_CPM_MCC2, | ||
111 | MPC8xx_CPM_SMC1, | ||
112 | MPC8xx_CPM_SMC2, | ||
113 | MPC8xx_CPM_USB, | ||
114 | }; | ||
115 | |||
100 | #endif /* !__ASSEMBLY__ */ | 116 | #endif /* !__ASSEMBLY__ */ |
101 | #endif /* CONFIG_8xx */ | 117 | #endif /* CONFIG_8xx */ |
102 | #endif /* __CONFIG_8xx_DEFS */ | 118 | #endif /* __CONFIG_8xx_DEFS */ |
diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h index 048f7c8596ee..549f44843c5e 100644 --- a/include/asm-ppc/ppc_sys.h +++ b/include/asm-ppc/ppc_sys.h | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <asm/mpc83xx.h> | 27 | #include <asm/mpc83xx.h> |
28 | #elif defined(CONFIG_85xx) | 28 | #elif defined(CONFIG_85xx) |
29 | #include <asm/mpc85xx.h> | 29 | #include <asm/mpc85xx.h> |
30 | #elif defined(CONFIG_8xx) | ||
31 | #include <asm/mpc8xx.h> | ||
30 | #elif defined(CONFIG_PPC_MPC52xx) | 32 | #elif defined(CONFIG_PPC_MPC52xx) |
31 | #include <asm/mpc52xx.h> | 33 | #include <asm/mpc52xx.h> |
32 | #elif defined(CONFIG_MPC10X_BRIDGE) | 34 | #elif defined(CONFIG_MPC10X_BRIDGE) |
diff --git a/include/asm-ppc/tlbflush.h b/include/asm-ppc/tlbflush.h index 9850f53f54b0..9afee4ffc835 100644 --- a/include/asm-ppc/tlbflush.h +++ b/include/asm-ppc/tlbflush.h | |||
@@ -72,7 +72,7 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, | |||
72 | static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, | 72 | static inline void flush_tlb_page_nohash(struct vm_area_struct *vma, |
73 | unsigned long vmaddr) | 73 | unsigned long vmaddr) |
74 | { _tlbie(vmaddr); } | 74 | { _tlbie(vmaddr); } |
75 | static inline void flush_tlb_range(struct mm_struct *mm, | 75 | static inline void flush_tlb_range(struct vm_area_struct *vma, |
76 | unsigned long start, unsigned long end) | 76 | unsigned long start, unsigned long end) |
77 | { __tlbia(); } | 77 | { __tlbia(); } |
78 | static inline void flush_tlb_kernel_range(unsigned long start, | 78 | static inline void flush_tlb_kernel_range(unsigned long start, |
diff --git a/include/asm-s390/futex.h b/include/asm-s390/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-s390/futex.h +++ b/include/asm-s390/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-sh/futex.h b/include/asm-sh/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-sh/futex.h +++ b/include/asm-sh/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-sh64/futex.h b/include/asm-sh64/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-sh64/futex.h +++ b/include/asm-sh64/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-sparc/futex.h b/include/asm-sparc/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-sparc/futex.h +++ b/include/asm-sparc/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-sparc64/cacheflush.h b/include/asm-sparc64/cacheflush.h index 51b26e81d828..ededd2659eab 100644 --- a/include/asm-sparc64/cacheflush.h +++ b/include/asm-sparc64/cacheflush.h | |||
@@ -4,13 +4,6 @@ | |||
4 | #include <linux/config.h> | 4 | #include <linux/config.h> |
5 | #include <asm/page.h> | 5 | #include <asm/page.h> |
6 | 6 | ||
7 | /* Flushing for D-cache alias handling is only needed if | ||
8 | * the page size is smaller than 16K. | ||
9 | */ | ||
10 | #if PAGE_SHIFT < 14 | ||
11 | #define DCACHE_ALIASING_POSSIBLE | ||
12 | #endif | ||
13 | |||
14 | #ifndef __ASSEMBLY__ | 7 | #ifndef __ASSEMBLY__ |
15 | 8 | ||
16 | #include <linux/mm.h> | 9 | #include <linux/mm.h> |
diff --git a/include/asm-sparc64/futex.h b/include/asm-sparc64/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-sparc64/futex.h +++ b/include/asm-sparc64/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-sparc64/ide.h b/include/asm-sparc64/ide.h index 4c1098474c73..c393f815b0be 100644 --- a/include/asm-sparc64/ide.h +++ b/include/asm-sparc64/ide.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <asm/io.h> | 15 | #include <asm/io.h> |
16 | #include <asm/spitfire.h> | 16 | #include <asm/spitfire.h> |
17 | #include <asm/cacheflush.h> | 17 | #include <asm/cacheflush.h> |
18 | #include <asm/page.h> | ||
18 | 19 | ||
19 | #ifndef MAX_HWIFS | 20 | #ifndef MAX_HWIFS |
20 | # ifdef CONFIG_BLK_DEV_IDEPCI | 21 | # ifdef CONFIG_BLK_DEV_IDEPCI |
diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h index c9f8ef208ea5..7f8d764abc47 100644 --- a/include/asm-sparc64/page.h +++ b/include/asm-sparc64/page.h | |||
@@ -21,6 +21,13 @@ | |||
21 | #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) | 21 | #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) |
22 | #define PAGE_MASK (~(PAGE_SIZE-1)) | 22 | #define PAGE_MASK (~(PAGE_SIZE-1)) |
23 | 23 | ||
24 | /* Flushing for D-cache alias handling is only needed if | ||
25 | * the page size is smaller than 16K. | ||
26 | */ | ||
27 | #if PAGE_SHIFT < 14 | ||
28 | #define DCACHE_ALIASING_POSSIBLE | ||
29 | #endif | ||
30 | |||
24 | #ifdef __KERNEL__ | 31 | #ifdef __KERNEL__ |
25 | 32 | ||
26 | #ifndef __ASSEMBLY__ | 33 | #ifndef __ASSEMBLY__ |
diff --git a/include/asm-sparc64/pgalloc.h b/include/asm-sparc64/pgalloc.h index b9b1914aae63..a96067cca963 100644 --- a/include/asm-sparc64/pgalloc.h +++ b/include/asm-sparc64/pgalloc.h | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <asm/spitfire.h> | 10 | #include <asm/spitfire.h> |
11 | #include <asm/cpudata.h> | 11 | #include <asm/cpudata.h> |
12 | #include <asm/cacheflush.h> | 12 | #include <asm/cacheflush.h> |
13 | #include <asm/page.h> | ||
13 | 14 | ||
14 | /* Page table allocation/freeing. */ | 15 | /* Page table allocation/freeing. */ |
15 | #ifdef CONFIG_SMP | 16 | #ifdef CONFIG_SMP |
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index a2b4f5ed4625..a297f6144f0f 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h | |||
@@ -24,21 +24,23 @@ | |||
24 | #include <asm/processor.h> | 24 | #include <asm/processor.h> |
25 | #include <asm/const.h> | 25 | #include <asm/const.h> |
26 | 26 | ||
27 | /* The kernel image occupies 0x4000000 to 0x1000000 (4MB --> 16MB). | 27 | /* The kernel image occupies 0x4000000 to 0x1000000 (4MB --> 32MB). |
28 | * The page copy blockops use 0x1000000 to 0x18000000 (16MB --> 24MB). | 28 | * The page copy blockops can use 0x2000000 to 0x10000000. |
29 | * The PROM resides in an area spanning 0xf0000000 to 0x100000000. | 29 | * The PROM resides in an area spanning 0xf0000000 to 0x100000000. |
30 | * The vmalloc area spans 0x140000000 to 0x200000000. | 30 | * The vmalloc area spans 0x100000000 to 0x200000000. |
31 | * Since modules need to be in the lowest 32-bits of the address space, | ||
32 | * we place them right before the OBP area from 0x10000000 to 0xf0000000. | ||
31 | * There is a single static kernel PMD which maps from 0x0 to address | 33 | * There is a single static kernel PMD which maps from 0x0 to address |
32 | * 0x400000000. | 34 | * 0x400000000. |
33 | */ | 35 | */ |
34 | #define TLBTEMP_BASE _AC(0x0000000001000000,UL) | 36 | #define TLBTEMP_BASE _AC(0x0000000002000000,UL) |
35 | #define MODULES_VADDR _AC(0x0000000002000000,UL) | 37 | #define MODULES_VADDR _AC(0x0000000010000000,UL) |
36 | #define MODULES_LEN _AC(0x000000007e000000,UL) | 38 | #define MODULES_LEN _AC(0x00000000e0000000,UL) |
37 | #define MODULES_END _AC(0x0000000080000000,UL) | 39 | #define MODULES_END _AC(0x00000000f0000000,UL) |
38 | #define VMALLOC_START _AC(0x0000000140000000,UL) | ||
39 | #define VMALLOC_END _AC(0x0000000200000000,UL) | ||
40 | #define LOW_OBP_ADDRESS _AC(0x00000000f0000000,UL) | 40 | #define LOW_OBP_ADDRESS _AC(0x00000000f0000000,UL) |
41 | #define HI_OBP_ADDRESS _AC(0x0000000100000000,UL) | 41 | #define HI_OBP_ADDRESS _AC(0x0000000100000000,UL) |
42 | #define VMALLOC_START _AC(0x0000000100000000,UL) | ||
43 | #define VMALLOC_END _AC(0x0000000200000000,UL) | ||
42 | 44 | ||
43 | /* XXX All of this needs to be rethought so we can take advantage | 45 | /* XXX All of this needs to be rethought so we can take advantage |
44 | * XXX cheetah's full 64-bit virtual address space, ie. no more hole | 46 | * XXX cheetah's full 64-bit virtual address space, ie. no more hole |
diff --git a/include/asm-um/futex.h b/include/asm-um/futex.h index 2cac5ecd9d00..142ee2d8e0fd 100644 --- a/include/asm-um/futex.h +++ b/include/asm-um/futex.h | |||
@@ -1,53 +1,12 @@ | |||
1 | #ifndef _ASM_FUTEX_H | 1 | #ifndef __UM_FUTEX_H |
2 | #define _ASM_FUTEX_H | 2 | #define __UM_FUTEX_H |
3 | |||
4 | #ifdef __KERNEL__ | ||
5 | 3 | ||
6 | #include <linux/futex.h> | 4 | #include <linux/futex.h> |
7 | #include <asm/errno.h> | 5 | #include <asm/errno.h> |
6 | #include <asm/system.h> | ||
7 | #include <asm/processor.h> | ||
8 | #include <asm/uaccess.h> | 8 | #include <asm/uaccess.h> |
9 | 9 | ||
10 | static inline int | 10 | #include "asm/arch/futex.h" |
11 | futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | ||
12 | { | ||
13 | int op = (encoded_op >> 28) & 7; | ||
14 | int cmp = (encoded_op >> 24) & 15; | ||
15 | int oparg = (encoded_op << 8) >> 20; | ||
16 | int cmparg = (encoded_op << 20) >> 20; | ||
17 | int oldval = 0, ret, tem; | ||
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | ||
19 | oparg = 1 << oparg; | ||
20 | |||
21 | if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) | ||
22 | return -EFAULT; | ||
23 | |||
24 | inc_preempt_count(); | ||
25 | |||
26 | switch (op) { | ||
27 | case FUTEX_OP_SET: | ||
28 | case FUTEX_OP_ADD: | ||
29 | case FUTEX_OP_OR: | ||
30 | case FUTEX_OP_ANDN: | ||
31 | case FUTEX_OP_XOR: | ||
32 | default: | ||
33 | ret = -ENOSYS; | ||
34 | } | ||
35 | 11 | ||
36 | dec_preempt_count(); | ||
37 | |||
38 | if (!ret) { | ||
39 | switch (cmp) { | ||
40 | case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break; | ||
41 | case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break; | ||
42 | case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break; | ||
43 | case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break; | ||
44 | case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break; | ||
45 | case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break; | ||
46 | default: ret = -ENOSYS; | ||
47 | } | ||
48 | } | ||
49 | return ret; | ||
50 | } | ||
51 | |||
52 | #endif | ||
53 | #endif | 12 | #endif |
diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h index b2fc94fbc2d9..2d242360c3d6 100644 --- a/include/asm-um/processor-generic.h +++ b/include/asm-um/processor-generic.h | |||
@@ -21,6 +21,7 @@ struct thread_struct { | |||
21 | * copy_thread) to mark that we are begin called from userspace (fork / | 21 | * copy_thread) to mark that we are begin called from userspace (fork / |
22 | * vfork / clone), and reset to 0 after. It is left to 0 when called | 22 | * vfork / clone), and reset to 0 after. It is left to 0 when called |
23 | * from kernelspace (i.e. kernel_thread() or fork_idle(), as of 2.6.11). */ | 23 | * from kernelspace (i.e. kernel_thread() or fork_idle(), as of 2.6.11). */ |
24 | struct task_struct *saved_task; | ||
24 | int forking; | 25 | int forking; |
25 | int nsyscalls; | 26 | int nsyscalls; |
26 | struct pt_regs regs; | 27 | struct pt_regs regs; |
diff --git a/include/asm-um/system-i386.h b/include/asm-um/system-i386.h index ea8381de3cc9..c436263e67ba 100644 --- a/include/asm-um/system-i386.h +++ b/include/asm-um/system-i386.h | |||
@@ -3,6 +3,4 @@ | |||
3 | 3 | ||
4 | #include "asm/system-generic.h" | 4 | #include "asm/system-generic.h" |
5 | 5 | ||
6 | #define __HAVE_ARCH_CMPXCHG 1 | ||
7 | |||
8 | #endif | 6 | #endif |
diff --git a/include/asm-v850/futex.h b/include/asm-v850/futex.h index 2cac5ecd9d00..9feff4ce1424 100644 --- a/include/asm-v850/futex.h +++ b/include/asm-v850/futex.h | |||
@@ -14,7 +14,7 @@ futex_atomic_op_inuser (int encoded_op, int __user *uaddr) | |||
14 | int cmp = (encoded_op >> 24) & 15; | 14 | int cmp = (encoded_op >> 24) & 15; |
15 | int oparg = (encoded_op << 8) >> 20; | 15 | int oparg = (encoded_op << 8) >> 20; |
16 | int cmparg = (encoded_op << 20) >> 20; | 16 | int cmparg = (encoded_op << 20) >> 20; |
17 | int oldval = 0, ret, tem; | 17 | int oldval = 0, ret; |
18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) | 18 | if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) |
19 | oparg = 1 << oparg; | 19 | oparg = 1 << oparg; |
20 | 20 | ||
diff --git a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h index 594e610f4a1e..68ac3c62fe3d 100644 --- a/include/asm-x86_64/desc.h +++ b/include/asm-x86_64/desc.h | |||
@@ -8,6 +8,8 @@ | |||
8 | #ifndef __ASSEMBLY__ | 8 | #ifndef __ASSEMBLY__ |
9 | 9 | ||
10 | #include <linux/string.h> | 10 | #include <linux/string.h> |
11 | #include <linux/smp.h> | ||
12 | |||
11 | #include <asm/segment.h> | 13 | #include <asm/segment.h> |
12 | #include <asm/mmu.h> | 14 | #include <asm/mmu.h> |
13 | 15 | ||
diff --git a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h index 5fde6f4d6c1e..04bd756efc67 100644 --- a/include/linux/byteorder/generic.h +++ b/include/linux/byteorder/generic.h | |||
@@ -5,6 +5,10 @@ | |||
5 | * linux/byteorder_generic.h | 5 | * linux/byteorder_generic.h |
6 | * Generic Byte-reordering support | 6 | * Generic Byte-reordering support |
7 | * | 7 | * |
8 | * The "... p" macros, like le64_to_cpup, can be used with pointers | ||
9 | * to unaligned data, but there will be a performance penalty on | ||
10 | * some architectures. Use get_unaligned for unaligned data. | ||
11 | * | ||
8 | * Francois-Rene Rideau <fare@tunes.org> 19970707 | 12 | * Francois-Rene Rideau <fare@tunes.org> 19970707 |
9 | * gathered all the good ideas from all asm-foo/byteorder.h into one file, | 13 | * gathered all the good ideas from all asm-foo/byteorder.h into one file, |
10 | * cleaned them up. | 14 | * cleaned them up. |
diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 8bf4bacb5051..71fab4311e92 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h | |||
@@ -4,16 +4,6 @@ | |||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | #include <asm/byteorder.h> | 5 | #include <asm/byteorder.h> |
6 | 6 | ||
7 | /* Structure describing an Internet (DCCP) socket address. */ | ||
8 | struct sockaddr_dccp { | ||
9 | __u16 sdccp_family; /* Address family */ | ||
10 | __u16 sdccp_port; /* Port number */ | ||
11 | __u32 sdccp_addr; /* Internet address */ | ||
12 | __u32 sdccp_service; /* Service */ | ||
13 | /* Pad to size of `struct sockaddr': 16 bytes . */ | ||
14 | __u32 sdccp_pad; | ||
15 | }; | ||
16 | |||
17 | /** | 7 | /** |
18 | * struct dccp_hdr - generic part of DCCP packet header | 8 | * struct dccp_hdr - generic part of DCCP packet header |
19 | * | 9 | * |
@@ -188,6 +178,11 @@ enum { | |||
188 | 178 | ||
189 | /* DCCP socket options */ | 179 | /* DCCP socket options */ |
190 | #define DCCP_SOCKOPT_PACKET_SIZE 1 | 180 | #define DCCP_SOCKOPT_PACKET_SIZE 1 |
181 | #define DCCP_SOCKOPT_SERVICE 2 | ||
182 | #define DCCP_SOCKOPT_CCID_RX_INFO 128 | ||
183 | #define DCCP_SOCKOPT_CCID_TX_INFO 192 | ||
184 | |||
185 | #define DCCP_SERVICE_LIST_MAX_LEN 32 | ||
191 | 186 | ||
192 | #ifdef __KERNEL__ | 187 | #ifdef __KERNEL__ |
193 | 188 | ||
@@ -337,7 +332,8 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb) | |||
337 | */ | 332 | */ |
338 | struct dccp_options { | 333 | struct dccp_options { |
339 | __u64 dccpo_sequence_window; | 334 | __u64 dccpo_sequence_window; |
340 | __u8 dccpo_ccid; | 335 | __u8 dccpo_rx_ccid; |
336 | __u8 dccpo_tx_ccid; | ||
341 | __u8 dccpo_send_ack_vector; | 337 | __u8 dccpo_send_ack_vector; |
342 | __u8 dccpo_send_ndp_count; | 338 | __u8 dccpo_send_ndp_count; |
343 | }; | 339 | }; |
@@ -360,14 +356,8 @@ static inline struct dccp_request_sock *dccp_rsk(const struct request_sock *req) | |||
360 | 356 | ||
361 | extern struct inet_timewait_death_row dccp_death_row; | 357 | extern struct inet_timewait_death_row dccp_death_row; |
362 | 358 | ||
363 | /* Read about the ECN nonce to see why it is 253 */ | ||
364 | #define DCCP_MAX_ACK_VECTOR_LEN 253 | ||
365 | |||
366 | struct dccp_options_received { | 359 | struct dccp_options_received { |
367 | u32 dccpor_ndp:24, | 360 | u32 dccpor_ndp; /* only 24 bits */ |
368 | dccpor_ack_vector_len:8; | ||
369 | u32 dccpor_ack_vector_idx:10; | ||
370 | /* 22 bits hole, try to pack */ | ||
371 | u32 dccpor_timestamp; | 361 | u32 dccpor_timestamp; |
372 | u32 dccpor_timestamp_echo; | 362 | u32 dccpor_timestamp_echo; |
373 | u32 dccpor_elapsed_time; | 363 | u32 dccpor_elapsed_time; |
@@ -382,6 +372,27 @@ enum dccp_role { | |||
382 | DCCP_ROLE_SERVER, | 372 | DCCP_ROLE_SERVER, |
383 | }; | 373 | }; |
384 | 374 | ||
375 | struct dccp_service_list { | ||
376 | __u32 dccpsl_nr; | ||
377 | __u32 dccpsl_list[0]; | ||
378 | }; | ||
379 | |||
380 | #define DCCP_SERVICE_INVALID_VALUE htonl((__u32)-1) | ||
381 | |||
382 | static inline int dccp_list_has_service(const struct dccp_service_list *sl, | ||
383 | const u32 service) | ||
384 | { | ||
385 | if (likely(sl != NULL)) { | ||
386 | u32 i = sl->dccpsl_nr; | ||
387 | while (i--) | ||
388 | if (sl->dccpsl_list[i] == service) | ||
389 | return 1; | ||
390 | } | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | struct dccp_ackvec; | ||
395 | |||
385 | /** | 396 | /** |
386 | * struct dccp_sock - DCCP socket state | 397 | * struct dccp_sock - DCCP socket state |
387 | * | 398 | * |
@@ -402,7 +413,7 @@ enum dccp_role { | |||
402 | * @dccps_packet_size - Set thru setsockopt | 413 | * @dccps_packet_size - Set thru setsockopt |
403 | * @dccps_role - Role of this sock, one of %dccp_role | 414 | * @dccps_role - Role of this sock, one of %dccp_role |
404 | * @dccps_ndp_count - number of Non Data Packets since last data packet | 415 | * @dccps_ndp_count - number of Non Data Packets since last data packet |
405 | * @dccps_hc_rx_ackpkts - receiver half connection acked packets | 416 | * @dccps_hc_rx_ackvec - rx half connection ack vector |
406 | */ | 417 | */ |
407 | struct dccp_sock { | 418 | struct dccp_sock { |
408 | /* inet_connection_sock has to be the first member of dccp_sock */ | 419 | /* inet_connection_sock has to be the first member of dccp_sock */ |
@@ -417,7 +428,8 @@ struct dccp_sock { | |||
417 | __u64 dccps_gss; | 428 | __u64 dccps_gss; |
418 | __u64 dccps_gsr; | 429 | __u64 dccps_gsr; |
419 | __u64 dccps_gar; | 430 | __u64 dccps_gar; |
420 | unsigned long dccps_service; | 431 | __u32 dccps_service; |
432 | struct dccp_service_list *dccps_service_list; | ||
421 | struct timeval dccps_timestamp_time; | 433 | struct timeval dccps_timestamp_time; |
422 | __u32 dccps_timestamp_echo; | 434 | __u32 dccps_timestamp_echo; |
423 | __u32 dccps_packet_size; | 435 | __u32 dccps_packet_size; |
@@ -426,7 +438,7 @@ struct dccp_sock { | |||
426 | __u32 dccps_pmtu_cookie; | 438 | __u32 dccps_pmtu_cookie; |
427 | __u32 dccps_mss_cache; | 439 | __u32 dccps_mss_cache; |
428 | struct dccp_options dccps_options; | 440 | struct dccp_options dccps_options; |
429 | struct dccp_ackpkts *dccps_hc_rx_ackpkts; | 441 | struct dccp_ackvec *dccps_hc_rx_ackvec; |
430 | void *dccps_hc_rx_ccid_private; | 442 | void *dccps_hc_rx_ccid_private; |
431 | void *dccps_hc_tx_ccid_private; | 443 | void *dccps_hc_tx_ccid_private; |
432 | struct ccid *dccps_hc_rx_ccid; | 444 | struct ccid *dccps_hc_rx_ccid; |
@@ -443,6 +455,11 @@ static inline struct dccp_sock *dccp_sk(const struct sock *sk) | |||
443 | return (struct dccp_sock *)sk; | 455 | return (struct dccp_sock *)sk; |
444 | } | 456 | } |
445 | 457 | ||
458 | static inline int dccp_service_not_initialized(const struct sock *sk) | ||
459 | { | ||
460 | return dccp_sk(sk)->dccps_service == DCCP_SERVICE_INVALID_VALUE; | ||
461 | } | ||
462 | |||
446 | static inline const char *dccp_role(const struct sock *sk) | 463 | static inline const char *dccp_role(const struct sock *sk) |
447 | { | 464 | { |
448 | switch (dccp_sk(sk)->dccps_role) { | 465 | switch (dccp_sk(sk)->dccps_role) { |
diff --git a/include/linux/i2c.h b/include/linux/i2c.h index be35332b67e6..3d49a305bf88 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h | |||
@@ -230,11 +230,6 @@ struct i2c_adapter { | |||
230 | struct device dev; /* the adapter device */ | 230 | struct device dev; /* the adapter device */ |
231 | struct class_device class_dev; /* the class device */ | 231 | struct class_device class_dev; /* the class device */ |
232 | 232 | ||
233 | #ifdef CONFIG_PROC_FS | ||
234 | /* No need to set this when you initialize the adapter */ | ||
235 | int inode; | ||
236 | #endif /* def CONFIG_PROC_FS */ | ||
237 | |||
238 | int nr; | 233 | int nr; |
239 | struct list_head clients; | 234 | struct list_head clients; |
240 | struct list_head list; | 235 | struct list_head list; |
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 17d0c0d40b0e..eef0876d8307 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h | |||
@@ -42,8 +42,8 @@ struct hlist_node; | |||
42 | struct vlan_ethhdr { | 42 | struct vlan_ethhdr { |
43 | unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ | 43 | unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ |
44 | unsigned char h_source[ETH_ALEN]; /* source ether addr */ | 44 | unsigned char h_source[ETH_ALEN]; /* source ether addr */ |
45 | unsigned short h_vlan_proto; /* Should always be 0x8100 */ | 45 | __be16 h_vlan_proto; /* Should always be 0x8100 */ |
46 | unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */ | 46 | __be16 h_vlan_TCI; /* Encapsulates priority and VLAN ID */ |
47 | unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */ | 47 | unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */ |
48 | }; | 48 | }; |
49 | 49 | ||
@@ -55,8 +55,8 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb) | |||
55 | } | 55 | } |
56 | 56 | ||
57 | struct vlan_hdr { | 57 | struct vlan_hdr { |
58 | unsigned short h_vlan_TCI; /* Encapsulates priority and VLAN ID */ | 58 | __be16 h_vlan_TCI; /* Encapsulates priority and VLAN ID */ |
59 | unsigned short h_vlan_encapsulated_proto; /* packet type ID field (or len) */ | 59 | __be16 h_vlan_encapsulated_proto; /* packet type ID field (or len) */ |
60 | }; | 60 | }; |
61 | 61 | ||
62 | #define VLAN_VID_MASK 0xfff | 62 | #define VLAN_VID_MASK 0xfff |
diff --git a/include/linux/joystick.h b/include/linux/joystick.h index 06b9af77eb7f..5fd20ddd7ae3 100644 --- a/include/linux/joystick.h +++ b/include/linux/joystick.h | |||
@@ -111,29 +111,30 @@ struct js_corr { | |||
111 | #define JS_SET_ALL 8 | 111 | #define JS_SET_ALL 8 |
112 | 112 | ||
113 | struct JS_DATA_TYPE { | 113 | struct JS_DATA_TYPE { |
114 | __s32 buttons; | 114 | int32_t buttons; |
115 | __s32 x; | 115 | int32_t x; |
116 | __s32 y; | 116 | int32_t y; |
117 | }; | 117 | }; |
118 | 118 | ||
119 | struct JS_DATA_SAVE_TYPE_32 { | 119 | struct JS_DATA_SAVE_TYPE_32 { |
120 | __s32 JS_TIMEOUT; | 120 | int32_t JS_TIMEOUT; |
121 | __s32 BUSY; | 121 | int32_t BUSY; |
122 | __s32 JS_EXPIRETIME; | 122 | int32_t JS_EXPIRETIME; |
123 | __s32 JS_TIMELIMIT; | 123 | int32_t JS_TIMELIMIT; |
124 | struct JS_DATA_TYPE JS_SAVE; | 124 | struct JS_DATA_TYPE JS_SAVE; |
125 | struct JS_DATA_TYPE JS_CORR; | 125 | struct JS_DATA_TYPE JS_CORR; |
126 | }; | 126 | }; |
127 | 127 | ||
128 | struct JS_DATA_SAVE_TYPE_64 { | 128 | struct JS_DATA_SAVE_TYPE_64 { |
129 | __s32 JS_TIMEOUT; | 129 | int32_t JS_TIMEOUT; |
130 | __s32 BUSY; | 130 | int32_t BUSY; |
131 | __s64 JS_EXPIRETIME; | 131 | int64_t JS_EXPIRETIME; |
132 | __s64 JS_TIMELIMIT; | 132 | int64_t JS_TIMELIMIT; |
133 | struct JS_DATA_TYPE JS_SAVE; | 133 | struct JS_DATA_TYPE JS_SAVE; |
134 | struct JS_DATA_TYPE JS_CORR; | 134 | struct JS_DATA_TYPE JS_CORR; |
135 | }; | 135 | }; |
136 | 136 | ||
137 | #ifdef __KERNEL__ | ||
137 | #if BITS_PER_LONG == 64 | 138 | #if BITS_PER_LONG == 64 |
138 | #define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_64 | 139 | #define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_64 |
139 | #elif BITS_PER_LONG == 32 | 140 | #elif BITS_PER_LONG == 32 |
@@ -141,5 +142,6 @@ struct JS_DATA_SAVE_TYPE_64 { | |||
141 | #else | 142 | #else |
142 | #error Unexpected BITS_PER_LONG | 143 | #error Unexpected BITS_PER_LONG |
143 | #endif | 144 | #endif |
145 | #endif | ||
144 | 146 | ||
145 | #endif /* _LINUX_JOYSTICK_H */ | 147 | #endif /* _LINUX_JOYSTICK_H */ |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 82d7024f0765..097b3a3c693d 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -136,6 +136,7 @@ extern unsigned int kobjsize(const void *objp); | |||
136 | #define VM_EXEC 0x00000004 | 136 | #define VM_EXEC 0x00000004 |
137 | #define VM_SHARED 0x00000008 | 137 | #define VM_SHARED 0x00000008 |
138 | 138 | ||
139 | /* mprotect() hardcodes VM_MAYREAD >> 4 == VM_READ, and so for r/w/x bits. */ | ||
139 | #define VM_MAYREAD 0x00000010 /* limits for mprotect() etc */ | 140 | #define VM_MAYREAD 0x00000010 /* limits for mprotect() etc */ |
140 | #define VM_MAYWRITE 0x00000020 | 141 | #define VM_MAYWRITE 0x00000020 |
141 | #define VM_MAYEXEC 0x00000040 | 142 | #define VM_MAYEXEC 0x00000040 |
@@ -350,7 +351,8 @@ static inline void put_page(struct page *page) | |||
350 | * only one copy in memory, at most, normally. | 351 | * only one copy in memory, at most, normally. |
351 | * | 352 | * |
352 | * For the non-reserved pages, page_count(page) denotes a reference count. | 353 | * For the non-reserved pages, page_count(page) denotes a reference count. |
353 | * page_count() == 0 means the page is free. | 354 | * page_count() == 0 means the page is free. page->lru is then used for |
355 | * freelist management in the buddy allocator. | ||
354 | * page_count() == 1 means the page is used for exactly one purpose | 356 | * page_count() == 1 means the page is used for exactly one purpose |
355 | * (e.g. a private data page of one process). | 357 | * (e.g. a private data page of one process). |
356 | * | 358 | * |
@@ -376,10 +378,8 @@ static inline void put_page(struct page *page) | |||
376 | * attaches, plus 1 if `private' contains something, plus one for | 378 | * attaches, plus 1 if `private' contains something, plus one for |
377 | * the page cache itself. | 379 | * the page cache itself. |
378 | * | 380 | * |
379 | * All pages belonging to an inode are in these doubly linked lists: | 381 | * Instead of keeping dirty/clean pages in per address-space lists, we instead |
380 | * mapping->clean_pages, mapping->dirty_pages and mapping->locked_pages; | 382 | * now tag pages as dirty/under writeback in the radix tree. |
381 | * using the page->list list_head. These fields are also used for | ||
382 | * freelist managemet (when page_count()==0). | ||
383 | * | 383 | * |
384 | * There is also a per-mapping radix tree mapping index to the page | 384 | * There is also a per-mapping radix tree mapping index to the page |
385 | * in memory if present. The tree is rooted at mapping->root. | 385 | * in memory if present. The tree is rooted at mapping->root. |
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index 7e033e9271a8..bace72a76cc4 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h | |||
@@ -133,11 +133,13 @@ enum ip_conntrack_expect_events { | |||
133 | 133 | ||
134 | #include <linux/netfilter_ipv4/ip_conntrack_tcp.h> | 134 | #include <linux/netfilter_ipv4/ip_conntrack_tcp.h> |
135 | #include <linux/netfilter_ipv4/ip_conntrack_icmp.h> | 135 | #include <linux/netfilter_ipv4/ip_conntrack_icmp.h> |
136 | #include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h> | ||
136 | #include <linux/netfilter_ipv4/ip_conntrack_sctp.h> | 137 | #include <linux/netfilter_ipv4/ip_conntrack_sctp.h> |
137 | 138 | ||
138 | /* per conntrack: protocol private data */ | 139 | /* per conntrack: protocol private data */ |
139 | union ip_conntrack_proto { | 140 | union ip_conntrack_proto { |
140 | /* insert conntrack proto private data here */ | 141 | /* insert conntrack proto private data here */ |
142 | struct ip_ct_gre gre; | ||
141 | struct ip_ct_sctp sctp; | 143 | struct ip_ct_sctp sctp; |
142 | struct ip_ct_tcp tcp; | 144 | struct ip_ct_tcp tcp; |
143 | struct ip_ct_icmp icmp; | 145 | struct ip_ct_icmp icmp; |
@@ -148,6 +150,7 @@ union ip_conntrack_expect_proto { | |||
148 | }; | 150 | }; |
149 | 151 | ||
150 | /* Add protocol helper include file here */ | 152 | /* Add protocol helper include file here */ |
153 | #include <linux/netfilter_ipv4/ip_conntrack_pptp.h> | ||
151 | #include <linux/netfilter_ipv4/ip_conntrack_amanda.h> | 154 | #include <linux/netfilter_ipv4/ip_conntrack_amanda.h> |
152 | #include <linux/netfilter_ipv4/ip_conntrack_ftp.h> | 155 | #include <linux/netfilter_ipv4/ip_conntrack_ftp.h> |
153 | #include <linux/netfilter_ipv4/ip_conntrack_irc.h> | 156 | #include <linux/netfilter_ipv4/ip_conntrack_irc.h> |
@@ -155,12 +158,20 @@ union ip_conntrack_expect_proto { | |||
155 | /* per conntrack: application helper private data */ | 158 | /* per conntrack: application helper private data */ |
156 | union ip_conntrack_help { | 159 | union ip_conntrack_help { |
157 | /* insert conntrack helper private data (master) here */ | 160 | /* insert conntrack helper private data (master) here */ |
161 | struct ip_ct_pptp_master ct_pptp_info; | ||
158 | struct ip_ct_ftp_master ct_ftp_info; | 162 | struct ip_ct_ftp_master ct_ftp_info; |
159 | struct ip_ct_irc_master ct_irc_info; | 163 | struct ip_ct_irc_master ct_irc_info; |
160 | }; | 164 | }; |
161 | 165 | ||
162 | #ifdef CONFIG_IP_NF_NAT_NEEDED | 166 | #ifdef CONFIG_IP_NF_NAT_NEEDED |
163 | #include <linux/netfilter_ipv4/ip_nat.h> | 167 | #include <linux/netfilter_ipv4/ip_nat.h> |
168 | #include <linux/netfilter_ipv4/ip_nat_pptp.h> | ||
169 | |||
170 | /* per conntrack: nat application helper private data */ | ||
171 | union ip_conntrack_nat_help { | ||
172 | /* insert nat helper private data here */ | ||
173 | struct ip_nat_pptp nat_pptp_info; | ||
174 | }; | ||
164 | #endif | 175 | #endif |
165 | 176 | ||
166 | #include <linux/types.h> | 177 | #include <linux/types.h> |
@@ -223,6 +234,7 @@ struct ip_conntrack | |||
223 | #ifdef CONFIG_IP_NF_NAT_NEEDED | 234 | #ifdef CONFIG_IP_NF_NAT_NEEDED |
224 | struct { | 235 | struct { |
225 | struct ip_nat_info info; | 236 | struct ip_nat_info info; |
237 | union ip_conntrack_nat_help help; | ||
226 | #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ | 238 | #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ |
227 | defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) | 239 | defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) |
228 | int masq_index; | 240 | int masq_index; |
@@ -372,7 +384,7 @@ extern struct ip_conntrack_expect * | |||
372 | __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple); | 384 | __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple); |
373 | 385 | ||
374 | extern struct ip_conntrack_expect * | 386 | extern struct ip_conntrack_expect * |
375 | ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple); | 387 | ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple); |
376 | 388 | ||
377 | extern struct ip_conntrack_tuple_hash * | 389 | extern struct ip_conntrack_tuple_hash * |
378 | __ip_conntrack_find(const struct ip_conntrack_tuple *tuple, | 390 | __ip_conntrack_find(const struct ip_conntrack_tuple *tuple, |
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_pptp.h b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h new file mode 100644 index 000000000000..389e3851d52f --- /dev/null +++ b/include/linux/netfilter_ipv4/ip_conntrack_pptp.h | |||
@@ -0,0 +1,332 @@ | |||
1 | /* PPTP constants and structs */ | ||
2 | #ifndef _CONNTRACK_PPTP_H | ||
3 | #define _CONNTRACK_PPTP_H | ||
4 | |||
5 | /* state of the control session */ | ||
6 | enum pptp_ctrlsess_state { | ||
7 | PPTP_SESSION_NONE, /* no session present */ | ||
8 | PPTP_SESSION_ERROR, /* some session error */ | ||
9 | PPTP_SESSION_STOPREQ, /* stop_sess request seen */ | ||
10 | PPTP_SESSION_REQUESTED, /* start_sess request seen */ | ||
11 | PPTP_SESSION_CONFIRMED, /* session established */ | ||
12 | }; | ||
13 | |||
14 | /* state of the call inside the control session */ | ||
15 | enum pptp_ctrlcall_state { | ||
16 | PPTP_CALL_NONE, | ||
17 | PPTP_CALL_ERROR, | ||
18 | PPTP_CALL_OUT_REQ, | ||
19 | PPTP_CALL_OUT_CONF, | ||
20 | PPTP_CALL_IN_REQ, | ||
21 | PPTP_CALL_IN_REP, | ||
22 | PPTP_CALL_IN_CONF, | ||
23 | PPTP_CALL_CLEAR_REQ, | ||
24 | }; | ||
25 | |||
26 | |||
27 | /* conntrack private data */ | ||
28 | struct ip_ct_pptp_master { | ||
29 | enum pptp_ctrlsess_state sstate; /* session state */ | ||
30 | |||
31 | /* everything below is going to be per-expectation in newnat, | ||
32 | * since there could be more than one call within one session */ | ||
33 | enum pptp_ctrlcall_state cstate; /* call state */ | ||
34 | u_int16_t pac_call_id; /* call id of PAC, host byte order */ | ||
35 | u_int16_t pns_call_id; /* call id of PNS, host byte order */ | ||
36 | |||
37 | /* in pre-2.6.11 this used to be per-expect. Now it is per-conntrack | ||
38 | * and therefore imposes a fixed limit on the number of maps */ | ||
39 | struct ip_ct_gre_keymap *keymap_orig, *keymap_reply; | ||
40 | }; | ||
41 | |||
42 | /* conntrack_expect private member */ | ||
43 | struct ip_ct_pptp_expect { | ||
44 | enum pptp_ctrlcall_state cstate; /* call state */ | ||
45 | u_int16_t pac_call_id; /* call id of PAC */ | ||
46 | u_int16_t pns_call_id; /* call id of PNS */ | ||
47 | }; | ||
48 | |||
49 | |||
50 | #ifdef __KERNEL__ | ||
51 | |||
52 | #define IP_CONNTR_PPTP PPTP_CONTROL_PORT | ||
53 | |||
54 | #define PPTP_CONTROL_PORT 1723 | ||
55 | |||
56 | #define PPTP_PACKET_CONTROL 1 | ||
57 | #define PPTP_PACKET_MGMT 2 | ||
58 | |||
59 | #define PPTP_MAGIC_COOKIE 0x1a2b3c4d | ||
60 | |||
61 | struct pptp_pkt_hdr { | ||
62 | __u16 packetLength; | ||
63 | __u16 packetType; | ||
64 | __u32 magicCookie; | ||
65 | }; | ||
66 | |||
67 | /* PptpControlMessageType values */ | ||
68 | #define PPTP_START_SESSION_REQUEST 1 | ||
69 | #define PPTP_START_SESSION_REPLY 2 | ||
70 | #define PPTP_STOP_SESSION_REQUEST 3 | ||
71 | #define PPTP_STOP_SESSION_REPLY 4 | ||
72 | #define PPTP_ECHO_REQUEST 5 | ||
73 | #define PPTP_ECHO_REPLY 6 | ||
74 | #define PPTP_OUT_CALL_REQUEST 7 | ||
75 | #define PPTP_OUT_CALL_REPLY 8 | ||
76 | #define PPTP_IN_CALL_REQUEST 9 | ||
77 | #define PPTP_IN_CALL_REPLY 10 | ||
78 | #define PPTP_IN_CALL_CONNECT 11 | ||
79 | #define PPTP_CALL_CLEAR_REQUEST 12 | ||
80 | #define PPTP_CALL_DISCONNECT_NOTIFY 13 | ||
81 | #define PPTP_WAN_ERROR_NOTIFY 14 | ||
82 | #define PPTP_SET_LINK_INFO 15 | ||
83 | |||
84 | #define PPTP_MSG_MAX 15 | ||
85 | |||
86 | /* PptpGeneralError values */ | ||
87 | #define PPTP_ERROR_CODE_NONE 0 | ||
88 | #define PPTP_NOT_CONNECTED 1 | ||
89 | #define PPTP_BAD_FORMAT 2 | ||
90 | #define PPTP_BAD_VALUE 3 | ||
91 | #define PPTP_NO_RESOURCE 4 | ||
92 | #define PPTP_BAD_CALLID 5 | ||
93 | #define PPTP_REMOVE_DEVICE_ERROR 6 | ||
94 | |||
95 | struct PptpControlHeader { | ||
96 | __u16 messageType; | ||
97 | __u16 reserved; | ||
98 | }; | ||
99 | |||
100 | /* FramingCapability Bitmap Values */ | ||
101 | #define PPTP_FRAME_CAP_ASYNC 0x1 | ||
102 | #define PPTP_FRAME_CAP_SYNC 0x2 | ||
103 | |||
104 | /* BearerCapability Bitmap Values */ | ||
105 | #define PPTP_BEARER_CAP_ANALOG 0x1 | ||
106 | #define PPTP_BEARER_CAP_DIGITAL 0x2 | ||
107 | |||
108 | struct PptpStartSessionRequest { | ||
109 | __u16 protocolVersion; | ||
110 | __u8 reserved1; | ||
111 | __u8 reserved2; | ||
112 | __u32 framingCapability; | ||
113 | __u32 bearerCapability; | ||
114 | __u16 maxChannels; | ||
115 | __u16 firmwareRevision; | ||
116 | __u8 hostName[64]; | ||
117 | __u8 vendorString[64]; | ||
118 | }; | ||
119 | |||
120 | /* PptpStartSessionResultCode Values */ | ||
121 | #define PPTP_START_OK 1 | ||
122 | #define PPTP_START_GENERAL_ERROR 2 | ||
123 | #define PPTP_START_ALREADY_CONNECTED 3 | ||
124 | #define PPTP_START_NOT_AUTHORIZED 4 | ||
125 | #define PPTP_START_UNKNOWN_PROTOCOL 5 | ||
126 | |||
127 | struct PptpStartSessionReply { | ||
128 | __u16 protocolVersion; | ||
129 | __u8 resultCode; | ||
130 | __u8 generalErrorCode; | ||
131 | __u32 framingCapability; | ||
132 | __u32 bearerCapability; | ||
133 | __u16 maxChannels; | ||
134 | __u16 firmwareRevision; | ||
135 | __u8 hostName[64]; | ||
136 | __u8 vendorString[64]; | ||
137 | }; | ||
138 | |||
139 | /* PptpStopReasons */ | ||
140 | #define PPTP_STOP_NONE 1 | ||
141 | #define PPTP_STOP_PROTOCOL 2 | ||
142 | #define PPTP_STOP_LOCAL_SHUTDOWN 3 | ||
143 | |||
144 | struct PptpStopSessionRequest { | ||
145 | __u8 reason; | ||
146 | }; | ||
147 | |||
148 | /* PptpStopSessionResultCode */ | ||
149 | #define PPTP_STOP_OK 1 | ||
150 | #define PPTP_STOP_GENERAL_ERROR 2 | ||
151 | |||
152 | struct PptpStopSessionReply { | ||
153 | __u8 resultCode; | ||
154 | __u8 generalErrorCode; | ||
155 | }; | ||
156 | |||
157 | struct PptpEchoRequest { | ||
158 | __u32 identNumber; | ||
159 | }; | ||
160 | |||
161 | /* PptpEchoReplyResultCode */ | ||
162 | #define PPTP_ECHO_OK 1 | ||
163 | #define PPTP_ECHO_GENERAL_ERROR 2 | ||
164 | |||
165 | struct PptpEchoReply { | ||
166 | __u32 identNumber; | ||
167 | __u8 resultCode; | ||
168 | __u8 generalErrorCode; | ||
169 | __u16 reserved; | ||
170 | }; | ||
171 | |||
172 | /* PptpFramingType */ | ||
173 | #define PPTP_ASYNC_FRAMING 1 | ||
174 | #define PPTP_SYNC_FRAMING 2 | ||
175 | #define PPTP_DONT_CARE_FRAMING 3 | ||
176 | |||
177 | /* PptpCallBearerType */ | ||
178 | #define PPTP_ANALOG_TYPE 1 | ||
179 | #define PPTP_DIGITAL_TYPE 2 | ||
180 | #define PPTP_DONT_CARE_BEARER_TYPE 3 | ||
181 | |||
182 | struct PptpOutCallRequest { | ||
183 | __u16 callID; | ||
184 | __u16 callSerialNumber; | ||
185 | __u32 minBPS; | ||
186 | __u32 maxBPS; | ||
187 | __u32 bearerType; | ||
188 | __u32 framingType; | ||
189 | __u16 packetWindow; | ||
190 | __u16 packetProcDelay; | ||
191 | __u16 reserved1; | ||
192 | __u16 phoneNumberLength; | ||
193 | __u16 reserved2; | ||
194 | __u8 phoneNumber[64]; | ||
195 | __u8 subAddress[64]; | ||
196 | }; | ||
197 | |||
198 | /* PptpCallResultCode */ | ||
199 | #define PPTP_OUTCALL_CONNECT 1 | ||
200 | #define PPTP_OUTCALL_GENERAL_ERROR 2 | ||
201 | #define PPTP_OUTCALL_NO_CARRIER 3 | ||
202 | #define PPTP_OUTCALL_BUSY 4 | ||
203 | #define PPTP_OUTCALL_NO_DIAL_TONE 5 | ||
204 | #define PPTP_OUTCALL_TIMEOUT 6 | ||
205 | #define PPTP_OUTCALL_DONT_ACCEPT 7 | ||
206 | |||
207 | struct PptpOutCallReply { | ||
208 | __u16 callID; | ||
209 | __u16 peersCallID; | ||
210 | __u8 resultCode; | ||
211 | __u8 generalErrorCode; | ||
212 | __u16 causeCode; | ||
213 | __u32 connectSpeed; | ||
214 | __u16 packetWindow; | ||
215 | __u16 packetProcDelay; | ||
216 | __u32 physChannelID; | ||
217 | }; | ||
218 | |||
219 | struct PptpInCallRequest { | ||
220 | __u16 callID; | ||
221 | __u16 callSerialNumber; | ||
222 | __u32 callBearerType; | ||
223 | __u32 physChannelID; | ||
224 | __u16 dialedNumberLength; | ||
225 | __u16 dialingNumberLength; | ||
226 | __u8 dialedNumber[64]; | ||
227 | __u8 dialingNumber[64]; | ||
228 | __u8 subAddress[64]; | ||
229 | }; | ||
230 | |||
231 | /* PptpInCallResultCode */ | ||
232 | #define PPTP_INCALL_ACCEPT 1 | ||
233 | #define PPTP_INCALL_GENERAL_ERROR 2 | ||
234 | #define PPTP_INCALL_DONT_ACCEPT 3 | ||
235 | |||
236 | struct PptpInCallReply { | ||
237 | __u16 callID; | ||
238 | __u16 peersCallID; | ||
239 | __u8 resultCode; | ||
240 | __u8 generalErrorCode; | ||
241 | __u16 packetWindow; | ||
242 | __u16 packetProcDelay; | ||
243 | __u16 reserved; | ||
244 | }; | ||
245 | |||
246 | struct PptpInCallConnected { | ||
247 | __u16 peersCallID; | ||
248 | __u16 reserved; | ||
249 | __u32 connectSpeed; | ||
250 | __u16 packetWindow; | ||
251 | __u16 packetProcDelay; | ||
252 | __u32 callFramingType; | ||
253 | }; | ||
254 | |||
255 | struct PptpClearCallRequest { | ||
256 | __u16 callID; | ||
257 | __u16 reserved; | ||
258 | }; | ||
259 | |||
260 | struct PptpCallDisconnectNotify { | ||
261 | __u16 callID; | ||
262 | __u8 resultCode; | ||
263 | __u8 generalErrorCode; | ||
264 | __u16 causeCode; | ||
265 | __u16 reserved; | ||
266 | __u8 callStatistics[128]; | ||
267 | }; | ||
268 | |||
269 | struct PptpWanErrorNotify { | ||
270 | __u16 peersCallID; | ||
271 | __u16 reserved; | ||
272 | __u32 crcErrors; | ||
273 | __u32 framingErrors; | ||
274 | __u32 hardwareOverRuns; | ||
275 | __u32 bufferOverRuns; | ||
276 | __u32 timeoutErrors; | ||
277 | __u32 alignmentErrors; | ||
278 | }; | ||
279 | |||
280 | struct PptpSetLinkInfo { | ||
281 | __u16 peersCallID; | ||
282 | __u16 reserved; | ||
283 | __u32 sendAccm; | ||
284 | __u32 recvAccm; | ||
285 | }; | ||
286 | |||
287 | |||
288 | struct pptp_priv_data { | ||
289 | __u16 call_id; | ||
290 | __u16 mcall_id; | ||
291 | __u16 pcall_id; | ||
292 | }; | ||
293 | |||
294 | union pptp_ctrl_union { | ||
295 | struct PptpStartSessionRequest sreq; | ||
296 | struct PptpStartSessionReply srep; | ||
297 | struct PptpStopSessionRequest streq; | ||
298 | struct PptpStopSessionReply strep; | ||
299 | struct PptpOutCallRequest ocreq; | ||
300 | struct PptpOutCallReply ocack; | ||
301 | struct PptpInCallRequest icreq; | ||
302 | struct PptpInCallReply icack; | ||
303 | struct PptpInCallConnected iccon; | ||
304 | struct PptpClearCallRequest clrreq; | ||
305 | struct PptpCallDisconnectNotify disc; | ||
306 | struct PptpWanErrorNotify wanerr; | ||
307 | struct PptpSetLinkInfo setlink; | ||
308 | }; | ||
309 | |||
310 | extern int | ||
311 | (*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb, | ||
312 | struct ip_conntrack *ct, | ||
313 | enum ip_conntrack_info ctinfo, | ||
314 | struct PptpControlHeader *ctlh, | ||
315 | union pptp_ctrl_union *pptpReq); | ||
316 | |||
317 | extern int | ||
318 | (*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb, | ||
319 | struct ip_conntrack *ct, | ||
320 | enum ip_conntrack_info ctinfo, | ||
321 | struct PptpControlHeader *ctlh, | ||
322 | union pptp_ctrl_union *pptpReq); | ||
323 | |||
324 | extern int | ||
325 | (*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *exp_orig, | ||
326 | struct ip_conntrack_expect *exp_reply); | ||
327 | |||
328 | extern void | ||
329 | (*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct, | ||
330 | struct ip_conntrack_expect *exp); | ||
331 | #endif /* __KERNEL__ */ | ||
332 | #endif /* _CONNTRACK_PPTP_H */ | ||
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h new file mode 100644 index 000000000000..8d090ef82f5f --- /dev/null +++ b/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h | |||
@@ -0,0 +1,114 @@ | |||
1 | #ifndef _CONNTRACK_PROTO_GRE_H | ||
2 | #define _CONNTRACK_PROTO_GRE_H | ||
3 | #include <asm/byteorder.h> | ||
4 | |||
5 | /* GRE PROTOCOL HEADER */ | ||
6 | |||
7 | /* GRE Version field */ | ||
8 | #define GRE_VERSION_1701 0x0 | ||
9 | #define GRE_VERSION_PPTP 0x1 | ||
10 | |||
11 | /* GRE Protocol field */ | ||
12 | #define GRE_PROTOCOL_PPTP 0x880B | ||
13 | |||
14 | /* GRE Flags */ | ||
15 | #define GRE_FLAG_C 0x80 | ||
16 | #define GRE_FLAG_R 0x40 | ||
17 | #define GRE_FLAG_K 0x20 | ||
18 | #define GRE_FLAG_S 0x10 | ||
19 | #define GRE_FLAG_A 0x80 | ||
20 | |||
21 | #define GRE_IS_C(f) ((f)&GRE_FLAG_C) | ||
22 | #define GRE_IS_R(f) ((f)&GRE_FLAG_R) | ||
23 | #define GRE_IS_K(f) ((f)&GRE_FLAG_K) | ||
24 | #define GRE_IS_S(f) ((f)&GRE_FLAG_S) | ||
25 | #define GRE_IS_A(f) ((f)&GRE_FLAG_A) | ||
26 | |||
27 | /* GRE is a mess: Four different standards */ | ||
28 | struct gre_hdr { | ||
29 | #if defined(__LITTLE_ENDIAN_BITFIELD) | ||
30 | __u16 rec:3, | ||
31 | srr:1, | ||
32 | seq:1, | ||
33 | key:1, | ||
34 | routing:1, | ||
35 | csum:1, | ||
36 | version:3, | ||
37 | reserved:4, | ||
38 | ack:1; | ||
39 | #elif defined(__BIG_ENDIAN_BITFIELD) | ||
40 | __u16 csum:1, | ||
41 | routing:1, | ||
42 | key:1, | ||
43 | seq:1, | ||
44 | srr:1, | ||
45 | rec:3, | ||
46 | ack:1, | ||
47 | reserved:4, | ||
48 | version:3; | ||
49 | #else | ||
50 | #error "Adjust your <asm/byteorder.h> defines" | ||
51 | #endif | ||
52 | __u16 protocol; | ||
53 | }; | ||
54 | |||
55 | /* modified GRE header for PPTP */ | ||
56 | struct gre_hdr_pptp { | ||
57 | __u8 flags; /* bitfield */ | ||
58 | __u8 version; /* should be GRE_VERSION_PPTP */ | ||
59 | __u16 protocol; /* should be GRE_PROTOCOL_PPTP */ | ||
60 | __u16 payload_len; /* size of ppp payload, not inc. gre header */ | ||
61 | __u16 call_id; /* peer's call_id for this session */ | ||
62 | __u32 seq; /* sequence number. Present if S==1 */ | ||
63 | __u32 ack; /* seq number of highest packet recieved by */ | ||
64 | /* sender in this session */ | ||
65 | }; | ||
66 | |||
67 | |||
68 | /* this is part of ip_conntrack */ | ||
69 | struct ip_ct_gre { | ||
70 | unsigned int stream_timeout; | ||
71 | unsigned int timeout; | ||
72 | }; | ||
73 | |||
74 | #ifdef __KERNEL__ | ||
75 | struct ip_conntrack_expect; | ||
76 | struct ip_conntrack; | ||
77 | |||
78 | /* structure for original <-> reply keymap */ | ||
79 | struct ip_ct_gre_keymap { | ||
80 | struct list_head list; | ||
81 | |||
82 | struct ip_conntrack_tuple tuple; | ||
83 | }; | ||
84 | |||
85 | /* add new tuple->key_reply pair to keymap */ | ||
86 | int ip_ct_gre_keymap_add(struct ip_conntrack *ct, | ||
87 | struct ip_conntrack_tuple *t, | ||
88 | int reply); | ||
89 | |||
90 | /* delete keymap entries */ | ||
91 | void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct); | ||
92 | |||
93 | |||
94 | /* get pointer to gre key, if present */ | ||
95 | static inline u_int32_t *gre_key(struct gre_hdr *greh) | ||
96 | { | ||
97 | if (!greh->key) | ||
98 | return NULL; | ||
99 | if (greh->csum || greh->routing) | ||
100 | return (u_int32_t *) (greh+sizeof(*greh)+4); | ||
101 | return (u_int32_t *) (greh+sizeof(*greh)); | ||
102 | } | ||
103 | |||
104 | /* get pointer ot gre csum, if present */ | ||
105 | static inline u_int16_t *gre_csum(struct gre_hdr *greh) | ||
106 | { | ||
107 | if (!greh->csum) | ||
108 | return NULL; | ||
109 | return (u_int16_t *) (greh+sizeof(*greh)); | ||
110 | } | ||
111 | |||
112 | #endif /* __KERNEL__ */ | ||
113 | |||
114 | #endif /* _CONNTRACK_PROTO_GRE_H */ | ||
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h index c33f0b5e0d0a..14dc0f7b6556 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack_tuple.h +++ b/include/linux/netfilter_ipv4/ip_conntrack_tuple.h | |||
@@ -28,6 +28,9 @@ union ip_conntrack_manip_proto | |||
28 | struct { | 28 | struct { |
29 | u_int16_t port; | 29 | u_int16_t port; |
30 | } sctp; | 30 | } sctp; |
31 | struct { | ||
32 | u_int16_t key; /* key is 32bit, pptp only uses 16 */ | ||
33 | } gre; | ||
31 | }; | 34 | }; |
32 | 35 | ||
33 | /* The manipulable part of the tuple. */ | 36 | /* The manipulable part of the tuple. */ |
@@ -61,6 +64,10 @@ struct ip_conntrack_tuple | |||
61 | struct { | 64 | struct { |
62 | u_int16_t port; | 65 | u_int16_t port; |
63 | } sctp; | 66 | } sctp; |
67 | struct { | ||
68 | u_int16_t key; /* key is 32bit, | ||
69 | * pptp only uses 16 */ | ||
70 | } gre; | ||
64 | } u; | 71 | } u; |
65 | 72 | ||
66 | /* The protocol. */ | 73 | /* The protocol. */ |
diff --git a/include/linux/netfilter_ipv4/ip_nat_pptp.h b/include/linux/netfilter_ipv4/ip_nat_pptp.h new file mode 100644 index 000000000000..eaf66c2e8f93 --- /dev/null +++ b/include/linux/netfilter_ipv4/ip_nat_pptp.h | |||
@@ -0,0 +1,11 @@ | |||
1 | /* PPTP constants and structs */ | ||
2 | #ifndef _NAT_PPTP_H | ||
3 | #define _NAT_PPTP_H | ||
4 | |||
5 | /* conntrack private data */ | ||
6 | struct ip_nat_pptp { | ||
7 | u_int16_t pns_call_id; /* NAT'ed PNS call id */ | ||
8 | u_int16_t pac_call_id; /* NAT'ed PAC call id */ | ||
9 | }; | ||
10 | |||
11 | #endif /* _NAT_PPTP_H */ | ||
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index 58c72a52dc65..59f70b34e029 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h | |||
@@ -455,6 +455,9 @@ extern unsigned int ip6t_do_table(struct sk_buff **pskb, | |||
455 | 455 | ||
456 | /* Check for an extension */ | 456 | /* Check for an extension */ |
457 | extern int ip6t_ext_hdr(u8 nexthdr); | 457 | extern int ip6t_ext_hdr(u8 nexthdr); |
458 | /* find specified header and get offset to it */ | ||
459 | extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, | ||
460 | u8 target); | ||
458 | 461 | ||
459 | #define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1)) | 462 | #define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1)) |
460 | 463 | ||
diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 7bbd25970c9e..bdebdc564506 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #define NETLINK_IP6_FW 13 | 20 | #define NETLINK_IP6_FW 13 |
21 | #define NETLINK_DNRTMSG 14 /* DECnet routing messages */ | 21 | #define NETLINK_DNRTMSG 14 /* DECnet routing messages */ |
22 | #define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ | 22 | #define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ |
23 | #define NETLINK_GENERIC 16 | ||
23 | 24 | ||
24 | #define MAX_LINKS 32 | 25 | #define MAX_LINKS 32 |
25 | 26 | ||
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f6c1a142286a..c49d28eca561 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -491,6 +491,7 @@ | |||
491 | #define PCI_DEVICE_ID_AMI_MEGARAID2 0x9060 | 491 | #define PCI_DEVICE_ID_AMI_MEGARAID2 0x9060 |
492 | 492 | ||
493 | #define PCI_VENDOR_ID_AMD 0x1022 | 493 | #define PCI_VENDOR_ID_AMD 0x1022 |
494 | #define PCI_DEVICE_ID_AMD_K8_NB 0x1100 | ||
494 | #define PCI_DEVICE_ID_AMD_LANCE 0x2000 | 495 | #define PCI_DEVICE_ID_AMD_LANCE 0x2000 |
495 | #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 | 496 | #define PCI_DEVICE_ID_AMD_LANCE_HOME 0x2001 |
496 | #define PCI_DEVICE_ID_AMD_SCSI 0x2020 | 497 | #define PCI_DEVICE_ID_AMD_SCSI 0x2020 |
@@ -1355,7 +1356,7 @@ | |||
1355 | #define PCI_DEVICE_ID_RME_DIGI96 0x3fc0 | 1356 | #define PCI_DEVICE_ID_RME_DIGI96 0x3fc0 |
1356 | #define PCI_DEVICE_ID_RME_DIGI96_8 0x3fc1 | 1357 | #define PCI_DEVICE_ID_RME_DIGI96_8 0x3fc1 |
1357 | #define PCI_DEVICE_ID_RME_DIGI96_8_PRO 0x3fc2 | 1358 | #define PCI_DEVICE_ID_RME_DIGI96_8_PRO 0x3fc2 |
1358 | #define PCI_DEVICE_IDRME__DIGI96_8_PAD_OR_PST 0x3fc3 | 1359 | #define PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST 0x3fc3 |
1359 | #define PCI_DEVICE_ID_XILINX_HAMMERFALL 0x3fc4 | 1360 | #define PCI_DEVICE_ID_XILINX_HAMMERFALL 0x3fc4 |
1360 | #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5 | 1361 | #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5 |
1361 | #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6 | 1362 | #define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6 |
@@ -2252,6 +2253,9 @@ | |||
2252 | 2253 | ||
2253 | #define PCI_VENDOR_ID_INFINICON 0x1820 | 2254 | #define PCI_VENDOR_ID_INFINICON 0x1820 |
2254 | 2255 | ||
2256 | #define PCI_VENDOR_ID_SITECOM 0x182d | ||
2257 | #define PCI_DEVICE_ID_SITECOM_DC105V2 0x3069 | ||
2258 | |||
2255 | #define PCI_VENDOR_ID_TOPSPIN 0x1867 | 2259 | #define PCI_VENDOR_ID_TOPSPIN 0x1867 |
2256 | 2260 | ||
2257 | #define PCI_VENDOR_ID_TDI 0x192E | 2261 | #define PCI_VENDOR_ID_TDI 0x192E |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 425f58c8ea4a..a6f03e473737 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
@@ -508,5 +508,7 @@ asmlinkage long sys_keyctl(int cmd, unsigned long arg2, unsigned long arg3, | |||
508 | 508 | ||
509 | asmlinkage long sys_ioprio_set(int which, int who, int ioprio); | 509 | asmlinkage long sys_ioprio_set(int which, int who, int ioprio); |
510 | asmlinkage long sys_ioprio_get(int which, int who); | 510 | asmlinkage long sys_ioprio_get(int which, int who); |
511 | asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask, | ||
512 | unsigned long maxnode); | ||
511 | 513 | ||
512 | #endif | 514 | #endif |
diff --git a/include/linux/tfrc.h b/include/linux/tfrc.h new file mode 100644 index 000000000000..7dab7831c3cb --- /dev/null +++ b/include/linux/tfrc.h | |||
@@ -0,0 +1,35 @@ | |||
1 | #ifndef _LINUX_TFRC_H_ | ||
2 | #define _LINUX_TFRC_H_ | ||
3 | /* | ||
4 | * include/linux/tfrc.h | ||
5 | * | ||
6 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | ||
7 | * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> | ||
8 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> | ||
9 | * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/types.h> | ||
18 | |||
19 | struct tfrc_rx_info { | ||
20 | __u32 tfrcrx_x_recv; | ||
21 | __u32 tfrcrx_rtt; | ||
22 | __u32 tfrcrx_p; | ||
23 | }; | ||
24 | |||
25 | struct tfrc_tx_info { | ||
26 | __u32 tfrctx_x; | ||
27 | __u32 tfrctx_x_recv; | ||
28 | __u32 tfrctx_x_calc; | ||
29 | __u32 tfrctx_rtt; | ||
30 | __u32 tfrctx_p; | ||
31 | __u32 tfrctx_rto; | ||
32 | __u32 tfrctx_ipi; | ||
33 | }; | ||
34 | |||
35 | #endif /* _LINUX_TFRC_H_ */ | ||
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index e426641c519f..06b4235aa016 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h | |||
@@ -84,6 +84,7 @@ | |||
84 | #define IP_VS_CONN_F_IN_SEQ 0x0400 /* must do input seq adjust */ | 84 | #define IP_VS_CONN_F_IN_SEQ 0x0400 /* must do input seq adjust */ |
85 | #define IP_VS_CONN_F_SEQ_MASK 0x0600 /* in/out sequence mask */ | 85 | #define IP_VS_CONN_F_SEQ_MASK 0x0600 /* in/out sequence mask */ |
86 | #define IP_VS_CONN_F_NO_CPORT 0x0800 /* no client port set yet */ | 86 | #define IP_VS_CONN_F_NO_CPORT 0x0800 /* no client port set yet */ |
87 | #define IP_VS_CONN_F_TEMPLATE 0x1000 /* template, not connection */ | ||
87 | 88 | ||
88 | /* Move it to better place one day, for now keep it unique */ | 89 | /* Move it to better place one day, for now keep it unique */ |
89 | #define NFC_IPVS_PROPERTY 0x10000 | 90 | #define NFC_IPVS_PROPERTY 0x10000 |
@@ -739,6 +740,8 @@ enum { | |||
739 | 740 | ||
740 | extern struct ip_vs_conn *ip_vs_conn_in_get | 741 | extern struct ip_vs_conn *ip_vs_conn_in_get |
741 | (int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port); | 742 | (int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port); |
743 | extern struct ip_vs_conn *ip_vs_ct_in_get | ||
744 | (int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port); | ||
742 | extern struct ip_vs_conn *ip_vs_conn_out_get | 745 | extern struct ip_vs_conn *ip_vs_conn_out_get |
743 | (int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port); | 746 | (int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port); |
744 | 747 | ||
diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h index 53184a38fdf6..0e293fe733b0 100644 --- a/include/rdma/ib_mad.h +++ b/include/rdma/ib_mad.h | |||
@@ -108,6 +108,13 @@ | |||
108 | #define IB_QP1_QKEY 0x80010000 | 108 | #define IB_QP1_QKEY 0x80010000 |
109 | #define IB_QP_SET_QKEY 0x80000000 | 109 | #define IB_QP_SET_QKEY 0x80000000 |
110 | 110 | ||
111 | enum { | ||
112 | IB_MGMT_MAD_DATA = 232, | ||
113 | IB_MGMT_RMPP_DATA = 220, | ||
114 | IB_MGMT_VENDOR_DATA = 216, | ||
115 | IB_MGMT_SA_DATA = 200 | ||
116 | }; | ||
117 | |||
111 | struct ib_mad_hdr { | 118 | struct ib_mad_hdr { |
112 | u8 base_version; | 119 | u8 base_version; |
113 | u8 mgmt_class; | 120 | u8 mgmt_class; |
@@ -149,20 +156,20 @@ struct ib_sa_hdr { | |||
149 | 156 | ||
150 | struct ib_mad { | 157 | struct ib_mad { |
151 | struct ib_mad_hdr mad_hdr; | 158 | struct ib_mad_hdr mad_hdr; |
152 | u8 data[232]; | 159 | u8 data[IB_MGMT_MAD_DATA]; |
153 | }; | 160 | }; |
154 | 161 | ||
155 | struct ib_rmpp_mad { | 162 | struct ib_rmpp_mad { |
156 | struct ib_mad_hdr mad_hdr; | 163 | struct ib_mad_hdr mad_hdr; |
157 | struct ib_rmpp_hdr rmpp_hdr; | 164 | struct ib_rmpp_hdr rmpp_hdr; |
158 | u8 data[220]; | 165 | u8 data[IB_MGMT_RMPP_DATA]; |
159 | }; | 166 | }; |
160 | 167 | ||
161 | struct ib_sa_mad { | 168 | struct ib_sa_mad { |
162 | struct ib_mad_hdr mad_hdr; | 169 | struct ib_mad_hdr mad_hdr; |
163 | struct ib_rmpp_hdr rmpp_hdr; | 170 | struct ib_rmpp_hdr rmpp_hdr; |
164 | struct ib_sa_hdr sa_hdr; | 171 | struct ib_sa_hdr sa_hdr; |
165 | u8 data[200]; | 172 | u8 data[IB_MGMT_SA_DATA]; |
166 | } __attribute__ ((packed)); | 173 | } __attribute__ ((packed)); |
167 | 174 | ||
168 | struct ib_vendor_mad { | 175 | struct ib_vendor_mad { |
@@ -170,7 +177,7 @@ struct ib_vendor_mad { | |||
170 | struct ib_rmpp_hdr rmpp_hdr; | 177 | struct ib_rmpp_hdr rmpp_hdr; |
171 | u8 reserved; | 178 | u8 reserved; |
172 | u8 oui[3]; | 179 | u8 oui[3]; |
173 | u8 data[216]; | 180 | u8 data[IB_MGMT_VENDOR_DATA]; |
174 | }; | 181 | }; |
175 | 182 | ||
176 | struct ib_class_port_info | 183 | struct ib_class_port_info |
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 916144be208b..69313ba7505b 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h | |||
@@ -439,6 +439,8 @@ enum scsi_host_state { | |||
439 | SHOST_CANCEL, | 439 | SHOST_CANCEL, |
440 | SHOST_DEL, | 440 | SHOST_DEL, |
441 | SHOST_RECOVERY, | 441 | SHOST_RECOVERY, |
442 | SHOST_CANCEL_RECOVERY, | ||
443 | SHOST_DEL_RECOVERY, | ||
442 | }; | 444 | }; |
443 | 445 | ||
444 | struct Scsi_Host { | 446 | struct Scsi_Host { |
@@ -465,8 +467,6 @@ struct Scsi_Host { | |||
465 | 467 | ||
466 | struct list_head eh_cmd_q; | 468 | struct list_head eh_cmd_q; |
467 | struct task_struct * ehandler; /* Error recovery thread. */ | 469 | struct task_struct * ehandler; /* Error recovery thread. */ |
468 | struct semaphore * eh_wait; /* The error recovery thread waits | ||
469 | on this. */ | ||
470 | struct semaphore * eh_action; /* Wait for specific actions on the | 470 | struct semaphore * eh_action; /* Wait for specific actions on the |
471 | host. */ | 471 | host. */ |
472 | unsigned int eh_active:1; /* Indicates the eh thread is awake and active if | 472 | unsigned int eh_active:1; /* Indicates the eh thread is awake and active if |
@@ -621,6 +621,13 @@ static inline struct Scsi_Host *dev_to_shost(struct device *dev) | |||
621 | return container_of(dev, struct Scsi_Host, shost_gendev); | 621 | return container_of(dev, struct Scsi_Host, shost_gendev); |
622 | } | 622 | } |
623 | 623 | ||
624 | static inline int scsi_host_in_recovery(struct Scsi_Host *shost) | ||
625 | { | ||
626 | return shost->shost_state == SHOST_RECOVERY || | ||
627 | shost->shost_state == SHOST_CANCEL_RECOVERY || | ||
628 | shost->shost_state == SHOST_DEL_RECOVERY; | ||
629 | } | ||
630 | |||
624 | extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *); | 631 | extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *); |
625 | extern void scsi_flush_work(struct Scsi_Host *); | 632 | extern void scsi_flush_work(struct Scsi_Host *); |
626 | 633 | ||
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 115db056dc6b..b0d445437372 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h | |||
@@ -103,8 +103,8 @@ enum fc_port_state { | |||
103 | incapable of reporting */ | 103 | incapable of reporting */ |
104 | #define FC_PORTSPEED_1GBIT 1 | 104 | #define FC_PORTSPEED_1GBIT 1 |
105 | #define FC_PORTSPEED_2GBIT 2 | 105 | #define FC_PORTSPEED_2GBIT 2 |
106 | #define FC_PORTSPEED_10GBIT 4 | 106 | #define FC_PORTSPEED_4GBIT 4 |
107 | #define FC_PORTSPEED_4GBIT 8 | 107 | #define FC_PORTSPEED_10GBIT 8 |
108 | #define FC_PORTSPEED_NOT_NEGOTIATED (1 << 15) /* Speed not established */ | 108 | #define FC_PORTSPEED_NOT_NEGOTIATED (1 << 15) /* Speed not established */ |
109 | 109 | ||
110 | /* | 110 | /* |
diff --git a/kernel/exit.c b/kernel/exit.c index 6d2089a1bce7..ee6d8b8abef5 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -371,6 +371,12 @@ static inline void close_files(struct files_struct * files) | |||
371 | struct fdtable *fdt; | 371 | struct fdtable *fdt; |
372 | 372 | ||
373 | j = 0; | 373 | j = 0; |
374 | |||
375 | /* | ||
376 | * It is safe to dereference the fd table without RCU or | ||
377 | * ->file_lock because this is the last reference to the | ||
378 | * files structure. | ||
379 | */ | ||
374 | fdt = files_fdtable(files); | 380 | fdt = files_fdtable(files); |
375 | for (;;) { | 381 | for (;;) { |
376 | unsigned long set; | 382 | unsigned long set; |
diff --git a/kernel/fork.c b/kernel/fork.c index 8149f3602881..533ce27f4b2c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1062,7 +1062,8 @@ static task_t *copy_process(unsigned long clone_flags, | |||
1062 | * parent's CPU). This avoids alot of nasty races. | 1062 | * parent's CPU). This avoids alot of nasty races. |
1063 | */ | 1063 | */ |
1064 | p->cpus_allowed = current->cpus_allowed; | 1064 | p->cpus_allowed = current->cpus_allowed; |
1065 | if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed))) | 1065 | if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed) || |
1066 | !cpu_online(task_cpu(p)))) | ||
1066 | set_task_cpu(p, smp_processor_id()); | 1067 | set_task_cpu(p, smp_processor_id()); |
1067 | 1068 | ||
1068 | /* | 1069 | /* |
diff --git a/kernel/printk.c b/kernel/printk.c index a967605bc2e3..4b8f0f9230a4 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -488,6 +488,11 @@ static int __init printk_time_setup(char *str) | |||
488 | 488 | ||
489 | __setup("time", printk_time_setup); | 489 | __setup("time", printk_time_setup); |
490 | 490 | ||
491 | __attribute__((weak)) unsigned long long printk_clock(void) | ||
492 | { | ||
493 | return sched_clock(); | ||
494 | } | ||
495 | |||
491 | /* | 496 | /* |
492 | * This is printk. It can be called from any context. We want it to work. | 497 | * This is printk. It can be called from any context. We want it to work. |
493 | * | 498 | * |
@@ -565,7 +570,7 @@ asmlinkage int vprintk(const char *fmt, va_list args) | |||
565 | loglev_char = default_message_loglevel | 570 | loglev_char = default_message_loglevel |
566 | + '0'; | 571 | + '0'; |
567 | } | 572 | } |
568 | t = sched_clock(); | 573 | t = printk_clock(); |
569 | nanosec_rem = do_div(t, 1000000000); | 574 | nanosec_rem = do_div(t, 1000000000); |
570 | tlen = sprintf(tbuf, | 575 | tlen = sprintf(tbuf, |
571 | "<%c>[%5lu.%06lu] ", | 576 | "<%c>[%5lu.%06lu] ", |
diff --git a/kernel/sys.c b/kernel/sys.c index c80412be2302..f723522e6986 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -1728,8 +1728,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
1728 | error = put_user(current->pdeath_signal, (int __user *)arg2); | 1728 | error = put_user(current->pdeath_signal, (int __user *)arg2); |
1729 | break; | 1729 | break; |
1730 | case PR_GET_DUMPABLE: | 1730 | case PR_GET_DUMPABLE: |
1731 | if (current->mm->dumpable) | 1731 | error = current->mm->dumpable; |
1732 | error = 1; | ||
1733 | break; | 1732 | break; |
1734 | case PR_SET_DUMPABLE: | 1733 | case PR_SET_DUMPABLE: |
1735 | if (arg2 < 0 || arg2 > 2) { | 1734 | if (arg2 < 0 || arg2 > 2) { |
diff --git a/lib/dec_and_lock.c b/lib/dec_and_lock.c index 2377af057d09..305a9663aee3 100644 --- a/lib/dec_and_lock.c +++ b/lib/dec_and_lock.c | |||
@@ -1,7 +1,41 @@ | |||
1 | #include <linux/module.h> | 1 | #include <linux/module.h> |
2 | #include <linux/spinlock.h> | 2 | #include <linux/spinlock.h> |
3 | #include <asm/atomic.h> | 3 | #include <asm/atomic.h> |
4 | #include <asm/system.h> | ||
4 | 5 | ||
6 | #ifdef __HAVE_ARCH_CMPXCHG | ||
7 | /* | ||
8 | * This is an implementation of the notion of "decrement a | ||
9 | * reference count, and return locked if it decremented to zero". | ||
10 | * | ||
11 | * This implementation can be used on any architecture that | ||
12 | * has a cmpxchg, and where atomic->value is an int holding | ||
13 | * the value of the atomic (i.e. the high bits aren't used | ||
14 | * for a lock or anything like that). | ||
15 | */ | ||
16 | int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) | ||
17 | { | ||
18 | int counter; | ||
19 | int newcount; | ||
20 | |||
21 | for (;;) { | ||
22 | counter = atomic_read(atomic); | ||
23 | newcount = counter - 1; | ||
24 | if (!newcount) | ||
25 | break; /* do it the slow way */ | ||
26 | |||
27 | newcount = cmpxchg(&atomic->counter, counter, newcount); | ||
28 | if (newcount == counter) | ||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | spin_lock(lock); | ||
33 | if (atomic_dec_and_test(atomic)) | ||
34 | return 1; | ||
35 | spin_unlock(lock); | ||
36 | return 0; | ||
37 | } | ||
38 | #else | ||
5 | /* | 39 | /* |
6 | * This is an architecture-neutral, but slow, | 40 | * This is an architecture-neutral, but slow, |
7 | * implementation of the notion of "decrement | 41 | * implementation of the notion of "decrement |
@@ -33,5 +67,6 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock) | |||
33 | spin_unlock(lock); | 67 | spin_unlock(lock); |
34 | return 0; | 68 | return 0; |
35 | } | 69 | } |
70 | #endif | ||
36 | 71 | ||
37 | EXPORT_SYMBOL(_atomic_dec_and_lock); | 72 | EXPORT_SYMBOL(_atomic_dec_and_lock); |
diff --git a/mm/Kconfig b/mm/Kconfig index 4e9937ac3529..391ffc54d136 100644 --- a/mm/Kconfig +++ b/mm/Kconfig | |||
@@ -29,7 +29,7 @@ config FLATMEM_MANUAL | |||
29 | If unsure, choose this option (Flat Memory) over any other. | 29 | If unsure, choose this option (Flat Memory) over any other. |
30 | 30 | ||
31 | config DISCONTIGMEM_MANUAL | 31 | config DISCONTIGMEM_MANUAL |
32 | bool "Discontigious Memory" | 32 | bool "Discontiguous Memory" |
33 | depends on ARCH_DISCONTIGMEM_ENABLE | 33 | depends on ARCH_DISCONTIGMEM_ENABLE |
34 | help | 34 | help |
35 | This option provides enhanced support for discontiguous | 35 | This option provides enhanced support for discontiguous |
@@ -52,7 +52,7 @@ config SPARSEMEM_MANUAL | |||
52 | memory hotplug systems. This is normal. | 52 | memory hotplug systems. This is normal. |
53 | 53 | ||
54 | For many other systems, this will be an alternative to | 54 | For many other systems, this will be an alternative to |
55 | "Discontigious Memory". This option provides some potential | 55 | "Discontiguous Memory". This option provides some potential |
56 | performance benefits, along with decreased code complexity, | 56 | performance benefits, along with decreased code complexity, |
57 | but it is newer, and more experimental. | 57 | but it is newer, and more experimental. |
58 | 58 | ||
@@ -1640,7 +1640,7 @@ static void unmap_vma_list(struct mm_struct *mm, struct vm_area_struct *vma) | |||
1640 | /* | 1640 | /* |
1641 | * Get rid of page table information in the indicated region. | 1641 | * Get rid of page table information in the indicated region. |
1642 | * | 1642 | * |
1643 | * Called with the page table lock held. | 1643 | * Called with the mm semaphore held. |
1644 | */ | 1644 | */ |
1645 | static void unmap_region(struct mm_struct *mm, | 1645 | static void unmap_region(struct mm_struct *mm, |
1646 | struct vm_area_struct *vma, struct vm_area_struct *prev, | 1646 | struct vm_area_struct *vma, struct vm_area_struct *prev, |
@@ -1993,6 +1993,9 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma) | |||
1993 | __vma = find_vma_prepare(mm,vma->vm_start,&prev,&rb_link,&rb_parent); | 1993 | __vma = find_vma_prepare(mm,vma->vm_start,&prev,&rb_link,&rb_parent); |
1994 | if (__vma && __vma->vm_start < vma->vm_end) | 1994 | if (__vma && __vma->vm_start < vma->vm_end) |
1995 | return -ENOMEM; | 1995 | return -ENOMEM; |
1996 | if ((vma->vm_flags & VM_ACCOUNT) && | ||
1997 | security_vm_enough_memory(vma_pages(vma))) | ||
1998 | return -ENOMEM; | ||
1996 | vma_link(mm, vma, prev, rb_link, rb_parent); | 1999 | vma_link(mm, vma, prev, rb_link, rb_parent); |
1997 | return 0; | 2000 | return 0; |
1998 | } | 2001 | } |
diff --git a/mm/mprotect.c b/mm/mprotect.c index e9fbd013ad9a..57577f63b305 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c | |||
@@ -248,7 +248,8 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot) | |||
248 | 248 | ||
249 | newflags = vm_flags | (vma->vm_flags & ~(VM_READ | VM_WRITE | VM_EXEC)); | 249 | newflags = vm_flags | (vma->vm_flags & ~(VM_READ | VM_WRITE | VM_EXEC)); |
250 | 250 | ||
251 | if ((newflags & ~(newflags >> 4)) & 0xf) { | 251 | /* newflags >> 4 shift VM_MAY% in place of VM_% */ |
252 | if ((newflags & ~(newflags >> 4)) & (VM_READ | VM_WRITE | VM_EXEC)) { | ||
252 | error = -EACCES; | 253 | error = -EACCES; |
253 | goto out; | 254 | goto out; |
254 | } | 255 | } |
@@ -659,7 +659,7 @@ static inline kmem_cache_t *__find_general_cachep(size_t size, | |||
659 | * kmem_cache_create(), or __kmalloc(), before | 659 | * kmem_cache_create(), or __kmalloc(), before |
660 | * the generic caches are initialized. | 660 | * the generic caches are initialized. |
661 | */ | 661 | */ |
662 | BUG_ON(csizep->cs_cachep == NULL); | 662 | BUG_ON(malloc_sizes[INDEX_AC].cs_cachep == NULL); |
663 | #endif | 663 | #endif |
664 | while (size > csizep->cs_size) | 664 | while (size > csizep->cs_size) |
665 | csizep++; | 665 | csizep++; |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 145f5cde96cf..b74864889670 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -120,7 +120,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, | |||
120 | unsigned short vid; | 120 | unsigned short vid; |
121 | struct net_device_stats *stats; | 121 | struct net_device_stats *stats; |
122 | unsigned short vlan_TCI; | 122 | unsigned short vlan_TCI; |
123 | unsigned short proto; | 123 | __be16 proto; |
124 | 124 | ||
125 | /* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */ | 125 | /* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */ |
126 | vlan_TCI = ntohs(vhdr->h_vlan_TCI); | 126 | vlan_TCI = ntohs(vhdr->h_vlan_TCI); |
diff --git a/net/Kconfig b/net/Kconfig index 2bdd5623fdd5..60f6f321bd76 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -140,6 +140,7 @@ config BRIDGE_NETFILTER | |||
140 | 140 | ||
141 | If unsure, say N. | 141 | If unsure, say N. |
142 | 142 | ||
143 | source "net/netfilter/Kconfig" | ||
143 | source "net/ipv4/netfilter/Kconfig" | 144 | source "net/ipv4/netfilter/Kconfig" |
144 | source "net/ipv6/netfilter/Kconfig" | 145 | source "net/ipv6/netfilter/Kconfig" |
145 | source "net/decnet/netfilter/Kconfig" | 146 | source "net/decnet/netfilter/Kconfig" |
@@ -206,8 +207,6 @@ config NET_PKTGEN | |||
206 | To compile this code as a module, choose M here: the | 207 | To compile this code as a module, choose M here: the |
207 | module will be called pktgen. | 208 | module will be called pktgen. |
208 | 209 | ||
209 | source "net/netfilter/Kconfig" | ||
210 | |||
211 | endmenu | 210 | endmenu |
212 | 211 | ||
213 | endmenu | 212 | endmenu |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 2d52fee63a8c..d8e36b775125 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -214,9 +214,11 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) | |||
214 | .tos = RT_TOS(iph->tos)} }, .proto = 0}; | 214 | .tos = RT_TOS(iph->tos)} }, .proto = 0}; |
215 | 215 | ||
216 | if (!ip_route_output_key(&rt, &fl)) { | 216 | if (!ip_route_output_key(&rt, &fl)) { |
217 | /* Bridged-and-DNAT'ed traffic doesn't | 217 | /* - Bridged-and-DNAT'ed traffic doesn't |
218 | * require ip_forwarding. */ | 218 | * require ip_forwarding. |
219 | if (((struct dst_entry *)rt)->dev == dev) { | 219 | * - Deal with redirected traffic. */ |
220 | if (((struct dst_entry *)rt)->dev == dev || | ||
221 | rt->rt_type == RTN_LOCAL) { | ||
220 | skb->dst = (struct dst_entry *)rt; | 222 | skb->dst = (struct dst_entry *)rt; |
221 | goto bridged_dnat; | 223 | goto bridged_dnat; |
222 | } | 224 | } |
diff --git a/net/dccp/Makefile b/net/dccp/Makefile index fb97bb042455..344a8da153fc 100644 --- a/net/dccp/Makefile +++ b/net/dccp/Makefile | |||
@@ -3,6 +3,8 @@ obj-$(CONFIG_IP_DCCP) += dccp.o | |||
3 | dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o \ | 3 | dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o \ |
4 | timer.o | 4 | timer.o |
5 | 5 | ||
6 | dccp-$(CONFIG_IP_DCCP_ACKVEC) += ackvec.o | ||
7 | |||
6 | obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o | 8 | obj-$(CONFIG_INET_DCCP_DIAG) += dccp_diag.o |
7 | 9 | ||
8 | dccp_diag-y := diag.o | 10 | dccp_diag-y := diag.o |
diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c new file mode 100644 index 000000000000..6530283eafca --- /dev/null +++ b/net/dccp/ackvec.c | |||
@@ -0,0 +1,419 @@ | |||
1 | /* | ||
2 | * net/dccp/ackvec.c | ||
3 | * | ||
4 | * An implementation of the DCCP protocol | ||
5 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; version 2 of the License; | ||
10 | */ | ||
11 | |||
12 | #include "ackvec.h" | ||
13 | #include "dccp.h" | ||
14 | |||
15 | #include <linux/dccp.h> | ||
16 | #include <linux/skbuff.h> | ||
17 | |||
18 | #include <net/sock.h> | ||
19 | |||
20 | int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb) | ||
21 | { | ||
22 | struct dccp_sock *dp = dccp_sk(sk); | ||
23 | struct dccp_ackvec *av = dp->dccps_hc_rx_ackvec; | ||
24 | int len = av->dccpav_vec_len + 2; | ||
25 | struct timeval now; | ||
26 | u32 elapsed_time; | ||
27 | unsigned char *to, *from; | ||
28 | |||
29 | dccp_timestamp(sk, &now); | ||
30 | elapsed_time = timeval_delta(&now, &av->dccpav_time) / 10; | ||
31 | |||
32 | if (elapsed_time != 0) | ||
33 | dccp_insert_option_elapsed_time(sk, skb, elapsed_time); | ||
34 | |||
35 | if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) | ||
36 | return -1; | ||
37 | |||
38 | /* | ||
39 | * XXX: now we have just one ack vector sent record, so | ||
40 | * we have to wait for it to be cleared. | ||
41 | * | ||
42 | * Of course this is not acceptable, but this is just for | ||
43 | * basic testing now. | ||
44 | */ | ||
45 | if (av->dccpav_ack_seqno != DCCP_MAX_SEQNO + 1) | ||
46 | return -1; | ||
47 | |||
48 | DCCP_SKB_CB(skb)->dccpd_opt_len += len; | ||
49 | |||
50 | to = skb_push(skb, len); | ||
51 | *to++ = DCCPO_ACK_VECTOR_0; | ||
52 | *to++ = len; | ||
53 | |||
54 | len = av->dccpav_vec_len; | ||
55 | from = av->dccpav_buf + av->dccpav_buf_head; | ||
56 | |||
57 | /* Check if buf_head wraps */ | ||
58 | if (av->dccpav_buf_head + len > av->dccpav_vec_len) { | ||
59 | const u32 tailsize = (av->dccpav_vec_len - av->dccpav_buf_head); | ||
60 | |||
61 | memcpy(to, from, tailsize); | ||
62 | to += tailsize; | ||
63 | len -= tailsize; | ||
64 | from = av->dccpav_buf; | ||
65 | } | ||
66 | |||
67 | memcpy(to, from, len); | ||
68 | /* | ||
69 | * From draft-ietf-dccp-spec-11.txt: | ||
70 | * | ||
71 | * For each acknowledgement it sends, the HC-Receiver will add an | ||
72 | * acknowledgement record. ack_seqno will equal the HC-Receiver | ||
73 | * sequence number it used for the ack packet; ack_ptr will equal | ||
74 | * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will | ||
75 | * equal buf_nonce. | ||
76 | * | ||
77 | * This implemention uses just one ack record for now. | ||
78 | */ | ||
79 | av->dccpav_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq; | ||
80 | av->dccpav_ack_ptr = av->dccpav_buf_head; | ||
81 | av->dccpav_ack_ackno = av->dccpav_buf_ackno; | ||
82 | av->dccpav_ack_nonce = av->dccpav_buf_nonce; | ||
83 | av->dccpav_sent_len = av->dccpav_vec_len; | ||
84 | |||
85 | dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, " | ||
86 | "ack_ackno=%llu\n", | ||
87 | debug_prefix, av->dccpav_sent_len, | ||
88 | (unsigned long long)av->dccpav_ack_seqno, | ||
89 | (unsigned long long)av->dccpav_ack_ackno); | ||
90 | return -1; | ||
91 | } | ||
92 | |||
93 | struct dccp_ackvec *dccp_ackvec_alloc(const unsigned int len, | ||
94 | const unsigned int __nocast priority) | ||
95 | { | ||
96 | struct dccp_ackvec *av = kmalloc(sizeof(*av) + len, priority); | ||
97 | |||
98 | if (av != NULL) { | ||
99 | av->dccpav_buf_len = len; | ||
100 | av->dccpav_buf_head = | ||
101 | av->dccpav_buf_tail = av->dccpav_buf_len - 1; | ||
102 | av->dccpav_buf_ackno = | ||
103 | av->dccpav_ack_ackno = av->dccpav_ack_seqno = ~0LLU; | ||
104 | av->dccpav_buf_nonce = av->dccpav_buf_nonce = 0; | ||
105 | av->dccpav_ack_ptr = 0; | ||
106 | av->dccpav_time.tv_sec = 0; | ||
107 | av->dccpav_time.tv_usec = 0; | ||
108 | av->dccpav_sent_len = av->dccpav_vec_len = 0; | ||
109 | } | ||
110 | |||
111 | return av; | ||
112 | } | ||
113 | |||
114 | void dccp_ackvec_free(struct dccp_ackvec *av) | ||
115 | { | ||
116 | kfree(av); | ||
117 | } | ||
118 | |||
119 | static inline u8 dccp_ackvec_state(const struct dccp_ackvec *av, | ||
120 | const unsigned int index) | ||
121 | { | ||
122 | return av->dccpav_buf[index] & DCCP_ACKVEC_STATE_MASK; | ||
123 | } | ||
124 | |||
125 | static inline u8 dccp_ackvec_len(const struct dccp_ackvec *av, | ||
126 | const unsigned int index) | ||
127 | { | ||
128 | return av->dccpav_buf[index] & DCCP_ACKVEC_LEN_MASK; | ||
129 | } | ||
130 | |||
131 | /* | ||
132 | * If several packets are missing, the HC-Receiver may prefer to enter multiple | ||
133 | * bytes with run length 0, rather than a single byte with a larger run length; | ||
134 | * this simplifies table updates if one of the missing packets arrives. | ||
135 | */ | ||
136 | static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av, | ||
137 | const unsigned int packets, | ||
138 | const unsigned char state) | ||
139 | { | ||
140 | unsigned int gap; | ||
141 | signed long new_head; | ||
142 | |||
143 | if (av->dccpav_vec_len + packets > av->dccpav_buf_len) | ||
144 | return -ENOBUFS; | ||
145 | |||
146 | gap = packets - 1; | ||
147 | new_head = av->dccpav_buf_head - packets; | ||
148 | |||
149 | if (new_head < 0) { | ||
150 | if (gap > 0) { | ||
151 | memset(av->dccpav_buf, DCCP_ACKVEC_STATE_NOT_RECEIVED, | ||
152 | gap + new_head + 1); | ||
153 | gap = -new_head; | ||
154 | } | ||
155 | new_head += av->dccpav_buf_len; | ||
156 | } | ||
157 | |||
158 | av->dccpav_buf_head = new_head; | ||
159 | |||
160 | if (gap > 0) | ||
161 | memset(av->dccpav_buf + av->dccpav_buf_head + 1, | ||
162 | DCCP_ACKVEC_STATE_NOT_RECEIVED, gap); | ||
163 | |||
164 | av->dccpav_buf[av->dccpav_buf_head] = state; | ||
165 | av->dccpav_vec_len += packets; | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | /* | ||
170 | * Implements the draft-ietf-dccp-spec-11.txt Appendix A | ||
171 | */ | ||
172 | int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, | ||
173 | const u64 ackno, const u8 state) | ||
174 | { | ||
175 | /* | ||
176 | * Check at the right places if the buffer is full, if it is, tell the | ||
177 | * caller to start dropping packets till the HC-Sender acks our ACK | ||
178 | * vectors, when we will free up space in dccpav_buf. | ||
179 | * | ||
180 | * We may well decide to do buffer compression, etc, but for now lets | ||
181 | * just drop. | ||
182 | * | ||
183 | * From Appendix A: | ||
184 | * | ||
185 | * Of course, the circular buffer may overflow, either when the | ||
186 | * HC-Sender is sending data at a very high rate, when the | ||
187 | * HC-Receiver's acknowledgements are not reaching the HC-Sender, | ||
188 | * or when the HC-Sender is forgetting to acknowledge those acks | ||
189 | * (so the HC-Receiver is unable to clean up old state). In this | ||
190 | * case, the HC-Receiver should either compress the buffer (by | ||
191 | * increasing run lengths when possible), transfer its state to | ||
192 | * a larger buffer, or, as a last resort, drop all received | ||
193 | * packets, without processing them whatsoever, until its buffer | ||
194 | * shrinks again. | ||
195 | */ | ||
196 | |||
197 | /* See if this is the first ackno being inserted */ | ||
198 | if (av->dccpav_vec_len == 0) { | ||
199 | av->dccpav_buf[av->dccpav_buf_head] = state; | ||
200 | av->dccpav_vec_len = 1; | ||
201 | } else if (after48(ackno, av->dccpav_buf_ackno)) { | ||
202 | const u64 delta = dccp_delta_seqno(av->dccpav_buf_ackno, | ||
203 | ackno); | ||
204 | |||
205 | /* | ||
206 | * Look if the state of this packet is the same as the | ||
207 | * previous ackno and if so if we can bump the head len. | ||
208 | */ | ||
209 | if (delta == 1 && | ||
210 | dccp_ackvec_state(av, av->dccpav_buf_head) == state && | ||
211 | (dccp_ackvec_len(av, av->dccpav_buf_head) < | ||
212 | DCCP_ACKVEC_LEN_MASK)) | ||
213 | av->dccpav_buf[av->dccpav_buf_head]++; | ||
214 | else if (dccp_ackvec_set_buf_head_state(av, delta, state)) | ||
215 | return -ENOBUFS; | ||
216 | } else { | ||
217 | /* | ||
218 | * A.1.2. Old Packets | ||
219 | * | ||
220 | * When a packet with Sequence Number S arrives, and | ||
221 | * S <= buf_ackno, the HC-Receiver will scan the table | ||
222 | * for the byte corresponding to S. (Indexing structures | ||
223 | * could reduce the complexity of this scan.) | ||
224 | */ | ||
225 | u64 delta = dccp_delta_seqno(ackno, av->dccpav_buf_ackno); | ||
226 | unsigned int index = av->dccpav_buf_head; | ||
227 | |||
228 | while (1) { | ||
229 | const u8 len = dccp_ackvec_len(av, index); | ||
230 | const u8 state = dccp_ackvec_state(av, index); | ||
231 | /* | ||
232 | * valid packets not yet in dccpav_buf have a reserved | ||
233 | * entry, with a len equal to 0. | ||
234 | */ | ||
235 | if (state == DCCP_ACKVEC_STATE_NOT_RECEIVED && | ||
236 | len == 0 && delta == 0) { /* Found our | ||
237 | reserved seat! */ | ||
238 | dccp_pr_debug("Found %llu reserved seat!\n", | ||
239 | (unsigned long long)ackno); | ||
240 | av->dccpav_buf[index] = state; | ||
241 | goto out; | ||
242 | } | ||
243 | /* len == 0 means one packet */ | ||
244 | if (delta < len + 1) | ||
245 | goto out_duplicate; | ||
246 | |||
247 | delta -= len + 1; | ||
248 | if (++index == av->dccpav_buf_len) | ||
249 | index = 0; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | av->dccpav_buf_ackno = ackno; | ||
254 | dccp_timestamp(sk, &av->dccpav_time); | ||
255 | out: | ||
256 | dccp_pr_debug(""); | ||
257 | return 0; | ||
258 | |||
259 | out_duplicate: | ||
260 | /* Duplicate packet */ | ||
261 | dccp_pr_debug("Received a dup or already considered lost " | ||
262 | "packet: %llu\n", (unsigned long long)ackno); | ||
263 | return -EILSEQ; | ||
264 | } | ||
265 | |||
266 | #ifdef CONFIG_IP_DCCP_DEBUG | ||
267 | void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len) | ||
268 | { | ||
269 | if (!dccp_debug) | ||
270 | return; | ||
271 | |||
272 | printk("ACK vector len=%d, ackno=%llu |", len, | ||
273 | (unsigned long long)ackno); | ||
274 | |||
275 | while (len--) { | ||
276 | const u8 state = (*vector & DCCP_ACKVEC_STATE_MASK) >> 6; | ||
277 | const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; | ||
278 | |||
279 | printk("%d,%d|", state, rl); | ||
280 | ++vector; | ||
281 | } | ||
282 | |||
283 | printk("\n"); | ||
284 | } | ||
285 | |||
286 | void dccp_ackvec_print(const struct dccp_ackvec *av) | ||
287 | { | ||
288 | dccp_ackvector_print(av->dccpav_buf_ackno, | ||
289 | av->dccpav_buf + av->dccpav_buf_head, | ||
290 | av->dccpav_vec_len); | ||
291 | } | ||
292 | #endif | ||
293 | |||
294 | static void dccp_ackvec_trow_away_ack_record(struct dccp_ackvec *av) | ||
295 | { | ||
296 | /* | ||
297 | * As we're keeping track of the ack vector size (dccpav_vec_len) and | ||
298 | * the sent ack vector size (dccpav_sent_len) we don't need | ||
299 | * dccpav_buf_tail at all, but keep this code here as in the future | ||
300 | * we'll implement a vector of ack records, as suggested in | ||
301 | * draft-ietf-dccp-spec-11.txt Appendix A. -acme | ||
302 | */ | ||
303 | #if 0 | ||
304 | av->dccpav_buf_tail = av->dccpav_ack_ptr + 1; | ||
305 | if (av->dccpav_buf_tail >= av->dccpav_vec_len) | ||
306 | av->dccpav_buf_tail -= av->dccpav_vec_len; | ||
307 | #endif | ||
308 | av->dccpav_vec_len -= av->dccpav_sent_len; | ||
309 | } | ||
310 | |||
311 | void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, struct sock *sk, | ||
312 | const u64 ackno) | ||
313 | { | ||
314 | /* Check if we actually sent an ACK vector */ | ||
315 | if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1) | ||
316 | return; | ||
317 | |||
318 | if (ackno == av->dccpav_ack_seqno) { | ||
319 | #ifdef CONFIG_IP_DCCP_DEBUG | ||
320 | struct dccp_sock *dp = dccp_sk(sk); | ||
321 | const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? | ||
322 | "CLIENT rx ack: " : "server rx ack: "; | ||
323 | #endif | ||
324 | dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, " | ||
325 | "ack_ackno=%llu, ACKED!\n", | ||
326 | debug_prefix, 1, | ||
327 | (unsigned long long)av->dccpav_ack_seqno, | ||
328 | (unsigned long long)av->dccpav_ack_ackno); | ||
329 | dccp_ackvec_trow_away_ack_record(av); | ||
330 | av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | static void dccp_ackvec_check_rcv_ackvector(struct dccp_ackvec *av, | ||
335 | struct sock *sk, u64 ackno, | ||
336 | const unsigned char len, | ||
337 | const unsigned char *vector) | ||
338 | { | ||
339 | unsigned char i; | ||
340 | |||
341 | /* Check if we actually sent an ACK vector */ | ||
342 | if (av->dccpav_ack_seqno == DCCP_MAX_SEQNO + 1) | ||
343 | return; | ||
344 | /* | ||
345 | * We're in the receiver half connection, so if the received an ACK | ||
346 | * vector ackno (e.g. 50) before dccpav_ack_seqno (e.g. 52), we're | ||
347 | * not interested. | ||
348 | * | ||
349 | * Extra explanation with example: | ||
350 | * | ||
351 | * if we received an ACK vector with ackno 50, it can only be acking | ||
352 | * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent). | ||
353 | */ | ||
354 | /* dccp_pr_debug("is %llu < %llu? ", ackno, av->dccpav_ack_seqno); */ | ||
355 | if (before48(ackno, av->dccpav_ack_seqno)) { | ||
356 | /* dccp_pr_debug_cat("yes\n"); */ | ||
357 | return; | ||
358 | } | ||
359 | /* dccp_pr_debug_cat("no\n"); */ | ||
360 | |||
361 | i = len; | ||
362 | while (i--) { | ||
363 | const u8 rl = *vector & DCCP_ACKVEC_LEN_MASK; | ||
364 | u64 ackno_end_rl; | ||
365 | |||
366 | dccp_set_seqno(&ackno_end_rl, ackno - rl); | ||
367 | |||
368 | /* | ||
369 | * dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl, | ||
370 | * av->dccpav_ack_seqno, ackno); | ||
371 | */ | ||
372 | if (between48(av->dccpav_ack_seqno, ackno_end_rl, ackno)) { | ||
373 | const u8 state = (*vector & | ||
374 | DCCP_ACKVEC_STATE_MASK) >> 6; | ||
375 | /* dccp_pr_debug_cat("yes\n"); */ | ||
376 | |||
377 | if (state != DCCP_ACKVEC_STATE_NOT_RECEIVED) { | ||
378 | #ifdef CONFIG_IP_DCCP_DEBUG | ||
379 | struct dccp_sock *dp = dccp_sk(sk); | ||
380 | const char *debug_prefix = | ||
381 | dp->dccps_role == DCCP_ROLE_CLIENT ? | ||
382 | "CLIENT rx ack: " : "server rx ack: "; | ||
383 | #endif | ||
384 | dccp_pr_debug("%sACK vector 0, len=%d, " | ||
385 | "ack_seqno=%llu, ack_ackno=%llu, " | ||
386 | "ACKED!\n", | ||
387 | debug_prefix, len, | ||
388 | (unsigned long long) | ||
389 | av->dccpav_ack_seqno, | ||
390 | (unsigned long long) | ||
391 | av->dccpav_ack_ackno); | ||
392 | dccp_ackvec_trow_away_ack_record(av); | ||
393 | } | ||
394 | /* | ||
395 | * If dccpav_ack_seqno was not received, no problem | ||
396 | * we'll send another ACK vector. | ||
397 | */ | ||
398 | av->dccpav_ack_seqno = DCCP_MAX_SEQNO + 1; | ||
399 | break; | ||
400 | } | ||
401 | /* dccp_pr_debug_cat("no\n"); */ | ||
402 | |||
403 | dccp_set_seqno(&ackno, ackno_end_rl - 1); | ||
404 | ++vector; | ||
405 | } | ||
406 | } | ||
407 | |||
408 | int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, | ||
409 | const u8 opt, const u8 *value, const u8 len) | ||
410 | { | ||
411 | if (len > DCCP_MAX_ACKVEC_LEN) | ||
412 | return -1; | ||
413 | |||
414 | /* dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, value, len); */ | ||
415 | dccp_ackvec_check_rcv_ackvector(dccp_sk(sk)->dccps_hc_rx_ackvec, sk, | ||
416 | DCCP_SKB_CB(skb)->dccpd_ack_seq, | ||
417 | len, value); | ||
418 | return 0; | ||
419 | } | ||
diff --git a/net/dccp/ackvec.h b/net/dccp/ackvec.h new file mode 100644 index 000000000000..8ca51c9191f7 --- /dev/null +++ b/net/dccp/ackvec.h | |||
@@ -0,0 +1,133 @@ | |||
1 | #ifndef _ACKVEC_H | ||
2 | #define _ACKVEC_H | ||
3 | /* | ||
4 | * net/dccp/ackvec.h | ||
5 | * | ||
6 | * An implementation of the DCCP protocol | ||
7 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@mandriva.com> | ||
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 version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/compiler.h> | ||
16 | #include <linux/time.h> | ||
17 | #include <linux/types.h> | ||
18 | |||
19 | /* Read about the ECN nonce to see why it is 253 */ | ||
20 | #define DCCP_MAX_ACKVEC_LEN 253 | ||
21 | |||
22 | #define DCCP_ACKVEC_STATE_RECEIVED 0 | ||
23 | #define DCCP_ACKVEC_STATE_ECN_MARKED (1 << 6) | ||
24 | #define DCCP_ACKVEC_STATE_NOT_RECEIVED (3 << 6) | ||
25 | |||
26 | #define DCCP_ACKVEC_STATE_MASK 0xC0 /* 11000000 */ | ||
27 | #define DCCP_ACKVEC_LEN_MASK 0x3F /* 00111111 */ | ||
28 | |||
29 | /** struct dccp_ackvec - ack vector | ||
30 | * | ||
31 | * This data structure is the one defined in the DCCP draft | ||
32 | * Appendix A. | ||
33 | * | ||
34 | * @dccpav_buf_head - circular buffer head | ||
35 | * @dccpav_buf_tail - circular buffer tail | ||
36 | * @dccpav_buf_ackno - ack # of the most recent packet acknowledgeable in the | ||
37 | * buffer (i.e. %dccpav_buf_head) | ||
38 | * @dccpav_buf_nonce - the one-bit sum of the ECN Nonces on all packets acked | ||
39 | * by the buffer with State 0 | ||
40 | * | ||
41 | * Additionally, the HC-Receiver must keep some information about the | ||
42 | * Ack Vectors it has recently sent. For each packet sent carrying an | ||
43 | * Ack Vector, it remembers four variables: | ||
44 | * | ||
45 | * @dccpav_ack_seqno - the Sequence Number used for the packet | ||
46 | * (HC-Receiver seqno) | ||
47 | * @dccpav_ack_ptr - the value of buf_head at the time of acknowledgement. | ||
48 | * @dccpav_ack_ackno - the Acknowledgement Number used for the packet | ||
49 | * (HC-Sender seqno) | ||
50 | * @dccpav_ack_nonce - the one-bit sum of the ECN Nonces for all State 0. | ||
51 | * | ||
52 | * @dccpav_buf_len - circular buffer length | ||
53 | * @dccpav_time - the time in usecs | ||
54 | * @dccpav_buf - circular buffer of acknowledgeable packets | ||
55 | */ | ||
56 | struct dccp_ackvec { | ||
57 | unsigned int dccpav_buf_head; | ||
58 | unsigned int dccpav_buf_tail; | ||
59 | u64 dccpav_buf_ackno; | ||
60 | u64 dccpav_ack_seqno; | ||
61 | u64 dccpav_ack_ackno; | ||
62 | unsigned int dccpav_ack_ptr; | ||
63 | unsigned int dccpav_sent_len; | ||
64 | unsigned int dccpav_vec_len; | ||
65 | unsigned int dccpav_buf_len; | ||
66 | struct timeval dccpav_time; | ||
67 | u8 dccpav_buf_nonce; | ||
68 | u8 dccpav_ack_nonce; | ||
69 | u8 dccpav_buf[0]; | ||
70 | }; | ||
71 | |||
72 | struct sock; | ||
73 | struct sk_buff; | ||
74 | |||
75 | #ifdef CONFIG_IP_DCCP_ACKVEC | ||
76 | extern struct dccp_ackvec *dccp_ackvec_alloc(unsigned int len, | ||
77 | const unsigned int __nocast priority); | ||
78 | extern void dccp_ackvec_free(struct dccp_ackvec *av); | ||
79 | |||
80 | extern int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, | ||
81 | const u64 ackno, const u8 state); | ||
82 | |||
83 | extern void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, | ||
84 | struct sock *sk, const u64 ackno); | ||
85 | extern int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, | ||
86 | const u8 opt, const u8 *value, const u8 len); | ||
87 | |||
88 | extern int dccp_insert_option_ackvec(struct sock *sk, struct sk_buff *skb); | ||
89 | |||
90 | static inline int dccp_ackvec_pending(const struct dccp_ackvec *av) | ||
91 | { | ||
92 | return av->dccpav_sent_len != av->dccpav_vec_len; | ||
93 | } | ||
94 | #else /* CONFIG_IP_DCCP_ACKVEC */ | ||
95 | static inline struct dccp_ackvec *dccp_ackvec_alloc(unsigned int len, | ||
96 | const unsigned int __nocast priority) | ||
97 | { | ||
98 | return NULL; | ||
99 | } | ||
100 | |||
101 | static inline void dccp_ackvec_free(struct dccp_ackvec *av) | ||
102 | { | ||
103 | } | ||
104 | |||
105 | static inline int dccp_ackvec_add(struct dccp_ackvec *av, const struct sock *sk, | ||
106 | const u64 ackno, const u8 state) | ||
107 | { | ||
108 | return -1; | ||
109 | } | ||
110 | |||
111 | static inline void dccp_ackvec_check_rcv_ackno(struct dccp_ackvec *av, | ||
112 | struct sock *sk, const u64 ackno) | ||
113 | { | ||
114 | } | ||
115 | |||
116 | static inline int dccp_ackvec_parse(struct sock *sk, const struct sk_buff *skb, | ||
117 | const u8 opt, const u8 *value, const u8 len) | ||
118 | { | ||
119 | return -1; | ||
120 | } | ||
121 | |||
122 | static inline int dccp_insert_option_ackvec(const struct sock *sk, | ||
123 | const struct sk_buff *skb) | ||
124 | { | ||
125 | return -1; | ||
126 | } | ||
127 | |||
128 | static inline int dccp_ackvec_pending(const struct dccp_ackvec *av) | ||
129 | { | ||
130 | return 0; | ||
131 | } | ||
132 | #endif /* CONFIG_IP_DCCP_ACKVEC */ | ||
133 | #endif /* _ACKVEC_H */ | ||
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index 962f1e9e2f7e..21e55142dcd3 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h | |||
@@ -14,6 +14,7 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <net/sock.h> | 16 | #include <net/sock.h> |
17 | #include <linux/compiler.h> | ||
17 | #include <linux/dccp.h> | 18 | #include <linux/dccp.h> |
18 | #include <linux/list.h> | 19 | #include <linux/list.h> |
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
@@ -54,6 +55,14 @@ struct ccid { | |||
54 | struct tcp_info *info); | 55 | struct tcp_info *info); |
55 | void (*ccid_hc_tx_get_info)(struct sock *sk, | 56 | void (*ccid_hc_tx_get_info)(struct sock *sk, |
56 | struct tcp_info *info); | 57 | struct tcp_info *info); |
58 | int (*ccid_hc_rx_getsockopt)(struct sock *sk, | ||
59 | const int optname, int len, | ||
60 | u32 __user *optval, | ||
61 | int __user *optlen); | ||
62 | int (*ccid_hc_tx_getsockopt)(struct sock *sk, | ||
63 | const int optname, int len, | ||
64 | u32 __user *optval, | ||
65 | int __user *optlen); | ||
57 | }; | 66 | }; |
58 | 67 | ||
59 | extern int ccid_register(struct ccid *ccid); | 68 | extern int ccid_register(struct ccid *ccid); |
@@ -177,4 +186,26 @@ static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk, | |||
177 | if (ccid->ccid_hc_tx_get_info != NULL) | 186 | if (ccid->ccid_hc_tx_get_info != NULL) |
178 | ccid->ccid_hc_tx_get_info(sk, info); | 187 | ccid->ccid_hc_tx_get_info(sk, info); |
179 | } | 188 | } |
189 | |||
190 | static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk, | ||
191 | const int optname, int len, | ||
192 | u32 __user *optval, int __user *optlen) | ||
193 | { | ||
194 | int rc = -ENOPROTOOPT; | ||
195 | if (ccid->ccid_hc_rx_getsockopt != NULL) | ||
196 | rc = ccid->ccid_hc_rx_getsockopt(sk, optname, len, | ||
197 | optval, optlen); | ||
198 | return rc; | ||
199 | } | ||
200 | |||
201 | static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk, | ||
202 | const int optname, int len, | ||
203 | u32 __user *optval, int __user *optlen) | ||
204 | { | ||
205 | int rc = -ENOPROTOOPT; | ||
206 | if (ccid->ccid_hc_tx_getsockopt != NULL) | ||
207 | rc = ccid->ccid_hc_tx_getsockopt(sk, optname, len, | ||
208 | optval, optlen); | ||
209 | return rc; | ||
210 | } | ||
180 | #endif /* _CCID_H */ | 211 | #endif /* _CCID_H */ |
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 38aa84986118..aa68e0ab274d 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -1120,6 +1120,60 @@ static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info) | |||
1120 | info->tcpi_rtt = hctx->ccid3hctx_rtt; | 1120 | info->tcpi_rtt = hctx->ccid3hctx_rtt; |
1121 | } | 1121 | } |
1122 | 1122 | ||
1123 | static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len, | ||
1124 | u32 __user *optval, int __user *optlen) | ||
1125 | { | ||
1126 | const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); | ||
1127 | const void *val; | ||
1128 | |||
1129 | /* Listen socks doesn't have a private CCID block */ | ||
1130 | if (sk->sk_state == DCCP_LISTEN) | ||
1131 | return -EINVAL; | ||
1132 | |||
1133 | switch (optname) { | ||
1134 | case DCCP_SOCKOPT_CCID_RX_INFO: | ||
1135 | if (len < sizeof(hcrx->ccid3hcrx_tfrc)) | ||
1136 | return -EINVAL; | ||
1137 | len = sizeof(hcrx->ccid3hcrx_tfrc); | ||
1138 | val = &hcrx->ccid3hcrx_tfrc; | ||
1139 | break; | ||
1140 | default: | ||
1141 | return -ENOPROTOOPT; | ||
1142 | } | ||
1143 | |||
1144 | if (put_user(len, optlen) || copy_to_user(optval, val, len)) | ||
1145 | return -EFAULT; | ||
1146 | |||
1147 | return 0; | ||
1148 | } | ||
1149 | |||
1150 | static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, | ||
1151 | u32 __user *optval, int __user *optlen) | ||
1152 | { | ||
1153 | const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | ||
1154 | const void *val; | ||
1155 | |||
1156 | /* Listen socks doesn't have a private CCID block */ | ||
1157 | if (sk->sk_state == DCCP_LISTEN) | ||
1158 | return -EINVAL; | ||
1159 | |||
1160 | switch (optname) { | ||
1161 | case DCCP_SOCKOPT_CCID_TX_INFO: | ||
1162 | if (len < sizeof(hctx->ccid3hctx_tfrc)) | ||
1163 | return -EINVAL; | ||
1164 | len = sizeof(hctx->ccid3hctx_tfrc); | ||
1165 | val = &hctx->ccid3hctx_tfrc; | ||
1166 | break; | ||
1167 | default: | ||
1168 | return -ENOPROTOOPT; | ||
1169 | } | ||
1170 | |||
1171 | if (put_user(len, optlen) || copy_to_user(optval, val, len)) | ||
1172 | return -EFAULT; | ||
1173 | |||
1174 | return 0; | ||
1175 | } | ||
1176 | |||
1123 | static struct ccid ccid3 = { | 1177 | static struct ccid ccid3 = { |
1124 | .ccid_id = 3, | 1178 | .ccid_id = 3, |
1125 | .ccid_name = "ccid3", | 1179 | .ccid_name = "ccid3", |
@@ -1139,6 +1193,8 @@ static struct ccid ccid3 = { | |||
1139 | .ccid_hc_rx_packet_recv = ccid3_hc_rx_packet_recv, | 1193 | .ccid_hc_rx_packet_recv = ccid3_hc_rx_packet_recv, |
1140 | .ccid_hc_rx_get_info = ccid3_hc_rx_get_info, | 1194 | .ccid_hc_rx_get_info = ccid3_hc_rx_get_info, |
1141 | .ccid_hc_tx_get_info = ccid3_hc_tx_get_info, | 1195 | .ccid_hc_tx_get_info = ccid3_hc_tx_get_info, |
1196 | .ccid_hc_rx_getsockopt = ccid3_hc_rx_getsockopt, | ||
1197 | .ccid_hc_tx_getsockopt = ccid3_hc_tx_getsockopt, | ||
1142 | }; | 1198 | }; |
1143 | 1199 | ||
1144 | module_param(ccid3_debug, int, 0444); | 1200 | module_param(ccid3_debug, int, 0444); |
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index eb248778eea3..0bde4583d091 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/list.h> | 40 | #include <linux/list.h> |
41 | #include <linux/time.h> | 41 | #include <linux/time.h> |
42 | #include <linux/types.h> | 42 | #include <linux/types.h> |
43 | #include <linux/tfrc.h> | ||
43 | 44 | ||
44 | #define TFRC_MIN_PACKET_SIZE 16 | 45 | #define TFRC_MIN_PACKET_SIZE 16 |
45 | #define TFRC_STD_PACKET_SIZE 256 | 46 | #define TFRC_STD_PACKET_SIZE 256 |
@@ -93,12 +94,15 @@ struct ccid3_options_received { | |||
93 | * @ccid3hctx_hist - Packet history | 94 | * @ccid3hctx_hist - Packet history |
94 | */ | 95 | */ |
95 | struct ccid3_hc_tx_sock { | 96 | struct ccid3_hc_tx_sock { |
96 | u32 ccid3hctx_x; | 97 | struct tfrc_tx_info ccid3hctx_tfrc; |
97 | u32 ccid3hctx_x_recv; | 98 | #define ccid3hctx_x ccid3hctx_tfrc.tfrctx_x |
98 | u32 ccid3hctx_x_calc; | 99 | #define ccid3hctx_x_recv ccid3hctx_tfrc.tfrctx_x_recv |
100 | #define ccid3hctx_x_calc ccid3hctx_tfrc.tfrctx_x_calc | ||
101 | #define ccid3hctx_rtt ccid3hctx_tfrc.tfrctx_rtt | ||
102 | #define ccid3hctx_p ccid3hctx_tfrc.tfrctx_p | ||
103 | #define ccid3hctx_t_rto ccid3hctx_tfrc.tfrctx_rto | ||
104 | #define ccid3hctx_t_ipi ccid3hctx_tfrc.tfrctx_ipi | ||
99 | u16 ccid3hctx_s; | 105 | u16 ccid3hctx_s; |
100 | u32 ccid3hctx_rtt; | ||
101 | u32 ccid3hctx_p; | ||
102 | u8 ccid3hctx_state; | 106 | u8 ccid3hctx_state; |
103 | u8 ccid3hctx_last_win_count; | 107 | u8 ccid3hctx_last_win_count; |
104 | u8 ccid3hctx_idle; | 108 | u8 ccid3hctx_idle; |
@@ -106,19 +110,19 @@ struct ccid3_hc_tx_sock { | |||
106 | struct timer_list ccid3hctx_no_feedback_timer; | 110 | struct timer_list ccid3hctx_no_feedback_timer; |
107 | struct timeval ccid3hctx_t_ld; | 111 | struct timeval ccid3hctx_t_ld; |
108 | struct timeval ccid3hctx_t_nom; | 112 | struct timeval ccid3hctx_t_nom; |
109 | u32 ccid3hctx_t_rto; | ||
110 | u32 ccid3hctx_t_ipi; | ||
111 | u32 ccid3hctx_delta; | 113 | u32 ccid3hctx_delta; |
112 | struct list_head ccid3hctx_hist; | 114 | struct list_head ccid3hctx_hist; |
113 | struct ccid3_options_received ccid3hctx_options_received; | 115 | struct ccid3_options_received ccid3hctx_options_received; |
114 | }; | 116 | }; |
115 | 117 | ||
116 | struct ccid3_hc_rx_sock { | 118 | struct ccid3_hc_rx_sock { |
119 | struct tfrc_rx_info ccid3hcrx_tfrc; | ||
120 | #define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv | ||
121 | #define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt | ||
122 | #define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p | ||
117 | u64 ccid3hcrx_seqno_last_counter:48, | 123 | u64 ccid3hcrx_seqno_last_counter:48, |
118 | ccid3hcrx_state:8, | 124 | ccid3hcrx_state:8, |
119 | ccid3hcrx_last_counter:4; | 125 | ccid3hcrx_last_counter:4; |
120 | u32 ccid3hcrx_rtt; | ||
121 | u32 ccid3hcrx_p; | ||
122 | u32 ccid3hcrx_bytes_recv; | 126 | u32 ccid3hcrx_bytes_recv; |
123 | struct timeval ccid3hcrx_tstamp_last_feedback; | 127 | struct timeval ccid3hcrx_tstamp_last_feedback; |
124 | struct timeval ccid3hcrx_tstamp_last_ack; | 128 | struct timeval ccid3hcrx_tstamp_last_ack; |
@@ -127,7 +131,6 @@ struct ccid3_hc_rx_sock { | |||
127 | u16 ccid3hcrx_s; | 131 | u16 ccid3hcrx_s; |
128 | u32 ccid3hcrx_pinv; | 132 | u32 ccid3hcrx_pinv; |
129 | u32 ccid3hcrx_elapsed_time; | 133 | u32 ccid3hcrx_elapsed_time; |
130 | u32 ccid3hcrx_x_recv; | ||
131 | }; | 134 | }; |
132 | 135 | ||
133 | static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) | 136 | static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) |
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 95c4630b3b18..5871c027f9dc 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <net/snmp.h> | 17 | #include <net/snmp.h> |
18 | #include <net/sock.h> | 18 | #include <net/sock.h> |
19 | #include <net/tcp.h> | 19 | #include <net/tcp.h> |
20 | #include "ackvec.h" | ||
20 | 21 | ||
21 | #ifdef CONFIG_IP_DCCP_DEBUG | 22 | #ifdef CONFIG_IP_DCCP_DEBUG |
22 | extern int dccp_debug; | 23 | extern int dccp_debug; |
@@ -258,13 +259,12 @@ extern int dccp_v4_send_reset(struct sock *sk, | |||
258 | extern void dccp_send_close(struct sock *sk, const int active); | 259 | extern void dccp_send_close(struct sock *sk, const int active); |
259 | 260 | ||
260 | struct dccp_skb_cb { | 261 | struct dccp_skb_cb { |
261 | __u8 dccpd_type; | 262 | __u8 dccpd_type:4; |
262 | __u8 dccpd_reset_code; | 263 | __u8 dccpd_ccval:4; |
263 | __u8 dccpd_service; | 264 | __u8 dccpd_reset_code; |
264 | __u8 dccpd_ccval; | 265 | __u16 dccpd_opt_len; |
265 | __u64 dccpd_seq; | 266 | __u64 dccpd_seq; |
266 | __u64 dccpd_ack_seq; | 267 | __u64 dccpd_ack_seq; |
267 | int dccpd_opt_len; | ||
268 | }; | 268 | }; |
269 | 269 | ||
270 | #define DCCP_SKB_CB(__skb) ((struct dccp_skb_cb *)&((__skb)->cb[0])) | 270 | #define DCCP_SKB_CB(__skb) ((struct dccp_skb_cb *)&((__skb)->cb[0])) |
@@ -359,6 +359,17 @@ static inline void dccp_update_gss(struct sock *sk, u64 seq) | |||
359 | (dp->dccps_gss - | 359 | (dp->dccps_gss - |
360 | dp->dccps_options.dccpo_sequence_window + 1)); | 360 | dp->dccps_options.dccpo_sequence_window + 1)); |
361 | } | 361 | } |
362 | |||
363 | static inline int dccp_ack_pending(const struct sock *sk) | ||
364 | { | ||
365 | const struct dccp_sock *dp = dccp_sk(sk); | ||
366 | return dp->dccps_timestamp_echo != 0 || | ||
367 | #ifdef CONFIG_IP_DCCP_ACKVEC | ||
368 | (dp->dccps_options.dccpo_send_ack_vector && | ||
369 | dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) || | ||
370 | #endif | ||
371 | inet_csk_ack_scheduled(sk); | ||
372 | } | ||
362 | 373 | ||
363 | extern void dccp_insert_options(struct sock *sk, struct sk_buff *skb); | 374 | extern void dccp_insert_options(struct sock *sk, struct sk_buff *skb); |
364 | extern void dccp_insert_option_elapsed_time(struct sock *sk, | 375 | extern void dccp_insert_option_elapsed_time(struct sock *sk, |
@@ -372,65 +383,6 @@ extern void dccp_insert_option(struct sock *sk, struct sk_buff *skb, | |||
372 | 383 | ||
373 | extern struct socket *dccp_ctl_socket; | 384 | extern struct socket *dccp_ctl_socket; |
374 | 385 | ||
375 | #define DCCP_ACKPKTS_STATE_RECEIVED 0 | ||
376 | #define DCCP_ACKPKTS_STATE_ECN_MARKED (1 << 6) | ||
377 | #define DCCP_ACKPKTS_STATE_NOT_RECEIVED (3 << 6) | ||
378 | |||
379 | #define DCCP_ACKPKTS_STATE_MASK 0xC0 /* 11000000 */ | ||
380 | #define DCCP_ACKPKTS_LEN_MASK 0x3F /* 00111111 */ | ||
381 | |||
382 | /** struct dccp_ackpkts - acknowledgeable packets | ||
383 | * | ||
384 | * This data structure is the one defined in the DCCP draft | ||
385 | * Appendix A. | ||
386 | * | ||
387 | * @dccpap_buf_head - circular buffer head | ||
388 | * @dccpap_buf_tail - circular buffer tail | ||
389 | * @dccpap_buf_ackno - ack # of the most recent packet acknowledgeable in the | ||
390 | * buffer (i.e. %dccpap_buf_head) | ||
391 | * @dccpap_buf_nonce - the one-bit sum of the ECN Nonces on all packets acked | ||
392 | * by the buffer with State 0 | ||
393 | * | ||
394 | * Additionally, the HC-Receiver must keep some information about the | ||
395 | * Ack Vectors it has recently sent. For each packet sent carrying an | ||
396 | * Ack Vector, it remembers four variables: | ||
397 | * | ||
398 | * @dccpap_ack_seqno - the Sequence Number used for the packet | ||
399 | * (HC-Receiver seqno) | ||
400 | * @dccpap_ack_ptr - the value of buf_head at the time of acknowledgement. | ||
401 | * @dccpap_ack_ackno - the Acknowledgement Number used for the packet | ||
402 | * (HC-Sender seqno) | ||
403 | * @dccpap_ack_nonce - the one-bit sum of the ECN Nonces for all State 0. | ||
404 | * | ||
405 | * @dccpap_buf_len - circular buffer length | ||
406 | * @dccpap_time - the time in usecs | ||
407 | * @dccpap_buf - circular buffer of acknowledgeable packets | ||
408 | */ | ||
409 | struct dccp_ackpkts { | ||
410 | unsigned int dccpap_buf_head; | ||
411 | unsigned int dccpap_buf_tail; | ||
412 | u64 dccpap_buf_ackno; | ||
413 | u64 dccpap_ack_seqno; | ||
414 | u64 dccpap_ack_ackno; | ||
415 | unsigned int dccpap_ack_ptr; | ||
416 | unsigned int dccpap_buf_vector_len; | ||
417 | unsigned int dccpap_ack_vector_len; | ||
418 | unsigned int dccpap_buf_len; | ||
419 | struct timeval dccpap_time; | ||
420 | u8 dccpap_buf_nonce; | ||
421 | u8 dccpap_ack_nonce; | ||
422 | u8 dccpap_buf[0]; | ||
423 | }; | ||
424 | |||
425 | extern struct dccp_ackpkts * | ||
426 | dccp_ackpkts_alloc(unsigned int len, | ||
427 | const unsigned int __nocast priority); | ||
428 | extern void dccp_ackpkts_free(struct dccp_ackpkts *ap); | ||
429 | extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk, | ||
430 | u64 ackno, u8 state); | ||
431 | extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap, | ||
432 | struct sock *sk, u64 ackno); | ||
433 | |||
434 | extern void dccp_timestamp(const struct sock *sk, struct timeval *tv); | 386 | extern void dccp_timestamp(const struct sock *sk, struct timeval *tv); |
435 | 387 | ||
436 | static inline suseconds_t timeval_usecs(const struct timeval *tv) | 388 | static inline suseconds_t timeval_usecs(const struct timeval *tv) |
@@ -471,15 +423,4 @@ static inline void timeval_sub_usecs(struct timeval *tv, | |||
471 | } | 423 | } |
472 | } | 424 | } |
473 | 425 | ||
474 | #ifdef CONFIG_IP_DCCP_DEBUG | ||
475 | extern void dccp_ackvector_print(const u64 ackno, | ||
476 | const unsigned char *vector, int len); | ||
477 | extern void dccp_ackpkts_print(const struct dccp_ackpkts *ap); | ||
478 | #else | ||
479 | static inline void dccp_ackvector_print(const u64 ackno, | ||
480 | const unsigned char *vector, | ||
481 | int len) { } | ||
482 | static inline void dccp_ackpkts_print(const struct dccp_ackpkts *ap) { } | ||
483 | #endif | ||
484 | |||
485 | #endif /* _DCCP_H */ | 426 | #endif /* _DCCP_H */ |
diff --git a/net/dccp/input.c b/net/dccp/input.c index c74034cf7ede..1b6b2cb12376 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <net/sock.h> | 17 | #include <net/sock.h> |
18 | 18 | ||
19 | #include "ackvec.h" | ||
19 | #include "ccid.h" | 20 | #include "ccid.h" |
20 | #include "dccp.h" | 21 | #include "dccp.h" |
21 | 22 | ||
@@ -60,8 +61,8 @@ static inline void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb) | |||
60 | struct dccp_sock *dp = dccp_sk(sk); | 61 | struct dccp_sock *dp = dccp_sk(sk); |
61 | 62 | ||
62 | if (dp->dccps_options.dccpo_send_ack_vector) | 63 | if (dp->dccps_options.dccpo_send_ack_vector) |
63 | dccp_ackpkts_check_rcv_ackno(dp->dccps_hc_rx_ackpkts, sk, | 64 | dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk, |
64 | DCCP_SKB_CB(skb)->dccpd_ack_seq); | 65 | DCCP_SKB_CB(skb)->dccpd_ack_seq); |
65 | } | 66 | } |
66 | 67 | ||
67 | static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) | 68 | static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) |
@@ -164,37 +165,11 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, | |||
164 | if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) | 165 | if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) |
165 | dccp_event_ack_recv(sk, skb); | 166 | dccp_event_ack_recv(sk, skb); |
166 | 167 | ||
167 | /* | 168 | if (dp->dccps_options.dccpo_send_ack_vector && |
168 | * FIXME: check ECN to see if we should use | 169 | dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, |
169 | * DCCP_ACKPKTS_STATE_ECN_MARKED | 170 | DCCP_SKB_CB(skb)->dccpd_seq, |
170 | */ | 171 | DCCP_ACKVEC_STATE_RECEIVED)) |
171 | if (dp->dccps_options.dccpo_send_ack_vector) { | 172 | goto discard; |
172 | struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; | ||
173 | |||
174 | if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk, | ||
175 | DCCP_SKB_CB(skb)->dccpd_seq, | ||
176 | DCCP_ACKPKTS_STATE_RECEIVED)) { | ||
177 | LIMIT_NETDEBUG(KERN_WARNING "DCCP: acknowledgeable " | ||
178 | "packets buffer full!\n"); | ||
179 | ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1; | ||
180 | inet_csk_schedule_ack(sk); | ||
181 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, | ||
182 | TCP_DELACK_MIN, | ||
183 | DCCP_RTO_MAX); | ||
184 | goto discard; | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * FIXME: this activation is probably wrong, have to study more | ||
189 | * TCP delack machinery and how it fits into DCCP draft, but | ||
190 | * for now it kinda "works" 8) | ||
191 | */ | ||
192 | if (!inet_csk_ack_scheduled(sk)) { | ||
193 | inet_csk_schedule_ack(sk); | ||
194 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, 5 * HZ, | ||
195 | DCCP_RTO_MAX); | ||
196 | } | ||
197 | } | ||
198 | 173 | ||
199 | ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); | 174 | ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); |
200 | ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); | 175 | ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); |
@@ -384,9 +359,9 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, | |||
384 | } | 359 | } |
385 | 360 | ||
386 | out_invalid_packet: | 361 | out_invalid_packet: |
387 | return 1; /* dccp_v4_do_rcv will send a reset, but... | 362 | /* dccp_v4_do_rcv will send a reset */ |
388 | FIXME: the reset code should be | 363 | DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR; |
389 | DCCP_RESET_CODE_PACKET_ERROR */ | 364 | return 1; |
390 | } | 365 | } |
391 | 366 | ||
392 | static int dccp_rcv_respond_partopen_state_process(struct sock *sk, | 367 | static int dccp_rcv_respond_partopen_state_process(struct sock *sk, |
@@ -433,6 +408,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
433 | struct dccp_hdr *dh, unsigned len) | 408 | struct dccp_hdr *dh, unsigned len) |
434 | { | 409 | { |
435 | struct dccp_sock *dp = dccp_sk(sk); | 410 | struct dccp_sock *dp = dccp_sk(sk); |
411 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); | ||
436 | const int old_state = sk->sk_state; | 412 | const int old_state = sk->sk_state; |
437 | int queued = 0; | 413 | int queued = 0; |
438 | 414 | ||
@@ -473,7 +449,8 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
473 | if (dh->dccph_type == DCCP_PKT_RESET) | 449 | if (dh->dccph_type == DCCP_PKT_RESET) |
474 | goto discard; | 450 | goto discard; |
475 | 451 | ||
476 | /* Caller (dccp_v4_do_rcv) will send Reset(No Connection)*/ | 452 | /* Caller (dccp_v4_do_rcv) will send Reset */ |
453 | dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; | ||
477 | return 1; | 454 | return 1; |
478 | } | 455 | } |
479 | 456 | ||
@@ -487,36 +464,17 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
487 | if (dccp_parse_options(sk, skb)) | 464 | if (dccp_parse_options(sk, skb)) |
488 | goto discard; | 465 | goto discard; |
489 | 466 | ||
490 | if (DCCP_SKB_CB(skb)->dccpd_ack_seq != | 467 | if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) |
491 | DCCP_PKT_WITHOUT_ACK_SEQ) | ||
492 | dccp_event_ack_recv(sk, skb); | 468 | dccp_event_ack_recv(sk, skb); |
493 | 469 | ||
494 | ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); | 470 | ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); |
495 | ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); | 471 | ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); |
496 | 472 | ||
497 | /* | 473 | if (dp->dccps_options.dccpo_send_ack_vector && |
498 | * FIXME: check ECN to see if we should use | 474 | dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, |
499 | * DCCP_ACKPKTS_STATE_ECN_MARKED | 475 | DCCP_SKB_CB(skb)->dccpd_seq, |
500 | */ | 476 | DCCP_ACKVEC_STATE_RECEIVED)) |
501 | if (dp->dccps_options.dccpo_send_ack_vector) { | 477 | goto discard; |
502 | if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk, | ||
503 | DCCP_SKB_CB(skb)->dccpd_seq, | ||
504 | DCCP_ACKPKTS_STATE_RECEIVED)) | ||
505 | goto discard; | ||
506 | /* | ||
507 | * FIXME: this activation is probably wrong, have to | ||
508 | * study more TCP delack machinery and how it fits into | ||
509 | * DCCP draft, but for now it kinda "works" 8) | ||
510 | */ | ||
511 | if ((dp->dccps_hc_rx_ackpkts->dccpap_ack_seqno == | ||
512 | DCCP_MAX_SEQNO + 1) && | ||
513 | !inet_csk_ack_scheduled(sk)) { | ||
514 | inet_csk_schedule_ack(sk); | ||
515 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, | ||
516 | TCP_DELACK_MIN, | ||
517 | DCCP_RTO_MAX); | ||
518 | } | ||
519 | } | ||
520 | } | 478 | } |
521 | 479 | ||
522 | /* | 480 | /* |
@@ -551,8 +509,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
551 | dh->dccph_type == DCCP_PKT_REQUEST) || | 509 | dh->dccph_type == DCCP_PKT_REQUEST) || |
552 | (sk->sk_state == DCCP_RESPOND && | 510 | (sk->sk_state == DCCP_RESPOND && |
553 | dh->dccph_type == DCCP_PKT_DATA)) { | 511 | dh->dccph_type == DCCP_PKT_DATA)) { |
554 | dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, | 512 | dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC); |
555 | DCCP_PKT_SYNC); | ||
556 | goto discard; | 513 | goto discard; |
557 | } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) { | 514 | } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) { |
558 | dccp_rcv_closereq(sk, skb); | 515 | dccp_rcv_closereq(sk, skb); |
@@ -563,13 +520,13 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
563 | } | 520 | } |
564 | 521 | ||
565 | if (unlikely(dh->dccph_type == DCCP_PKT_SYNC)) { | 522 | if (unlikely(dh->dccph_type == DCCP_PKT_SYNC)) { |
566 | dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, | 523 | dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNCACK); |
567 | DCCP_PKT_SYNCACK); | ||
568 | goto discard; | 524 | goto discard; |
569 | } | 525 | } |
570 | 526 | ||
571 | switch (sk->sk_state) { | 527 | switch (sk->sk_state) { |
572 | case DCCP_CLOSED: | 528 | case DCCP_CLOSED: |
529 | dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; | ||
573 | return 1; | 530 | return 1; |
574 | 531 | ||
575 | case DCCP_REQUESTING: | 532 | case DCCP_REQUESTING: |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 2afaa464e7f0..40fe6afacde6 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <net/tcp_states.h> | 23 | #include <net/tcp_states.h> |
24 | #include <net/xfrm.h> | 24 | #include <net/xfrm.h> |
25 | 25 | ||
26 | #include "ackvec.h" | ||
26 | #include "ccid.h" | 27 | #include "ccid.h" |
27 | #include "dccp.h" | 28 | #include "dccp.h" |
28 | 29 | ||
@@ -246,6 +247,9 @@ static int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, | |||
246 | 247 | ||
247 | dp->dccps_role = DCCP_ROLE_CLIENT; | 248 | dp->dccps_role = DCCP_ROLE_CLIENT; |
248 | 249 | ||
250 | if (dccp_service_not_initialized(sk)) | ||
251 | return -EPROTO; | ||
252 | |||
249 | if (addr_len < sizeof(struct sockaddr_in)) | 253 | if (addr_len < sizeof(struct sockaddr_in)) |
250 | return -EINVAL; | 254 | return -EINVAL; |
251 | 255 | ||
@@ -661,6 +665,16 @@ static inline u64 dccp_v4_init_sequence(const struct sock *sk, | |||
661 | dccp_hdr(skb)->dccph_sport); | 665 | dccp_hdr(skb)->dccph_sport); |
662 | } | 666 | } |
663 | 667 | ||
668 | static inline int dccp_bad_service_code(const struct sock *sk, | ||
669 | const __u32 service) | ||
670 | { | ||
671 | const struct dccp_sock *dp = dccp_sk(sk); | ||
672 | |||
673 | if (dp->dccps_service == service) | ||
674 | return 0; | ||
675 | return !dccp_list_has_service(dp->dccps_service_list, service); | ||
676 | } | ||
677 | |||
664 | int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | 678 | int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) |
665 | { | 679 | { |
666 | struct inet_request_sock *ireq; | 680 | struct inet_request_sock *ireq; |
@@ -669,13 +683,22 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
669 | struct dccp_request_sock *dreq; | 683 | struct dccp_request_sock *dreq; |
670 | const __u32 saddr = skb->nh.iph->saddr; | 684 | const __u32 saddr = skb->nh.iph->saddr; |
671 | const __u32 daddr = skb->nh.iph->daddr; | 685 | const __u32 daddr = skb->nh.iph->daddr; |
686 | const __u32 service = dccp_hdr_request(skb)->dccph_req_service; | ||
687 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); | ||
688 | __u8 reset_code = DCCP_RESET_CODE_TOO_BUSY; | ||
672 | struct dst_entry *dst = NULL; | 689 | struct dst_entry *dst = NULL; |
673 | 690 | ||
674 | /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */ | 691 | /* Never answer to DCCP_PKT_REQUESTs send to broadcast or multicast */ |
675 | if (((struct rtable *)skb->dst)->rt_flags & | 692 | if (((struct rtable *)skb->dst)->rt_flags & |
676 | (RTCF_BROADCAST | RTCF_MULTICAST)) | 693 | (RTCF_BROADCAST | RTCF_MULTICAST)) { |
694 | reset_code = DCCP_RESET_CODE_NO_CONNECTION; | ||
677 | goto drop; | 695 | goto drop; |
696 | } | ||
678 | 697 | ||
698 | if (dccp_bad_service_code(sk, service)) { | ||
699 | reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE; | ||
700 | goto drop; | ||
701 | } | ||
679 | /* | 702 | /* |
680 | * TW buckets are converted to open requests without | 703 | * TW buckets are converted to open requests without |
681 | * limitations, they conserve resources and peer is | 704 | * limitations, they conserve resources and peer is |
@@ -718,9 +741,9 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
718 | * dccp_create_openreq_child. | 741 | * dccp_create_openreq_child. |
719 | */ | 742 | */ |
720 | dreq = dccp_rsk(req); | 743 | dreq = dccp_rsk(req); |
721 | dreq->dreq_isr = DCCP_SKB_CB(skb)->dccpd_seq; | 744 | dreq->dreq_isr = dcb->dccpd_seq; |
722 | dreq->dreq_iss = dccp_v4_init_sequence(sk, skb); | 745 | dreq->dreq_iss = dccp_v4_init_sequence(sk, skb); |
723 | dreq->dreq_service = dccp_hdr_request(skb)->dccph_req_service; | 746 | dreq->dreq_service = service; |
724 | 747 | ||
725 | if (dccp_v4_send_response(sk, req, dst)) | 748 | if (dccp_v4_send_response(sk, req, dst)) |
726 | goto drop_and_free; | 749 | goto drop_and_free; |
@@ -735,6 +758,7 @@ drop_and_free: | |||
735 | __reqsk_free(req); | 758 | __reqsk_free(req); |
736 | drop: | 759 | drop: |
737 | DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); | 760 | DCCP_INC_STATS_BH(DCCP_MIB_ATTEMPTFAILS); |
761 | dcb->dccpd_reset_code = reset_code; | ||
738 | return -1; | 762 | return -1; |
739 | } | 763 | } |
740 | 764 | ||
@@ -1005,7 +1029,6 @@ int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1005 | return 0; | 1029 | return 0; |
1006 | 1030 | ||
1007 | reset: | 1031 | reset: |
1008 | DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; | ||
1009 | dccp_v4_ctl_send_reset(skb); | 1032 | dccp_v4_ctl_send_reset(skb); |
1010 | discard: | 1033 | discard: |
1011 | kfree_skb(skb); | 1034 | kfree_skb(skb); |
@@ -1090,45 +1113,7 @@ int dccp_v4_rcv(struct sk_buff *skb) | |||
1090 | goto discard_it; | 1113 | goto discard_it; |
1091 | 1114 | ||
1092 | dh = dccp_hdr(skb); | 1115 | dh = dccp_hdr(skb); |
1093 | #if 0 | ||
1094 | /* | ||
1095 | * Use something like this to simulate some DATA/DATAACK loss to test | ||
1096 | * dccp_ackpkts_add, you'll get something like this on a session that | ||
1097 | * sends 10 DATA/DATAACK packets: | ||
1098 | * | ||
1099 | * ackpkts_print: 281473596467422 |0,0|3,0|0,0|3,0|0,0|3,0|0,0|3,0|0,1| | ||
1100 | * | ||
1101 | * 0, 0 means: DCCP_ACKPKTS_STATE_RECEIVED, RLE == just this packet | ||
1102 | * 0, 1 means: DCCP_ACKPKTS_STATE_RECEIVED, RLE == two adjacent packets | ||
1103 | * with the same state | ||
1104 | * 3, 0 means: DCCP_ACKPKTS_STATE_NOT_RECEIVED, RLE == just this packet | ||
1105 | * | ||
1106 | * So... | ||
1107 | * | ||
1108 | * 281473596467422 was received | ||
1109 | * 281473596467421 was not received | ||
1110 | * 281473596467420 was received | ||
1111 | * 281473596467419 was not received | ||
1112 | * 281473596467418 was received | ||
1113 | * 281473596467417 was not received | ||
1114 | * 281473596467416 was received | ||
1115 | * 281473596467415 was not received | ||
1116 | * 281473596467414 was received | ||
1117 | * 281473596467413 was received (this one was the 3way handshake | ||
1118 | * RESPONSE) | ||
1119 | * | ||
1120 | */ | ||
1121 | if (dh->dccph_type == DCCP_PKT_DATA || | ||
1122 | dh->dccph_type == DCCP_PKT_DATAACK) { | ||
1123 | static int discard = 0; | ||
1124 | 1116 | ||
1125 | if (discard) { | ||
1126 | discard = 0; | ||
1127 | goto discard_it; | ||
1128 | } | ||
1129 | discard = 1; | ||
1130 | } | ||
1131 | #endif | ||
1132 | DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb); | 1117 | DCCP_SKB_CB(skb)->dccpd_seq = dccp_hdr_seq(skb); |
1133 | DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type; | 1118 | DCCP_SKB_CB(skb)->dccpd_type = dh->dccph_type; |
1134 | 1119 | ||
@@ -1242,11 +1227,9 @@ static int dccp_v4_init_sock(struct sock *sk) | |||
1242 | do_gettimeofday(&dp->dccps_epoch); | 1227 | do_gettimeofday(&dp->dccps_epoch); |
1243 | 1228 | ||
1244 | if (dp->dccps_options.dccpo_send_ack_vector) { | 1229 | if (dp->dccps_options.dccpo_send_ack_vector) { |
1245 | dp->dccps_hc_rx_ackpkts = | 1230 | dp->dccps_hc_rx_ackvec = dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN, |
1246 | dccp_ackpkts_alloc(DCCP_MAX_ACK_VECTOR_LEN, | 1231 | GFP_KERNEL); |
1247 | GFP_KERNEL); | 1232 | if (dp->dccps_hc_rx_ackvec == NULL) |
1248 | |||
1249 | if (dp->dccps_hc_rx_ackpkts == NULL) | ||
1250 | return -ENOMEM; | 1233 | return -ENOMEM; |
1251 | } | 1234 | } |
1252 | 1235 | ||
@@ -1258,16 +1241,18 @@ static int dccp_v4_init_sock(struct sock *sk) | |||
1258 | * setsockopt(CCIDs-I-want/accept). -acme | 1241 | * setsockopt(CCIDs-I-want/accept). -acme |
1259 | */ | 1242 | */ |
1260 | if (likely(!dccp_ctl_socket_init)) { | 1243 | if (likely(!dccp_ctl_socket_init)) { |
1261 | dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_ccid, | 1244 | dp->dccps_hc_rx_ccid = ccid_init(dp->dccps_options.dccpo_rx_ccid, |
1262 | sk); | 1245 | sk); |
1263 | dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_ccid, | 1246 | dp->dccps_hc_tx_ccid = ccid_init(dp->dccps_options.dccpo_tx_ccid, |
1264 | sk); | 1247 | sk); |
1265 | if (dp->dccps_hc_rx_ccid == NULL || | 1248 | if (dp->dccps_hc_rx_ccid == NULL || |
1266 | dp->dccps_hc_tx_ccid == NULL) { | 1249 | dp->dccps_hc_tx_ccid == NULL) { |
1267 | ccid_exit(dp->dccps_hc_rx_ccid, sk); | 1250 | ccid_exit(dp->dccps_hc_rx_ccid, sk); |
1268 | ccid_exit(dp->dccps_hc_tx_ccid, sk); | 1251 | ccid_exit(dp->dccps_hc_tx_ccid, sk); |
1269 | dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts); | 1252 | if (dp->dccps_options.dccpo_send_ack_vector) { |
1270 | dp->dccps_hc_rx_ackpkts = NULL; | 1253 | dccp_ackvec_free(dp->dccps_hc_rx_ackvec); |
1254 | dp->dccps_hc_rx_ackvec = NULL; | ||
1255 | } | ||
1271 | dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; | 1256 | dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; |
1272 | return -ENOMEM; | 1257 | return -ENOMEM; |
1273 | } | 1258 | } |
@@ -1280,6 +1265,7 @@ static int dccp_v4_init_sock(struct sock *sk) | |||
1280 | sk->sk_write_space = dccp_write_space; | 1265 | sk->sk_write_space = dccp_write_space; |
1281 | dp->dccps_mss_cache = 536; | 1266 | dp->dccps_mss_cache = 536; |
1282 | dp->dccps_role = DCCP_ROLE_UNDEFINED; | 1267 | dp->dccps_role = DCCP_ROLE_UNDEFINED; |
1268 | dp->dccps_service = DCCP_SERVICE_INVALID_VALUE; | ||
1283 | 1269 | ||
1284 | return 0; | 1270 | return 0; |
1285 | } | 1271 | } |
@@ -1301,10 +1287,17 @@ static int dccp_v4_destroy_sock(struct sock *sk) | |||
1301 | if (inet_csk(sk)->icsk_bind_hash != NULL) | 1287 | if (inet_csk(sk)->icsk_bind_hash != NULL) |
1302 | inet_put_port(&dccp_hashinfo, sk); | 1288 | inet_put_port(&dccp_hashinfo, sk); |
1303 | 1289 | ||
1290 | if (dp->dccps_service_list != NULL) { | ||
1291 | kfree(dp->dccps_service_list); | ||
1292 | dp->dccps_service_list = NULL; | ||
1293 | } | ||
1294 | |||
1304 | ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); | 1295 | ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); |
1305 | ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); | 1296 | ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); |
1306 | dccp_ackpkts_free(dp->dccps_hc_rx_ackpkts); | 1297 | if (dp->dccps_options.dccpo_send_ack_vector) { |
1307 | dp->dccps_hc_rx_ackpkts = NULL; | 1298 | dccp_ackvec_free(dp->dccps_hc_rx_ackvec); |
1299 | dp->dccps_hc_rx_ackvec = NULL; | ||
1300 | } | ||
1308 | ccid_exit(dp->dccps_hc_rx_ccid, sk); | 1301 | ccid_exit(dp->dccps_hc_rx_ccid, sk); |
1309 | ccid_exit(dp->dccps_hc_tx_ccid, sk); | 1302 | ccid_exit(dp->dccps_hc_tx_ccid, sk); |
1310 | dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; | 1303 | dp->dccps_hc_rx_ccid = dp->dccps_hc_tx_ccid = NULL; |
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 18461bc04cbe..1393461898bb 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <net/xfrm.h> | 19 | #include <net/xfrm.h> |
20 | #include <net/inet_timewait_sock.h> | 20 | #include <net/inet_timewait_sock.h> |
21 | 21 | ||
22 | #include "ackvec.h" | ||
22 | #include "ccid.h" | 23 | #include "ccid.h" |
23 | #include "dccp.h" | 24 | #include "dccp.h" |
24 | 25 | ||
@@ -93,22 +94,24 @@ struct sock *dccp_create_openreq_child(struct sock *sk, | |||
93 | struct inet_connection_sock *newicsk = inet_csk(sk); | 94 | struct inet_connection_sock *newicsk = inet_csk(sk); |
94 | struct dccp_sock *newdp = dccp_sk(newsk); | 95 | struct dccp_sock *newdp = dccp_sk(newsk); |
95 | 96 | ||
96 | newdp->dccps_hc_rx_ackpkts = NULL; | 97 | newdp->dccps_role = DCCP_ROLE_SERVER; |
97 | newdp->dccps_role = DCCP_ROLE_SERVER; | 98 | newdp->dccps_hc_rx_ackvec = NULL; |
98 | newicsk->icsk_rto = DCCP_TIMEOUT_INIT; | 99 | newdp->dccps_service_list = NULL; |
100 | newdp->dccps_service = dreq->dreq_service; | ||
101 | newicsk->icsk_rto = DCCP_TIMEOUT_INIT; | ||
99 | do_gettimeofday(&newdp->dccps_epoch); | 102 | do_gettimeofday(&newdp->dccps_epoch); |
100 | 103 | ||
101 | if (newdp->dccps_options.dccpo_send_ack_vector) { | 104 | if (newdp->dccps_options.dccpo_send_ack_vector) { |
102 | newdp->dccps_hc_rx_ackpkts = | 105 | newdp->dccps_hc_rx_ackvec = |
103 | dccp_ackpkts_alloc(DCCP_MAX_ACK_VECTOR_LEN, | 106 | dccp_ackvec_alloc(DCCP_MAX_ACKVEC_LEN, |
104 | GFP_ATOMIC); | 107 | GFP_ATOMIC); |
105 | /* | 108 | /* |
106 | * XXX: We're using the same CCIDs set on the parent, | 109 | * XXX: We're using the same CCIDs set on the parent, |
107 | * i.e. sk_clone copied the master sock and left the | 110 | * i.e. sk_clone copied the master sock and left the |
108 | * CCID pointers for this child, that is why we do the | 111 | * CCID pointers for this child, that is why we do the |
109 | * __ccid_get calls. | 112 | * __ccid_get calls. |
110 | */ | 113 | */ |
111 | if (unlikely(newdp->dccps_hc_rx_ackpkts == NULL)) | 114 | if (unlikely(newdp->dccps_hc_rx_ackvec == NULL)) |
112 | goto out_free; | 115 | goto out_free; |
113 | } | 116 | } |
114 | 117 | ||
@@ -116,7 +119,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk, | |||
116 | newsk) != 0 || | 119 | newsk) != 0 || |
117 | ccid_hc_tx_init(newdp->dccps_hc_tx_ccid, | 120 | ccid_hc_tx_init(newdp->dccps_hc_tx_ccid, |
118 | newsk) != 0)) { | 121 | newsk) != 0)) { |
119 | dccp_ackpkts_free(newdp->dccps_hc_rx_ackpkts); | 122 | dccp_ackvec_free(newdp->dccps_hc_rx_ackvec); |
120 | ccid_hc_rx_exit(newdp->dccps_hc_rx_ccid, newsk); | 123 | ccid_hc_rx_exit(newdp->dccps_hc_rx_ccid, newsk); |
121 | ccid_hc_tx_exit(newdp->dccps_hc_tx_ccid, newsk); | 124 | ccid_hc_tx_exit(newdp->dccps_hc_tx_ccid, newsk); |
122 | out_free: | 125 | out_free: |
diff --git a/net/dccp/options.c b/net/dccp/options.c index d4c4242d8dd7..0a76426c9aea 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -18,19 +18,15 @@ | |||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
20 | 20 | ||
21 | #include "ackvec.h" | ||
21 | #include "ccid.h" | 22 | #include "ccid.h" |
22 | #include "dccp.h" | 23 | #include "dccp.h" |
23 | 24 | ||
24 | static void dccp_ackpkts_check_rcv_ackvector(struct dccp_ackpkts *ap, | ||
25 | struct sock *sk, | ||
26 | const u64 ackno, | ||
27 | const unsigned char len, | ||
28 | const unsigned char *vector); | ||
29 | |||
30 | /* stores the default values for new connection. may be changed with sysctl */ | 25 | /* stores the default values for new connection. may be changed with sysctl */ |
31 | static const struct dccp_options dccpo_default_values = { | 26 | static const struct dccp_options dccpo_default_values = { |
32 | .dccpo_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW, | 27 | .dccpo_sequence_window = DCCPF_INITIAL_SEQUENCE_WINDOW, |
33 | .dccpo_ccid = DCCPF_INITIAL_CCID, | 28 | .dccpo_rx_ccid = DCCPF_INITIAL_CCID, |
29 | .dccpo_tx_ccid = DCCPF_INITIAL_CCID, | ||
34 | .dccpo_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR, | 30 | .dccpo_send_ack_vector = DCCPF_INITIAL_SEND_ACK_VECTOR, |
35 | .dccpo_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT, | 31 | .dccpo_send_ndp_count = DCCPF_INITIAL_SEND_NDP_COUNT, |
36 | }; | 32 | }; |
@@ -113,25 +109,13 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
113 | opt_recv->dccpor_ndp); | 109 | opt_recv->dccpor_ndp); |
114 | break; | 110 | break; |
115 | case DCCPO_ACK_VECTOR_0: | 111 | case DCCPO_ACK_VECTOR_0: |
116 | if (len > DCCP_MAX_ACK_VECTOR_LEN) | 112 | case DCCPO_ACK_VECTOR_1: |
117 | goto out_invalid_option; | ||
118 | |||
119 | if (pkt_type == DCCP_PKT_DATA) | 113 | if (pkt_type == DCCP_PKT_DATA) |
120 | continue; | 114 | continue; |
121 | 115 | ||
122 | opt_recv->dccpor_ack_vector_len = len; | 116 | if (dp->dccps_options.dccpo_send_ack_vector && |
123 | opt_recv->dccpor_ack_vector_idx = value - options; | 117 | dccp_ackvec_parse(sk, skb, opt, value, len)) |
124 | 118 | goto out_invalid_option; | |
125 | dccp_pr_debug("%sACK vector 0, len=%d, ack_ackno=%llu\n", | ||
126 | debug_prefix, len, | ||
127 | (unsigned long long) | ||
128 | DCCP_SKB_CB(skb)->dccpd_ack_seq); | ||
129 | dccp_ackvector_print(DCCP_SKB_CB(skb)->dccpd_ack_seq, | ||
130 | value, len); | ||
131 | dccp_ackpkts_check_rcv_ackvector(dp->dccps_hc_rx_ackpkts, | ||
132 | sk, | ||
133 | DCCP_SKB_CB(skb)->dccpd_ack_seq, | ||
134 | len, value); | ||
135 | break; | 119 | break; |
136 | case DCCPO_TIMESTAMP: | 120 | case DCCPO_TIMESTAMP: |
137 | if (len != 4) | 121 | if (len != 4) |
@@ -352,86 +336,6 @@ void dccp_insert_option_elapsed_time(struct sock *sk, | |||
352 | 336 | ||
353 | EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time); | 337 | EXPORT_SYMBOL_GPL(dccp_insert_option_elapsed_time); |
354 | 338 | ||
355 | static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb) | ||
356 | { | ||
357 | struct dccp_sock *dp = dccp_sk(sk); | ||
358 | #ifdef CONFIG_IP_DCCP_DEBUG | ||
359 | const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? | ||
360 | "CLIENT TX opt: " : "server TX opt: "; | ||
361 | #endif | ||
362 | struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; | ||
363 | int len = ap->dccpap_buf_vector_len + 2; | ||
364 | struct timeval now; | ||
365 | u32 elapsed_time; | ||
366 | unsigned char *to, *from; | ||
367 | |||
368 | dccp_timestamp(sk, &now); | ||
369 | elapsed_time = timeval_delta(&now, &ap->dccpap_time) / 10; | ||
370 | |||
371 | if (elapsed_time != 0) | ||
372 | dccp_insert_option_elapsed_time(sk, skb, elapsed_time); | ||
373 | |||
374 | if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { | ||
375 | LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to " | ||
376 | "insert ACK Vector!\n"); | ||
377 | return; | ||
378 | } | ||
379 | |||
380 | /* | ||
381 | * XXX: now we have just one ack vector sent record, so | ||
382 | * we have to wait for it to be cleared. | ||
383 | * | ||
384 | * Of course this is not acceptable, but this is just for | ||
385 | * basic testing now. | ||
386 | */ | ||
387 | if (ap->dccpap_ack_seqno != DCCP_MAX_SEQNO + 1) | ||
388 | return; | ||
389 | |||
390 | DCCP_SKB_CB(skb)->dccpd_opt_len += len; | ||
391 | |||
392 | to = skb_push(skb, len); | ||
393 | *to++ = DCCPO_ACK_VECTOR_0; | ||
394 | *to++ = len; | ||
395 | |||
396 | len = ap->dccpap_buf_vector_len; | ||
397 | from = ap->dccpap_buf + ap->dccpap_buf_head; | ||
398 | |||
399 | /* Check if buf_head wraps */ | ||
400 | if (ap->dccpap_buf_head + len > ap->dccpap_buf_len) { | ||
401 | const unsigned int tailsize = (ap->dccpap_buf_len - | ||
402 | ap->dccpap_buf_head); | ||
403 | |||
404 | memcpy(to, from, tailsize); | ||
405 | to += tailsize; | ||
406 | len -= tailsize; | ||
407 | from = ap->dccpap_buf; | ||
408 | } | ||
409 | |||
410 | memcpy(to, from, len); | ||
411 | /* | ||
412 | * From draft-ietf-dccp-spec-11.txt: | ||
413 | * | ||
414 | * For each acknowledgement it sends, the HC-Receiver will add an | ||
415 | * acknowledgement record. ack_seqno will equal the HC-Receiver | ||
416 | * sequence number it used for the ack packet; ack_ptr will equal | ||
417 | * buf_head; ack_ackno will equal buf_ackno; and ack_nonce will | ||
418 | * equal buf_nonce. | ||
419 | * | ||
420 | * This implemention uses just one ack record for now. | ||
421 | */ | ||
422 | ap->dccpap_ack_seqno = DCCP_SKB_CB(skb)->dccpd_seq; | ||
423 | ap->dccpap_ack_ptr = ap->dccpap_buf_head; | ||
424 | ap->dccpap_ack_ackno = ap->dccpap_buf_ackno; | ||
425 | ap->dccpap_ack_nonce = ap->dccpap_buf_nonce; | ||
426 | ap->dccpap_ack_vector_len = ap->dccpap_buf_vector_len; | ||
427 | |||
428 | dccp_pr_debug("%sACK Vector 0, len=%d, ack_seqno=%llu, " | ||
429 | "ack_ackno=%llu\n", | ||
430 | debug_prefix, ap->dccpap_ack_vector_len, | ||
431 | (unsigned long long) ap->dccpap_ack_seqno, | ||
432 | (unsigned long long) ap->dccpap_ack_ackno); | ||
433 | } | ||
434 | |||
435 | void dccp_timestamp(const struct sock *sk, struct timeval *tv) | 339 | void dccp_timestamp(const struct sock *sk, struct timeval *tv) |
436 | { | 340 | { |
437 | const struct dccp_sock *dp = dccp_sk(sk); | 341 | const struct dccp_sock *dp = dccp_sk(sk); |
@@ -528,9 +432,8 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb) | |||
528 | 432 | ||
529 | if (!dccp_packet_without_ack(skb)) { | 433 | if (!dccp_packet_without_ack(skb)) { |
530 | if (dp->dccps_options.dccpo_send_ack_vector && | 434 | if (dp->dccps_options.dccpo_send_ack_vector && |
531 | (dp->dccps_hc_rx_ackpkts->dccpap_buf_ackno != | 435 | dccp_ackvec_pending(dp->dccps_hc_rx_ackvec)) |
532 | DCCP_MAX_SEQNO + 1)) | 436 | dccp_insert_option_ackvec(sk, skb); |
533 | dccp_insert_option_ack_vector(sk, skb); | ||
534 | if (dp->dccps_timestamp_echo != 0) | 437 | if (dp->dccps_timestamp_echo != 0) |
535 | dccp_insert_option_timestamp_echo(sk, skb); | 438 | dccp_insert_option_timestamp_echo(sk, skb); |
536 | } | 439 | } |
@@ -557,331 +460,3 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb) | |||
557 | } | 460 | } |
558 | } | 461 | } |
559 | } | 462 | } |
560 | |||
561 | struct dccp_ackpkts *dccp_ackpkts_alloc(const unsigned int len, | ||
562 | const unsigned int __nocast priority) | ||
563 | { | ||
564 | struct dccp_ackpkts *ap = kmalloc(sizeof(*ap) + len, priority); | ||
565 | |||
566 | if (ap != NULL) { | ||
567 | #ifdef CONFIG_IP_DCCP_DEBUG | ||
568 | memset(ap->dccpap_buf, 0xFF, len); | ||
569 | #endif | ||
570 | ap->dccpap_buf_len = len; | ||
571 | ap->dccpap_buf_head = | ||
572 | ap->dccpap_buf_tail = | ||
573 | ap->dccpap_buf_len - 1; | ||
574 | ap->dccpap_buf_ackno = | ||
575 | ap->dccpap_ack_ackno = | ||
576 | ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1; | ||
577 | ap->dccpap_buf_nonce = ap->dccpap_buf_nonce = 0; | ||
578 | ap->dccpap_ack_ptr = 0; | ||
579 | ap->dccpap_time.tv_sec = 0; | ||
580 | ap->dccpap_time.tv_usec = 0; | ||
581 | ap->dccpap_buf_vector_len = ap->dccpap_ack_vector_len = 0; | ||
582 | } | ||
583 | |||
584 | return ap; | ||
585 | } | ||
586 | |||
587 | void dccp_ackpkts_free(struct dccp_ackpkts *ap) | ||
588 | { | ||
589 | if (ap != NULL) { | ||
590 | #ifdef CONFIG_IP_DCCP_DEBUG | ||
591 | memset(ap, 0xFF, sizeof(*ap) + ap->dccpap_buf_len); | ||
592 | #endif | ||
593 | kfree(ap); | ||
594 | } | ||
595 | } | ||
596 | |||
597 | static inline u8 dccp_ackpkts_state(const struct dccp_ackpkts *ap, | ||
598 | const unsigned int index) | ||
599 | { | ||
600 | return ap->dccpap_buf[index] & DCCP_ACKPKTS_STATE_MASK; | ||
601 | } | ||
602 | |||
603 | static inline u8 dccp_ackpkts_len(const struct dccp_ackpkts *ap, | ||
604 | const unsigned int index) | ||
605 | { | ||
606 | return ap->dccpap_buf[index] & DCCP_ACKPKTS_LEN_MASK; | ||
607 | } | ||
608 | |||
609 | /* | ||
610 | * If several packets are missing, the HC-Receiver may prefer to enter multiple | ||
611 | * bytes with run length 0, rather than a single byte with a larger run length; | ||
612 | * this simplifies table updates if one of the missing packets arrives. | ||
613 | */ | ||
614 | static inline int dccp_ackpkts_set_buf_head_state(struct dccp_ackpkts *ap, | ||
615 | const unsigned int packets, | ||
616 | const unsigned char state) | ||
617 | { | ||
618 | unsigned int gap; | ||
619 | signed long new_head; | ||
620 | |||
621 | if (ap->dccpap_buf_vector_len + packets > ap->dccpap_buf_len) | ||
622 | return -ENOBUFS; | ||
623 | |||
624 | gap = packets - 1; | ||
625 | new_head = ap->dccpap_buf_head - packets; | ||
626 | |||
627 | if (new_head < 0) { | ||
628 | if (gap > 0) { | ||
629 | memset(ap->dccpap_buf, DCCP_ACKPKTS_STATE_NOT_RECEIVED, | ||
630 | gap + new_head + 1); | ||
631 | gap = -new_head; | ||
632 | } | ||
633 | new_head += ap->dccpap_buf_len; | ||
634 | } | ||
635 | |||
636 | ap->dccpap_buf_head = new_head; | ||
637 | |||
638 | if (gap > 0) | ||
639 | memset(ap->dccpap_buf + ap->dccpap_buf_head + 1, | ||
640 | DCCP_ACKPKTS_STATE_NOT_RECEIVED, gap); | ||
641 | |||
642 | ap->dccpap_buf[ap->dccpap_buf_head] = state; | ||
643 | ap->dccpap_buf_vector_len += packets; | ||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | /* | ||
648 | * Implements the draft-ietf-dccp-spec-11.txt Appendix A | ||
649 | */ | ||
650 | int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk, | ||
651 | u64 ackno, u8 state) | ||
652 | { | ||
653 | /* | ||
654 | * Check at the right places if the buffer is full, if it is, tell the | ||
655 | * caller to start dropping packets till the HC-Sender acks our ACK | ||
656 | * vectors, when we will free up space in dccpap_buf. | ||
657 | * | ||
658 | * We may well decide to do buffer compression, etc, but for now lets | ||
659 | * just drop. | ||
660 | * | ||
661 | * From Appendix A: | ||
662 | * | ||
663 | * Of course, the circular buffer may overflow, either when the | ||
664 | * HC-Sender is sending data at a very high rate, when the | ||
665 | * HC-Receiver's acknowledgements are not reaching the HC-Sender, | ||
666 | * or when the HC-Sender is forgetting to acknowledge those acks | ||
667 | * (so the HC-Receiver is unable to clean up old state). In this | ||
668 | * case, the HC-Receiver should either compress the buffer (by | ||
669 | * increasing run lengths when possible), transfer its state to | ||
670 | * a larger buffer, or, as a last resort, drop all received | ||
671 | * packets, without processing them whatsoever, until its buffer | ||
672 | * shrinks again. | ||
673 | */ | ||
674 | |||
675 | /* See if this is the first ackno being inserted */ | ||
676 | if (ap->dccpap_buf_vector_len == 0) { | ||
677 | ap->dccpap_buf[ap->dccpap_buf_head] = state; | ||
678 | ap->dccpap_buf_vector_len = 1; | ||
679 | } else if (after48(ackno, ap->dccpap_buf_ackno)) { | ||
680 | const u64 delta = dccp_delta_seqno(ap->dccpap_buf_ackno, | ||
681 | ackno); | ||
682 | |||
683 | /* | ||
684 | * Look if the state of this packet is the same as the | ||
685 | * previous ackno and if so if we can bump the head len. | ||
686 | */ | ||
687 | if (delta == 1 && | ||
688 | dccp_ackpkts_state(ap, ap->dccpap_buf_head) == state && | ||
689 | (dccp_ackpkts_len(ap, ap->dccpap_buf_head) < | ||
690 | DCCP_ACKPKTS_LEN_MASK)) | ||
691 | ap->dccpap_buf[ap->dccpap_buf_head]++; | ||
692 | else if (dccp_ackpkts_set_buf_head_state(ap, delta, state)) | ||
693 | return -ENOBUFS; | ||
694 | } else { | ||
695 | /* | ||
696 | * A.1.2. Old Packets | ||
697 | * | ||
698 | * When a packet with Sequence Number S arrives, and | ||
699 | * S <= buf_ackno, the HC-Receiver will scan the table | ||
700 | * for the byte corresponding to S. (Indexing structures | ||
701 | * could reduce the complexity of this scan.) | ||
702 | */ | ||
703 | u64 delta = dccp_delta_seqno(ackno, ap->dccpap_buf_ackno); | ||
704 | unsigned int index = ap->dccpap_buf_head; | ||
705 | |||
706 | while (1) { | ||
707 | const u8 len = dccp_ackpkts_len(ap, index); | ||
708 | const u8 state = dccp_ackpkts_state(ap, index); | ||
709 | /* | ||
710 | * valid packets not yet in dccpap_buf have a reserved | ||
711 | * entry, with a len equal to 0. | ||
712 | */ | ||
713 | if (state == DCCP_ACKPKTS_STATE_NOT_RECEIVED && | ||
714 | len == 0 && delta == 0) { /* Found our | ||
715 | reserved seat! */ | ||
716 | dccp_pr_debug("Found %llu reserved seat!\n", | ||
717 | (unsigned long long) ackno); | ||
718 | ap->dccpap_buf[index] = state; | ||
719 | goto out; | ||
720 | } | ||
721 | /* len == 0 means one packet */ | ||
722 | if (delta < len + 1) | ||
723 | goto out_duplicate; | ||
724 | |||
725 | delta -= len + 1; | ||
726 | if (++index == ap->dccpap_buf_len) | ||
727 | index = 0; | ||
728 | } | ||
729 | } | ||
730 | |||
731 | ap->dccpap_buf_ackno = ackno; | ||
732 | dccp_timestamp(sk, &ap->dccpap_time); | ||
733 | out: | ||
734 | dccp_pr_debug(""); | ||
735 | dccp_ackpkts_print(ap); | ||
736 | return 0; | ||
737 | |||
738 | out_duplicate: | ||
739 | /* Duplicate packet */ | ||
740 | dccp_pr_debug("Received a dup or already considered lost " | ||
741 | "packet: %llu\n", (unsigned long long) ackno); | ||
742 | return -EILSEQ; | ||
743 | } | ||
744 | |||
745 | #ifdef CONFIG_IP_DCCP_DEBUG | ||
746 | void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, | ||
747 | int len) | ||
748 | { | ||
749 | if (!dccp_debug) | ||
750 | return; | ||
751 | |||
752 | printk("ACK vector len=%d, ackno=%llu |", len, | ||
753 | (unsigned long long) ackno); | ||
754 | |||
755 | while (len--) { | ||
756 | const u8 state = (*vector & DCCP_ACKPKTS_STATE_MASK) >> 6; | ||
757 | const u8 rl = (*vector & DCCP_ACKPKTS_LEN_MASK); | ||
758 | |||
759 | printk("%d,%d|", state, rl); | ||
760 | ++vector; | ||
761 | } | ||
762 | |||
763 | printk("\n"); | ||
764 | } | ||
765 | |||
766 | void dccp_ackpkts_print(const struct dccp_ackpkts *ap) | ||
767 | { | ||
768 | dccp_ackvector_print(ap->dccpap_buf_ackno, | ||
769 | ap->dccpap_buf + ap->dccpap_buf_head, | ||
770 | ap->dccpap_buf_vector_len); | ||
771 | } | ||
772 | #endif | ||
773 | |||
774 | static void dccp_ackpkts_trow_away_ack_record(struct dccp_ackpkts *ap) | ||
775 | { | ||
776 | /* | ||
777 | * As we're keeping track of the ack vector size | ||
778 | * (dccpap_buf_vector_len) and the sent ack vector size | ||
779 | * (dccpap_ack_vector_len) we don't need dccpap_buf_tail at all, but | ||
780 | * keep this code here as in the future we'll implement a vector of | ||
781 | * ack records, as suggested in draft-ietf-dccp-spec-11.txt | ||
782 | * Appendix A. -acme | ||
783 | */ | ||
784 | #if 0 | ||
785 | ap->dccpap_buf_tail = ap->dccpap_ack_ptr + 1; | ||
786 | if (ap->dccpap_buf_tail >= ap->dccpap_buf_len) | ||
787 | ap->dccpap_buf_tail -= ap->dccpap_buf_len; | ||
788 | #endif | ||
789 | ap->dccpap_buf_vector_len -= ap->dccpap_ack_vector_len; | ||
790 | } | ||
791 | |||
792 | void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap, struct sock *sk, | ||
793 | u64 ackno) | ||
794 | { | ||
795 | /* Check if we actually sent an ACK vector */ | ||
796 | if (ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1) | ||
797 | return; | ||
798 | |||
799 | if (ackno == ap->dccpap_ack_seqno) { | ||
800 | #ifdef CONFIG_IP_DCCP_DEBUG | ||
801 | struct dccp_sock *dp = dccp_sk(sk); | ||
802 | const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? | ||
803 | "CLIENT rx ack: " : "server rx ack: "; | ||
804 | #endif | ||
805 | dccp_pr_debug("%sACK packet 0, len=%d, ack_seqno=%llu, " | ||
806 | "ack_ackno=%llu, ACKED!\n", | ||
807 | debug_prefix, 1, | ||
808 | (unsigned long long) ap->dccpap_ack_seqno, | ||
809 | (unsigned long long) ap->dccpap_ack_ackno); | ||
810 | dccp_ackpkts_trow_away_ack_record(ap); | ||
811 | ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1; | ||
812 | } | ||
813 | } | ||
814 | |||
815 | static void dccp_ackpkts_check_rcv_ackvector(struct dccp_ackpkts *ap, | ||
816 | struct sock *sk, u64 ackno, | ||
817 | const unsigned char len, | ||
818 | const unsigned char *vector) | ||
819 | { | ||
820 | unsigned char i; | ||
821 | |||
822 | /* Check if we actually sent an ACK vector */ | ||
823 | if (ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1) | ||
824 | return; | ||
825 | /* | ||
826 | * We're in the receiver half connection, so if the received an ACK | ||
827 | * vector ackno (e.g. 50) before dccpap_ack_seqno (e.g. 52), we're | ||
828 | * not interested. | ||
829 | * | ||
830 | * Extra explanation with example: | ||
831 | * | ||
832 | * if we received an ACK vector with ackno 50, it can only be acking | ||
833 | * 50, 49, 48, etc, not 52 (the seqno for the ACK vector we sent). | ||
834 | */ | ||
835 | /* dccp_pr_debug("is %llu < %llu? ", ackno, ap->dccpap_ack_seqno); */ | ||
836 | if (before48(ackno, ap->dccpap_ack_seqno)) { | ||
837 | /* dccp_pr_debug_cat("yes\n"); */ | ||
838 | return; | ||
839 | } | ||
840 | /* dccp_pr_debug_cat("no\n"); */ | ||
841 | |||
842 | i = len; | ||
843 | while (i--) { | ||
844 | const u8 rl = (*vector & DCCP_ACKPKTS_LEN_MASK); | ||
845 | u64 ackno_end_rl; | ||
846 | |||
847 | dccp_set_seqno(&ackno_end_rl, ackno - rl); | ||
848 | |||
849 | /* | ||
850 | * dccp_pr_debug("is %llu <= %llu <= %llu? ", ackno_end_rl, | ||
851 | * ap->dccpap_ack_seqno, ackno); | ||
852 | */ | ||
853 | if (between48(ap->dccpap_ack_seqno, ackno_end_rl, ackno)) { | ||
854 | const u8 state = (*vector & | ||
855 | DCCP_ACKPKTS_STATE_MASK) >> 6; | ||
856 | /* dccp_pr_debug_cat("yes\n"); */ | ||
857 | |||
858 | if (state != DCCP_ACKPKTS_STATE_NOT_RECEIVED) { | ||
859 | #ifdef CONFIG_IP_DCCP_DEBUG | ||
860 | struct dccp_sock *dp = dccp_sk(sk); | ||
861 | const char *debug_prefix = | ||
862 | dp->dccps_role == DCCP_ROLE_CLIENT ? | ||
863 | "CLIENT rx ack: " : "server rx ack: "; | ||
864 | #endif | ||
865 | dccp_pr_debug("%sACK vector 0, len=%d, " | ||
866 | "ack_seqno=%llu, ack_ackno=%llu, " | ||
867 | "ACKED!\n", | ||
868 | debug_prefix, len, | ||
869 | (unsigned long long) | ||
870 | ap->dccpap_ack_seqno, | ||
871 | (unsigned long long) | ||
872 | ap->dccpap_ack_ackno); | ||
873 | dccp_ackpkts_trow_away_ack_record(ap); | ||
874 | } | ||
875 | /* | ||
876 | * If dccpap_ack_seqno was not received, no problem | ||
877 | * we'll send another ACK vector. | ||
878 | */ | ||
879 | ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1; | ||
880 | break; | ||
881 | } | ||
882 | /* dccp_pr_debug_cat("no\n"); */ | ||
883 | |||
884 | dccp_set_seqno(&ackno, ackno_end_rl - 1); | ||
885 | ++vector; | ||
886 | } | ||
887 | } | ||
diff --git a/net/dccp/output.c b/net/dccp/output.c index ea6d0e91e511..4786bdcddcc9 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <net/sock.h> | 17 | #include <net/sock.h> |
18 | 18 | ||
19 | #include "ackvec.h" | ||
19 | #include "ccid.h" | 20 | #include "ccid.h" |
20 | #include "dccp.h" | 21 | #include "dccp.h" |
21 | 22 | ||
@@ -85,7 +86,7 @@ int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) | |||
85 | switch (dcb->dccpd_type) { | 86 | switch (dcb->dccpd_type) { |
86 | case DCCP_PKT_REQUEST: | 87 | case DCCP_PKT_REQUEST: |
87 | dccp_hdr_request(skb)->dccph_req_service = | 88 | dccp_hdr_request(skb)->dccph_req_service = |
88 | dcb->dccpd_service; | 89 | dp->dccps_service; |
89 | break; | 90 | break; |
90 | case DCCP_PKT_RESET: | 91 | case DCCP_PKT_RESET: |
91 | dccp_hdr_reset(skb)->dccph_reset_code = | 92 | dccp_hdr_reset(skb)->dccph_reset_code = |
@@ -225,7 +226,6 @@ int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo) | |||
225 | err = dccp_wait_for_ccid(sk, skb, timeo); | 226 | err = dccp_wait_for_ccid(sk, skb, timeo); |
226 | 227 | ||
227 | if (err == 0) { | 228 | if (err == 0) { |
228 | const struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; | ||
229 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); | 229 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); |
230 | const int len = skb->len; | 230 | const int len = skb->len; |
231 | 231 | ||
@@ -236,15 +236,7 @@ int dccp_write_xmit(struct sock *sk, struct sk_buff *skb, long *timeo) | |||
236 | inet_csk(sk)->icsk_rto, | 236 | inet_csk(sk)->icsk_rto, |
237 | DCCP_RTO_MAX); | 237 | DCCP_RTO_MAX); |
238 | dcb->dccpd_type = DCCP_PKT_DATAACK; | 238 | dcb->dccpd_type = DCCP_PKT_DATAACK; |
239 | /* | 239 | } else if (dccp_ack_pending(sk)) |
240 | * FIXME: we really should have a | ||
241 | * dccps_ack_pending or use icsk. | ||
242 | */ | ||
243 | } else if (inet_csk_ack_scheduled(sk) || | ||
244 | dp->dccps_timestamp_echo != 0 || | ||
245 | (dp->dccps_options.dccpo_send_ack_vector && | ||
246 | ap->dccpap_buf_ackno != DCCP_MAX_SEQNO + 1 && | ||
247 | ap->dccpap_ack_seqno == DCCP_MAX_SEQNO + 1)) | ||
248 | dcb->dccpd_type = DCCP_PKT_DATAACK; | 240 | dcb->dccpd_type = DCCP_PKT_DATAACK; |
249 | else | 241 | else |
250 | dcb->dccpd_type = DCCP_PKT_DATA; | 242 | dcb->dccpd_type = DCCP_PKT_DATA; |
@@ -270,6 +262,7 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, | |||
270 | struct request_sock *req) | 262 | struct request_sock *req) |
271 | { | 263 | { |
272 | struct dccp_hdr *dh; | 264 | struct dccp_hdr *dh; |
265 | struct dccp_request_sock *dreq; | ||
273 | const int dccp_header_size = sizeof(struct dccp_hdr) + | 266 | const int dccp_header_size = sizeof(struct dccp_hdr) + |
274 | sizeof(struct dccp_hdr_ext) + | 267 | sizeof(struct dccp_hdr_ext) + |
275 | sizeof(struct dccp_hdr_response); | 268 | sizeof(struct dccp_hdr_response); |
@@ -285,8 +278,9 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, | |||
285 | skb->dst = dst_clone(dst); | 278 | skb->dst = dst_clone(dst); |
286 | skb->csum = 0; | 279 | skb->csum = 0; |
287 | 280 | ||
281 | dreq = dccp_rsk(req); | ||
288 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE; | 282 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_RESPONSE; |
289 | DCCP_SKB_CB(skb)->dccpd_seq = dccp_rsk(req)->dreq_iss; | 283 | DCCP_SKB_CB(skb)->dccpd_seq = dreq->dreq_iss; |
290 | dccp_insert_options(sk, skb); | 284 | dccp_insert_options(sk, skb); |
291 | 285 | ||
292 | skb->h.raw = skb_push(skb, dccp_header_size); | 286 | skb->h.raw = skb_push(skb, dccp_header_size); |
@@ -300,8 +294,9 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, | |||
300 | DCCP_SKB_CB(skb)->dccpd_opt_len) / 4; | 294 | DCCP_SKB_CB(skb)->dccpd_opt_len) / 4; |
301 | dh->dccph_type = DCCP_PKT_RESPONSE; | 295 | dh->dccph_type = DCCP_PKT_RESPONSE; |
302 | dh->dccph_x = 1; | 296 | dh->dccph_x = 1; |
303 | dccp_hdr_set_seq(dh, dccp_rsk(req)->dreq_iss); | 297 | dccp_hdr_set_seq(dh, dreq->dreq_iss); |
304 | dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dccp_rsk(req)->dreq_isr); | 298 | dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), dreq->dreq_isr); |
299 | dccp_hdr_response(skb)->dccph_resp_service = dreq->dreq_service; | ||
305 | 300 | ||
306 | dh->dccph_checksum = dccp_v4_checksum(skb, inet_rsk(req)->loc_addr, | 301 | dh->dccph_checksum = dccp_v4_checksum(skb, inet_rsk(req)->loc_addr, |
307 | inet_rsk(req)->rmt_addr); | 302 | inet_rsk(req)->rmt_addr); |
@@ -397,9 +392,6 @@ int dccp_connect(struct sock *sk) | |||
397 | skb_reserve(skb, MAX_DCCP_HEADER); | 392 | skb_reserve(skb, MAX_DCCP_HEADER); |
398 | 393 | ||
399 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST; | 394 | DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST; |
400 | /* FIXME: set service to something meaningful, coming | ||
401 | * from userspace*/ | ||
402 | DCCP_SKB_CB(skb)->dccpd_service = 0; | ||
403 | skb->csum = 0; | 395 | skb->csum = 0; |
404 | skb_set_owner_w(skb, sk); | 396 | skb_set_owner_w(skb, sk); |
405 | 397 | ||
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 18a0e69c9dc7..a1cfd0e9e3bc 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c | |||
@@ -94,7 +94,15 @@ EXPORT_SYMBOL_GPL(dccp_state_name); | |||
94 | 94 | ||
95 | static inline int dccp_listen_start(struct sock *sk) | 95 | static inline int dccp_listen_start(struct sock *sk) |
96 | { | 96 | { |
97 | dccp_sk(sk)->dccps_role = DCCP_ROLE_LISTEN; | 97 | struct dccp_sock *dp = dccp_sk(sk); |
98 | |||
99 | dp->dccps_role = DCCP_ROLE_LISTEN; | ||
100 | /* | ||
101 | * Apps need to use setsockopt(DCCP_SOCKOPT_SERVICE) | ||
102 | * before calling listen() | ||
103 | */ | ||
104 | if (dccp_service_not_initialized(sk)) | ||
105 | return -EPROTO; | ||
98 | return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); | 106 | return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); |
99 | } | 107 | } |
100 | 108 | ||
@@ -202,6 +210,42 @@ int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
202 | return -ENOIOCTLCMD; | 210 | return -ENOIOCTLCMD; |
203 | } | 211 | } |
204 | 212 | ||
213 | static int dccp_setsockopt_service(struct sock *sk, const u32 service, | ||
214 | char __user *optval, int optlen) | ||
215 | { | ||
216 | struct dccp_sock *dp = dccp_sk(sk); | ||
217 | struct dccp_service_list *sl = NULL; | ||
218 | |||
219 | if (service == DCCP_SERVICE_INVALID_VALUE || | ||
220 | optlen > DCCP_SERVICE_LIST_MAX_LEN * sizeof(u32)) | ||
221 | return -EINVAL; | ||
222 | |||
223 | if (optlen > sizeof(service)) { | ||
224 | sl = kmalloc(optlen, GFP_KERNEL); | ||
225 | if (sl == NULL) | ||
226 | return -ENOMEM; | ||
227 | |||
228 | sl->dccpsl_nr = optlen / sizeof(u32) - 1; | ||
229 | if (copy_from_user(sl->dccpsl_list, | ||
230 | optval + sizeof(service), | ||
231 | optlen - sizeof(service)) || | ||
232 | dccp_list_has_service(sl, DCCP_SERVICE_INVALID_VALUE)) { | ||
233 | kfree(sl); | ||
234 | return -EFAULT; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | lock_sock(sk); | ||
239 | dp->dccps_service = service; | ||
240 | |||
241 | if (dp->dccps_service_list != NULL) | ||
242 | kfree(dp->dccps_service_list); | ||
243 | |||
244 | dp->dccps_service_list = sl; | ||
245 | release_sock(sk); | ||
246 | return 0; | ||
247 | } | ||
248 | |||
205 | int dccp_setsockopt(struct sock *sk, int level, int optname, | 249 | int dccp_setsockopt(struct sock *sk, int level, int optname, |
206 | char __user *optval, int optlen) | 250 | char __user *optval, int optlen) |
207 | { | 251 | { |
@@ -218,8 +262,10 @@ int dccp_setsockopt(struct sock *sk, int level, int optname, | |||
218 | if (get_user(val, (int __user *)optval)) | 262 | if (get_user(val, (int __user *)optval)) |
219 | return -EFAULT; | 263 | return -EFAULT; |
220 | 264 | ||
221 | lock_sock(sk); | 265 | if (optname == DCCP_SOCKOPT_SERVICE) |
266 | return dccp_setsockopt_service(sk, val, optval, optlen); | ||
222 | 267 | ||
268 | lock_sock(sk); | ||
223 | dp = dccp_sk(sk); | 269 | dp = dccp_sk(sk); |
224 | err = 0; | 270 | err = 0; |
225 | 271 | ||
@@ -236,6 +282,37 @@ int dccp_setsockopt(struct sock *sk, int level, int optname, | |||
236 | return err; | 282 | return err; |
237 | } | 283 | } |
238 | 284 | ||
285 | static int dccp_getsockopt_service(struct sock *sk, int len, | ||
286 | u32 __user *optval, | ||
287 | int __user *optlen) | ||
288 | { | ||
289 | const struct dccp_sock *dp = dccp_sk(sk); | ||
290 | const struct dccp_service_list *sl; | ||
291 | int err = -ENOENT, slen = 0, total_len = sizeof(u32); | ||
292 | |||
293 | lock_sock(sk); | ||
294 | if (dccp_service_not_initialized(sk)) | ||
295 | goto out; | ||
296 | |||
297 | if ((sl = dp->dccps_service_list) != NULL) { | ||
298 | slen = sl->dccpsl_nr * sizeof(u32); | ||
299 | total_len += slen; | ||
300 | } | ||
301 | |||
302 | err = -EINVAL; | ||
303 | if (total_len > len) | ||
304 | goto out; | ||
305 | |||
306 | err = 0; | ||
307 | if (put_user(total_len, optlen) || | ||
308 | put_user(dp->dccps_service, optval) || | ||
309 | (sl != NULL && copy_to_user(optval + 1, sl->dccpsl_list, slen))) | ||
310 | err = -EFAULT; | ||
311 | out: | ||
312 | release_sock(sk); | ||
313 | return err; | ||
314 | } | ||
315 | |||
239 | int dccp_getsockopt(struct sock *sk, int level, int optname, | 316 | int dccp_getsockopt(struct sock *sk, int level, int optname, |
240 | char __user *optval, int __user *optlen) | 317 | char __user *optval, int __user *optlen) |
241 | { | 318 | { |
@@ -248,8 +325,7 @@ int dccp_getsockopt(struct sock *sk, int level, int optname, | |||
248 | if (get_user(len, optlen)) | 325 | if (get_user(len, optlen)) |
249 | return -EFAULT; | 326 | return -EFAULT; |
250 | 327 | ||
251 | len = min_t(unsigned int, len, sizeof(int)); | 328 | if (len < sizeof(int)) |
252 | if (len < 0) | ||
253 | return -EINVAL; | 329 | return -EINVAL; |
254 | 330 | ||
255 | dp = dccp_sk(sk); | 331 | dp = dccp_sk(sk); |
@@ -257,7 +333,17 @@ int dccp_getsockopt(struct sock *sk, int level, int optname, | |||
257 | switch (optname) { | 333 | switch (optname) { |
258 | case DCCP_SOCKOPT_PACKET_SIZE: | 334 | case DCCP_SOCKOPT_PACKET_SIZE: |
259 | val = dp->dccps_packet_size; | 335 | val = dp->dccps_packet_size; |
336 | len = sizeof(dp->dccps_packet_size); | ||
260 | break; | 337 | break; |
338 | case DCCP_SOCKOPT_SERVICE: | ||
339 | return dccp_getsockopt_service(sk, len, | ||
340 | (u32 __user *)optval, optlen); | ||
341 | case 128 ... 191: | ||
342 | return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname, | ||
343 | len, (u32 __user *)optval, optlen); | ||
344 | case 192 ... 255: | ||
345 | return ccid_hc_tx_getsockopt(dp->dccps_hc_tx_ccid, sk, optname, | ||
346 | len, (u32 __user *)optval, optlen); | ||
261 | default: | 347 | default: |
262 | return -ENOPROTOOPT; | 348 | return -ENOPROTOOPT; |
263 | } | 349 | } |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 1b63b4824164..50c0519cd70d 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -43,7 +43,7 @@ | |||
43 | * 2 of the License, or (at your option) any later version. | 43 | * 2 of the License, or (at your option) any later version. |
44 | */ | 44 | */ |
45 | 45 | ||
46 | #define VERSION "0.403" | 46 | #define VERSION "0.404" |
47 | 47 | ||
48 | #include <linux/config.h> | 48 | #include <linux/config.h> |
49 | #include <asm/uaccess.h> | 49 | #include <asm/uaccess.h> |
@@ -224,7 +224,7 @@ static inline int tkey_mismatch(t_key a, int offset, t_key b) | |||
224 | Consider a node 'n' and its parent 'tp'. | 224 | Consider a node 'n' and its parent 'tp'. |
225 | 225 | ||
226 | If n is a leaf, every bit in its key is significant. Its presence is | 226 | If n is a leaf, every bit in its key is significant. Its presence is |
227 | necessitaded by path compression, since during a tree traversal (when | 227 | necessitated by path compression, since during a tree traversal (when |
228 | searching for a leaf - unless we are doing an insertion) we will completely | 228 | searching for a leaf - unless we are doing an insertion) we will completely |
229 | ignore all skipped bits we encounter. Thus we need to verify, at the end of | 229 | ignore all skipped bits we encounter. Thus we need to verify, at the end of |
230 | a potentially successful search, that we have indeed been walking the | 230 | a potentially successful search, that we have indeed been walking the |
@@ -836,11 +836,12 @@ static void trie_init(struct trie *t) | |||
836 | #endif | 836 | #endif |
837 | } | 837 | } |
838 | 838 | ||
839 | /* readside most use rcu_read_lock currently dump routines | 839 | /* readside must use rcu_read_lock currently dump routines |
840 | via get_fa_head and dump */ | 840 | via get_fa_head and dump */ |
841 | 841 | ||
842 | static struct leaf_info *find_leaf_info(struct hlist_head *head, int plen) | 842 | static struct leaf_info *find_leaf_info(struct leaf *l, int plen) |
843 | { | 843 | { |
844 | struct hlist_head *head = &l->list; | ||
844 | struct hlist_node *node; | 845 | struct hlist_node *node; |
845 | struct leaf_info *li; | 846 | struct leaf_info *li; |
846 | 847 | ||
@@ -853,7 +854,7 @@ static struct leaf_info *find_leaf_info(struct hlist_head *head, int plen) | |||
853 | 854 | ||
854 | static inline struct list_head * get_fa_head(struct leaf *l, int plen) | 855 | static inline struct list_head * get_fa_head(struct leaf *l, int plen) |
855 | { | 856 | { |
856 | struct leaf_info *li = find_leaf_info(&l->list, plen); | 857 | struct leaf_info *li = find_leaf_info(l, plen); |
857 | 858 | ||
858 | if (!li) | 859 | if (!li) |
859 | return NULL; | 860 | return NULL; |
@@ -1085,7 +1086,7 @@ fib_insert_node(struct trie *t, int *err, u32 key, int plen) | |||
1085 | } | 1086 | } |
1086 | 1087 | ||
1087 | if (tp && tp->pos + tp->bits > 32) | 1088 | if (tp && tp->pos + tp->bits > 32) |
1088 | printk("ERROR tp=%p pos=%d, bits=%d, key=%0x plen=%d\n", | 1089 | printk(KERN_WARNING "fib_trie tp=%p pos=%d, bits=%d, key=%0x plen=%d\n", |
1089 | tp, tp->pos, tp->bits, key, plen); | 1090 | tp, tp->pos, tp->bits, key, plen); |
1090 | 1091 | ||
1091 | /* Rebalance the trie */ | 1092 | /* Rebalance the trie */ |
@@ -1248,7 +1249,7 @@ err: | |||
1248 | } | 1249 | } |
1249 | 1250 | ||
1250 | 1251 | ||
1251 | /* should be clalled with rcu_read_lock */ | 1252 | /* should be called with rcu_read_lock */ |
1252 | static inline int check_leaf(struct trie *t, struct leaf *l, | 1253 | static inline int check_leaf(struct trie *t, struct leaf *l, |
1253 | t_key key, int *plen, const struct flowi *flp, | 1254 | t_key key, int *plen, const struct flowi *flp, |
1254 | struct fib_result *res) | 1255 | struct fib_result *res) |
@@ -1590,7 +1591,7 @@ fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta, | |||
1590 | rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req); | 1591 | rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req); |
1591 | 1592 | ||
1592 | l = fib_find_node(t, key); | 1593 | l = fib_find_node(t, key); |
1593 | li = find_leaf_info(&l->list, plen); | 1594 | li = find_leaf_info(l, plen); |
1594 | 1595 | ||
1595 | list_del_rcu(&fa->fa_list); | 1596 | list_del_rcu(&fa->fa_list); |
1596 | 1597 | ||
@@ -1714,7 +1715,6 @@ static int fn_trie_flush(struct fib_table *tb) | |||
1714 | 1715 | ||
1715 | t->revision++; | 1716 | t->revision++; |
1716 | 1717 | ||
1717 | rcu_read_lock(); | ||
1718 | for (h = 0; (l = nextleaf(t, l)) != NULL; h++) { | 1718 | for (h = 0; (l = nextleaf(t, l)) != NULL; h++) { |
1719 | found += trie_flush_leaf(t, l); | 1719 | found += trie_flush_leaf(t, l); |
1720 | 1720 | ||
@@ -1722,7 +1722,6 @@ static int fn_trie_flush(struct fib_table *tb) | |||
1722 | trie_leaf_remove(t, ll->key); | 1722 | trie_leaf_remove(t, ll->key); |
1723 | ll = l; | 1723 | ll = l; |
1724 | } | 1724 | } |
1725 | rcu_read_unlock(); | ||
1726 | 1725 | ||
1727 | if (ll && hlist_empty(&ll->list)) | 1726 | if (ll && hlist_empty(&ll->list)) |
1728 | trie_leaf_remove(t, ll->key); | 1727 | trie_leaf_remove(t, ll->key); |
@@ -1833,16 +1832,7 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fi | |||
1833 | i++; | 1832 | i++; |
1834 | continue; | 1833 | continue; |
1835 | } | 1834 | } |
1836 | if (fa->fa_info->fib_nh == NULL) { | 1835 | BUG_ON(!fa->fa_info); |
1837 | printk("Trie error _fib_nh=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen); | ||
1838 | i++; | ||
1839 | continue; | ||
1840 | } | ||
1841 | if (fa->fa_info == NULL) { | ||
1842 | printk("Trie error fa_info=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen); | ||
1843 | i++; | ||
1844 | continue; | ||
1845 | } | ||
1846 | 1836 | ||
1847 | if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid, | 1837 | if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid, |
1848 | cb->nlh->nlmsg_seq, | 1838 | cb->nlh->nlmsg_seq, |
@@ -1965,7 +1955,7 @@ struct fib_table * __init fib_hash_init(int id) | |||
1965 | trie_main = t; | 1955 | trie_main = t; |
1966 | 1956 | ||
1967 | if (id == RT_TABLE_LOCAL) | 1957 | if (id == RT_TABLE_LOCAL) |
1968 | printk("IPv4 FIB: Using LC-trie version %s\n", VERSION); | 1958 | printk(KERN_INFO "IPv4 FIB: Using LC-trie version %s\n", VERSION); |
1969 | 1959 | ||
1970 | return tb; | 1960 | return tb; |
1971 | } | 1961 | } |
@@ -2029,7 +2019,7 @@ static struct node *fib_trie_get_first(struct fib_trie_iter *iter, | |||
2029 | iter->tnode = (struct tnode *) n; | 2019 | iter->tnode = (struct tnode *) n; |
2030 | iter->trie = t; | 2020 | iter->trie = t; |
2031 | iter->index = 0; | 2021 | iter->index = 0; |
2032 | iter->depth = 0; | 2022 | iter->depth = 1; |
2033 | return n; | 2023 | return n; |
2034 | } | 2024 | } |
2035 | return NULL; | 2025 | return NULL; |
@@ -2274,11 +2264,12 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v) | |||
2274 | seq_puts(seq, "<local>:\n"); | 2264 | seq_puts(seq, "<local>:\n"); |
2275 | else | 2265 | else |
2276 | seq_puts(seq, "<main>:\n"); | 2266 | seq_puts(seq, "<main>:\n"); |
2277 | } else { | 2267 | } |
2278 | seq_indent(seq, iter->depth-1); | 2268 | seq_indent(seq, iter->depth-1); |
2279 | seq_printf(seq, " +-- %d.%d.%d.%d/%d\n", | 2269 | seq_printf(seq, " +-- %d.%d.%d.%d/%d %d %d %d\n", |
2280 | NIPQUAD(prf), tn->pos); | 2270 | NIPQUAD(prf), tn->pos, tn->bits, tn->full_children, |
2281 | } | 2271 | tn->empty_children); |
2272 | |||
2282 | } else { | 2273 | } else { |
2283 | struct leaf *l = (struct leaf *) n; | 2274 | struct leaf *l = (struct leaf *) n; |
2284 | int i; | 2275 | int i; |
@@ -2287,7 +2278,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v) | |||
2287 | seq_indent(seq, iter->depth); | 2278 | seq_indent(seq, iter->depth); |
2288 | seq_printf(seq, " |-- %d.%d.%d.%d\n", NIPQUAD(val)); | 2279 | seq_printf(seq, " |-- %d.%d.%d.%d\n", NIPQUAD(val)); |
2289 | for (i = 32; i >= 0; i--) { | 2280 | for (i = 32; i >= 0; i--) { |
2290 | struct leaf_info *li = find_leaf_info(&l->list, i); | 2281 | struct leaf_info *li = find_leaf_info(l, i); |
2291 | if (li) { | 2282 | if (li) { |
2292 | struct fib_alias *fa; | 2283 | struct fib_alias *fa; |
2293 | list_for_each_entry_rcu(fa, &li->falh, fa_list) { | 2284 | list_for_each_entry_rcu(fa, &li->falh, fa_list) { |
@@ -2383,7 +2374,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v) | |||
2383 | return 0; | 2374 | return 0; |
2384 | 2375 | ||
2385 | for (i=32; i>=0; i--) { | 2376 | for (i=32; i>=0; i--) { |
2386 | struct leaf_info *li = find_leaf_info(&l->list, i); | 2377 | struct leaf_info *li = find_leaf_info(l, i); |
2387 | struct fib_alias *fa; | 2378 | struct fib_alias *fa; |
2388 | u32 mask, prefix; | 2379 | u32 mask, prefix; |
2389 | 2380 | ||
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 44607f4767b8..70c44e4c3ceb 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -1603,7 +1603,7 @@ static void ip_mc_clear_src(struct ip_mc_list *pmc) | |||
1603 | } | 1603 | } |
1604 | pmc->sources = NULL; | 1604 | pmc->sources = NULL; |
1605 | pmc->sfmode = MCAST_EXCLUDE; | 1605 | pmc->sfmode = MCAST_EXCLUDE; |
1606 | pmc->sfcount[MCAST_EXCLUDE] = 0; | 1606 | pmc->sfcount[MCAST_INCLUDE] = 0; |
1607 | pmc->sfcount[MCAST_EXCLUDE] = 1; | 1607 | pmc->sfcount[MCAST_EXCLUDE] = 1; |
1608 | } | 1608 | } |
1609 | 1609 | ||
diff --git a/net/ipv4/ipvs/ip_vs_conn.c b/net/ipv4/ipvs/ip_vs_conn.c index e11952ea17af..f828fa2eb7de 100644 --- a/net/ipv4/ipvs/ip_vs_conn.c +++ b/net/ipv4/ipvs/ip_vs_conn.c | |||
@@ -196,6 +196,7 @@ static inline struct ip_vs_conn *__ip_vs_conn_in_get | |||
196 | list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { | 196 | list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { |
197 | if (s_addr==cp->caddr && s_port==cp->cport && | 197 | if (s_addr==cp->caddr && s_port==cp->cport && |
198 | d_port==cp->vport && d_addr==cp->vaddr && | 198 | d_port==cp->vport && d_addr==cp->vaddr && |
199 | ((!s_port) ^ (!(cp->flags & IP_VS_CONN_F_NO_CPORT))) && | ||
199 | protocol==cp->protocol) { | 200 | protocol==cp->protocol) { |
200 | /* HIT */ | 201 | /* HIT */ |
201 | atomic_inc(&cp->refcnt); | 202 | atomic_inc(&cp->refcnt); |
@@ -227,6 +228,40 @@ struct ip_vs_conn *ip_vs_conn_in_get | |||
227 | return cp; | 228 | return cp; |
228 | } | 229 | } |
229 | 230 | ||
231 | /* Get reference to connection template */ | ||
232 | struct ip_vs_conn *ip_vs_ct_in_get | ||
233 | (int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port) | ||
234 | { | ||
235 | unsigned hash; | ||
236 | struct ip_vs_conn *cp; | ||
237 | |||
238 | hash = ip_vs_conn_hashkey(protocol, s_addr, s_port); | ||
239 | |||
240 | ct_read_lock(hash); | ||
241 | |||
242 | list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { | ||
243 | if (s_addr==cp->caddr && s_port==cp->cport && | ||
244 | d_port==cp->vport && d_addr==cp->vaddr && | ||
245 | cp->flags & IP_VS_CONN_F_TEMPLATE && | ||
246 | protocol==cp->protocol) { | ||
247 | /* HIT */ | ||
248 | atomic_inc(&cp->refcnt); | ||
249 | goto out; | ||
250 | } | ||
251 | } | ||
252 | cp = NULL; | ||
253 | |||
254 | out: | ||
255 | ct_read_unlock(hash); | ||
256 | |||
257 | IP_VS_DBG(7, "template lookup/in %s %u.%u.%u.%u:%d->%u.%u.%u.%u:%d %s\n", | ||
258 | ip_vs_proto_name(protocol), | ||
259 | NIPQUAD(s_addr), ntohs(s_port), | ||
260 | NIPQUAD(d_addr), ntohs(d_port), | ||
261 | cp?"hit":"not hit"); | ||
262 | |||
263 | return cp; | ||
264 | } | ||
230 | 265 | ||
231 | /* | 266 | /* |
232 | * Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab. | 267 | * Gets ip_vs_conn associated with supplied parameters in the ip_vs_conn_tab. |
@@ -367,7 +402,7 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest) | |||
367 | atomic_read(&dest->refcnt)); | 402 | atomic_read(&dest->refcnt)); |
368 | 403 | ||
369 | /* Update the connection counters */ | 404 | /* Update the connection counters */ |
370 | if (cp->cport || (cp->flags & IP_VS_CONN_F_NO_CPORT)) { | 405 | if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) { |
371 | /* It is a normal connection, so increase the inactive | 406 | /* It is a normal connection, so increase the inactive |
372 | connection counter because it is in TCP SYNRECV | 407 | connection counter because it is in TCP SYNRECV |
373 | state (inactive) or other protocol inacive state */ | 408 | state (inactive) or other protocol inacive state */ |
@@ -406,7 +441,7 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp) | |||
406 | atomic_read(&dest->refcnt)); | 441 | atomic_read(&dest->refcnt)); |
407 | 442 | ||
408 | /* Update the connection counters */ | 443 | /* Update the connection counters */ |
409 | if (cp->cport || (cp->flags & IP_VS_CONN_F_NO_CPORT)) { | 444 | if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) { |
410 | /* It is a normal connection, so decrease the inactconns | 445 | /* It is a normal connection, so decrease the inactconns |
411 | or activeconns counter */ | 446 | or activeconns counter */ |
412 | if (cp->flags & IP_VS_CONN_F_INACTIVE) { | 447 | if (cp->flags & IP_VS_CONN_F_INACTIVE) { |
@@ -467,7 +502,7 @@ int ip_vs_check_template(struct ip_vs_conn *ct) | |||
467 | /* | 502 | /* |
468 | * Invalidate the connection template | 503 | * Invalidate the connection template |
469 | */ | 504 | */ |
470 | if (ct->cport) { | 505 | if (ct->vport != 65535) { |
471 | if (ip_vs_conn_unhash(ct)) { | 506 | if (ip_vs_conn_unhash(ct)) { |
472 | ct->dport = 65535; | 507 | ct->dport = 65535; |
473 | ct->vport = 65535; | 508 | ct->vport = 65535; |
@@ -776,7 +811,7 @@ void ip_vs_random_dropentry(void) | |||
776 | ct_write_lock_bh(hash); | 811 | ct_write_lock_bh(hash); |
777 | 812 | ||
778 | list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { | 813 | list_for_each_entry(cp, &ip_vs_conn_tab[hash], c_list) { |
779 | if (!cp->cport && !(cp->flags & IP_VS_CONN_F_NO_CPORT)) | 814 | if (cp->flags & IP_VS_CONN_F_TEMPLATE) |
780 | /* connection template */ | 815 | /* connection template */ |
781 | continue; | 816 | continue; |
782 | 817 | ||
diff --git a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c index 3ac7eeca04ac..981cc3244ef2 100644 --- a/net/ipv4/ipvs/ip_vs_core.c +++ b/net/ipv4/ipvs/ip_vs_core.c | |||
@@ -243,10 +243,10 @@ ip_vs_sched_persist(struct ip_vs_service *svc, | |||
243 | if (ports[1] == svc->port) { | 243 | if (ports[1] == svc->port) { |
244 | /* Check if a template already exists */ | 244 | /* Check if a template already exists */ |
245 | if (svc->port != FTPPORT) | 245 | if (svc->port != FTPPORT) |
246 | ct = ip_vs_conn_in_get(iph->protocol, snet, 0, | 246 | ct = ip_vs_ct_in_get(iph->protocol, snet, 0, |
247 | iph->daddr, ports[1]); | 247 | iph->daddr, ports[1]); |
248 | else | 248 | else |
249 | ct = ip_vs_conn_in_get(iph->protocol, snet, 0, | 249 | ct = ip_vs_ct_in_get(iph->protocol, snet, 0, |
250 | iph->daddr, 0); | 250 | iph->daddr, 0); |
251 | 251 | ||
252 | if (!ct || !ip_vs_check_template(ct)) { | 252 | if (!ct || !ip_vs_check_template(ct)) { |
@@ -272,14 +272,14 @@ ip_vs_sched_persist(struct ip_vs_service *svc, | |||
272 | iph->daddr, | 272 | iph->daddr, |
273 | ports[1], | 273 | ports[1], |
274 | dest->addr, dest->port, | 274 | dest->addr, dest->port, |
275 | 0, | 275 | IP_VS_CONN_F_TEMPLATE, |
276 | dest); | 276 | dest); |
277 | else | 277 | else |
278 | ct = ip_vs_conn_new(iph->protocol, | 278 | ct = ip_vs_conn_new(iph->protocol, |
279 | snet, 0, | 279 | snet, 0, |
280 | iph->daddr, 0, | 280 | iph->daddr, 0, |
281 | dest->addr, 0, | 281 | dest->addr, 0, |
282 | 0, | 282 | IP_VS_CONN_F_TEMPLATE, |
283 | dest); | 283 | dest); |
284 | if (ct == NULL) | 284 | if (ct == NULL) |
285 | return NULL; | 285 | return NULL; |
@@ -298,10 +298,10 @@ ip_vs_sched_persist(struct ip_vs_service *svc, | |||
298 | * port zero template: <protocol,caddr,0,vaddr,0,daddr,0> | 298 | * port zero template: <protocol,caddr,0,vaddr,0,daddr,0> |
299 | */ | 299 | */ |
300 | if (svc->fwmark) | 300 | if (svc->fwmark) |
301 | ct = ip_vs_conn_in_get(IPPROTO_IP, snet, 0, | 301 | ct = ip_vs_ct_in_get(IPPROTO_IP, snet, 0, |
302 | htonl(svc->fwmark), 0); | 302 | htonl(svc->fwmark), 0); |
303 | else | 303 | else |
304 | ct = ip_vs_conn_in_get(iph->protocol, snet, 0, | 304 | ct = ip_vs_ct_in_get(iph->protocol, snet, 0, |
305 | iph->daddr, 0); | 305 | iph->daddr, 0); |
306 | 306 | ||
307 | if (!ct || !ip_vs_check_template(ct)) { | 307 | if (!ct || !ip_vs_check_template(ct)) { |
@@ -326,14 +326,14 @@ ip_vs_sched_persist(struct ip_vs_service *svc, | |||
326 | snet, 0, | 326 | snet, 0, |
327 | htonl(svc->fwmark), 0, | 327 | htonl(svc->fwmark), 0, |
328 | dest->addr, 0, | 328 | dest->addr, 0, |
329 | 0, | 329 | IP_VS_CONN_F_TEMPLATE, |
330 | dest); | 330 | dest); |
331 | else | 331 | else |
332 | ct = ip_vs_conn_new(iph->protocol, | 332 | ct = ip_vs_conn_new(iph->protocol, |
333 | snet, 0, | 333 | snet, 0, |
334 | iph->daddr, 0, | 334 | iph->daddr, 0, |
335 | dest->addr, 0, | 335 | dest->addr, 0, |
336 | 0, | 336 | IP_VS_CONN_F_TEMPLATE, |
337 | dest); | 337 | dest); |
338 | if (ct == NULL) | 338 | if (ct == NULL) |
339 | return NULL; | 339 | return NULL; |
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c index 574d1f509b46..2e5ced3d8062 100644 --- a/net/ipv4/ipvs/ip_vs_sync.c +++ b/net/ipv4/ipvs/ip_vs_sync.c | |||
@@ -297,16 +297,24 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) | |||
297 | 297 | ||
298 | p = (char *)buffer + sizeof(struct ip_vs_sync_mesg); | 298 | p = (char *)buffer + sizeof(struct ip_vs_sync_mesg); |
299 | for (i=0; i<m->nr_conns; i++) { | 299 | for (i=0; i<m->nr_conns; i++) { |
300 | unsigned flags; | ||
301 | |||
300 | s = (struct ip_vs_sync_conn *)p; | 302 | s = (struct ip_vs_sync_conn *)p; |
301 | cp = ip_vs_conn_in_get(s->protocol, | 303 | flags = ntohs(s->flags); |
302 | s->caddr, s->cport, | 304 | if (!(flags & IP_VS_CONN_F_TEMPLATE)) |
303 | s->vaddr, s->vport); | 305 | cp = ip_vs_conn_in_get(s->protocol, |
306 | s->caddr, s->cport, | ||
307 | s->vaddr, s->vport); | ||
308 | else | ||
309 | cp = ip_vs_ct_in_get(s->protocol, | ||
310 | s->caddr, s->cport, | ||
311 | s->vaddr, s->vport); | ||
304 | if (!cp) { | 312 | if (!cp) { |
305 | cp = ip_vs_conn_new(s->protocol, | 313 | cp = ip_vs_conn_new(s->protocol, |
306 | s->caddr, s->cport, | 314 | s->caddr, s->cport, |
307 | s->vaddr, s->vport, | 315 | s->vaddr, s->vport, |
308 | s->daddr, s->dport, | 316 | s->daddr, s->dport, |
309 | ntohs(s->flags), NULL); | 317 | flags, NULL); |
310 | if (!cp) { | 318 | if (!cp) { |
311 | IP_VS_ERR("ip_vs_conn_new failed\n"); | 319 | IP_VS_ERR("ip_vs_conn_new failed\n"); |
312 | return; | 320 | return; |
@@ -315,11 +323,11 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen) | |||
315 | } else if (!cp->dest) { | 323 | } else if (!cp->dest) { |
316 | /* it is an entry created by the synchronization */ | 324 | /* it is an entry created by the synchronization */ |
317 | cp->state = ntohs(s->state); | 325 | cp->state = ntohs(s->state); |
318 | cp->flags = ntohs(s->flags) | IP_VS_CONN_F_HASHED; | 326 | cp->flags = flags | IP_VS_CONN_F_HASHED; |
319 | } /* Note that we don't touch its state and flags | 327 | } /* Note that we don't touch its state and flags |
320 | if it is a normal entry. */ | 328 | if it is a normal entry. */ |
321 | 329 | ||
322 | if (ntohs(s->flags) & IP_VS_CONN_F_SEQ_MASK) { | 330 | if (flags & IP_VS_CONN_F_SEQ_MASK) { |
323 | opt = (struct ip_vs_sync_conn_options *)&s[1]; | 331 | opt = (struct ip_vs_sync_conn_options *)&s[1]; |
324 | memcpy(&cp->in_seq, opt, sizeof(*opt)); | 332 | memcpy(&cp->in_seq, opt, sizeof(*opt)); |
325 | p += FULL_CONN_SIZE; | 333 | p += FULL_CONN_SIZE; |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 30aa8e2ee214..3cf9b451675c 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -51,6 +51,14 @@ config IP_NF_CONNTRACK_EVENTS | |||
51 | 51 | ||
52 | IF unsure, say `N'. | 52 | IF unsure, say `N'. |
53 | 53 | ||
54 | config IP_NF_CONNTRACK_NETLINK | ||
55 | tristate 'Connection tracking netlink interface' | ||
56 | depends on IP_NF_CONNTRACK && NETFILTER_NETLINK | ||
57 | depends on IP_NF_CONNTRACK!=y || NETFILTER_NETLINK!=m | ||
58 | help | ||
59 | This option enables support for a netlink-based userspace interface | ||
60 | |||
61 | |||
54 | config IP_NF_CT_PROTO_SCTP | 62 | config IP_NF_CT_PROTO_SCTP |
55 | tristate 'SCTP protocol connection tracking support (EXPERIMENTAL)' | 63 | tristate 'SCTP protocol connection tracking support (EXPERIMENTAL)' |
56 | depends on IP_NF_CONNTRACK && EXPERIMENTAL | 64 | depends on IP_NF_CONNTRACK && EXPERIMENTAL |
@@ -129,6 +137,22 @@ config IP_NF_AMANDA | |||
129 | 137 | ||
130 | To compile it as a module, choose M here. If unsure, say Y. | 138 | To compile it as a module, choose M here. If unsure, say Y. |
131 | 139 | ||
140 | config IP_NF_PPTP | ||
141 | tristate 'PPTP protocol support' | ||
142 | help | ||
143 | This module adds support for PPTP (Point to Point Tunnelling | ||
144 | Protocol, RFC2637) conncection tracking and NAT. | ||
145 | |||
146 | If you are running PPTP sessions over a stateful firewall or NAT | ||
147 | box, you may want to enable this feature. | ||
148 | |||
149 | Please note that not all PPTP modes of operation are supported yet. | ||
150 | For more info, read top of the file | ||
151 | net/ipv4/netfilter/ip_conntrack_pptp.c | ||
152 | |||
153 | If you want to compile it as a module, say M here and read | ||
154 | Documentation/modules.txt. If unsure, say `N'. | ||
155 | |||
132 | config IP_NF_QUEUE | 156 | config IP_NF_QUEUE |
133 | tristate "IP Userspace queueing via NETLINK (OBSOLETE)" | 157 | tristate "IP Userspace queueing via NETLINK (OBSOLETE)" |
134 | help | 158 | help |
@@ -613,6 +637,12 @@ config IP_NF_NAT_AMANDA | |||
613 | default IP_NF_NAT if IP_NF_AMANDA=y | 637 | default IP_NF_NAT if IP_NF_AMANDA=y |
614 | default m if IP_NF_AMANDA=m | 638 | default m if IP_NF_AMANDA=m |
615 | 639 | ||
640 | config IP_NF_NAT_PPTP | ||
641 | tristate | ||
642 | depends on IP_NF_NAT!=n && IP_NF_PPTP!=n | ||
643 | default IP_NF_NAT if IP_NF_PPTP=y | ||
644 | default m if IP_NF_PPTP=m | ||
645 | |||
616 | # mangle + specific targets | 646 | # mangle + specific targets |
617 | config IP_NF_MANGLE | 647 | config IP_NF_MANGLE |
618 | tristate "Packet mangling" | 648 | tristate "Packet mangling" |
@@ -774,11 +804,5 @@ config IP_NF_ARP_MANGLE | |||
774 | Allows altering the ARP packet payload: source and destination | 804 | Allows altering the ARP packet payload: source and destination |
775 | hardware and network addresses. | 805 | hardware and network addresses. |
776 | 806 | ||
777 | config IP_NF_CONNTRACK_NETLINK | ||
778 | tristate 'Connection tracking netlink interface' | ||
779 | depends on IP_NF_CONNTRACK && NETFILTER_NETLINK | ||
780 | help | ||
781 | This option enables support for a netlink-based userspace interface | ||
782 | |||
783 | endmenu | 807 | endmenu |
784 | 808 | ||
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 1ba0db746817..3d45d3c0283c 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -6,6 +6,9 @@ | |||
6 | ip_conntrack-objs := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o | 6 | ip_conntrack-objs := ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o |
7 | iptable_nat-objs := ip_nat_standalone.o ip_nat_rule.o ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o | 7 | iptable_nat-objs := ip_nat_standalone.o ip_nat_rule.o ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o |
8 | 8 | ||
9 | ip_conntrack_pptp-objs := ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o | ||
10 | ip_nat_pptp-objs := ip_nat_helper_pptp.o ip_nat_proto_gre.o | ||
11 | |||
9 | # connection tracking | 12 | # connection tracking |
10 | obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o | 13 | obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o |
11 | 14 | ||
@@ -17,6 +20,7 @@ obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o | |||
17 | obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o | 20 | obj-$(CONFIG_IP_NF_CT_PROTO_SCTP) += ip_conntrack_proto_sctp.o |
18 | 21 | ||
19 | # connection tracking helpers | 22 | # connection tracking helpers |
23 | obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o | ||
20 | obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o | 24 | obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o |
21 | obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o | 25 | obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o |
22 | obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o | 26 | obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o |
@@ -24,6 +28,7 @@ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o | |||
24 | obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o | 28 | obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o |
25 | 29 | ||
26 | # NAT helpers | 30 | # NAT helpers |
31 | obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o | ||
27 | obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o | 32 | obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o |
28 | obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o | 33 | obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o |
29 | obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o | 34 | obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o |
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 19cba16e6e1e..c1f82e0c81cf 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c | |||
@@ -233,7 +233,7 @@ __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple) | |||
233 | 233 | ||
234 | /* Just find a expectation corresponding to a tuple. */ | 234 | /* Just find a expectation corresponding to a tuple. */ |
235 | struct ip_conntrack_expect * | 235 | struct ip_conntrack_expect * |
236 | ip_conntrack_expect_find_get(const struct ip_conntrack_tuple *tuple) | 236 | ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple) |
237 | { | 237 | { |
238 | struct ip_conntrack_expect *i; | 238 | struct ip_conntrack_expect *i; |
239 | 239 | ||
@@ -1143,7 +1143,10 @@ void ip_ct_refresh_acct(struct ip_conntrack *ct, | |||
1143 | if (del_timer(&ct->timeout)) { | 1143 | if (del_timer(&ct->timeout)) { |
1144 | ct->timeout.expires = jiffies + extra_jiffies; | 1144 | ct->timeout.expires = jiffies + extra_jiffies; |
1145 | add_timer(&ct->timeout); | 1145 | add_timer(&ct->timeout); |
1146 | ip_conntrack_event_cache(IPCT_REFRESH, skb); | 1146 | /* FIXME: We loose some REFRESH events if this function |
1147 | * is called without an skb. I'll fix this later -HW */ | ||
1148 | if (skb) | ||
1149 | ip_conntrack_event_cache(IPCT_REFRESH, skb); | ||
1147 | } | 1150 | } |
1148 | ct_add_counters(ct, ctinfo, skb); | 1151 | ct_add_counters(ct, ctinfo, skb); |
1149 | write_unlock_bh(&ip_conntrack_lock); | 1152 | write_unlock_bh(&ip_conntrack_lock); |
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c new file mode 100644 index 000000000000..79db5b70d5f6 --- /dev/null +++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c | |||
@@ -0,0 +1,805 @@ | |||
1 | /* | ||
2 | * ip_conntrack_pptp.c - Version 3.0 | ||
3 | * | ||
4 | * Connection tracking support for PPTP (Point to Point Tunneling Protocol). | ||
5 | * PPTP is a a protocol for creating virtual private networks. | ||
6 | * It is a specification defined by Microsoft and some vendors | ||
7 | * working with Microsoft. PPTP is built on top of a modified | ||
8 | * version of the Internet Generic Routing Encapsulation Protocol. | ||
9 | * GRE is defined in RFC 1701 and RFC 1702. Documentation of | ||
10 | * PPTP can be found in RFC 2637 | ||
11 | * | ||
12 | * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org> | ||
13 | * | ||
14 | * Development of this code funded by Astaro AG (http://www.astaro.com/) | ||
15 | * | ||
16 | * Limitations: | ||
17 | * - We blindly assume that control connections are always | ||
18 | * established in PNS->PAC direction. This is a violation | ||
19 | * of RFFC2673 | ||
20 | * - We can only support one single call within each session | ||
21 | * | ||
22 | * TODO: | ||
23 | * - testing of incoming PPTP calls | ||
24 | * | ||
25 | * Changes: | ||
26 | * 2002-02-05 - Version 1.3 | ||
27 | * - Call ip_conntrack_unexpect_related() from | ||
28 | * pptp_destroy_siblings() to destroy expectations in case | ||
29 | * CALL_DISCONNECT_NOTIFY or tcp fin packet was seen | ||
30 | * (Philip Craig <philipc@snapgear.com>) | ||
31 | * - Add Version information at module loadtime | ||
32 | * 2002-02-10 - Version 1.6 | ||
33 | * - move to C99 style initializers | ||
34 | * - remove second expectation if first arrives | ||
35 | * 2004-10-22 - Version 2.0 | ||
36 | * - merge Mandrake's 2.6.x port with recent 2.6.x API changes | ||
37 | * - fix lots of linear skb assumptions from Mandrake's port | ||
38 | * 2005-06-10 - Version 2.1 | ||
39 | * - use ip_conntrack_expect_free() instead of kfree() on the | ||
40 | * expect's (which are from the slab for quite some time) | ||
41 | * 2005-06-10 - Version 3.0 | ||
42 | * - port helper to post-2.6.11 API changes, | ||
43 | * funded by Oxcoda NetBox Blue (http://www.netboxblue.com/) | ||
44 | * 2005-07-30 - Version 3.1 | ||
45 | * - port helper to 2.6.13 API changes | ||
46 | * | ||
47 | */ | ||
48 | |||
49 | #include <linux/config.h> | ||
50 | #include <linux/module.h> | ||
51 | #include <linux/netfilter.h> | ||
52 | #include <linux/ip.h> | ||
53 | #include <net/checksum.h> | ||
54 | #include <net/tcp.h> | ||
55 | |||
56 | #include <linux/netfilter_ipv4/ip_conntrack.h> | ||
57 | #include <linux/netfilter_ipv4/ip_conntrack_core.h> | ||
58 | #include <linux/netfilter_ipv4/ip_conntrack_helper.h> | ||
59 | #include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h> | ||
60 | #include <linux/netfilter_ipv4/ip_conntrack_pptp.h> | ||
61 | |||
62 | #define IP_CT_PPTP_VERSION "3.1" | ||
63 | |||
64 | MODULE_LICENSE("GPL"); | ||
65 | MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); | ||
66 | MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP"); | ||
67 | |||
68 | static DEFINE_SPINLOCK(ip_pptp_lock); | ||
69 | |||
70 | int | ||
71 | (*ip_nat_pptp_hook_outbound)(struct sk_buff **pskb, | ||
72 | struct ip_conntrack *ct, | ||
73 | enum ip_conntrack_info ctinfo, | ||
74 | struct PptpControlHeader *ctlh, | ||
75 | union pptp_ctrl_union *pptpReq); | ||
76 | |||
77 | int | ||
78 | (*ip_nat_pptp_hook_inbound)(struct sk_buff **pskb, | ||
79 | struct ip_conntrack *ct, | ||
80 | enum ip_conntrack_info ctinfo, | ||
81 | struct PptpControlHeader *ctlh, | ||
82 | union pptp_ctrl_union *pptpReq); | ||
83 | |||
84 | int | ||
85 | (*ip_nat_pptp_hook_exp_gre)(struct ip_conntrack_expect *expect_orig, | ||
86 | struct ip_conntrack_expect *expect_reply); | ||
87 | |||
88 | void | ||
89 | (*ip_nat_pptp_hook_expectfn)(struct ip_conntrack *ct, | ||
90 | struct ip_conntrack_expect *exp); | ||
91 | |||
92 | #if 0 | ||
93 | /* PptpControlMessageType names */ | ||
94 | const char *pptp_msg_name[] = { | ||
95 | "UNKNOWN_MESSAGE", | ||
96 | "START_SESSION_REQUEST", | ||
97 | "START_SESSION_REPLY", | ||
98 | "STOP_SESSION_REQUEST", | ||
99 | "STOP_SESSION_REPLY", | ||
100 | "ECHO_REQUEST", | ||
101 | "ECHO_REPLY", | ||
102 | "OUT_CALL_REQUEST", | ||
103 | "OUT_CALL_REPLY", | ||
104 | "IN_CALL_REQUEST", | ||
105 | "IN_CALL_REPLY", | ||
106 | "IN_CALL_CONNECT", | ||
107 | "CALL_CLEAR_REQUEST", | ||
108 | "CALL_DISCONNECT_NOTIFY", | ||
109 | "WAN_ERROR_NOTIFY", | ||
110 | "SET_LINK_INFO" | ||
111 | }; | ||
112 | EXPORT_SYMBOL(pptp_msg_name); | ||
113 | #define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args) | ||
114 | #else | ||
115 | #define DEBUGP(format, args...) | ||
116 | #endif | ||
117 | |||
118 | #define SECS *HZ | ||
119 | #define MINS * 60 SECS | ||
120 | #define HOURS * 60 MINS | ||
121 | |||
122 | #define PPTP_GRE_TIMEOUT (10 MINS) | ||
123 | #define PPTP_GRE_STREAM_TIMEOUT (5 HOURS) | ||
124 | |||
125 | static void pptp_expectfn(struct ip_conntrack *ct, | ||
126 | struct ip_conntrack_expect *exp) | ||
127 | { | ||
128 | DEBUGP("increasing timeouts\n"); | ||
129 | |||
130 | /* increase timeout of GRE data channel conntrack entry */ | ||
131 | ct->proto.gre.timeout = PPTP_GRE_TIMEOUT; | ||
132 | ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT; | ||
133 | |||
134 | /* Can you see how rusty this code is, compared with the pre-2.6.11 | ||
135 | * one? That's what happened to my shiny newnat of 2002 ;( -HW */ | ||
136 | |||
137 | if (!ip_nat_pptp_hook_expectfn) { | ||
138 | struct ip_conntrack_tuple inv_t; | ||
139 | struct ip_conntrack_expect *exp_other; | ||
140 | |||
141 | /* obviously this tuple inversion only works until you do NAT */ | ||
142 | invert_tuplepr(&inv_t, &exp->tuple); | ||
143 | DEBUGP("trying to unexpect other dir: "); | ||
144 | DUMP_TUPLE(&inv_t); | ||
145 | |||
146 | exp_other = ip_conntrack_expect_find(&inv_t); | ||
147 | if (exp_other) { | ||
148 | /* delete other expectation. */ | ||
149 | DEBUGP("found\n"); | ||
150 | ip_conntrack_unexpect_related(exp_other); | ||
151 | ip_conntrack_expect_put(exp_other); | ||
152 | } else { | ||
153 | DEBUGP("not found\n"); | ||
154 | } | ||
155 | } else { | ||
156 | /* we need more than simple inversion */ | ||
157 | ip_nat_pptp_hook_expectfn(ct, exp); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | static int destroy_sibling_or_exp(const struct ip_conntrack_tuple *t) | ||
162 | { | ||
163 | struct ip_conntrack_tuple_hash *h; | ||
164 | struct ip_conntrack_expect *exp; | ||
165 | |||
166 | DEBUGP("trying to timeout ct or exp for tuple "); | ||
167 | DUMP_TUPLE(t); | ||
168 | |||
169 | h = ip_conntrack_find_get(t, NULL); | ||
170 | if (h) { | ||
171 | struct ip_conntrack *sibling = tuplehash_to_ctrack(h); | ||
172 | DEBUGP("setting timeout of conntrack %p to 0\n", sibling); | ||
173 | sibling->proto.gre.timeout = 0; | ||
174 | sibling->proto.gre.stream_timeout = 0; | ||
175 | /* refresh_acct will not modify counters if skb == NULL */ | ||
176 | if (del_timer(&sibling->timeout)) | ||
177 | sibling->timeout.function((unsigned long)sibling); | ||
178 | ip_conntrack_put(sibling); | ||
179 | return 1; | ||
180 | } else { | ||
181 | exp = ip_conntrack_expect_find(t); | ||
182 | if (exp) { | ||
183 | DEBUGP("unexpect_related of expect %p\n", exp); | ||
184 | ip_conntrack_unexpect_related(exp); | ||
185 | ip_conntrack_expect_put(exp); | ||
186 | return 1; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | |||
194 | /* timeout GRE data connections */ | ||
195 | static void pptp_destroy_siblings(struct ip_conntrack *ct) | ||
196 | { | ||
197 | struct ip_conntrack_tuple t; | ||
198 | |||
199 | /* Since ct->sibling_list has literally rusted away in 2.6.11, | ||
200 | * we now need another way to find out about our sibling | ||
201 | * contrack and expects... -HW */ | ||
202 | |||
203 | /* try original (pns->pac) tuple */ | ||
204 | memcpy(&t, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, sizeof(t)); | ||
205 | t.dst.protonum = IPPROTO_GRE; | ||
206 | t.src.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id); | ||
207 | t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id); | ||
208 | |||
209 | if (!destroy_sibling_or_exp(&t)) | ||
210 | DEBUGP("failed to timeout original pns->pac ct/exp\n"); | ||
211 | |||
212 | /* try reply (pac->pns) tuple */ | ||
213 | memcpy(&t, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, sizeof(t)); | ||
214 | t.dst.protonum = IPPROTO_GRE; | ||
215 | t.src.u.gre.key = htons(ct->help.ct_pptp_info.pac_call_id); | ||
216 | t.dst.u.gre.key = htons(ct->help.ct_pptp_info.pns_call_id); | ||
217 | |||
218 | if (!destroy_sibling_or_exp(&t)) | ||
219 | DEBUGP("failed to timeout reply pac->pns ct/exp\n"); | ||
220 | } | ||
221 | |||
222 | /* expect GRE connections (PNS->PAC and PAC->PNS direction) */ | ||
223 | static inline int | ||
224 | exp_gre(struct ip_conntrack *master, | ||
225 | u_int32_t seq, | ||
226 | u_int16_t callid, | ||
227 | u_int16_t peer_callid) | ||
228 | { | ||
229 | struct ip_conntrack_tuple inv_tuple; | ||
230 | struct ip_conntrack_tuple exp_tuples[] = { | ||
231 | /* tuple in original direction, PNS->PAC */ | ||
232 | { .src = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip, | ||
233 | .u = { .gre = { .key = peer_callid } } | ||
234 | }, | ||
235 | .dst = { .ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip, | ||
236 | .u = { .gre = { .key = callid } }, | ||
237 | .protonum = IPPROTO_GRE | ||
238 | }, | ||
239 | }, | ||
240 | /* tuple in reply direction, PAC->PNS */ | ||
241 | { .src = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip, | ||
242 | .u = { .gre = { .key = callid } } | ||
243 | }, | ||
244 | .dst = { .ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip, | ||
245 | .u = { .gre = { .key = peer_callid } }, | ||
246 | .protonum = IPPROTO_GRE | ||
247 | }, | ||
248 | } | ||
249 | }; | ||
250 | struct ip_conntrack_expect *exp_orig, *exp_reply; | ||
251 | int ret = 1; | ||
252 | |||
253 | exp_orig = ip_conntrack_expect_alloc(master); | ||
254 | if (exp_orig == NULL) | ||
255 | goto out; | ||
256 | |||
257 | exp_reply = ip_conntrack_expect_alloc(master); | ||
258 | if (exp_reply == NULL) | ||
259 | goto out_put_orig; | ||
260 | |||
261 | memcpy(&exp_orig->tuple, &exp_tuples[0], sizeof(exp_orig->tuple)); | ||
262 | |||
263 | exp_orig->mask.src.ip = 0xffffffff; | ||
264 | exp_orig->mask.src.u.all = 0; | ||
265 | exp_orig->mask.dst.u.all = 0; | ||
266 | exp_orig->mask.dst.u.gre.key = 0xffff; | ||
267 | exp_orig->mask.dst.ip = 0xffffffff; | ||
268 | exp_orig->mask.dst.protonum = 0xff; | ||
269 | |||
270 | exp_orig->master = master; | ||
271 | exp_orig->expectfn = pptp_expectfn; | ||
272 | exp_orig->flags = 0; | ||
273 | |||
274 | exp_orig->dir = IP_CT_DIR_ORIGINAL; | ||
275 | |||
276 | /* both expectations are identical apart from tuple */ | ||
277 | memcpy(exp_reply, exp_orig, sizeof(*exp_reply)); | ||
278 | memcpy(&exp_reply->tuple, &exp_tuples[1], sizeof(exp_reply->tuple)); | ||
279 | |||
280 | exp_reply->dir = !exp_orig->dir; | ||
281 | |||
282 | if (ip_nat_pptp_hook_exp_gre) | ||
283 | ret = ip_nat_pptp_hook_exp_gre(exp_orig, exp_reply); | ||
284 | else { | ||
285 | |||
286 | DEBUGP("calling expect_related PNS->PAC"); | ||
287 | DUMP_TUPLE(&exp_orig->tuple); | ||
288 | |||
289 | if (ip_conntrack_expect_related(exp_orig) != 0) { | ||
290 | DEBUGP("cannot expect_related()\n"); | ||
291 | goto out_put_both; | ||
292 | } | ||
293 | |||
294 | DEBUGP("calling expect_related PAC->PNS"); | ||
295 | DUMP_TUPLE(&exp_reply->tuple); | ||
296 | |||
297 | if (ip_conntrack_expect_related(exp_reply) != 0) { | ||
298 | DEBUGP("cannot expect_related()\n"); | ||
299 | goto out_unexpect_orig; | ||
300 | } | ||
301 | |||
302 | /* Add GRE keymap entries */ | ||
303 | if (ip_ct_gre_keymap_add(master, &exp_reply->tuple, 0) != 0) { | ||
304 | DEBUGP("cannot keymap_add() exp\n"); | ||
305 | goto out_unexpect_both; | ||
306 | } | ||
307 | |||
308 | invert_tuplepr(&inv_tuple, &exp_reply->tuple); | ||
309 | if (ip_ct_gre_keymap_add(master, &inv_tuple, 1) != 0) { | ||
310 | ip_ct_gre_keymap_destroy(master); | ||
311 | DEBUGP("cannot keymap_add() exp_inv\n"); | ||
312 | goto out_unexpect_both; | ||
313 | } | ||
314 | ret = 0; | ||
315 | } | ||
316 | |||
317 | out_put_both: | ||
318 | ip_conntrack_expect_put(exp_reply); | ||
319 | out_put_orig: | ||
320 | ip_conntrack_expect_put(exp_orig); | ||
321 | out: | ||
322 | return ret; | ||
323 | |||
324 | out_unexpect_both: | ||
325 | ip_conntrack_unexpect_related(exp_reply); | ||
326 | out_unexpect_orig: | ||
327 | ip_conntrack_unexpect_related(exp_orig); | ||
328 | goto out_put_both; | ||
329 | } | ||
330 | |||
331 | static inline int | ||
332 | pptp_inbound_pkt(struct sk_buff **pskb, | ||
333 | struct tcphdr *tcph, | ||
334 | unsigned int nexthdr_off, | ||
335 | unsigned int datalen, | ||
336 | struct ip_conntrack *ct, | ||
337 | enum ip_conntrack_info ctinfo) | ||
338 | { | ||
339 | struct PptpControlHeader _ctlh, *ctlh; | ||
340 | unsigned int reqlen; | ||
341 | union pptp_ctrl_union _pptpReq, *pptpReq; | ||
342 | struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; | ||
343 | u_int16_t msg, *cid, *pcid; | ||
344 | u_int32_t seq; | ||
345 | |||
346 | ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh); | ||
347 | if (!ctlh) { | ||
348 | DEBUGP("error during skb_header_pointer\n"); | ||
349 | return NF_ACCEPT; | ||
350 | } | ||
351 | nexthdr_off += sizeof(_ctlh); | ||
352 | datalen -= sizeof(_ctlh); | ||
353 | |||
354 | reqlen = datalen; | ||
355 | if (reqlen > sizeof(*pptpReq)) | ||
356 | reqlen = sizeof(*pptpReq); | ||
357 | pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq); | ||
358 | if (!pptpReq) { | ||
359 | DEBUGP("error during skb_header_pointer\n"); | ||
360 | return NF_ACCEPT; | ||
361 | } | ||
362 | |||
363 | msg = ntohs(ctlh->messageType); | ||
364 | DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); | ||
365 | |||
366 | switch (msg) { | ||
367 | case PPTP_START_SESSION_REPLY: | ||
368 | if (reqlen < sizeof(_pptpReq.srep)) { | ||
369 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
370 | break; | ||
371 | } | ||
372 | |||
373 | /* server confirms new control session */ | ||
374 | if (info->sstate < PPTP_SESSION_REQUESTED) { | ||
375 | DEBUGP("%s without START_SESS_REQUEST\n", | ||
376 | pptp_msg_name[msg]); | ||
377 | break; | ||
378 | } | ||
379 | if (pptpReq->srep.resultCode == PPTP_START_OK) | ||
380 | info->sstate = PPTP_SESSION_CONFIRMED; | ||
381 | else | ||
382 | info->sstate = PPTP_SESSION_ERROR; | ||
383 | break; | ||
384 | |||
385 | case PPTP_STOP_SESSION_REPLY: | ||
386 | if (reqlen < sizeof(_pptpReq.strep)) { | ||
387 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
388 | break; | ||
389 | } | ||
390 | |||
391 | /* server confirms end of control session */ | ||
392 | if (info->sstate > PPTP_SESSION_STOPREQ) { | ||
393 | DEBUGP("%s without STOP_SESS_REQUEST\n", | ||
394 | pptp_msg_name[msg]); | ||
395 | break; | ||
396 | } | ||
397 | if (pptpReq->strep.resultCode == PPTP_STOP_OK) | ||
398 | info->sstate = PPTP_SESSION_NONE; | ||
399 | else | ||
400 | info->sstate = PPTP_SESSION_ERROR; | ||
401 | break; | ||
402 | |||
403 | case PPTP_OUT_CALL_REPLY: | ||
404 | if (reqlen < sizeof(_pptpReq.ocack)) { | ||
405 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
406 | break; | ||
407 | } | ||
408 | |||
409 | /* server accepted call, we now expect GRE frames */ | ||
410 | if (info->sstate != PPTP_SESSION_CONFIRMED) { | ||
411 | DEBUGP("%s but no session\n", pptp_msg_name[msg]); | ||
412 | break; | ||
413 | } | ||
414 | if (info->cstate != PPTP_CALL_OUT_REQ && | ||
415 | info->cstate != PPTP_CALL_OUT_CONF) { | ||
416 | DEBUGP("%s without OUTCALL_REQ\n", pptp_msg_name[msg]); | ||
417 | break; | ||
418 | } | ||
419 | if (pptpReq->ocack.resultCode != PPTP_OUTCALL_CONNECT) { | ||
420 | info->cstate = PPTP_CALL_NONE; | ||
421 | break; | ||
422 | } | ||
423 | |||
424 | cid = &pptpReq->ocack.callID; | ||
425 | pcid = &pptpReq->ocack.peersCallID; | ||
426 | |||
427 | info->pac_call_id = ntohs(*cid); | ||
428 | |||
429 | if (htons(info->pns_call_id) != *pcid) { | ||
430 | DEBUGP("%s for unknown callid %u\n", | ||
431 | pptp_msg_name[msg], ntohs(*pcid)); | ||
432 | break; | ||
433 | } | ||
434 | |||
435 | DEBUGP("%s, CID=%X, PCID=%X\n", pptp_msg_name[msg], | ||
436 | ntohs(*cid), ntohs(*pcid)); | ||
437 | |||
438 | info->cstate = PPTP_CALL_OUT_CONF; | ||
439 | |||
440 | seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr) | ||
441 | + sizeof(struct PptpControlHeader) | ||
442 | + ((void *)pcid - (void *)pptpReq); | ||
443 | |||
444 | if (exp_gre(ct, seq, *cid, *pcid) != 0) | ||
445 | printk("ip_conntrack_pptp: error during exp_gre\n"); | ||
446 | break; | ||
447 | |||
448 | case PPTP_IN_CALL_REQUEST: | ||
449 | if (reqlen < sizeof(_pptpReq.icack)) { | ||
450 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
451 | break; | ||
452 | } | ||
453 | |||
454 | /* server tells us about incoming call request */ | ||
455 | if (info->sstate != PPTP_SESSION_CONFIRMED) { | ||
456 | DEBUGP("%s but no session\n", pptp_msg_name[msg]); | ||
457 | break; | ||
458 | } | ||
459 | pcid = &pptpReq->icack.peersCallID; | ||
460 | DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid)); | ||
461 | info->cstate = PPTP_CALL_IN_REQ; | ||
462 | info->pac_call_id = ntohs(*pcid); | ||
463 | break; | ||
464 | |||
465 | case PPTP_IN_CALL_CONNECT: | ||
466 | if (reqlen < sizeof(_pptpReq.iccon)) { | ||
467 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
468 | break; | ||
469 | } | ||
470 | |||
471 | /* server tells us about incoming call established */ | ||
472 | if (info->sstate != PPTP_SESSION_CONFIRMED) { | ||
473 | DEBUGP("%s but no session\n", pptp_msg_name[msg]); | ||
474 | break; | ||
475 | } | ||
476 | if (info->sstate != PPTP_CALL_IN_REP | ||
477 | && info->sstate != PPTP_CALL_IN_CONF) { | ||
478 | DEBUGP("%s but never sent IN_CALL_REPLY\n", | ||
479 | pptp_msg_name[msg]); | ||
480 | break; | ||
481 | } | ||
482 | |||
483 | pcid = &pptpReq->iccon.peersCallID; | ||
484 | cid = &info->pac_call_id; | ||
485 | |||
486 | if (info->pns_call_id != ntohs(*pcid)) { | ||
487 | DEBUGP("%s for unknown CallID %u\n", | ||
488 | pptp_msg_name[msg], ntohs(*cid)); | ||
489 | break; | ||
490 | } | ||
491 | |||
492 | DEBUGP("%s, PCID=%X\n", pptp_msg_name[msg], ntohs(*pcid)); | ||
493 | info->cstate = PPTP_CALL_IN_CONF; | ||
494 | |||
495 | /* we expect a GRE connection from PAC to PNS */ | ||
496 | seq = ntohl(tcph->seq) + sizeof(struct pptp_pkt_hdr) | ||
497 | + sizeof(struct PptpControlHeader) | ||
498 | + ((void *)pcid - (void *)pptpReq); | ||
499 | |||
500 | if (exp_gre(ct, seq, *cid, *pcid) != 0) | ||
501 | printk("ip_conntrack_pptp: error during exp_gre\n"); | ||
502 | |||
503 | break; | ||
504 | |||
505 | case PPTP_CALL_DISCONNECT_NOTIFY: | ||
506 | if (reqlen < sizeof(_pptpReq.disc)) { | ||
507 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
508 | break; | ||
509 | } | ||
510 | |||
511 | /* server confirms disconnect */ | ||
512 | cid = &pptpReq->disc.callID; | ||
513 | DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid)); | ||
514 | info->cstate = PPTP_CALL_NONE; | ||
515 | |||
516 | /* untrack this call id, unexpect GRE packets */ | ||
517 | pptp_destroy_siblings(ct); | ||
518 | break; | ||
519 | |||
520 | case PPTP_WAN_ERROR_NOTIFY: | ||
521 | break; | ||
522 | |||
523 | case PPTP_ECHO_REQUEST: | ||
524 | case PPTP_ECHO_REPLY: | ||
525 | /* I don't have to explain these ;) */ | ||
526 | break; | ||
527 | default: | ||
528 | DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX) | ||
529 | ? pptp_msg_name[msg]:pptp_msg_name[0], msg); | ||
530 | break; | ||
531 | } | ||
532 | |||
533 | |||
534 | if (ip_nat_pptp_hook_inbound) | ||
535 | return ip_nat_pptp_hook_inbound(pskb, ct, ctinfo, ctlh, | ||
536 | pptpReq); | ||
537 | |||
538 | return NF_ACCEPT; | ||
539 | |||
540 | } | ||
541 | |||
542 | static inline int | ||
543 | pptp_outbound_pkt(struct sk_buff **pskb, | ||
544 | struct tcphdr *tcph, | ||
545 | unsigned int nexthdr_off, | ||
546 | unsigned int datalen, | ||
547 | struct ip_conntrack *ct, | ||
548 | enum ip_conntrack_info ctinfo) | ||
549 | { | ||
550 | struct PptpControlHeader _ctlh, *ctlh; | ||
551 | unsigned int reqlen; | ||
552 | union pptp_ctrl_union _pptpReq, *pptpReq; | ||
553 | struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; | ||
554 | u_int16_t msg, *cid, *pcid; | ||
555 | |||
556 | ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh); | ||
557 | if (!ctlh) | ||
558 | return NF_ACCEPT; | ||
559 | nexthdr_off += sizeof(_ctlh); | ||
560 | datalen -= sizeof(_ctlh); | ||
561 | |||
562 | reqlen = datalen; | ||
563 | if (reqlen > sizeof(*pptpReq)) | ||
564 | reqlen = sizeof(*pptpReq); | ||
565 | pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq); | ||
566 | if (!pptpReq) | ||
567 | return NF_ACCEPT; | ||
568 | |||
569 | msg = ntohs(ctlh->messageType); | ||
570 | DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); | ||
571 | |||
572 | switch (msg) { | ||
573 | case PPTP_START_SESSION_REQUEST: | ||
574 | /* client requests for new control session */ | ||
575 | if (info->sstate != PPTP_SESSION_NONE) { | ||
576 | DEBUGP("%s but we already have one", | ||
577 | pptp_msg_name[msg]); | ||
578 | } | ||
579 | info->sstate = PPTP_SESSION_REQUESTED; | ||
580 | break; | ||
581 | case PPTP_STOP_SESSION_REQUEST: | ||
582 | /* client requests end of control session */ | ||
583 | info->sstate = PPTP_SESSION_STOPREQ; | ||
584 | break; | ||
585 | |||
586 | case PPTP_OUT_CALL_REQUEST: | ||
587 | if (reqlen < sizeof(_pptpReq.ocreq)) { | ||
588 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
589 | /* FIXME: break; */ | ||
590 | } | ||
591 | |||
592 | /* client initiating connection to server */ | ||
593 | if (info->sstate != PPTP_SESSION_CONFIRMED) { | ||
594 | DEBUGP("%s but no session\n", | ||
595 | pptp_msg_name[msg]); | ||
596 | break; | ||
597 | } | ||
598 | info->cstate = PPTP_CALL_OUT_REQ; | ||
599 | /* track PNS call id */ | ||
600 | cid = &pptpReq->ocreq.callID; | ||
601 | DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*cid)); | ||
602 | info->pns_call_id = ntohs(*cid); | ||
603 | break; | ||
604 | case PPTP_IN_CALL_REPLY: | ||
605 | if (reqlen < sizeof(_pptpReq.icack)) { | ||
606 | DEBUGP("%s: short packet\n", pptp_msg_name[msg]); | ||
607 | break; | ||
608 | } | ||
609 | |||
610 | /* client answers incoming call */ | ||
611 | if (info->cstate != PPTP_CALL_IN_REQ | ||
612 | && info->cstate != PPTP_CALL_IN_REP) { | ||
613 | DEBUGP("%s without incall_req\n", | ||
614 | pptp_msg_name[msg]); | ||
615 | break; | ||
616 | } | ||
617 | if (pptpReq->icack.resultCode != PPTP_INCALL_ACCEPT) { | ||
618 | info->cstate = PPTP_CALL_NONE; | ||
619 | break; | ||
620 | } | ||
621 | pcid = &pptpReq->icack.peersCallID; | ||
622 | if (info->pac_call_id != ntohs(*pcid)) { | ||
623 | DEBUGP("%s for unknown call %u\n", | ||
624 | pptp_msg_name[msg], ntohs(*pcid)); | ||
625 | break; | ||
626 | } | ||
627 | DEBUGP("%s, CID=%X\n", pptp_msg_name[msg], ntohs(*pcid)); | ||
628 | /* part two of the three-way handshake */ | ||
629 | info->cstate = PPTP_CALL_IN_REP; | ||
630 | info->pns_call_id = ntohs(pptpReq->icack.callID); | ||
631 | break; | ||
632 | |||
633 | case PPTP_CALL_CLEAR_REQUEST: | ||
634 | /* client requests hangup of call */ | ||
635 | if (info->sstate != PPTP_SESSION_CONFIRMED) { | ||
636 | DEBUGP("CLEAR_CALL but no session\n"); | ||
637 | break; | ||
638 | } | ||
639 | /* FUTURE: iterate over all calls and check if | ||
640 | * call ID is valid. We don't do this without newnat, | ||
641 | * because we only know about last call */ | ||
642 | info->cstate = PPTP_CALL_CLEAR_REQ; | ||
643 | break; | ||
644 | case PPTP_SET_LINK_INFO: | ||
645 | break; | ||
646 | case PPTP_ECHO_REQUEST: | ||
647 | case PPTP_ECHO_REPLY: | ||
648 | /* I don't have to explain these ;) */ | ||
649 | break; | ||
650 | default: | ||
651 | DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)? | ||
652 | pptp_msg_name[msg]:pptp_msg_name[0], msg); | ||
653 | /* unknown: no need to create GRE masq table entry */ | ||
654 | break; | ||
655 | } | ||
656 | |||
657 | if (ip_nat_pptp_hook_outbound) | ||
658 | return ip_nat_pptp_hook_outbound(pskb, ct, ctinfo, ctlh, | ||
659 | pptpReq); | ||
660 | |||
661 | return NF_ACCEPT; | ||
662 | } | ||
663 | |||
664 | |||
665 | /* track caller id inside control connection, call expect_related */ | ||
666 | static int | ||
667 | conntrack_pptp_help(struct sk_buff **pskb, | ||
668 | struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) | ||
669 | |||
670 | { | ||
671 | struct pptp_pkt_hdr _pptph, *pptph; | ||
672 | struct tcphdr _tcph, *tcph; | ||
673 | u_int32_t tcplen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4; | ||
674 | u_int32_t datalen; | ||
675 | int dir = CTINFO2DIR(ctinfo); | ||
676 | struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; | ||
677 | unsigned int nexthdr_off; | ||
678 | |||
679 | int oldsstate, oldcstate; | ||
680 | int ret; | ||
681 | |||
682 | /* don't do any tracking before tcp handshake complete */ | ||
683 | if (ctinfo != IP_CT_ESTABLISHED | ||
684 | && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) { | ||
685 | DEBUGP("ctinfo = %u, skipping\n", ctinfo); | ||
686 | return NF_ACCEPT; | ||
687 | } | ||
688 | |||
689 | nexthdr_off = (*pskb)->nh.iph->ihl*4; | ||
690 | tcph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_tcph), &_tcph); | ||
691 | BUG_ON(!tcph); | ||
692 | nexthdr_off += tcph->doff * 4; | ||
693 | datalen = tcplen - tcph->doff * 4; | ||
694 | |||
695 | if (tcph->fin || tcph->rst) { | ||
696 | DEBUGP("RST/FIN received, timeouting GRE\n"); | ||
697 | /* can't do this after real newnat */ | ||
698 | info->cstate = PPTP_CALL_NONE; | ||
699 | |||
700 | /* untrack this call id, unexpect GRE packets */ | ||
701 | pptp_destroy_siblings(ct); | ||
702 | } | ||
703 | |||
704 | pptph = skb_header_pointer(*pskb, nexthdr_off, sizeof(_pptph), &_pptph); | ||
705 | if (!pptph) { | ||
706 | DEBUGP("no full PPTP header, can't track\n"); | ||
707 | return NF_ACCEPT; | ||
708 | } | ||
709 | nexthdr_off += sizeof(_pptph); | ||
710 | datalen -= sizeof(_pptph); | ||
711 | |||
712 | /* if it's not a control message we can't do anything with it */ | ||
713 | if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL || | ||
714 | ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) { | ||
715 | DEBUGP("not a control packet\n"); | ||
716 | return NF_ACCEPT; | ||
717 | } | ||
718 | |||
719 | oldsstate = info->sstate; | ||
720 | oldcstate = info->cstate; | ||
721 | |||
722 | spin_lock_bh(&ip_pptp_lock); | ||
723 | |||
724 | /* FIXME: We just blindly assume that the control connection is always | ||
725 | * established from PNS->PAC. However, RFC makes no guarantee */ | ||
726 | if (dir == IP_CT_DIR_ORIGINAL) | ||
727 | /* client -> server (PNS -> PAC) */ | ||
728 | ret = pptp_outbound_pkt(pskb, tcph, nexthdr_off, datalen, ct, | ||
729 | ctinfo); | ||
730 | else | ||
731 | /* server -> client (PAC -> PNS) */ | ||
732 | ret = pptp_inbound_pkt(pskb, tcph, nexthdr_off, datalen, ct, | ||
733 | ctinfo); | ||
734 | DEBUGP("sstate: %d->%d, cstate: %d->%d\n", | ||
735 | oldsstate, info->sstate, oldcstate, info->cstate); | ||
736 | spin_unlock_bh(&ip_pptp_lock); | ||
737 | |||
738 | return ret; | ||
739 | } | ||
740 | |||
741 | /* control protocol helper */ | ||
742 | static struct ip_conntrack_helper pptp = { | ||
743 | .list = { NULL, NULL }, | ||
744 | .name = "pptp", | ||
745 | .me = THIS_MODULE, | ||
746 | .max_expected = 2, | ||
747 | .timeout = 5 * 60, | ||
748 | .tuple = { .src = { .ip = 0, | ||
749 | .u = { .tcp = { .port = | ||
750 | __constant_htons(PPTP_CONTROL_PORT) } } | ||
751 | }, | ||
752 | .dst = { .ip = 0, | ||
753 | .u = { .all = 0 }, | ||
754 | .protonum = IPPROTO_TCP | ||
755 | } | ||
756 | }, | ||
757 | .mask = { .src = { .ip = 0, | ||
758 | .u = { .tcp = { .port = 0xffff } } | ||
759 | }, | ||
760 | .dst = { .ip = 0, | ||
761 | .u = { .all = 0 }, | ||
762 | .protonum = 0xff | ||
763 | } | ||
764 | }, | ||
765 | .help = conntrack_pptp_help | ||
766 | }; | ||
767 | |||
768 | extern void __exit ip_ct_proto_gre_fini(void); | ||
769 | extern int __init ip_ct_proto_gre_init(void); | ||
770 | |||
771 | /* ip_conntrack_pptp initialization */ | ||
772 | static int __init init(void) | ||
773 | { | ||
774 | int retcode; | ||
775 | |||
776 | retcode = ip_ct_proto_gre_init(); | ||
777 | if (retcode < 0) | ||
778 | return retcode; | ||
779 | |||
780 | DEBUGP(" registering helper\n"); | ||
781 | if ((retcode = ip_conntrack_helper_register(&pptp))) { | ||
782 | printk(KERN_ERR "Unable to register conntrack application " | ||
783 | "helper for pptp: %d\n", retcode); | ||
784 | ip_ct_proto_gre_fini(); | ||
785 | return retcode; | ||
786 | } | ||
787 | |||
788 | printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION); | ||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | static void __exit fini(void) | ||
793 | { | ||
794 | ip_conntrack_helper_unregister(&pptp); | ||
795 | ip_ct_proto_gre_fini(); | ||
796 | printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION); | ||
797 | } | ||
798 | |||
799 | module_init(init); | ||
800 | module_exit(fini); | ||
801 | |||
802 | EXPORT_SYMBOL(ip_nat_pptp_hook_outbound); | ||
803 | EXPORT_SYMBOL(ip_nat_pptp_hook_inbound); | ||
804 | EXPORT_SYMBOL(ip_nat_pptp_hook_exp_gre); | ||
805 | EXPORT_SYMBOL(ip_nat_pptp_hook_expectfn); | ||
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 15aef3564742..b08a432efcf8 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c | |||
@@ -1270,7 +1270,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1270 | if (err < 0) | 1270 | if (err < 0) |
1271 | return err; | 1271 | return err; |
1272 | 1272 | ||
1273 | exp = ip_conntrack_expect_find_get(&tuple); | 1273 | exp = ip_conntrack_expect_find(&tuple); |
1274 | if (!exp) | 1274 | if (!exp) |
1275 | return -ENOENT; | 1275 | return -ENOENT; |
1276 | 1276 | ||
@@ -1318,7 +1318,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
1318 | return err; | 1318 | return err; |
1319 | 1319 | ||
1320 | /* bump usage count to 2 */ | 1320 | /* bump usage count to 2 */ |
1321 | exp = ip_conntrack_expect_find_get(&tuple); | 1321 | exp = ip_conntrack_expect_find(&tuple); |
1322 | if (!exp) | 1322 | if (!exp) |
1323 | return -ENOENT; | 1323 | return -ENOENT; |
1324 | 1324 | ||
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c new file mode 100644 index 000000000000..de3cb9db6f85 --- /dev/null +++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c | |||
@@ -0,0 +1,327 @@ | |||
1 | /* | ||
2 | * ip_conntrack_proto_gre.c - Version 3.0 | ||
3 | * | ||
4 | * Connection tracking protocol helper module for GRE. | ||
5 | * | ||
6 | * GRE is a generic encapsulation protocol, which is generally not very | ||
7 | * suited for NAT, as it has no protocol-specific part as port numbers. | ||
8 | * | ||
9 | * It has an optional key field, which may help us distinguishing two | ||
10 | * connections between the same two hosts. | ||
11 | * | ||
12 | * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 | ||
13 | * | ||
14 | * PPTP is built on top of a modified version of GRE, and has a mandatory | ||
15 | * field called "CallID", which serves us for the same purpose as the key | ||
16 | * field in plain GRE. | ||
17 | * | ||
18 | * Documentation about PPTP can be found in RFC 2637 | ||
19 | * | ||
20 | * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org> | ||
21 | * | ||
22 | * Development of this code funded by Astaro AG (http://www.astaro.com/) | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <linux/config.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/types.h> | ||
29 | #include <linux/timer.h> | ||
30 | #include <linux/netfilter.h> | ||
31 | #include <linux/ip.h> | ||
32 | #include <linux/in.h> | ||
33 | #include <linux/list.h> | ||
34 | |||
35 | static DEFINE_RWLOCK(ip_ct_gre_lock); | ||
36 | #define ASSERT_READ_LOCK(x) | ||
37 | #define ASSERT_WRITE_LOCK(x) | ||
38 | |||
39 | #include <linux/netfilter_ipv4/listhelp.h> | ||
40 | #include <linux/netfilter_ipv4/ip_conntrack_protocol.h> | ||
41 | #include <linux/netfilter_ipv4/ip_conntrack_helper.h> | ||
42 | #include <linux/netfilter_ipv4/ip_conntrack_core.h> | ||
43 | |||
44 | #include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h> | ||
45 | #include <linux/netfilter_ipv4/ip_conntrack_pptp.h> | ||
46 | |||
47 | MODULE_LICENSE("GPL"); | ||
48 | MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); | ||
49 | MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE"); | ||
50 | |||
51 | /* shamelessly stolen from ip_conntrack_proto_udp.c */ | ||
52 | #define GRE_TIMEOUT (30*HZ) | ||
53 | #define GRE_STREAM_TIMEOUT (180*HZ) | ||
54 | |||
55 | #if 0 | ||
56 | #define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args) | ||
57 | #define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x\n", \ | ||
58 | NIPQUAD((x)->src.ip), ntohs((x)->src.u.gre.key), \ | ||
59 | NIPQUAD((x)->dst.ip), ntohs((x)->dst.u.gre.key)) | ||
60 | #else | ||
61 | #define DEBUGP(x, args...) | ||
62 | #define DUMP_TUPLE_GRE(x) | ||
63 | #endif | ||
64 | |||
65 | /* GRE KEYMAP HANDLING FUNCTIONS */ | ||
66 | static LIST_HEAD(gre_keymap_list); | ||
67 | |||
68 | static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km, | ||
69 | const struct ip_conntrack_tuple *t) | ||
70 | { | ||
71 | return ((km->tuple.src.ip == t->src.ip) && | ||
72 | (km->tuple.dst.ip == t->dst.ip) && | ||
73 | (km->tuple.dst.protonum == t->dst.protonum) && | ||
74 | (km->tuple.dst.u.all == t->dst.u.all)); | ||
75 | } | ||
76 | |||
77 | /* look up the source key for a given tuple */ | ||
78 | static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t) | ||
79 | { | ||
80 | struct ip_ct_gre_keymap *km; | ||
81 | u_int32_t key = 0; | ||
82 | |||
83 | read_lock_bh(&ip_ct_gre_lock); | ||
84 | km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn, | ||
85 | struct ip_ct_gre_keymap *, t); | ||
86 | if (km) | ||
87 | key = km->tuple.src.u.gre.key; | ||
88 | read_unlock_bh(&ip_ct_gre_lock); | ||
89 | |||
90 | DEBUGP("lookup src key 0x%x up key for ", key); | ||
91 | DUMP_TUPLE_GRE(t); | ||
92 | |||
93 | return key; | ||
94 | } | ||
95 | |||
96 | /* add a single keymap entry, associate with specified master ct */ | ||
97 | int | ||
98 | ip_ct_gre_keymap_add(struct ip_conntrack *ct, | ||
99 | struct ip_conntrack_tuple *t, int reply) | ||
100 | { | ||
101 | struct ip_ct_gre_keymap **exist_km, *km, *old; | ||
102 | |||
103 | if (!ct->helper || strcmp(ct->helper->name, "pptp")) { | ||
104 | DEBUGP("refusing to add GRE keymap to non-pptp session\n"); | ||
105 | return -1; | ||
106 | } | ||
107 | |||
108 | if (!reply) | ||
109 | exist_km = &ct->help.ct_pptp_info.keymap_orig; | ||
110 | else | ||
111 | exist_km = &ct->help.ct_pptp_info.keymap_reply; | ||
112 | |||
113 | if (*exist_km) { | ||
114 | /* check whether it's a retransmission */ | ||
115 | old = LIST_FIND(&gre_keymap_list, gre_key_cmpfn, | ||
116 | struct ip_ct_gre_keymap *, t); | ||
117 | if (old == *exist_km) { | ||
118 | DEBUGP("retransmission\n"); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | DEBUGP("trying to override keymap_%s for ct %p\n", | ||
123 | reply? "reply":"orig", ct); | ||
124 | return -EEXIST; | ||
125 | } | ||
126 | |||
127 | km = kmalloc(sizeof(*km), GFP_ATOMIC); | ||
128 | if (!km) | ||
129 | return -ENOMEM; | ||
130 | |||
131 | memcpy(&km->tuple, t, sizeof(*t)); | ||
132 | *exist_km = km; | ||
133 | |||
134 | DEBUGP("adding new entry %p: ", km); | ||
135 | DUMP_TUPLE_GRE(&km->tuple); | ||
136 | |||
137 | write_lock_bh(&ip_ct_gre_lock); | ||
138 | list_append(&gre_keymap_list, km); | ||
139 | write_unlock_bh(&ip_ct_gre_lock); | ||
140 | |||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | /* destroy the keymap entries associated with specified master ct */ | ||
145 | void ip_ct_gre_keymap_destroy(struct ip_conntrack *ct) | ||
146 | { | ||
147 | DEBUGP("entering for ct %p\n", ct); | ||
148 | |||
149 | if (!ct->helper || strcmp(ct->helper->name, "pptp")) { | ||
150 | DEBUGP("refusing to destroy GRE keymap to non-pptp session\n"); | ||
151 | return; | ||
152 | } | ||
153 | |||
154 | write_lock_bh(&ip_ct_gre_lock); | ||
155 | if (ct->help.ct_pptp_info.keymap_orig) { | ||
156 | DEBUGP("removing %p from list\n", | ||
157 | ct->help.ct_pptp_info.keymap_orig); | ||
158 | list_del(&ct->help.ct_pptp_info.keymap_orig->list); | ||
159 | kfree(ct->help.ct_pptp_info.keymap_orig); | ||
160 | ct->help.ct_pptp_info.keymap_orig = NULL; | ||
161 | } | ||
162 | if (ct->help.ct_pptp_info.keymap_reply) { | ||
163 | DEBUGP("removing %p from list\n", | ||
164 | ct->help.ct_pptp_info.keymap_reply); | ||
165 | list_del(&ct->help.ct_pptp_info.keymap_reply->list); | ||
166 | kfree(ct->help.ct_pptp_info.keymap_reply); | ||
167 | ct->help.ct_pptp_info.keymap_reply = NULL; | ||
168 | } | ||
169 | write_unlock_bh(&ip_ct_gre_lock); | ||
170 | } | ||
171 | |||
172 | |||
173 | /* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */ | ||
174 | |||
175 | /* invert gre part of tuple */ | ||
176 | static int gre_invert_tuple(struct ip_conntrack_tuple *tuple, | ||
177 | const struct ip_conntrack_tuple *orig) | ||
178 | { | ||
179 | tuple->dst.u.gre.key = orig->src.u.gre.key; | ||
180 | tuple->src.u.gre.key = orig->dst.u.gre.key; | ||
181 | |||
182 | return 1; | ||
183 | } | ||
184 | |||
185 | /* gre hdr info to tuple */ | ||
186 | static int gre_pkt_to_tuple(const struct sk_buff *skb, | ||
187 | unsigned int dataoff, | ||
188 | struct ip_conntrack_tuple *tuple) | ||
189 | { | ||
190 | struct gre_hdr_pptp _pgrehdr, *pgrehdr; | ||
191 | u_int32_t srckey; | ||
192 | struct gre_hdr _grehdr, *grehdr; | ||
193 | |||
194 | /* first only delinearize old RFC1701 GRE header */ | ||
195 | grehdr = skb_header_pointer(skb, dataoff, sizeof(_grehdr), &_grehdr); | ||
196 | if (!grehdr || grehdr->version != GRE_VERSION_PPTP) { | ||
197 | /* try to behave like "ip_conntrack_proto_generic" */ | ||
198 | tuple->src.u.all = 0; | ||
199 | tuple->dst.u.all = 0; | ||
200 | return 1; | ||
201 | } | ||
202 | |||
203 | /* PPTP header is variable length, only need up to the call_id field */ | ||
204 | pgrehdr = skb_header_pointer(skb, dataoff, 8, &_pgrehdr); | ||
205 | if (!pgrehdr) | ||
206 | return 1; | ||
207 | |||
208 | if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) { | ||
209 | DEBUGP("GRE_VERSION_PPTP but unknown proto\n"); | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | tuple->dst.u.gre.key = pgrehdr->call_id; | ||
214 | srckey = gre_keymap_lookup(tuple); | ||
215 | tuple->src.u.gre.key = srckey; | ||
216 | |||
217 | return 1; | ||
218 | } | ||
219 | |||
220 | /* print gre part of tuple */ | ||
221 | static int gre_print_tuple(struct seq_file *s, | ||
222 | const struct ip_conntrack_tuple *tuple) | ||
223 | { | ||
224 | return seq_printf(s, "srckey=0x%x dstkey=0x%x ", | ||
225 | ntohs(tuple->src.u.gre.key), | ||
226 | ntohs(tuple->dst.u.gre.key)); | ||
227 | } | ||
228 | |||
229 | /* print private data for conntrack */ | ||
230 | static int gre_print_conntrack(struct seq_file *s, | ||
231 | const struct ip_conntrack *ct) | ||
232 | { | ||
233 | return seq_printf(s, "timeout=%u, stream_timeout=%u ", | ||
234 | (ct->proto.gre.timeout / HZ), | ||
235 | (ct->proto.gre.stream_timeout / HZ)); | ||
236 | } | ||
237 | |||
238 | /* Returns verdict for packet, and may modify conntrack */ | ||
239 | static int gre_packet(struct ip_conntrack *ct, | ||
240 | const struct sk_buff *skb, | ||
241 | enum ip_conntrack_info conntrackinfo) | ||
242 | { | ||
243 | /* If we've seen traffic both ways, this is a GRE connection. | ||
244 | * Extend timeout. */ | ||
245 | if (ct->status & IPS_SEEN_REPLY) { | ||
246 | ip_ct_refresh_acct(ct, conntrackinfo, skb, | ||
247 | ct->proto.gre.stream_timeout); | ||
248 | /* Also, more likely to be important, and not a probe. */ | ||
249 | set_bit(IPS_ASSURED_BIT, &ct->status); | ||
250 | } else | ||
251 | ip_ct_refresh_acct(ct, conntrackinfo, skb, | ||
252 | ct->proto.gre.timeout); | ||
253 | |||
254 | return NF_ACCEPT; | ||
255 | } | ||
256 | |||
257 | /* Called when a new connection for this protocol found. */ | ||
258 | static int gre_new(struct ip_conntrack *ct, | ||
259 | const struct sk_buff *skb) | ||
260 | { | ||
261 | DEBUGP(": "); | ||
262 | DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | ||
263 | |||
264 | /* initialize to sane value. Ideally a conntrack helper | ||
265 | * (e.g. in case of pptp) is increasing them */ | ||
266 | ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT; | ||
267 | ct->proto.gre.timeout = GRE_TIMEOUT; | ||
268 | |||
269 | return 1; | ||
270 | } | ||
271 | |||
272 | /* Called when a conntrack entry has already been removed from the hashes | ||
273 | * and is about to be deleted from memory */ | ||
274 | static void gre_destroy(struct ip_conntrack *ct) | ||
275 | { | ||
276 | struct ip_conntrack *master = ct->master; | ||
277 | DEBUGP(" entering\n"); | ||
278 | |||
279 | if (!master) | ||
280 | DEBUGP("no master !?!\n"); | ||
281 | else | ||
282 | ip_ct_gre_keymap_destroy(master); | ||
283 | } | ||
284 | |||
285 | /* protocol helper struct */ | ||
286 | static struct ip_conntrack_protocol gre = { | ||
287 | .proto = IPPROTO_GRE, | ||
288 | .name = "gre", | ||
289 | .pkt_to_tuple = gre_pkt_to_tuple, | ||
290 | .invert_tuple = gre_invert_tuple, | ||
291 | .print_tuple = gre_print_tuple, | ||
292 | .print_conntrack = gre_print_conntrack, | ||
293 | .packet = gre_packet, | ||
294 | .new = gre_new, | ||
295 | .destroy = gre_destroy, | ||
296 | .me = THIS_MODULE, | ||
297 | #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ | ||
298 | defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) | ||
299 | .tuple_to_nfattr = ip_ct_port_tuple_to_nfattr, | ||
300 | .nfattr_to_tuple = ip_ct_port_nfattr_to_tuple, | ||
301 | #endif | ||
302 | }; | ||
303 | |||
304 | /* ip_conntrack_proto_gre initialization */ | ||
305 | int __init ip_ct_proto_gre_init(void) | ||
306 | { | ||
307 | return ip_conntrack_protocol_register(&gre); | ||
308 | } | ||
309 | |||
310 | void __exit ip_ct_proto_gre_fini(void) | ||
311 | { | ||
312 | struct list_head *pos, *n; | ||
313 | |||
314 | /* delete all keymap entries */ | ||
315 | write_lock_bh(&ip_ct_gre_lock); | ||
316 | list_for_each_safe(pos, n, &gre_keymap_list) { | ||
317 | DEBUGP("deleting keymap %p at module unload time\n", pos); | ||
318 | list_del(pos); | ||
319 | kfree(pos); | ||
320 | } | ||
321 | write_unlock_bh(&ip_ct_gre_lock); | ||
322 | |||
323 | ip_conntrack_protocol_unregister(&gre); | ||
324 | } | ||
325 | |||
326 | EXPORT_SYMBOL(ip_ct_gre_keymap_add); | ||
327 | EXPORT_SYMBOL(ip_ct_gre_keymap_destroy); | ||
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index ae3e3e655db5..d3c7808010ec 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c | |||
@@ -993,11 +993,11 @@ EXPORT_SYMBOL(ip_ct_refresh_acct); | |||
993 | 993 | ||
994 | EXPORT_SYMBOL(ip_conntrack_expect_alloc); | 994 | EXPORT_SYMBOL(ip_conntrack_expect_alloc); |
995 | EXPORT_SYMBOL(ip_conntrack_expect_put); | 995 | EXPORT_SYMBOL(ip_conntrack_expect_put); |
996 | EXPORT_SYMBOL_GPL(ip_conntrack_expect_find_get); | 996 | EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find); |
997 | EXPORT_SYMBOL_GPL(ip_conntrack_expect_find); | ||
997 | EXPORT_SYMBOL(ip_conntrack_expect_related); | 998 | EXPORT_SYMBOL(ip_conntrack_expect_related); |
998 | EXPORT_SYMBOL(ip_conntrack_unexpect_related); | 999 | EXPORT_SYMBOL(ip_conntrack_unexpect_related); |
999 | EXPORT_SYMBOL_GPL(ip_conntrack_expect_list); | 1000 | EXPORT_SYMBOL_GPL(ip_conntrack_expect_list); |
1000 | EXPORT_SYMBOL_GPL(__ip_conntrack_expect_find); | ||
1001 | EXPORT_SYMBOL_GPL(ip_ct_unlink_expect); | 1001 | EXPORT_SYMBOL_GPL(ip_ct_unlink_expect); |
1002 | 1002 | ||
1003 | EXPORT_SYMBOL(ip_conntrack_tuple_taken); | 1003 | EXPORT_SYMBOL(ip_conntrack_tuple_taken); |
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 1adedb743f60..c3ea891d38e7 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c | |||
@@ -578,6 +578,8 @@ ip_nat_port_nfattr_to_range(struct nfattr *tb[], struct ip_nat_range *range) | |||
578 | 578 | ||
579 | return ret; | 579 | return ret; |
580 | } | 580 | } |
581 | EXPORT_SYMBOL_GPL(ip_nat_port_nfattr_to_range); | ||
582 | EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr); | ||
581 | #endif | 583 | #endif |
582 | 584 | ||
583 | int __init ip_nat_init(void) | 585 | int __init ip_nat_init(void) |
diff --git a/net/ipv4/netfilter/ip_nat_helper_pptp.c b/net/ipv4/netfilter/ip_nat_helper_pptp.c new file mode 100644 index 000000000000..3cdd0684d30d --- /dev/null +++ b/net/ipv4/netfilter/ip_nat_helper_pptp.c | |||
@@ -0,0 +1,401 @@ | |||
1 | /* | ||
2 | * ip_nat_pptp.c - Version 3.0 | ||
3 | * | ||
4 | * NAT support for PPTP (Point to Point Tunneling Protocol). | ||
5 | * PPTP is a a protocol for creating virtual private networks. | ||
6 | * It is a specification defined by Microsoft and some vendors | ||
7 | * working with Microsoft. PPTP is built on top of a modified | ||
8 | * version of the Internet Generic Routing Encapsulation Protocol. | ||
9 | * GRE is defined in RFC 1701 and RFC 1702. Documentation of | ||
10 | * PPTP can be found in RFC 2637 | ||
11 | * | ||
12 | * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org> | ||
13 | * | ||
14 | * Development of this code funded by Astaro AG (http://www.astaro.com/) | ||
15 | * | ||
16 | * TODO: - NAT to a unique tuple, not to TCP source port | ||
17 | * (needs netfilter tuple reservation) | ||
18 | * | ||
19 | * Changes: | ||
20 | * 2002-02-10 - Version 1.3 | ||
21 | * - Use ip_nat_mangle_tcp_packet() because of cloned skb's | ||
22 | * in local connections (Philip Craig <philipc@snapgear.com>) | ||
23 | * - add checks for magicCookie and pptp version | ||
24 | * - make argument list of pptp_{out,in}bound_packet() shorter | ||
25 | * - move to C99 style initializers | ||
26 | * - print version number at module loadtime | ||
27 | * 2003-09-22 - Version 1.5 | ||
28 | * - use SNATed tcp sourceport as callid, since we get called before | ||
29 | * TCP header is mangled (Philip Craig <philipc@snapgear.com>) | ||
30 | * 2004-10-22 - Version 2.0 | ||
31 | * - kernel 2.6.x version | ||
32 | * 2005-06-10 - Version 3.0 | ||
33 | * - kernel >= 2.6.11 version, | ||
34 | * funded by Oxcoda NetBox Blue (http://www.netboxblue.com/) | ||
35 | * | ||
36 | */ | ||
37 | |||
38 | #include <linux/config.h> | ||
39 | #include <linux/module.h> | ||
40 | #include <linux/ip.h> | ||
41 | #include <linux/tcp.h> | ||
42 | #include <net/tcp.h> | ||
43 | |||
44 | #include <linux/netfilter_ipv4/ip_nat.h> | ||
45 | #include <linux/netfilter_ipv4/ip_nat_rule.h> | ||
46 | #include <linux/netfilter_ipv4/ip_nat_helper.h> | ||
47 | #include <linux/netfilter_ipv4/ip_nat_pptp.h> | ||
48 | #include <linux/netfilter_ipv4/ip_conntrack_core.h> | ||
49 | #include <linux/netfilter_ipv4/ip_conntrack_helper.h> | ||
50 | #include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h> | ||
51 | #include <linux/netfilter_ipv4/ip_conntrack_pptp.h> | ||
52 | |||
53 | #define IP_NAT_PPTP_VERSION "3.0" | ||
54 | |||
55 | MODULE_LICENSE("GPL"); | ||
56 | MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); | ||
57 | MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP"); | ||
58 | |||
59 | |||
60 | #if 0 | ||
61 | extern const char *pptp_msg_name[]; | ||
62 | #define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \ | ||
63 | __FUNCTION__, ## args) | ||
64 | #else | ||
65 | #define DEBUGP(format, args...) | ||
66 | #endif | ||
67 | |||
68 | static void pptp_nat_expected(struct ip_conntrack *ct, | ||
69 | struct ip_conntrack_expect *exp) | ||
70 | { | ||
71 | struct ip_conntrack *master = ct->master; | ||
72 | struct ip_conntrack_expect *other_exp; | ||
73 | struct ip_conntrack_tuple t; | ||
74 | struct ip_ct_pptp_master *ct_pptp_info; | ||
75 | struct ip_nat_pptp *nat_pptp_info; | ||
76 | |||
77 | ct_pptp_info = &master->help.ct_pptp_info; | ||
78 | nat_pptp_info = &master->nat.help.nat_pptp_info; | ||
79 | |||
80 | /* And here goes the grand finale of corrosion... */ | ||
81 | |||
82 | if (exp->dir == IP_CT_DIR_ORIGINAL) { | ||
83 | DEBUGP("we are PNS->PAC\n"); | ||
84 | /* therefore, build tuple for PAC->PNS */ | ||
85 | t.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip; | ||
86 | t.src.u.gre.key = htons(master->help.ct_pptp_info.pac_call_id); | ||
87 | t.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip; | ||
88 | t.dst.u.gre.key = htons(master->help.ct_pptp_info.pns_call_id); | ||
89 | t.dst.protonum = IPPROTO_GRE; | ||
90 | } else { | ||
91 | DEBUGP("we are PAC->PNS\n"); | ||
92 | /* build tuple for PNS->PAC */ | ||
93 | t.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip; | ||
94 | t.src.u.gre.key = | ||
95 | htons(master->nat.help.nat_pptp_info.pns_call_id); | ||
96 | t.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip; | ||
97 | t.dst.u.gre.key = | ||
98 | htons(master->nat.help.nat_pptp_info.pac_call_id); | ||
99 | t.dst.protonum = IPPROTO_GRE; | ||
100 | } | ||
101 | |||
102 | DEBUGP("trying to unexpect other dir: "); | ||
103 | DUMP_TUPLE(&t); | ||
104 | other_exp = ip_conntrack_expect_find(&t); | ||
105 | if (other_exp) { | ||
106 | ip_conntrack_unexpect_related(other_exp); | ||
107 | ip_conntrack_expect_put(other_exp); | ||
108 | DEBUGP("success\n"); | ||
109 | } else { | ||
110 | DEBUGP("not found!\n"); | ||
111 | } | ||
112 | |||
113 | ip_nat_follow_master(ct, exp); | ||
114 | } | ||
115 | |||
116 | /* outbound packets == from PNS to PAC */ | ||
117 | static int | ||
118 | pptp_outbound_pkt(struct sk_buff **pskb, | ||
119 | struct ip_conntrack *ct, | ||
120 | enum ip_conntrack_info ctinfo, | ||
121 | struct PptpControlHeader *ctlh, | ||
122 | union pptp_ctrl_union *pptpReq) | ||
123 | |||
124 | { | ||
125 | struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info; | ||
126 | struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; | ||
127 | |||
128 | u_int16_t msg, *cid = NULL, new_callid; | ||
129 | |||
130 | new_callid = htons(ct_pptp_info->pns_call_id); | ||
131 | |||
132 | switch (msg = ntohs(ctlh->messageType)) { | ||
133 | case PPTP_OUT_CALL_REQUEST: | ||
134 | cid = &pptpReq->ocreq.callID; | ||
135 | /* FIXME: ideally we would want to reserve a call ID | ||
136 | * here. current netfilter NAT core is not able to do | ||
137 | * this :( For now we use TCP source port. This breaks | ||
138 | * multiple calls within one control session */ | ||
139 | |||
140 | /* save original call ID in nat_info */ | ||
141 | nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id; | ||
142 | |||
143 | /* don't use tcph->source since we are at a DSTmanip | ||
144 | * hook (e.g. PREROUTING) and pkt is not mangled yet */ | ||
145 | new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port; | ||
146 | |||
147 | /* save new call ID in ct info */ | ||
148 | ct_pptp_info->pns_call_id = ntohs(new_callid); | ||
149 | break; | ||
150 | case PPTP_IN_CALL_REPLY: | ||
151 | cid = &pptpReq->icreq.callID; | ||
152 | break; | ||
153 | case PPTP_CALL_CLEAR_REQUEST: | ||
154 | cid = &pptpReq->clrreq.callID; | ||
155 | break; | ||
156 | default: | ||
157 | DEBUGP("unknown outbound packet 0x%04x:%s\n", msg, | ||
158 | (msg <= PPTP_MSG_MAX)? | ||
159 | pptp_msg_name[msg]:pptp_msg_name[0]); | ||
160 | /* fall through */ | ||
161 | |||
162 | case PPTP_SET_LINK_INFO: | ||
163 | /* only need to NAT in case PAC is behind NAT box */ | ||
164 | case PPTP_START_SESSION_REQUEST: | ||
165 | case PPTP_START_SESSION_REPLY: | ||
166 | case PPTP_STOP_SESSION_REQUEST: | ||
167 | case PPTP_STOP_SESSION_REPLY: | ||
168 | case PPTP_ECHO_REQUEST: | ||
169 | case PPTP_ECHO_REPLY: | ||
170 | /* no need to alter packet */ | ||
171 | return NF_ACCEPT; | ||
172 | } | ||
173 | |||
174 | /* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass | ||
175 | * down to here */ | ||
176 | |||
177 | IP_NF_ASSERT(cid); | ||
178 | |||
179 | DEBUGP("altering call id from 0x%04x to 0x%04x\n", | ||
180 | ntohs(*cid), ntohs(new_callid)); | ||
181 | |||
182 | /* mangle packet */ | ||
183 | if (ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, | ||
184 | (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)), | ||
185 | sizeof(new_callid), | ||
186 | (char *)&new_callid, | ||
187 | sizeof(new_callid)) == 0) | ||
188 | return NF_DROP; | ||
189 | |||
190 | return NF_ACCEPT; | ||
191 | } | ||
192 | |||
193 | static int | ||
194 | pptp_exp_gre(struct ip_conntrack_expect *expect_orig, | ||
195 | struct ip_conntrack_expect *expect_reply) | ||
196 | { | ||
197 | struct ip_ct_pptp_master *ct_pptp_info = | ||
198 | &expect_orig->master->help.ct_pptp_info; | ||
199 | struct ip_nat_pptp *nat_pptp_info = | ||
200 | &expect_orig->master->nat.help.nat_pptp_info; | ||
201 | |||
202 | struct ip_conntrack *ct = expect_orig->master; | ||
203 | |||
204 | struct ip_conntrack_tuple inv_t; | ||
205 | struct ip_conntrack_tuple *orig_t, *reply_t; | ||
206 | |||
207 | /* save original PAC call ID in nat_info */ | ||
208 | nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id; | ||
209 | |||
210 | /* alter expectation */ | ||
211 | orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; | ||
212 | reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; | ||
213 | |||
214 | /* alter expectation for PNS->PAC direction */ | ||
215 | invert_tuplepr(&inv_t, &expect_orig->tuple); | ||
216 | expect_orig->saved_proto.gre.key = htons(nat_pptp_info->pac_call_id); | ||
217 | expect_orig->tuple.src.u.gre.key = htons(nat_pptp_info->pns_call_id); | ||
218 | expect_orig->tuple.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); | ||
219 | inv_t.src.ip = reply_t->src.ip; | ||
220 | inv_t.dst.ip = reply_t->dst.ip; | ||
221 | inv_t.src.u.gre.key = htons(nat_pptp_info->pac_call_id); | ||
222 | inv_t.dst.u.gre.key = htons(ct_pptp_info->pns_call_id); | ||
223 | |||
224 | if (!ip_conntrack_expect_related(expect_orig)) { | ||
225 | DEBUGP("successfully registered expect\n"); | ||
226 | } else { | ||
227 | DEBUGP("can't expect_related(expect_orig)\n"); | ||
228 | return 1; | ||
229 | } | ||
230 | |||
231 | /* alter expectation for PAC->PNS direction */ | ||
232 | invert_tuplepr(&inv_t, &expect_reply->tuple); | ||
233 | expect_reply->saved_proto.gre.key = htons(nat_pptp_info->pns_call_id); | ||
234 | expect_reply->tuple.src.u.gre.key = htons(nat_pptp_info->pac_call_id); | ||
235 | expect_reply->tuple.dst.u.gre.key = htons(ct_pptp_info->pns_call_id); | ||
236 | inv_t.src.ip = orig_t->src.ip; | ||
237 | inv_t.dst.ip = orig_t->dst.ip; | ||
238 | inv_t.src.u.gre.key = htons(nat_pptp_info->pns_call_id); | ||
239 | inv_t.dst.u.gre.key = htons(ct_pptp_info->pac_call_id); | ||
240 | |||
241 | if (!ip_conntrack_expect_related(expect_reply)) { | ||
242 | DEBUGP("successfully registered expect\n"); | ||
243 | } else { | ||
244 | DEBUGP("can't expect_related(expect_reply)\n"); | ||
245 | ip_conntrack_unexpect_related(expect_orig); | ||
246 | return 1; | ||
247 | } | ||
248 | |||
249 | if (ip_ct_gre_keymap_add(ct, &expect_reply->tuple, 0) < 0) { | ||
250 | DEBUGP("can't register original keymap\n"); | ||
251 | ip_conntrack_unexpect_related(expect_orig); | ||
252 | ip_conntrack_unexpect_related(expect_reply); | ||
253 | return 1; | ||
254 | } | ||
255 | |||
256 | if (ip_ct_gre_keymap_add(ct, &inv_t, 1) < 0) { | ||
257 | DEBUGP("can't register reply keymap\n"); | ||
258 | ip_conntrack_unexpect_related(expect_orig); | ||
259 | ip_conntrack_unexpect_related(expect_reply); | ||
260 | ip_ct_gre_keymap_destroy(ct); | ||
261 | return 1; | ||
262 | } | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | /* inbound packets == from PAC to PNS */ | ||
268 | static int | ||
269 | pptp_inbound_pkt(struct sk_buff **pskb, | ||
270 | struct ip_conntrack *ct, | ||
271 | enum ip_conntrack_info ctinfo, | ||
272 | struct PptpControlHeader *ctlh, | ||
273 | union pptp_ctrl_union *pptpReq) | ||
274 | { | ||
275 | struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info; | ||
276 | u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL; | ||
277 | |||
278 | int ret = NF_ACCEPT, rv; | ||
279 | |||
280 | new_pcid = htons(nat_pptp_info->pns_call_id); | ||
281 | |||
282 | switch (msg = ntohs(ctlh->messageType)) { | ||
283 | case PPTP_OUT_CALL_REPLY: | ||
284 | pcid = &pptpReq->ocack.peersCallID; | ||
285 | cid = &pptpReq->ocack.callID; | ||
286 | break; | ||
287 | case PPTP_IN_CALL_CONNECT: | ||
288 | pcid = &pptpReq->iccon.peersCallID; | ||
289 | break; | ||
290 | case PPTP_IN_CALL_REQUEST: | ||
291 | /* only need to nat in case PAC is behind NAT box */ | ||
292 | break; | ||
293 | case PPTP_WAN_ERROR_NOTIFY: | ||
294 | pcid = &pptpReq->wanerr.peersCallID; | ||
295 | break; | ||
296 | case PPTP_CALL_DISCONNECT_NOTIFY: | ||
297 | pcid = &pptpReq->disc.callID; | ||
298 | break; | ||
299 | case PPTP_SET_LINK_INFO: | ||
300 | pcid = &pptpReq->setlink.peersCallID; | ||
301 | break; | ||
302 | |||
303 | default: | ||
304 | DEBUGP("unknown inbound packet %s\n", (msg <= PPTP_MSG_MAX)? | ||
305 | pptp_msg_name[msg]:pptp_msg_name[0]); | ||
306 | /* fall through */ | ||
307 | |||
308 | case PPTP_START_SESSION_REQUEST: | ||
309 | case PPTP_START_SESSION_REPLY: | ||
310 | case PPTP_STOP_SESSION_REQUEST: | ||
311 | case PPTP_STOP_SESSION_REPLY: | ||
312 | case PPTP_ECHO_REQUEST: | ||
313 | case PPTP_ECHO_REPLY: | ||
314 | /* no need to alter packet */ | ||
315 | return NF_ACCEPT; | ||
316 | } | ||
317 | |||
318 | /* only OUT_CALL_REPLY, IN_CALL_CONNECT, IN_CALL_REQUEST, | ||
319 | * WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */ | ||
320 | |||
321 | /* mangle packet */ | ||
322 | IP_NF_ASSERT(pcid); | ||
323 | DEBUGP("altering peer call id from 0x%04x to 0x%04x\n", | ||
324 | ntohs(*pcid), ntohs(new_pcid)); | ||
325 | |||
326 | rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, | ||
327 | (void *)pcid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)), | ||
328 | sizeof(new_pcid), (char *)&new_pcid, | ||
329 | sizeof(new_pcid)); | ||
330 | if (rv != NF_ACCEPT) | ||
331 | return rv; | ||
332 | |||
333 | if (new_cid) { | ||
334 | IP_NF_ASSERT(cid); | ||
335 | DEBUGP("altering call id from 0x%04x to 0x%04x\n", | ||
336 | ntohs(*cid), ntohs(new_cid)); | ||
337 | rv = ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, | ||
338 | (void *)cid - ((void *)ctlh - sizeof(struct pptp_pkt_hdr)), | ||
339 | sizeof(new_cid), | ||
340 | (char *)&new_cid, | ||
341 | sizeof(new_cid)); | ||
342 | if (rv != NF_ACCEPT) | ||
343 | return rv; | ||
344 | } | ||
345 | |||
346 | /* check for earlier return value of 'switch' above */ | ||
347 | if (ret != NF_ACCEPT) | ||
348 | return ret; | ||
349 | |||
350 | /* great, at least we don't need to resize packets */ | ||
351 | return NF_ACCEPT; | ||
352 | } | ||
353 | |||
354 | |||
355 | extern int __init ip_nat_proto_gre_init(void); | ||
356 | extern void __exit ip_nat_proto_gre_fini(void); | ||
357 | |||
358 | static int __init init(void) | ||
359 | { | ||
360 | int ret; | ||
361 | |||
362 | DEBUGP("%s: registering NAT helper\n", __FILE__); | ||
363 | |||
364 | ret = ip_nat_proto_gre_init(); | ||
365 | if (ret < 0) | ||
366 | return ret; | ||
367 | |||
368 | BUG_ON(ip_nat_pptp_hook_outbound); | ||
369 | ip_nat_pptp_hook_outbound = &pptp_outbound_pkt; | ||
370 | |||
371 | BUG_ON(ip_nat_pptp_hook_inbound); | ||
372 | ip_nat_pptp_hook_inbound = &pptp_inbound_pkt; | ||
373 | |||
374 | BUG_ON(ip_nat_pptp_hook_exp_gre); | ||
375 | ip_nat_pptp_hook_exp_gre = &pptp_exp_gre; | ||
376 | |||
377 | BUG_ON(ip_nat_pptp_hook_expectfn); | ||
378 | ip_nat_pptp_hook_expectfn = &pptp_nat_expected; | ||
379 | |||
380 | printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION); | ||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | static void __exit fini(void) | ||
385 | { | ||
386 | DEBUGP("cleanup_module\n" ); | ||
387 | |||
388 | ip_nat_pptp_hook_expectfn = NULL; | ||
389 | ip_nat_pptp_hook_exp_gre = NULL; | ||
390 | ip_nat_pptp_hook_inbound = NULL; | ||
391 | ip_nat_pptp_hook_outbound = NULL; | ||
392 | |||
393 | ip_nat_proto_gre_fini(); | ||
394 | /* Make sure noone calls it, meanwhile */ | ||
395 | synchronize_net(); | ||
396 | |||
397 | printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION); | ||
398 | } | ||
399 | |||
400 | module_init(init); | ||
401 | module_exit(fini); | ||
diff --git a/net/ipv4/netfilter/ip_nat_proto_gre.c b/net/ipv4/netfilter/ip_nat_proto_gre.c new file mode 100644 index 000000000000..7c1285401672 --- /dev/null +++ b/net/ipv4/netfilter/ip_nat_proto_gre.c | |||
@@ -0,0 +1,214 @@ | |||
1 | /* | ||
2 | * ip_nat_proto_gre.c - Version 2.0 | ||
3 | * | ||
4 | * NAT protocol helper module for GRE. | ||
5 | * | ||
6 | * GRE is a generic encapsulation protocol, which is generally not very | ||
7 | * suited for NAT, as it has no protocol-specific part as port numbers. | ||
8 | * | ||
9 | * It has an optional key field, which may help us distinguishing two | ||
10 | * connections between the same two hosts. | ||
11 | * | ||
12 | * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 | ||
13 | * | ||
14 | * PPTP is built on top of a modified version of GRE, and has a mandatory | ||
15 | * field called "CallID", which serves us for the same purpose as the key | ||
16 | * field in plain GRE. | ||
17 | * | ||
18 | * Documentation about PPTP can be found in RFC 2637 | ||
19 | * | ||
20 | * (C) 2000-2005 by Harald Welte <laforge@gnumonks.org> | ||
21 | * | ||
22 | * Development of this code funded by Astaro AG (http://www.astaro.com/) | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <linux/config.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/ip.h> | ||
29 | #include <linux/netfilter_ipv4/ip_nat.h> | ||
30 | #include <linux/netfilter_ipv4/ip_nat_rule.h> | ||
31 | #include <linux/netfilter_ipv4/ip_nat_protocol.h> | ||
32 | #include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h> | ||
33 | |||
34 | MODULE_LICENSE("GPL"); | ||
35 | MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); | ||
36 | MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE"); | ||
37 | |||
38 | #if 0 | ||
39 | #define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \ | ||
40 | __FUNCTION__, ## args) | ||
41 | #else | ||
42 | #define DEBUGP(x, args...) | ||
43 | #endif | ||
44 | |||
45 | /* is key in given range between min and max */ | ||
46 | static int | ||
47 | gre_in_range(const struct ip_conntrack_tuple *tuple, | ||
48 | enum ip_nat_manip_type maniptype, | ||
49 | const union ip_conntrack_manip_proto *min, | ||
50 | const union ip_conntrack_manip_proto *max) | ||
51 | { | ||
52 | u_int32_t key; | ||
53 | |||
54 | if (maniptype == IP_NAT_MANIP_SRC) | ||
55 | key = tuple->src.u.gre.key; | ||
56 | else | ||
57 | key = tuple->dst.u.gre.key; | ||
58 | |||
59 | return ntohl(key) >= ntohl(min->gre.key) | ||
60 | && ntohl(key) <= ntohl(max->gre.key); | ||
61 | } | ||
62 | |||
63 | /* generate unique tuple ... */ | ||
64 | static int | ||
65 | gre_unique_tuple(struct ip_conntrack_tuple *tuple, | ||
66 | const struct ip_nat_range *range, | ||
67 | enum ip_nat_manip_type maniptype, | ||
68 | const struct ip_conntrack *conntrack) | ||
69 | { | ||
70 | static u_int16_t key; | ||
71 | u_int16_t *keyptr; | ||
72 | unsigned int min, i, range_size; | ||
73 | |||
74 | if (maniptype == IP_NAT_MANIP_SRC) | ||
75 | keyptr = &tuple->src.u.gre.key; | ||
76 | else | ||
77 | keyptr = &tuple->dst.u.gre.key; | ||
78 | |||
79 | if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { | ||
80 | DEBUGP("%p: NATing GRE PPTP\n", conntrack); | ||
81 | min = 1; | ||
82 | range_size = 0xffff; | ||
83 | } else { | ||
84 | min = ntohl(range->min.gre.key); | ||
85 | range_size = ntohl(range->max.gre.key) - min + 1; | ||
86 | } | ||
87 | |||
88 | DEBUGP("min = %u, range_size = %u\n", min, range_size); | ||
89 | |||
90 | for (i = 0; i < range_size; i++, key++) { | ||
91 | *keyptr = htonl(min + key % range_size); | ||
92 | if (!ip_nat_used_tuple(tuple, conntrack)) | ||
93 | return 1; | ||
94 | } | ||
95 | |||
96 | DEBUGP("%p: no NAT mapping\n", conntrack); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | /* manipulate a GRE packet according to maniptype */ | ||
102 | static int | ||
103 | gre_manip_pkt(struct sk_buff **pskb, | ||
104 | unsigned int iphdroff, | ||
105 | const struct ip_conntrack_tuple *tuple, | ||
106 | enum ip_nat_manip_type maniptype) | ||
107 | { | ||
108 | struct gre_hdr *greh; | ||
109 | struct gre_hdr_pptp *pgreh; | ||
110 | struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff); | ||
111 | unsigned int hdroff = iphdroff + iph->ihl*4; | ||
112 | |||
113 | /* pgreh includes two optional 32bit fields which are not required | ||
114 | * to be there. That's where the magic '8' comes from */ | ||
115 | if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh)-8)) | ||
116 | return 0; | ||
117 | |||
118 | greh = (void *)(*pskb)->data + hdroff; | ||
119 | pgreh = (struct gre_hdr_pptp *) greh; | ||
120 | |||
121 | /* we only have destination manip of a packet, since 'source key' | ||
122 | * is not present in the packet itself */ | ||
123 | if (maniptype == IP_NAT_MANIP_DST) { | ||
124 | /* key manipulation is always dest */ | ||
125 | switch (greh->version) { | ||
126 | case 0: | ||
127 | if (!greh->key) { | ||
128 | DEBUGP("can't nat GRE w/o key\n"); | ||
129 | break; | ||
130 | } | ||
131 | if (greh->csum) { | ||
132 | /* FIXME: Never tested this code... */ | ||
133 | *(gre_csum(greh)) = | ||
134 | ip_nat_cheat_check(~*(gre_key(greh)), | ||
135 | tuple->dst.u.gre.key, | ||
136 | *(gre_csum(greh))); | ||
137 | } | ||
138 | *(gre_key(greh)) = tuple->dst.u.gre.key; | ||
139 | break; | ||
140 | case GRE_VERSION_PPTP: | ||
141 | DEBUGP("call_id -> 0x%04x\n", | ||
142 | ntohl(tuple->dst.u.gre.key)); | ||
143 | pgreh->call_id = htons(ntohl(tuple->dst.u.gre.key)); | ||
144 | break; | ||
145 | default: | ||
146 | DEBUGP("can't nat unknown GRE version\n"); | ||
147 | return 0; | ||
148 | break; | ||
149 | } | ||
150 | } | ||
151 | return 1; | ||
152 | } | ||
153 | |||
154 | /* print out a nat tuple */ | ||
155 | static unsigned int | ||
156 | gre_print(char *buffer, | ||
157 | const struct ip_conntrack_tuple *match, | ||
158 | const struct ip_conntrack_tuple *mask) | ||
159 | { | ||
160 | unsigned int len = 0; | ||
161 | |||
162 | if (mask->src.u.gre.key) | ||
163 | len += sprintf(buffer + len, "srckey=0x%x ", | ||
164 | ntohl(match->src.u.gre.key)); | ||
165 | |||
166 | if (mask->dst.u.gre.key) | ||
167 | len += sprintf(buffer + len, "dstkey=0x%x ", | ||
168 | ntohl(match->src.u.gre.key)); | ||
169 | |||
170 | return len; | ||
171 | } | ||
172 | |||
173 | /* print a range of keys */ | ||
174 | static unsigned int | ||
175 | gre_print_range(char *buffer, const struct ip_nat_range *range) | ||
176 | { | ||
177 | if (range->min.gre.key != 0 | ||
178 | || range->max.gre.key != 0xFFFF) { | ||
179 | if (range->min.gre.key == range->max.gre.key) | ||
180 | return sprintf(buffer, "key 0x%x ", | ||
181 | ntohl(range->min.gre.key)); | ||
182 | else | ||
183 | return sprintf(buffer, "keys 0x%u-0x%u ", | ||
184 | ntohl(range->min.gre.key), | ||
185 | ntohl(range->max.gre.key)); | ||
186 | } else | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | /* nat helper struct */ | ||
191 | static struct ip_nat_protocol gre = { | ||
192 | .name = "GRE", | ||
193 | .protonum = IPPROTO_GRE, | ||
194 | .manip_pkt = gre_manip_pkt, | ||
195 | .in_range = gre_in_range, | ||
196 | .unique_tuple = gre_unique_tuple, | ||
197 | .print = gre_print, | ||
198 | .print_range = gre_print_range, | ||
199 | #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \ | ||
200 | defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE) | ||
201 | .range_to_nfattr = ip_nat_port_range_to_nfattr, | ||
202 | .nfattr_to_range = ip_nat_port_nfattr_to_range, | ||
203 | #endif | ||
204 | }; | ||
205 | |||
206 | int __init ip_nat_proto_gre_init(void) | ||
207 | { | ||
208 | return ip_nat_protocol_register(&gre); | ||
209 | } | ||
210 | |||
211 | void __exit ip_nat_proto_gre_fini(void) | ||
212 | { | ||
213 | ip_nat_protocol_unregister(&gre); | ||
214 | } | ||
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 7d38913754b1..9bcb398fbc1f 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/config.h> | 13 | #include <linux/config.h> |
14 | #include <linux/proc_fs.h> | 14 | #include <linux/proc_fs.h> |
15 | #include <linux/jhash.h> | 15 | #include <linux/jhash.h> |
16 | #include <linux/bitops.h> | ||
16 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
17 | #include <linux/ip.h> | 18 | #include <linux/ip.h> |
18 | #include <linux/tcp.h> | 19 | #include <linux/tcp.h> |
@@ -30,7 +31,7 @@ | |||
30 | #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h> | 31 | #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h> |
31 | #include <linux/netfilter_ipv4/ip_conntrack.h> | 32 | #include <linux/netfilter_ipv4/ip_conntrack.h> |
32 | 33 | ||
33 | #define CLUSTERIP_VERSION "0.7" | 34 | #define CLUSTERIP_VERSION "0.8" |
34 | 35 | ||
35 | #define DEBUG_CLUSTERIP | 36 | #define DEBUG_CLUSTERIP |
36 | 37 | ||
@@ -49,13 +50,14 @@ MODULE_DESCRIPTION("iptables target for CLUSTERIP"); | |||
49 | struct clusterip_config { | 50 | struct clusterip_config { |
50 | struct list_head list; /* list of all configs */ | 51 | struct list_head list; /* list of all configs */ |
51 | atomic_t refcount; /* reference count */ | 52 | atomic_t refcount; /* reference count */ |
53 | atomic_t entries; /* number of entries/rules | ||
54 | * referencing us */ | ||
52 | 55 | ||
53 | u_int32_t clusterip; /* the IP address */ | 56 | u_int32_t clusterip; /* the IP address */ |
54 | u_int8_t clustermac[ETH_ALEN]; /* the MAC address */ | 57 | u_int8_t clustermac[ETH_ALEN]; /* the MAC address */ |
55 | struct net_device *dev; /* device */ | 58 | struct net_device *dev; /* device */ |
56 | u_int16_t num_total_nodes; /* total number of nodes */ | 59 | u_int16_t num_total_nodes; /* total number of nodes */ |
57 | u_int16_t num_local_nodes; /* number of local nodes */ | 60 | unsigned long local_nodes; /* node number array */ |
58 | u_int16_t local_nodes[CLUSTERIP_MAX_NODES]; /* node number array */ | ||
59 | 61 | ||
60 | #ifdef CONFIG_PROC_FS | 62 | #ifdef CONFIG_PROC_FS |
61 | struct proc_dir_entry *pde; /* proc dir entry */ | 63 | struct proc_dir_entry *pde; /* proc dir entry */ |
@@ -66,8 +68,7 @@ struct clusterip_config { | |||
66 | 68 | ||
67 | static LIST_HEAD(clusterip_configs); | 69 | static LIST_HEAD(clusterip_configs); |
68 | 70 | ||
69 | /* clusterip_lock protects the clusterip_configs list _AND_ the configurable | 71 | /* clusterip_lock protects the clusterip_configs list */ |
70 | * data within all structurses (num_local_nodes, local_nodes[]) */ | ||
71 | static DEFINE_RWLOCK(clusterip_lock); | 72 | static DEFINE_RWLOCK(clusterip_lock); |
72 | 73 | ||
73 | #ifdef CONFIG_PROC_FS | 74 | #ifdef CONFIG_PROC_FS |
@@ -76,23 +77,48 @@ static struct proc_dir_entry *clusterip_procdir; | |||
76 | #endif | 77 | #endif |
77 | 78 | ||
78 | static inline void | 79 | static inline void |
79 | clusterip_config_get(struct clusterip_config *c) { | 80 | clusterip_config_get(struct clusterip_config *c) |
81 | { | ||
80 | atomic_inc(&c->refcount); | 82 | atomic_inc(&c->refcount); |
81 | } | 83 | } |
82 | 84 | ||
83 | static inline void | 85 | static inline void |
84 | clusterip_config_put(struct clusterip_config *c) { | 86 | clusterip_config_put(struct clusterip_config *c) |
85 | if (atomic_dec_and_test(&c->refcount)) { | 87 | { |
88 | if (atomic_dec_and_test(&c->refcount)) | ||
89 | kfree(c); | ||
90 | } | ||
91 | |||
92 | /* increase the count of entries(rules) using/referencing this config */ | ||
93 | static inline void | ||
94 | clusterip_config_entry_get(struct clusterip_config *c) | ||
95 | { | ||
96 | atomic_inc(&c->entries); | ||
97 | } | ||
98 | |||
99 | /* decrease the count of entries using/referencing this config. If last | ||
100 | * entry(rule) is removed, remove the config from lists, but don't free it | ||
101 | * yet, since proc-files could still be holding references */ | ||
102 | static inline void | ||
103 | clusterip_config_entry_put(struct clusterip_config *c) | ||
104 | { | ||
105 | if (atomic_dec_and_test(&c->entries)) { | ||
86 | write_lock_bh(&clusterip_lock); | 106 | write_lock_bh(&clusterip_lock); |
87 | list_del(&c->list); | 107 | list_del(&c->list); |
88 | write_unlock_bh(&clusterip_lock); | 108 | write_unlock_bh(&clusterip_lock); |
109 | |||
89 | dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0); | 110 | dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0); |
90 | dev_put(c->dev); | 111 | dev_put(c->dev); |
91 | kfree(c); | 112 | |
113 | /* In case anyone still accesses the file, the open/close | ||
114 | * functions are also incrementing the refcount on their own, | ||
115 | * so it's safe to remove the entry even if it's in use. */ | ||
116 | #ifdef CONFIG_PROC_FS | ||
117 | remove_proc_entry(c->pde->name, c->pde->parent); | ||
118 | #endif | ||
92 | } | 119 | } |
93 | } | 120 | } |
94 | 121 | ||
95 | |||
96 | static struct clusterip_config * | 122 | static struct clusterip_config * |
97 | __clusterip_config_find(u_int32_t clusterip) | 123 | __clusterip_config_find(u_int32_t clusterip) |
98 | { | 124 | { |
@@ -111,7 +137,7 @@ __clusterip_config_find(u_int32_t clusterip) | |||
111 | } | 137 | } |
112 | 138 | ||
113 | static inline struct clusterip_config * | 139 | static inline struct clusterip_config * |
114 | clusterip_config_find_get(u_int32_t clusterip) | 140 | clusterip_config_find_get(u_int32_t clusterip, int entry) |
115 | { | 141 | { |
116 | struct clusterip_config *c; | 142 | struct clusterip_config *c; |
117 | 143 | ||
@@ -122,11 +148,24 @@ clusterip_config_find_get(u_int32_t clusterip) | |||
122 | return NULL; | 148 | return NULL; |
123 | } | 149 | } |
124 | atomic_inc(&c->refcount); | 150 | atomic_inc(&c->refcount); |
151 | if (entry) | ||
152 | atomic_inc(&c->entries); | ||
125 | read_unlock_bh(&clusterip_lock); | 153 | read_unlock_bh(&clusterip_lock); |
126 | 154 | ||
127 | return c; | 155 | return c; |
128 | } | 156 | } |
129 | 157 | ||
158 | static void | ||
159 | clusterip_config_init_nodelist(struct clusterip_config *c, | ||
160 | const struct ipt_clusterip_tgt_info *i) | ||
161 | { | ||
162 | int n; | ||
163 | |||
164 | for (n = 0; n < i->num_local_nodes; n++) { | ||
165 | set_bit(i->local_nodes[n] - 1, &c->local_nodes); | ||
166 | } | ||
167 | } | ||
168 | |||
130 | static struct clusterip_config * | 169 | static struct clusterip_config * |
131 | clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip, | 170 | clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip, |
132 | struct net_device *dev) | 171 | struct net_device *dev) |
@@ -143,11 +182,11 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip, | |||
143 | c->clusterip = ip; | 182 | c->clusterip = ip; |
144 | memcpy(&c->clustermac, &i->clustermac, ETH_ALEN); | 183 | memcpy(&c->clustermac, &i->clustermac, ETH_ALEN); |
145 | c->num_total_nodes = i->num_total_nodes; | 184 | c->num_total_nodes = i->num_total_nodes; |
146 | c->num_local_nodes = i->num_local_nodes; | 185 | clusterip_config_init_nodelist(c, i); |
147 | memcpy(&c->local_nodes, &i->local_nodes, sizeof(c->local_nodes)); | ||
148 | c->hash_mode = i->hash_mode; | 186 | c->hash_mode = i->hash_mode; |
149 | c->hash_initval = i->hash_initval; | 187 | c->hash_initval = i->hash_initval; |
150 | atomic_set(&c->refcount, 1); | 188 | atomic_set(&c->refcount, 1); |
189 | atomic_set(&c->entries, 1); | ||
151 | 190 | ||
152 | #ifdef CONFIG_PROC_FS | 191 | #ifdef CONFIG_PROC_FS |
153 | /* create proc dir entry */ | 192 | /* create proc dir entry */ |
@@ -171,53 +210,28 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip, | |||
171 | static int | 210 | static int |
172 | clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum) | 211 | clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum) |
173 | { | 212 | { |
174 | int i; | ||
175 | |||
176 | write_lock_bh(&clusterip_lock); | ||
177 | 213 | ||
178 | if (c->num_local_nodes >= CLUSTERIP_MAX_NODES | 214 | if (nodenum == 0 || |
179 | || nodenum > CLUSTERIP_MAX_NODES) { | 215 | nodenum > c->num_total_nodes) |
180 | write_unlock_bh(&clusterip_lock); | ||
181 | return 1; | 216 | return 1; |
182 | } | ||
183 | |||
184 | /* check if we alrady have this number in our array */ | ||
185 | for (i = 0; i < c->num_local_nodes; i++) { | ||
186 | if (c->local_nodes[i] == nodenum) { | ||
187 | write_unlock_bh(&clusterip_lock); | ||
188 | return 1; | ||
189 | } | ||
190 | } | ||
191 | 217 | ||
192 | c->local_nodes[c->num_local_nodes++] = nodenum; | 218 | /* check if we already have this number in our bitfield */ |
219 | if (test_and_set_bit(nodenum - 1, &c->local_nodes)) | ||
220 | return 1; | ||
193 | 221 | ||
194 | write_unlock_bh(&clusterip_lock); | ||
195 | return 0; | 222 | return 0; |
196 | } | 223 | } |
197 | 224 | ||
198 | static int | 225 | static int |
199 | clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum) | 226 | clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum) |
200 | { | 227 | { |
201 | int i; | 228 | if (nodenum == 0 || |
202 | 229 | nodenum > c->num_total_nodes) | |
203 | write_lock_bh(&clusterip_lock); | ||
204 | |||
205 | if (c->num_local_nodes <= 1 || nodenum > CLUSTERIP_MAX_NODES) { | ||
206 | write_unlock_bh(&clusterip_lock); | ||
207 | return 1; | 230 | return 1; |
208 | } | ||
209 | 231 | ||
210 | for (i = 0; i < c->num_local_nodes; i++) { | 232 | if (test_and_clear_bit(nodenum - 1, &c->local_nodes)) |
211 | if (c->local_nodes[i] == nodenum) { | 233 | return 0; |
212 | int size = sizeof(u_int16_t)*(c->num_local_nodes-(i+1)); | ||
213 | memmove(&c->local_nodes[i], &c->local_nodes[i+1], size); | ||
214 | c->num_local_nodes--; | ||
215 | write_unlock_bh(&clusterip_lock); | ||
216 | return 0; | ||
217 | } | ||
218 | } | ||
219 | 234 | ||
220 | write_unlock_bh(&clusterip_lock); | ||
221 | return 1; | 235 | return 1; |
222 | } | 236 | } |
223 | 237 | ||
@@ -285,25 +299,7 @@ clusterip_hashfn(struct sk_buff *skb, struct clusterip_config *config) | |||
285 | static inline int | 299 | static inline int |
286 | clusterip_responsible(struct clusterip_config *config, u_int32_t hash) | 300 | clusterip_responsible(struct clusterip_config *config, u_int32_t hash) |
287 | { | 301 | { |
288 | int i; | 302 | return test_bit(hash - 1, &config->local_nodes); |
289 | |||
290 | read_lock_bh(&clusterip_lock); | ||
291 | |||
292 | if (config->num_local_nodes == 0) { | ||
293 | read_unlock_bh(&clusterip_lock); | ||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | for (i = 0; i < config->num_local_nodes; i++) { | ||
298 | if (config->local_nodes[i] == hash) { | ||
299 | read_unlock_bh(&clusterip_lock); | ||
300 | return 1; | ||
301 | } | ||
302 | } | ||
303 | |||
304 | read_unlock_bh(&clusterip_lock); | ||
305 | |||
306 | return 0; | ||
307 | } | 303 | } |
308 | 304 | ||
309 | /*********************************************************************** | 305 | /*********************************************************************** |
@@ -415,8 +411,26 @@ checkentry(const char *tablename, | |||
415 | 411 | ||
416 | /* FIXME: further sanity checks */ | 412 | /* FIXME: further sanity checks */ |
417 | 413 | ||
418 | config = clusterip_config_find_get(e->ip.dst.s_addr); | 414 | config = clusterip_config_find_get(e->ip.dst.s_addr, 1); |
419 | if (!config) { | 415 | if (config) { |
416 | if (cipinfo->config != NULL) { | ||
417 | /* Case A: This is an entry that gets reloaded, since | ||
418 | * it still has a cipinfo->config pointer. Simply | ||
419 | * increase the entry refcount and return */ | ||
420 | if (cipinfo->config != config) { | ||
421 | printk(KERN_ERR "CLUSTERIP: Reloaded entry " | ||
422 | "has invalid config pointer!\n"); | ||
423 | return 0; | ||
424 | } | ||
425 | clusterip_config_entry_get(cipinfo->config); | ||
426 | } else { | ||
427 | /* Case B: This is a new rule referring to an existing | ||
428 | * clusterip config. */ | ||
429 | cipinfo->config = config; | ||
430 | clusterip_config_entry_get(cipinfo->config); | ||
431 | } | ||
432 | } else { | ||
433 | /* Case C: This is a completely new clusterip config */ | ||
420 | if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) { | 434 | if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) { |
421 | printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr)); | 435 | printk(KERN_WARNING "CLUSTERIP: no config found for %u.%u.%u.%u, need 'new'\n", NIPQUAD(e->ip.dst.s_addr)); |
422 | return 0; | 436 | return 0; |
@@ -443,10 +457,9 @@ checkentry(const char *tablename, | |||
443 | } | 457 | } |
444 | dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0); | 458 | dev_mc_add(config->dev,config->clustermac, ETH_ALEN, 0); |
445 | } | 459 | } |
460 | cipinfo->config = config; | ||
446 | } | 461 | } |
447 | 462 | ||
448 | cipinfo->config = config; | ||
449 | |||
450 | return 1; | 463 | return 1; |
451 | } | 464 | } |
452 | 465 | ||
@@ -455,13 +468,10 @@ static void destroy(void *matchinfo, unsigned int matchinfosize) | |||
455 | { | 468 | { |
456 | struct ipt_clusterip_tgt_info *cipinfo = matchinfo; | 469 | struct ipt_clusterip_tgt_info *cipinfo = matchinfo; |
457 | 470 | ||
458 | /* we first remove the proc entry and then drop the reference | 471 | /* if no more entries are referencing the config, remove it |
459 | * count. In case anyone still accesses the file, the open/close | 472 | * from the list and destroy the proc entry */ |
460 | * functions are also incrementing the refcount on their own */ | 473 | clusterip_config_entry_put(cipinfo->config); |
461 | #ifdef CONFIG_PROC_FS | 474 | |
462 | remove_proc_entry(cipinfo->config->pde->name, | ||
463 | cipinfo->config->pde->parent); | ||
464 | #endif | ||
465 | clusterip_config_put(cipinfo->config); | 475 | clusterip_config_put(cipinfo->config); |
466 | } | 476 | } |
467 | 477 | ||
@@ -533,7 +543,7 @@ arp_mangle(unsigned int hook, | |||
533 | 543 | ||
534 | /* if there is no clusterip configuration for the arp reply's | 544 | /* if there is no clusterip configuration for the arp reply's |
535 | * source ip, we don't want to mangle it */ | 545 | * source ip, we don't want to mangle it */ |
536 | c = clusterip_config_find_get(payload->src_ip); | 546 | c = clusterip_config_find_get(payload->src_ip, 0); |
537 | if (!c) | 547 | if (!c) |
538 | return NF_ACCEPT; | 548 | return NF_ACCEPT; |
539 | 549 | ||
@@ -574,56 +584,69 @@ static struct nf_hook_ops cip_arp_ops = { | |||
574 | 584 | ||
575 | #ifdef CONFIG_PROC_FS | 585 | #ifdef CONFIG_PROC_FS |
576 | 586 | ||
587 | struct clusterip_seq_position { | ||
588 | unsigned int pos; /* position */ | ||
589 | unsigned int weight; /* number of bits set == size */ | ||
590 | unsigned int bit; /* current bit */ | ||
591 | unsigned long val; /* current value */ | ||
592 | }; | ||
593 | |||
577 | static void *clusterip_seq_start(struct seq_file *s, loff_t *pos) | 594 | static void *clusterip_seq_start(struct seq_file *s, loff_t *pos) |
578 | { | 595 | { |
579 | struct proc_dir_entry *pde = s->private; | 596 | struct proc_dir_entry *pde = s->private; |
580 | struct clusterip_config *c = pde->data; | 597 | struct clusterip_config *c = pde->data; |
581 | unsigned int *nodeidx; | 598 | unsigned int weight; |
582 | 599 | u_int32_t local_nodes; | |
583 | read_lock_bh(&clusterip_lock); | 600 | struct clusterip_seq_position *idx; |
584 | if (*pos >= c->num_local_nodes) | 601 | |
602 | /* FIXME: possible race */ | ||
603 | local_nodes = c->local_nodes; | ||
604 | weight = hweight32(local_nodes); | ||
605 | if (*pos >= weight) | ||
585 | return NULL; | 606 | return NULL; |
586 | 607 | ||
587 | nodeidx = kmalloc(sizeof(unsigned int), GFP_KERNEL); | 608 | idx = kmalloc(sizeof(struct clusterip_seq_position), GFP_KERNEL); |
588 | if (!nodeidx) | 609 | if (!idx) |
589 | return ERR_PTR(-ENOMEM); | 610 | return ERR_PTR(-ENOMEM); |
590 | 611 | ||
591 | *nodeidx = *pos; | 612 | idx->pos = *pos; |
592 | return nodeidx; | 613 | idx->weight = weight; |
614 | idx->bit = ffs(local_nodes); | ||
615 | idx->val = local_nodes; | ||
616 | clear_bit(idx->bit - 1, &idx->val); | ||
617 | |||
618 | return idx; | ||
593 | } | 619 | } |
594 | 620 | ||
595 | static void *clusterip_seq_next(struct seq_file *s, void *v, loff_t *pos) | 621 | static void *clusterip_seq_next(struct seq_file *s, void *v, loff_t *pos) |
596 | { | 622 | { |
597 | struct proc_dir_entry *pde = s->private; | 623 | struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v; |
598 | struct clusterip_config *c = pde->data; | ||
599 | unsigned int *nodeidx = (unsigned int *)v; | ||
600 | 624 | ||
601 | *pos = ++(*nodeidx); | 625 | *pos = ++idx->pos; |
602 | if (*pos >= c->num_local_nodes) { | 626 | if (*pos >= idx->weight) { |
603 | kfree(v); | 627 | kfree(v); |
604 | return NULL; | 628 | return NULL; |
605 | } | 629 | } |
606 | return nodeidx; | 630 | idx->bit = ffs(idx->val); |
631 | clear_bit(idx->bit - 1, &idx->val); | ||
632 | return idx; | ||
607 | } | 633 | } |
608 | 634 | ||
609 | static void clusterip_seq_stop(struct seq_file *s, void *v) | 635 | static void clusterip_seq_stop(struct seq_file *s, void *v) |
610 | { | 636 | { |
611 | kfree(v); | 637 | kfree(v); |
612 | |||
613 | read_unlock_bh(&clusterip_lock); | ||
614 | } | 638 | } |
615 | 639 | ||
616 | static int clusterip_seq_show(struct seq_file *s, void *v) | 640 | static int clusterip_seq_show(struct seq_file *s, void *v) |
617 | { | 641 | { |
618 | struct proc_dir_entry *pde = s->private; | 642 | struct clusterip_seq_position *idx = (struct clusterip_seq_position *)v; |
619 | struct clusterip_config *c = pde->data; | ||
620 | unsigned int *nodeidx = (unsigned int *)v; | ||
621 | 643 | ||
622 | if (*nodeidx != 0) | 644 | if (idx->pos != 0) |
623 | seq_putc(s, ','); | 645 | seq_putc(s, ','); |
624 | seq_printf(s, "%u", c->local_nodes[*nodeidx]); | ||
625 | 646 | ||
626 | if (*nodeidx == c->num_local_nodes-1) | 647 | seq_printf(s, "%u", idx->bit); |
648 | |||
649 | if (idx->pos == idx->weight - 1) | ||
627 | seq_putc(s, '\n'); | 650 | seq_putc(s, '\n'); |
628 | 651 | ||
629 | return 0; | 652 | return 0; |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 304bb0a1d4f0..4b0d7e4d6269 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -361,7 +361,7 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
361 | 361 | ||
362 | if (type && code) { | 362 | if (type && code) { |
363 | get_user(fl->fl_icmp_type, type); | 363 | get_user(fl->fl_icmp_type, type); |
364 | __get_user(fl->fl_icmp_code, code); | 364 | get_user(fl->fl_icmp_code, code); |
365 | probed = 1; | 365 | probed = 1; |
366 | } | 366 | } |
367 | break; | 367 | break; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 29222b964951..a7537c7bbd06 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -979,14 +979,19 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
979 | if (!before(TCP_SKB_CB(skb)->seq, end_seq)) | 979 | if (!before(TCP_SKB_CB(skb)->seq, end_seq)) |
980 | break; | 980 | break; |
981 | 981 | ||
982 | in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) && | ||
983 | !before(end_seq, TCP_SKB_CB(skb)->end_seq); | ||
984 | |||
982 | pcount = tcp_skb_pcount(skb); | 985 | pcount = tcp_skb_pcount(skb); |
983 | 986 | ||
984 | if (pcount > 1 && | 987 | if (pcount > 1 && !in_sack && |
985 | (after(start_seq, TCP_SKB_CB(skb)->seq) || | 988 | after(TCP_SKB_CB(skb)->end_seq, start_seq)) { |
986 | before(end_seq, TCP_SKB_CB(skb)->end_seq))) { | ||
987 | unsigned int pkt_len; | 989 | unsigned int pkt_len; |
988 | 990 | ||
989 | if (after(start_seq, TCP_SKB_CB(skb)->seq)) | 991 | in_sack = !after(start_seq, |
992 | TCP_SKB_CB(skb)->seq); | ||
993 | |||
994 | if (!in_sack) | ||
990 | pkt_len = (start_seq - | 995 | pkt_len = (start_seq - |
991 | TCP_SKB_CB(skb)->seq); | 996 | TCP_SKB_CB(skb)->seq); |
992 | else | 997 | else |
@@ -999,9 +1004,6 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
999 | 1004 | ||
1000 | fack_count += pcount; | 1005 | fack_count += pcount; |
1001 | 1006 | ||
1002 | in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) && | ||
1003 | !before(end_seq, TCP_SKB_CB(skb)->end_seq); | ||
1004 | |||
1005 | sacked = TCP_SKB_CB(skb)->sacked; | 1007 | sacked = TCP_SKB_CB(skb)->sacked; |
1006 | 1008 | ||
1007 | /* Account D-SACK for retransmitted packet. */ | 1009 | /* Account D-SACK for retransmitted packet. */ |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index a88db28b0af7..b1a63b2c6b4a 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -384,7 +384,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, | |||
384 | newtp->frto_counter = 0; | 384 | newtp->frto_counter = 0; |
385 | newtp->frto_highmark = 0; | 385 | newtp->frto_highmark = 0; |
386 | 386 | ||
387 | newicsk->icsk_ca_ops = &tcp_reno; | 387 | newicsk->icsk_ca_ops = &tcp_init_congestion_ops; |
388 | 388 | ||
389 | tcp_set_ca_state(newsk, TCP_CA_Open); | 389 | tcp_set_ca_state(newsk, TCP_CA_Open); |
390 | tcp_init_xmit_timers(newsk); | 390 | tcp_init_xmit_timers(newsk); |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index c10e4435e3b1..5dd6dd7d091e 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -435,6 +435,8 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss | |||
435 | int nsize, old_factor; | 435 | int nsize, old_factor; |
436 | u16 flags; | 436 | u16 flags; |
437 | 437 | ||
438 | BUG_ON(len >= skb->len); | ||
439 | |||
438 | nsize = skb_headlen(skb) - len; | 440 | nsize = skb_headlen(skb) - len; |
439 | if (nsize < 0) | 441 | if (nsize < 0) |
440 | nsize = 0; | 442 | nsize = 0; |
@@ -459,9 +461,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss | |||
459 | flags = TCP_SKB_CB(skb)->flags; | 461 | flags = TCP_SKB_CB(skb)->flags; |
460 | TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH); | 462 | TCP_SKB_CB(skb)->flags = flags & ~(TCPCB_FLAG_FIN|TCPCB_FLAG_PSH); |
461 | TCP_SKB_CB(buff)->flags = flags; | 463 | TCP_SKB_CB(buff)->flags = flags; |
462 | TCP_SKB_CB(buff)->sacked = | 464 | TCP_SKB_CB(buff)->sacked = TCP_SKB_CB(skb)->sacked; |
463 | (TCP_SKB_CB(skb)->sacked & | ||
464 | (TCPCB_LOST | TCPCB_EVER_RETRANS | TCPCB_AT_TAIL)); | ||
465 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL; | 465 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_AT_TAIL; |
466 | 466 | ||
467 | if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) { | 467 | if (!skb_shinfo(skb)->nr_frags && skb->ip_summed != CHECKSUM_HW) { |
@@ -499,6 +499,12 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss | |||
499 | tcp_skb_pcount(buff); | 499 | tcp_skb_pcount(buff); |
500 | 500 | ||
501 | tp->packets_out -= diff; | 501 | tp->packets_out -= diff; |
502 | |||
503 | if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED) | ||
504 | tp->sacked_out -= diff; | ||
505 | if (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) | ||
506 | tp->retrans_out -= diff; | ||
507 | |||
502 | if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) { | 508 | if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) { |
503 | tp->lost_out -= diff; | 509 | tp->lost_out -= diff; |
504 | tp->left_out -= diff; | 510 | tp->left_out -= diff; |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 29fed6e58d0a..519899fb11d5 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -1968,7 +1968,7 @@ static void ip6_mc_clear_src(struct ifmcaddr6 *pmc) | |||
1968 | } | 1968 | } |
1969 | pmc->mca_sources = NULL; | 1969 | pmc->mca_sources = NULL; |
1970 | pmc->mca_sfmode = MCAST_EXCLUDE; | 1970 | pmc->mca_sfmode = MCAST_EXCLUDE; |
1971 | pmc->mca_sfcount[MCAST_EXCLUDE] = 0; | 1971 | pmc->mca_sfcount[MCAST_INCLUDE] = 0; |
1972 | pmc->mca_sfcount[MCAST_EXCLUDE] = 1; | 1972 | pmc->mca_sfcount[MCAST_EXCLUDE] = 1; |
1973 | } | 1973 | } |
1974 | 1974 | ||
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1cb8adb2787f..2da514b16d95 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -1955,6 +1955,57 @@ static void __exit fini(void) | |||
1955 | #endif | 1955 | #endif |
1956 | } | 1956 | } |
1957 | 1957 | ||
1958 | /* | ||
1959 | * find specified header up to transport protocol header. | ||
1960 | * If found target header, the offset to the header is set to *offset | ||
1961 | * and return 0. otherwise, return -1. | ||
1962 | * | ||
1963 | * Notes: - non-1st Fragment Header isn't skipped. | ||
1964 | * - ESP header isn't skipped. | ||
1965 | * - The target header may be trancated. | ||
1966 | */ | ||
1967 | int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, u8 target) | ||
1968 | { | ||
1969 | unsigned int start = (u8*)(skb->nh.ipv6h + 1) - skb->data; | ||
1970 | u8 nexthdr = skb->nh.ipv6h->nexthdr; | ||
1971 | unsigned int len = skb->len - start; | ||
1972 | |||
1973 | while (nexthdr != target) { | ||
1974 | struct ipv6_opt_hdr _hdr, *hp; | ||
1975 | unsigned int hdrlen; | ||
1976 | |||
1977 | if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) | ||
1978 | return -1; | ||
1979 | hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr); | ||
1980 | if (hp == NULL) | ||
1981 | return -1; | ||
1982 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
1983 | unsigned short _frag_off, *fp; | ||
1984 | fp = skb_header_pointer(skb, | ||
1985 | start+offsetof(struct frag_hdr, | ||
1986 | frag_off), | ||
1987 | sizeof(_frag_off), | ||
1988 | &_frag_off); | ||
1989 | if (fp == NULL) | ||
1990 | return -1; | ||
1991 | |||
1992 | if (ntohs(*fp) & ~0x7) | ||
1993 | return -1; | ||
1994 | hdrlen = 8; | ||
1995 | } else if (nexthdr == NEXTHDR_AUTH) | ||
1996 | hdrlen = (hp->hdrlen + 2) << 2; | ||
1997 | else | ||
1998 | hdrlen = ipv6_optlen(hp); | ||
1999 | |||
2000 | nexthdr = hp->nexthdr; | ||
2001 | len -= hdrlen; | ||
2002 | start += hdrlen; | ||
2003 | } | ||
2004 | |||
2005 | *offset = start; | ||
2006 | return 0; | ||
2007 | } | ||
2008 | |||
1958 | EXPORT_SYMBOL(ip6t_register_table); | 2009 | EXPORT_SYMBOL(ip6t_register_table); |
1959 | EXPORT_SYMBOL(ip6t_unregister_table); | 2010 | EXPORT_SYMBOL(ip6t_unregister_table); |
1960 | EXPORT_SYMBOL(ip6t_do_table); | 2011 | EXPORT_SYMBOL(ip6t_do_table); |
@@ -1963,6 +2014,7 @@ EXPORT_SYMBOL(ip6t_unregister_match); | |||
1963 | EXPORT_SYMBOL(ip6t_register_target); | 2014 | EXPORT_SYMBOL(ip6t_register_target); |
1964 | EXPORT_SYMBOL(ip6t_unregister_target); | 2015 | EXPORT_SYMBOL(ip6t_unregister_target); |
1965 | EXPORT_SYMBOL(ip6t_ext_hdr); | 2016 | EXPORT_SYMBOL(ip6t_ext_hdr); |
2017 | EXPORT_SYMBOL(ipv6_find_hdr); | ||
1966 | 2018 | ||
1967 | module_init(init); | 2019 | module_init(init); |
1968 | module_exit(fini); | 2020 | module_exit(fini); |
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index d5b94f142bba..dde37793d20b 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c | |||
@@ -48,92 +48,21 @@ match(const struct sk_buff *skb, | |||
48 | unsigned int protoff, | 48 | unsigned int protoff, |
49 | int *hotdrop) | 49 | int *hotdrop) |
50 | { | 50 | { |
51 | struct ip_auth_hdr *ah = NULL, _ah; | 51 | struct ip_auth_hdr *ah, _ah; |
52 | const struct ip6t_ah *ahinfo = matchinfo; | 52 | const struct ip6t_ah *ahinfo = matchinfo; |
53 | unsigned int temp; | ||
54 | int len; | ||
55 | u8 nexthdr; | ||
56 | unsigned int ptr; | 53 | unsigned int ptr; |
57 | unsigned int hdrlen = 0; | 54 | unsigned int hdrlen = 0; |
58 | 55 | ||
59 | /*DEBUGP("IPv6 AH entered\n");*/ | 56 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH) < 0) |
60 | /* if (opt->auth == 0) return 0; | ||
61 | * It does not filled on output */ | ||
62 | |||
63 | /* type of the 1st exthdr */ | ||
64 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
65 | /* pointer to the 1st exthdr */ | ||
66 | ptr = sizeof(struct ipv6hdr); | ||
67 | /* available length */ | ||
68 | len = skb->len - ptr; | ||
69 | temp = 0; | ||
70 | |||
71 | while (ip6t_ext_hdr(nexthdr)) { | ||
72 | struct ipv6_opt_hdr _hdr, *hp; | ||
73 | |||
74 | DEBUGP("ipv6_ah header iteration \n"); | ||
75 | |||
76 | /* Is there enough space for the next ext header? */ | ||
77 | if (len < sizeof(struct ipv6_opt_hdr)) | ||
78 | return 0; | ||
79 | /* No more exthdr -> evaluate */ | ||
80 | if (nexthdr == NEXTHDR_NONE) | ||
81 | break; | ||
82 | /* ESP -> evaluate */ | ||
83 | if (nexthdr == NEXTHDR_ESP) | ||
84 | break; | ||
85 | |||
86 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
87 | BUG_ON(hp == NULL); | ||
88 | |||
89 | /* Calculate the header length */ | ||
90 | if (nexthdr == NEXTHDR_FRAGMENT) | ||
91 | hdrlen = 8; | ||
92 | else if (nexthdr == NEXTHDR_AUTH) | ||
93 | hdrlen = (hp->hdrlen+2)<<2; | ||
94 | else | ||
95 | hdrlen = ipv6_optlen(hp); | ||
96 | |||
97 | /* AH -> evaluate */ | ||
98 | if (nexthdr == NEXTHDR_AUTH) { | ||
99 | temp |= MASK_AH; | ||
100 | break; | ||
101 | } | ||
102 | |||
103 | |||
104 | /* set the flag */ | ||
105 | switch (nexthdr) { | ||
106 | case NEXTHDR_HOP: | ||
107 | case NEXTHDR_ROUTING: | ||
108 | case NEXTHDR_FRAGMENT: | ||
109 | case NEXTHDR_AUTH: | ||
110 | case NEXTHDR_DEST: | ||
111 | break; | ||
112 | default: | ||
113 | DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr); | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | nexthdr = hp->nexthdr; | ||
118 | len -= hdrlen; | ||
119 | ptr += hdrlen; | ||
120 | if (ptr > skb->len) { | ||
121 | DEBUGP("ipv6_ah: new pointer too large! \n"); | ||
122 | break; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | /* AH header not found */ | ||
127 | if (temp != MASK_AH) | ||
128 | return 0; | 57 | return 0; |
129 | 58 | ||
130 | if (len < sizeof(struct ip_auth_hdr)){ | 59 | ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); |
60 | if (ah == NULL) { | ||
131 | *hotdrop = 1; | 61 | *hotdrop = 1; |
132 | return 0; | 62 | return 0; |
133 | } | 63 | } |
134 | 64 | ||
135 | ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); | 65 | hdrlen = (ah->hdrlen + 2) << 2; |
136 | BUG_ON(ah == NULL); | ||
137 | 66 | ||
138 | DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); | 67 | DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); |
139 | DEBUGP("RES %04X ", ah->reserved); | 68 | DEBUGP("RES %04X ", ah->reserved); |
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c index 540925e4a7a8..c450a635e54b 100644 --- a/net/ipv6/netfilter/ip6t_dst.c +++ b/net/ipv6/netfilter/ip6t_dst.c | |||
@@ -63,8 +63,6 @@ match(const struct sk_buff *skb, | |||
63 | struct ipv6_opt_hdr _optsh, *oh; | 63 | struct ipv6_opt_hdr _optsh, *oh; |
64 | const struct ip6t_opts *optinfo = matchinfo; | 64 | const struct ip6t_opts *optinfo = matchinfo; |
65 | unsigned int temp; | 65 | unsigned int temp; |
66 | unsigned int len; | ||
67 | u8 nexthdr; | ||
68 | unsigned int ptr; | 66 | unsigned int ptr; |
69 | unsigned int hdrlen = 0; | 67 | unsigned int hdrlen = 0; |
70 | unsigned int ret = 0; | 68 | unsigned int ret = 0; |
@@ -72,97 +70,25 @@ match(const struct sk_buff *skb, | |||
72 | u8 _optlen, *lp = NULL; | 70 | u8 _optlen, *lp = NULL; |
73 | unsigned int optlen; | 71 | unsigned int optlen; |
74 | 72 | ||
75 | /* type of the 1st exthdr */ | ||
76 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
77 | /* pointer to the 1st exthdr */ | ||
78 | ptr = sizeof(struct ipv6hdr); | ||
79 | /* available length */ | ||
80 | len = skb->len - ptr; | ||
81 | temp = 0; | ||
82 | |||
83 | while (ip6t_ext_hdr(nexthdr)) { | ||
84 | struct ipv6_opt_hdr _hdr, *hp; | ||
85 | |||
86 | DEBUGP("ipv6_opts header iteration \n"); | ||
87 | |||
88 | /* Is there enough space for the next ext header? */ | ||
89 | if (len < (int)sizeof(struct ipv6_opt_hdr)) | ||
90 | return 0; | ||
91 | /* No more exthdr -> evaluate */ | ||
92 | if (nexthdr == NEXTHDR_NONE) { | ||
93 | break; | ||
94 | } | ||
95 | /* ESP -> evaluate */ | ||
96 | if (nexthdr == NEXTHDR_ESP) { | ||
97 | break; | ||
98 | } | ||
99 | |||
100 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
101 | BUG_ON(hp == NULL); | ||
102 | |||
103 | /* Calculate the header length */ | ||
104 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
105 | hdrlen = 8; | ||
106 | } else if (nexthdr == NEXTHDR_AUTH) | ||
107 | hdrlen = (hp->hdrlen+2)<<2; | ||
108 | else | ||
109 | hdrlen = ipv6_optlen(hp); | ||
110 | |||
111 | /* OPTS -> evaluate */ | ||
112 | #if HOPBYHOP | 73 | #if HOPBYHOP |
113 | if (nexthdr == NEXTHDR_HOP) { | 74 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0) |
114 | temp |= MASK_HOPOPTS; | ||
115 | #else | 75 | #else |
116 | if (nexthdr == NEXTHDR_DEST) { | 76 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0) |
117 | temp |= MASK_DSTOPTS; | ||
118 | #endif | 77 | #endif |
119 | break; | 78 | return 0; |
120 | } | ||
121 | |||
122 | 79 | ||
123 | /* set the flag */ | 80 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); |
124 | switch (nexthdr){ | 81 | if (oh == NULL){ |
125 | case NEXTHDR_HOP: | ||
126 | case NEXTHDR_ROUTING: | ||
127 | case NEXTHDR_FRAGMENT: | ||
128 | case NEXTHDR_AUTH: | ||
129 | case NEXTHDR_DEST: | ||
130 | break; | ||
131 | default: | ||
132 | DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr); | ||
133 | return 0; | ||
134 | break; | ||
135 | } | ||
136 | |||
137 | nexthdr = hp->nexthdr; | ||
138 | len -= hdrlen; | ||
139 | ptr += hdrlen; | ||
140 | if ( ptr > skb->len ) { | ||
141 | DEBUGP("ipv6_opts: new pointer is too large! \n"); | ||
142 | break; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | /* OPTIONS header not found */ | ||
147 | #if HOPBYHOP | ||
148 | if ( temp != MASK_HOPOPTS ) return 0; | ||
149 | #else | ||
150 | if ( temp != MASK_DSTOPTS ) return 0; | ||
151 | #endif | ||
152 | |||
153 | if (len < (int)sizeof(struct ipv6_opt_hdr)){ | ||
154 | *hotdrop = 1; | 82 | *hotdrop = 1; |
155 | return 0; | 83 | return 0; |
156 | } | 84 | } |
157 | 85 | ||
158 | if (len < hdrlen){ | 86 | hdrlen = ipv6_optlen(oh); |
87 | if (skb->len - ptr < hdrlen){ | ||
159 | /* Packet smaller than it's length field */ | 88 | /* Packet smaller than it's length field */ |
160 | return 0; | 89 | return 0; |
161 | } | 90 | } |
162 | 91 | ||
163 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); | ||
164 | BUG_ON(oh == NULL); | ||
165 | |||
166 | DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); | 92 | DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); |
167 | 93 | ||
168 | DEBUGP("len %02X %04X %02X ", | 94 | DEBUGP("len %02X %04X %02X ", |
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c index e39dd236fd8e..24bc0cde43a1 100644 --- a/net/ipv6/netfilter/ip6t_esp.c +++ b/net/ipv6/netfilter/ip6t_esp.c | |||
@@ -48,87 +48,22 @@ match(const struct sk_buff *skb, | |||
48 | unsigned int protoff, | 48 | unsigned int protoff, |
49 | int *hotdrop) | 49 | int *hotdrop) |
50 | { | 50 | { |
51 | struct ip_esp_hdr _esp, *eh = NULL; | 51 | struct ip_esp_hdr _esp, *eh; |
52 | const struct ip6t_esp *espinfo = matchinfo; | 52 | const struct ip6t_esp *espinfo = matchinfo; |
53 | unsigned int temp; | ||
54 | int len; | ||
55 | u8 nexthdr; | ||
56 | unsigned int ptr; | 53 | unsigned int ptr; |
57 | 54 | ||
58 | /* Make sure this isn't an evil packet */ | 55 | /* Make sure this isn't an evil packet */ |
59 | /*DEBUGP("ipv6_esp entered \n");*/ | 56 | /*DEBUGP("ipv6_esp entered \n");*/ |
60 | 57 | ||
61 | /* type of the 1st exthdr */ | 58 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ESP) < 0) |
62 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
63 | /* pointer to the 1st exthdr */ | ||
64 | ptr = sizeof(struct ipv6hdr); | ||
65 | /* available length */ | ||
66 | len = skb->len - ptr; | ||
67 | temp = 0; | ||
68 | |||
69 | while (ip6t_ext_hdr(nexthdr)) { | ||
70 | struct ipv6_opt_hdr _hdr, *hp; | ||
71 | int hdrlen; | ||
72 | |||
73 | DEBUGP("ipv6_esp header iteration \n"); | ||
74 | |||
75 | /* Is there enough space for the next ext header? */ | ||
76 | if (len < sizeof(struct ipv6_opt_hdr)) | ||
77 | return 0; | ||
78 | /* No more exthdr -> evaluate */ | ||
79 | if (nexthdr == NEXTHDR_NONE) | ||
80 | break; | ||
81 | /* ESP -> evaluate */ | ||
82 | if (nexthdr == NEXTHDR_ESP) { | ||
83 | temp |= MASK_ESP; | ||
84 | break; | ||
85 | } | ||
86 | |||
87 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
88 | BUG_ON(hp == NULL); | ||
89 | |||
90 | /* Calculate the header length */ | ||
91 | if (nexthdr == NEXTHDR_FRAGMENT) | ||
92 | hdrlen = 8; | ||
93 | else if (nexthdr == NEXTHDR_AUTH) | ||
94 | hdrlen = (hp->hdrlen+2)<<2; | ||
95 | else | ||
96 | hdrlen = ipv6_optlen(hp); | ||
97 | |||
98 | /* set the flag */ | ||
99 | switch (nexthdr) { | ||
100 | case NEXTHDR_HOP: | ||
101 | case NEXTHDR_ROUTING: | ||
102 | case NEXTHDR_FRAGMENT: | ||
103 | case NEXTHDR_AUTH: | ||
104 | case NEXTHDR_DEST: | ||
105 | break; | ||
106 | default: | ||
107 | DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr); | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | nexthdr = hp->nexthdr; | ||
112 | len -= hdrlen; | ||
113 | ptr += hdrlen; | ||
114 | if (ptr > skb->len) { | ||
115 | DEBUGP("ipv6_esp: new pointer too large! \n"); | ||
116 | break; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | /* ESP header not found */ | ||
121 | if (temp != MASK_ESP) | ||
122 | return 0; | 59 | return 0; |
123 | 60 | ||
124 | if (len < sizeof(struct ip_esp_hdr)) { | 61 | eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp); |
62 | if (eh == NULL) { | ||
125 | *hotdrop = 1; | 63 | *hotdrop = 1; |
126 | return 0; | 64 | return 0; |
127 | } | 65 | } |
128 | 66 | ||
129 | eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp); | ||
130 | BUG_ON(eh == NULL); | ||
131 | |||
132 | DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi)); | 67 | DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi)); |
133 | 68 | ||
134 | return (eh != NULL) | 69 | return (eh != NULL) |
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index 4bfa30a9bc80..085d5f8eea29 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c | |||
@@ -48,90 +48,18 @@ match(const struct sk_buff *skb, | |||
48 | unsigned int protoff, | 48 | unsigned int protoff, |
49 | int *hotdrop) | 49 | int *hotdrop) |
50 | { | 50 | { |
51 | struct frag_hdr _frag, *fh = NULL; | 51 | struct frag_hdr _frag, *fh; |
52 | const struct ip6t_frag *fraginfo = matchinfo; | 52 | const struct ip6t_frag *fraginfo = matchinfo; |
53 | unsigned int temp; | ||
54 | int len; | ||
55 | u8 nexthdr; | ||
56 | unsigned int ptr; | 53 | unsigned int ptr; |
57 | unsigned int hdrlen = 0; | ||
58 | |||
59 | /* type of the 1st exthdr */ | ||
60 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
61 | /* pointer to the 1st exthdr */ | ||
62 | ptr = sizeof(struct ipv6hdr); | ||
63 | /* available length */ | ||
64 | len = skb->len - ptr; | ||
65 | temp = 0; | ||
66 | |||
67 | while (ip6t_ext_hdr(nexthdr)) { | ||
68 | struct ipv6_opt_hdr _hdr, *hp; | ||
69 | |||
70 | DEBUGP("ipv6_frag header iteration \n"); | ||
71 | |||
72 | /* Is there enough space for the next ext header? */ | ||
73 | if (len < (int)sizeof(struct ipv6_opt_hdr)) | ||
74 | return 0; | ||
75 | /* No more exthdr -> evaluate */ | ||
76 | if (nexthdr == NEXTHDR_NONE) { | ||
77 | break; | ||
78 | } | ||
79 | /* ESP -> evaluate */ | ||
80 | if (nexthdr == NEXTHDR_ESP) { | ||
81 | break; | ||
82 | } | ||
83 | |||
84 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
85 | BUG_ON(hp == NULL); | ||
86 | |||
87 | /* Calculate the header length */ | ||
88 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
89 | hdrlen = 8; | ||
90 | } else if (nexthdr == NEXTHDR_AUTH) | ||
91 | hdrlen = (hp->hdrlen+2)<<2; | ||
92 | else | ||
93 | hdrlen = ipv6_optlen(hp); | ||
94 | |||
95 | /* FRAG -> evaluate */ | ||
96 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
97 | temp |= MASK_FRAGMENT; | ||
98 | break; | ||
99 | } | ||
100 | |||
101 | |||
102 | /* set the flag */ | ||
103 | switch (nexthdr){ | ||
104 | case NEXTHDR_HOP: | ||
105 | case NEXTHDR_ROUTING: | ||
106 | case NEXTHDR_FRAGMENT: | ||
107 | case NEXTHDR_AUTH: | ||
108 | case NEXTHDR_DEST: | ||
109 | break; | ||
110 | default: | ||
111 | DEBUGP("ipv6_frag match: unknown nextheader %u\n",nexthdr); | ||
112 | return 0; | ||
113 | break; | ||
114 | } | ||
115 | |||
116 | nexthdr = hp->nexthdr; | ||
117 | len -= hdrlen; | ||
118 | ptr += hdrlen; | ||
119 | if ( ptr > skb->len ) { | ||
120 | DEBUGP("ipv6_frag: new pointer too large! \n"); | ||
121 | break; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | /* FRAG header not found */ | ||
126 | if ( temp != MASK_FRAGMENT ) return 0; | ||
127 | |||
128 | if (len < sizeof(struct frag_hdr)){ | ||
129 | *hotdrop = 1; | ||
130 | return 0; | ||
131 | } | ||
132 | 54 | ||
133 | fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); | 55 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT) < 0) |
134 | BUG_ON(fh == NULL); | 56 | return 0; |
57 | |||
58 | fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); | ||
59 | if (fh == NULL){ | ||
60 | *hotdrop = 1; | ||
61 | return 0; | ||
62 | } | ||
135 | 63 | ||
136 | DEBUGP("INFO %04X ", fh->frag_off); | 64 | DEBUGP("INFO %04X ", fh->frag_off); |
137 | DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); | 65 | DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7); |
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index 27f3650d127e..1d09485111d0 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c | |||
@@ -63,8 +63,6 @@ match(const struct sk_buff *skb, | |||
63 | struct ipv6_opt_hdr _optsh, *oh; | 63 | struct ipv6_opt_hdr _optsh, *oh; |
64 | const struct ip6t_opts *optinfo = matchinfo; | 64 | const struct ip6t_opts *optinfo = matchinfo; |
65 | unsigned int temp; | 65 | unsigned int temp; |
66 | unsigned int len; | ||
67 | u8 nexthdr; | ||
68 | unsigned int ptr; | 66 | unsigned int ptr; |
69 | unsigned int hdrlen = 0; | 67 | unsigned int hdrlen = 0; |
70 | unsigned int ret = 0; | 68 | unsigned int ret = 0; |
@@ -72,97 +70,25 @@ match(const struct sk_buff *skb, | |||
72 | u8 _optlen, *lp = NULL; | 70 | u8 _optlen, *lp = NULL; |
73 | unsigned int optlen; | 71 | unsigned int optlen; |
74 | 72 | ||
75 | /* type of the 1st exthdr */ | ||
76 | nexthdr = skb->nh.ipv6h->nexthdr; | ||
77 | /* pointer to the 1st exthdr */ | ||
78 | ptr = sizeof(struct ipv6hdr); | ||
79 | /* available length */ | ||
80 | len = skb->len - ptr; | ||
81 | temp = 0; | ||
82 | |||
83 | while (ip6t_ext_hdr(nexthdr)) { | ||
84 | struct ipv6_opt_hdr _hdr, *hp; | ||
85 | |||
86 | DEBUGP("ipv6_opts header iteration \n"); | ||
87 | |||
88 | /* Is there enough space for the next ext header? */ | ||
89 | if (len < (int)sizeof(struct ipv6_opt_hdr)) | ||
90 | return 0; | ||
91 | /* No more exthdr -> evaluate */ | ||
92 | if (nexthdr == NEXTHDR_NONE) { | ||
93 | break; | ||
94 | } | ||
95 | /* ESP -> evaluate */ | ||
96 | if (nexthdr == NEXTHDR_ESP) { | ||
97 | break; | ||
98 | } | ||
99 | |||
100 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
101 | BUG_ON(hp == NULL); | ||
102 | |||
103 | /* Calculate the header length */ | ||
104 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
105 | hdrlen = 8; | ||
106 | } else if (nexthdr == NEXTHDR_AUTH) | ||
107 | hdrlen = (hp->hdrlen+2)<<2; | ||
108 | else | ||
109 | hdrlen = ipv6_optlen(hp); | ||
110 | |||
111 | /* OPTS -> evaluate */ | ||
112 | #if HOPBYHOP | 73 | #if HOPBYHOP |
113 | if (nexthdr == NEXTHDR_HOP) { | 74 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_HOP) < 0) |
114 | temp |= MASK_HOPOPTS; | ||
115 | #else | 75 | #else |
116 | if (nexthdr == NEXTHDR_DEST) { | 76 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_DEST) < 0) |
117 | temp |= MASK_DSTOPTS; | ||
118 | #endif | 77 | #endif |
119 | break; | 78 | return 0; |
120 | } | ||
121 | |||
122 | 79 | ||
123 | /* set the flag */ | 80 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); |
124 | switch (nexthdr){ | 81 | if (oh == NULL){ |
125 | case NEXTHDR_HOP: | ||
126 | case NEXTHDR_ROUTING: | ||
127 | case NEXTHDR_FRAGMENT: | ||
128 | case NEXTHDR_AUTH: | ||
129 | case NEXTHDR_DEST: | ||
130 | break; | ||
131 | default: | ||
132 | DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr); | ||
133 | return 0; | ||
134 | break; | ||
135 | } | ||
136 | |||
137 | nexthdr = hp->nexthdr; | ||
138 | len -= hdrlen; | ||
139 | ptr += hdrlen; | ||
140 | if ( ptr > skb->len ) { | ||
141 | DEBUGP("ipv6_opts: new pointer is too large! \n"); | ||
142 | break; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | /* OPTIONS header not found */ | ||
147 | #if HOPBYHOP | ||
148 | if ( temp != MASK_HOPOPTS ) return 0; | ||
149 | #else | ||
150 | if ( temp != MASK_DSTOPTS ) return 0; | ||
151 | #endif | ||
152 | |||
153 | if (len < (int)sizeof(struct ipv6_opt_hdr)){ | ||
154 | *hotdrop = 1; | 82 | *hotdrop = 1; |
155 | return 0; | 83 | return 0; |
156 | } | 84 | } |
157 | 85 | ||
158 | if (len < hdrlen){ | 86 | hdrlen = ipv6_optlen(oh); |
87 | if (skb->len - ptr < hdrlen){ | ||
159 | /* Packet smaller than it's length field */ | 88 | /* Packet smaller than it's length field */ |
160 | return 0; | 89 | return 0; |
161 | } | 90 | } |
162 | 91 | ||
163 | oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); | ||
164 | BUG_ON(oh == NULL); | ||
165 | |||
166 | DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); | 92 | DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen); |
167 | 93 | ||
168 | DEBUGP("len %02X %04X %02X ", | 94 | DEBUGP("len %02X %04X %02X ", |
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index 2bb670037df3..beb2fd5cebbb 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c | |||
@@ -50,98 +50,29 @@ match(const struct sk_buff *skb, | |||
50 | unsigned int protoff, | 50 | unsigned int protoff, |
51 | int *hotdrop) | 51 | int *hotdrop) |
52 | { | 52 | { |
53 | struct ipv6_rt_hdr _route, *rh = NULL; | 53 | struct ipv6_rt_hdr _route, *rh; |
54 | const struct ip6t_rt *rtinfo = matchinfo; | 54 | const struct ip6t_rt *rtinfo = matchinfo; |
55 | unsigned int temp; | 55 | unsigned int temp; |
56 | unsigned int len; | ||
57 | u8 nexthdr; | ||
58 | unsigned int ptr; | 56 | unsigned int ptr; |
59 | unsigned int hdrlen = 0; | 57 | unsigned int hdrlen = 0; |
60 | unsigned int ret = 0; | 58 | unsigned int ret = 0; |
61 | struct in6_addr *ap, _addr; | 59 | struct in6_addr *ap, _addr; |
62 | 60 | ||
63 | /* type of the 1st exthdr */ | 61 | if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING) < 0) |
64 | nexthdr = skb->nh.ipv6h->nexthdr; | 62 | return 0; |
65 | /* pointer to the 1st exthdr */ | ||
66 | ptr = sizeof(struct ipv6hdr); | ||
67 | /* available length */ | ||
68 | len = skb->len - ptr; | ||
69 | temp = 0; | ||
70 | 63 | ||
71 | while (ip6t_ext_hdr(nexthdr)) { | 64 | rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); |
72 | struct ipv6_opt_hdr _hdr, *hp; | 65 | if (rh == NULL){ |
73 | |||
74 | DEBUGP("ipv6_rt header iteration \n"); | ||
75 | |||
76 | /* Is there enough space for the next ext header? */ | ||
77 | if (len < (int)sizeof(struct ipv6_opt_hdr)) | ||
78 | return 0; | ||
79 | /* No more exthdr -> evaluate */ | ||
80 | if (nexthdr == NEXTHDR_NONE) { | ||
81 | break; | ||
82 | } | ||
83 | /* ESP -> evaluate */ | ||
84 | if (nexthdr == NEXTHDR_ESP) { | ||
85 | break; | ||
86 | } | ||
87 | |||
88 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
89 | BUG_ON(hp == NULL); | ||
90 | |||
91 | /* Calculate the header length */ | ||
92 | if (nexthdr == NEXTHDR_FRAGMENT) { | ||
93 | hdrlen = 8; | ||
94 | } else if (nexthdr == NEXTHDR_AUTH) | ||
95 | hdrlen = (hp->hdrlen+2)<<2; | ||
96 | else | ||
97 | hdrlen = ipv6_optlen(hp); | ||
98 | |||
99 | /* ROUTING -> evaluate */ | ||
100 | if (nexthdr == NEXTHDR_ROUTING) { | ||
101 | temp |= MASK_ROUTING; | ||
102 | break; | ||
103 | } | ||
104 | |||
105 | |||
106 | /* set the flag */ | ||
107 | switch (nexthdr){ | ||
108 | case NEXTHDR_HOP: | ||
109 | case NEXTHDR_ROUTING: | ||
110 | case NEXTHDR_FRAGMENT: | ||
111 | case NEXTHDR_AUTH: | ||
112 | case NEXTHDR_DEST: | ||
113 | break; | ||
114 | default: | ||
115 | DEBUGP("ipv6_rt match: unknown nextheader %u\n",nexthdr); | ||
116 | return 0; | ||
117 | break; | ||
118 | } | ||
119 | |||
120 | nexthdr = hp->nexthdr; | ||
121 | len -= hdrlen; | ||
122 | ptr += hdrlen; | ||
123 | if ( ptr > skb->len ) { | ||
124 | DEBUGP("ipv6_rt: new pointer is too large! \n"); | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | /* ROUTING header not found */ | ||
130 | if ( temp != MASK_ROUTING ) return 0; | ||
131 | |||
132 | if (len < (int)sizeof(struct ipv6_rt_hdr)){ | ||
133 | *hotdrop = 1; | 66 | *hotdrop = 1; |
134 | return 0; | 67 | return 0; |
135 | } | 68 | } |
136 | 69 | ||
137 | if (len < hdrlen){ | 70 | hdrlen = ipv6_optlen(rh); |
71 | if (skb->len - ptr < hdrlen){ | ||
138 | /* Pcket smaller than its length field */ | 72 | /* Pcket smaller than its length field */ |
139 | return 0; | 73 | return 0; |
140 | } | 74 | } |
141 | 75 | ||
142 | rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); | ||
143 | BUG_ON(rh == NULL); | ||
144 | |||
145 | DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); | 76 | DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen); |
146 | DEBUGP("TYPE %04X ", rh->type); | 77 | DEBUGP("TYPE %04X ", rh->type); |
147 | DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); | 78 | DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left); |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 5aa3691c578d..a1265a320b11 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -627,7 +627,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) | |||
627 | 627 | ||
628 | if (type && code) { | 628 | if (type && code) { |
629 | get_user(fl->fl_icmp_type, type); | 629 | get_user(fl->fl_icmp_type, type); |
630 | __get_user(fl->fl_icmp_code, code); | 630 | get_user(fl->fl_icmp_code, code); |
631 | probed = 1; | 631 | probed = 1; |
632 | } | 632 | } |
633 | break; | 633 | break; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 69b146843a20..6001948600f3 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -405,9 +405,8 @@ static struct sock *udp_v6_mcast_next(struct sock *sk, | |||
405 | continue; | 405 | continue; |
406 | 406 | ||
407 | if (!ipv6_addr_any(&np->rcv_saddr)) { | 407 | if (!ipv6_addr_any(&np->rcv_saddr)) { |
408 | if (ipv6_addr_equal(&np->rcv_saddr, loc_addr)) | 408 | if (!ipv6_addr_equal(&np->rcv_saddr, loc_addr)) |
409 | return s; | 409 | continue; |
410 | continue; | ||
411 | } | 410 | } |
412 | if(!inet6_mc_check(s, loc_addr, rmt_addr)) | 411 | if(!inet6_mc_check(s, loc_addr, rmt_addr)) |
413 | continue; | 412 | continue; |
@@ -640,6 +639,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
640 | int tclass = -1; | 639 | int tclass = -1; |
641 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; | 640 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; |
642 | int err; | 641 | int err; |
642 | int connected = 0; | ||
643 | 643 | ||
644 | /* destination address check */ | 644 | /* destination address check */ |
645 | if (sin6) { | 645 | if (sin6) { |
@@ -749,6 +749,7 @@ do_udp_sendmsg: | |||
749 | fl->fl_ip_dport = inet->dport; | 749 | fl->fl_ip_dport = inet->dport; |
750 | daddr = &np->daddr; | 750 | daddr = &np->daddr; |
751 | fl->fl6_flowlabel = np->flow_label; | 751 | fl->fl6_flowlabel = np->flow_label; |
752 | connected = 1; | ||
752 | } | 753 | } |
753 | 754 | ||
754 | if (!fl->oif) | 755 | if (!fl->oif) |
@@ -771,6 +772,7 @@ do_udp_sendmsg: | |||
771 | } | 772 | } |
772 | if (!(opt->opt_nflen|opt->opt_flen)) | 773 | if (!(opt->opt_nflen|opt->opt_flen)) |
773 | opt = NULL; | 774 | opt = NULL; |
775 | connected = 0; | ||
774 | } | 776 | } |
775 | if (opt == NULL) | 777 | if (opt == NULL) |
776 | opt = np->opt; | 778 | opt = np->opt; |
@@ -788,10 +790,13 @@ do_udp_sendmsg: | |||
788 | ipv6_addr_copy(&final, &fl->fl6_dst); | 790 | ipv6_addr_copy(&final, &fl->fl6_dst); |
789 | ipv6_addr_copy(&fl->fl6_dst, rt0->addr); | 791 | ipv6_addr_copy(&fl->fl6_dst, rt0->addr); |
790 | final_p = &final; | 792 | final_p = &final; |
793 | connected = 0; | ||
791 | } | 794 | } |
792 | 795 | ||
793 | if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) | 796 | if (!fl->oif && ipv6_addr_is_multicast(&fl->fl6_dst)) { |
794 | fl->oif = np->mcast_oif; | 797 | fl->oif = np->mcast_oif; |
798 | connected = 0; | ||
799 | } | ||
795 | 800 | ||
796 | err = ip6_dst_lookup(sk, &dst, fl); | 801 | err = ip6_dst_lookup(sk, &dst, fl); |
797 | if (err) | 802 | if (err) |
@@ -847,7 +852,7 @@ do_append_data: | |||
847 | else if (!corkreq) | 852 | else if (!corkreq) |
848 | err = udp_v6_push_pending_frames(sk, up); | 853 | err = udp_v6_push_pending_frames(sk, up); |
849 | 854 | ||
850 | if (dst) | 855 | if (dst && connected) |
851 | ip6_dst_store(sk, dst, | 856 | ip6_dst_store(sk, dst, |
852 | ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? | 857 | ipv6_addr_equal(&fl->fl6_dst, &np->daddr) ? |
853 | &np->daddr : NULL); | 858 | &np->daddr : NULL); |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8690f171c1ef..ee865d88183b 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -36,6 +36,11 @@ | |||
36 | * Michal Ostrowski : Module initialization cleanup. | 36 | * Michal Ostrowski : Module initialization cleanup. |
37 | * Ulises Alonso : Frame number limit removal and | 37 | * Ulises Alonso : Frame number limit removal and |
38 | * packet_set_ring memory leak. | 38 | * packet_set_ring memory leak. |
39 | * Eric Biederman : Allow for > 8 byte hardware addresses. | ||
40 | * The convention is that longer addresses | ||
41 | * will simply extend the hardware address | ||
42 | * byte arrays at the end of sockaddr_ll | ||
43 | * and packet_mreq. | ||
39 | * | 44 | * |
40 | * This program is free software; you can redistribute it and/or | 45 | * This program is free software; you can redistribute it and/or |
41 | * modify it under the terms of the GNU General Public License | 46 | * modify it under the terms of the GNU General Public License |
@@ -161,7 +166,17 @@ struct packet_mclist | |||
161 | int count; | 166 | int count; |
162 | unsigned short type; | 167 | unsigned short type; |
163 | unsigned short alen; | 168 | unsigned short alen; |
164 | unsigned char addr[8]; | 169 | unsigned char addr[MAX_ADDR_LEN]; |
170 | }; | ||
171 | /* identical to struct packet_mreq except it has | ||
172 | * a longer address field. | ||
173 | */ | ||
174 | struct packet_mreq_max | ||
175 | { | ||
176 | int mr_ifindex; | ||
177 | unsigned short mr_type; | ||
178 | unsigned short mr_alen; | ||
179 | unsigned char mr_address[MAX_ADDR_LEN]; | ||
165 | }; | 180 | }; |
166 | #endif | 181 | #endif |
167 | #ifdef CONFIG_PACKET_MMAP | 182 | #ifdef CONFIG_PACKET_MMAP |
@@ -716,6 +731,8 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
716 | err = -EINVAL; | 731 | err = -EINVAL; |
717 | if (msg->msg_namelen < sizeof(struct sockaddr_ll)) | 732 | if (msg->msg_namelen < sizeof(struct sockaddr_ll)) |
718 | goto out; | 733 | goto out; |
734 | if (msg->msg_namelen < (saddr->sll_halen + offsetof(struct sockaddr_ll, sll_addr))) | ||
735 | goto out; | ||
719 | ifindex = saddr->sll_ifindex; | 736 | ifindex = saddr->sll_ifindex; |
720 | proto = saddr->sll_protocol; | 737 | proto = saddr->sll_protocol; |
721 | addr = saddr->sll_addr; | 738 | addr = saddr->sll_addr; |
@@ -744,6 +761,12 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
744 | if (dev->hard_header) { | 761 | if (dev->hard_header) { |
745 | int res; | 762 | int res; |
746 | err = -EINVAL; | 763 | err = -EINVAL; |
764 | if (saddr) { | ||
765 | if (saddr->sll_halen != dev->addr_len) | ||
766 | goto out_free; | ||
767 | if (saddr->sll_hatype != dev->type) | ||
768 | goto out_free; | ||
769 | } | ||
747 | res = dev->hard_header(skb, dev, ntohs(proto), addr, NULL, len); | 770 | res = dev->hard_header(skb, dev, ntohs(proto), addr, NULL, len); |
748 | if (sock->type != SOCK_DGRAM) { | 771 | if (sock->type != SOCK_DGRAM) { |
749 | skb->tail = skb->data; | 772 | skb->tail = skb->data; |
@@ -1045,6 +1068,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1045 | struct sock *sk = sock->sk; | 1068 | struct sock *sk = sock->sk; |
1046 | struct sk_buff *skb; | 1069 | struct sk_buff *skb; |
1047 | int copied, err; | 1070 | int copied, err; |
1071 | struct sockaddr_ll *sll; | ||
1048 | 1072 | ||
1049 | err = -EINVAL; | 1073 | err = -EINVAL; |
1050 | if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT)) | 1074 | if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT)) |
@@ -1057,16 +1081,6 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1057 | #endif | 1081 | #endif |
1058 | 1082 | ||
1059 | /* | 1083 | /* |
1060 | * If the address length field is there to be filled in, we fill | ||
1061 | * it in now. | ||
1062 | */ | ||
1063 | |||
1064 | if (sock->type == SOCK_PACKET) | ||
1065 | msg->msg_namelen = sizeof(struct sockaddr_pkt); | ||
1066 | else | ||
1067 | msg->msg_namelen = sizeof(struct sockaddr_ll); | ||
1068 | |||
1069 | /* | ||
1070 | * Call the generic datagram receiver. This handles all sorts | 1084 | * Call the generic datagram receiver. This handles all sorts |
1071 | * of horrible races and re-entrancy so we can forget about it | 1085 | * of horrible races and re-entrancy so we can forget about it |
1072 | * in the protocol layers. | 1086 | * in the protocol layers. |
@@ -1087,6 +1101,17 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1087 | goto out; | 1101 | goto out; |
1088 | 1102 | ||
1089 | /* | 1103 | /* |
1104 | * If the address length field is there to be filled in, we fill | ||
1105 | * it in now. | ||
1106 | */ | ||
1107 | |||
1108 | sll = (struct sockaddr_ll*)skb->cb; | ||
1109 | if (sock->type == SOCK_PACKET) | ||
1110 | msg->msg_namelen = sizeof(struct sockaddr_pkt); | ||
1111 | else | ||
1112 | msg->msg_namelen = sll->sll_halen + offsetof(struct sockaddr_ll, sll_addr); | ||
1113 | |||
1114 | /* | ||
1090 | * You lose any data beyond the buffer you gave. If it worries a | 1115 | * You lose any data beyond the buffer you gave. If it worries a |
1091 | * user program they can ask the device for its MTU anyway. | 1116 | * user program they can ask the device for its MTU anyway. |
1092 | */ | 1117 | */ |
@@ -1166,7 +1191,7 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr, | |||
1166 | sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */ | 1191 | sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */ |
1167 | sll->sll_halen = 0; | 1192 | sll->sll_halen = 0; |
1168 | } | 1193 | } |
1169 | *uaddr_len = sizeof(*sll); | 1194 | *uaddr_len = offsetof(struct sockaddr_ll, sll_addr) + sll->sll_halen; |
1170 | 1195 | ||
1171 | return 0; | 1196 | return 0; |
1172 | } | 1197 | } |
@@ -1199,7 +1224,7 @@ static void packet_dev_mclist(struct net_device *dev, struct packet_mclist *i, i | |||
1199 | } | 1224 | } |
1200 | } | 1225 | } |
1201 | 1226 | ||
1202 | static int packet_mc_add(struct sock *sk, struct packet_mreq *mreq) | 1227 | static int packet_mc_add(struct sock *sk, struct packet_mreq_max *mreq) |
1203 | { | 1228 | { |
1204 | struct packet_sock *po = pkt_sk(sk); | 1229 | struct packet_sock *po = pkt_sk(sk); |
1205 | struct packet_mclist *ml, *i; | 1230 | struct packet_mclist *ml, *i; |
@@ -1249,7 +1274,7 @@ done: | |||
1249 | return err; | 1274 | return err; |
1250 | } | 1275 | } |
1251 | 1276 | ||
1252 | static int packet_mc_drop(struct sock *sk, struct packet_mreq *mreq) | 1277 | static int packet_mc_drop(struct sock *sk, struct packet_mreq_max *mreq) |
1253 | { | 1278 | { |
1254 | struct packet_mclist *ml, **mlp; | 1279 | struct packet_mclist *ml, **mlp; |
1255 | 1280 | ||
@@ -1315,11 +1340,17 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv | |||
1315 | case PACKET_ADD_MEMBERSHIP: | 1340 | case PACKET_ADD_MEMBERSHIP: |
1316 | case PACKET_DROP_MEMBERSHIP: | 1341 | case PACKET_DROP_MEMBERSHIP: |
1317 | { | 1342 | { |
1318 | struct packet_mreq mreq; | 1343 | struct packet_mreq_max mreq; |
1319 | if (optlen<sizeof(mreq)) | 1344 | int len = optlen; |
1345 | memset(&mreq, 0, sizeof(mreq)); | ||
1346 | if (len < sizeof(struct packet_mreq)) | ||
1320 | return -EINVAL; | 1347 | return -EINVAL; |
1321 | if (copy_from_user(&mreq,optval,sizeof(mreq))) | 1348 | if (len > sizeof(mreq)) |
1349 | len = sizeof(mreq); | ||
1350 | if (copy_from_user(&mreq,optval,len)) | ||
1322 | return -EFAULT; | 1351 | return -EFAULT; |
1352 | if (len < (mreq.mr_alen + offsetof(struct packet_mreq, mr_address))) | ||
1353 | return -EINVAL; | ||
1323 | if (optname == PACKET_ADD_MEMBERSHIP) | 1354 | if (optname == PACKET_ADD_MEMBERSHIP) |
1324 | ret = packet_mc_add(sk, &mreq); | 1355 | ret = packet_mc_add(sk, &mreq); |
1325 | else | 1356 | else |
diff --git a/net/socket.c b/net/socket.c index c699e93c33d7..f9264472377f 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -1862,7 +1862,8 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag | |||
1862 | if (err < 0) | 1862 | if (err < 0) |
1863 | goto out_freeiov; | 1863 | goto out_freeiov; |
1864 | } | 1864 | } |
1865 | err = __put_user(msg_sys.msg_flags, COMPAT_FLAGS(msg)); | 1865 | err = __put_user((msg_sys.msg_flags & ~MSG_CMSG_COMPAT), |
1866 | COMPAT_FLAGS(msg)); | ||
1866 | if (err) | 1867 | if (err) |
1867 | goto out_freeiov; | 1868 | goto out_freeiov; |
1868 | if (MSG_CMSG_COMPAT & flags) | 1869 | if (MSG_CMSG_COMPAT & flags) |
diff --git a/security/seclvl.c b/security/seclvl.c index dc4e17b6eaf6..1caac0164643 100644 --- a/security/seclvl.c +++ b/security/seclvl.c | |||
@@ -252,10 +252,9 @@ passwd_write_file(struct file * file, const char __user * buf, | |||
252 | } | 252 | } |
253 | 253 | ||
254 | if (count < 0 || count >= PAGE_SIZE) | 254 | if (count < 0 || count >= PAGE_SIZE) |
255 | return -ENOMEM; | ||
256 | if (*ppos != 0) { | ||
257 | return -EINVAL; | 255 | return -EINVAL; |
258 | } | 256 | if (*ppos != 0) |
257 | return -EINVAL; | ||
259 | page = (char *)get_zeroed_page(GFP_KERNEL); | 258 | page = (char *)get_zeroed_page(GFP_KERNEL); |
260 | if (!page) | 259 | if (!page) |
261 | return -ENOMEM; | 260 | return -ENOMEM; |
@@ -265,9 +264,8 @@ passwd_write_file(struct file * file, const char __user * buf, | |||
265 | 264 | ||
266 | len = strlen(page); | 265 | len = strlen(page); |
267 | /* ``echo "secret" > seclvl/passwd'' includes a newline */ | 266 | /* ``echo "secret" > seclvl/passwd'' includes a newline */ |
268 | if (page[len - 1] == '\n') { | 267 | if (page[len - 1] == '\n') |
269 | len--; | 268 | len--; |
270 | } | ||
271 | /* Hash the password, then compare the hashed values */ | 269 | /* Hash the password, then compare the hashed values */ |
272 | if ((rc = plaintext_to_sha1(tmp, page, len))) { | 270 | if ((rc = plaintext_to_sha1(tmp, page, len))) { |
273 | seclvl_printk(0, KERN_ERR, "Error hashing password: rc = " | 271 | seclvl_printk(0, KERN_ERR, "Error hashing password: rc = " |
@@ -275,9 +273,8 @@ passwd_write_file(struct file * file, const char __user * buf, | |||
275 | return rc; | 273 | return rc; |
276 | } | 274 | } |
277 | for (i = 0; i < SHA1_DIGEST_SIZE; i++) { | 275 | for (i = 0; i < SHA1_DIGEST_SIZE; i++) { |
278 | if (hashedPassword[i] != tmp[i]) { | 276 | if (hashedPassword[i] != tmp[i]) |
279 | return -EPERM; | 277 | return -EPERM; |
280 | } | ||
281 | } | 278 | } |
282 | seclvl_printk(0, KERN_INFO, | 279 | seclvl_printk(0, KERN_INFO, |
283 | "Password accepted; seclvl reduced to 0.\n"); | 280 | "Password accepted; seclvl reduced to 0.\n"); |
@@ -482,9 +479,8 @@ static void seclvl_file_free_security(struct file *filp) | |||
482 | */ | 479 | */ |
483 | static int seclvl_umount(struct vfsmount *mnt, int flags) | 480 | static int seclvl_umount(struct vfsmount *mnt, int flags) |
484 | { | 481 | { |
485 | if (current->pid == 1) { | 482 | if (current->pid == 1) |
486 | return 0; | 483 | return 0; |
487 | } | ||
488 | if (seclvl == 2) { | 484 | if (seclvl == 2) { |
489 | seclvl_printk(1, KERN_WARNING, "Attempt to unmount in secure " | 485 | seclvl_printk(1, KERN_WARNING, "Attempt to unmount in secure " |
490 | "level %d\n", seclvl); | 486 | "level %d\n", seclvl); |
@@ -638,9 +634,8 @@ static int __init seclvl_init(void) | |||
638 | static void __exit seclvl_exit(void) | 634 | static void __exit seclvl_exit(void) |
639 | { | 635 | { |
640 | securityfs_remove(seclvl_ino); | 636 | securityfs_remove(seclvl_ino); |
641 | if (*passwd || *sha1_passwd) { | 637 | if (*passwd || *sha1_passwd) |
642 | securityfs_remove(passwd_ino); | 638 | securityfs_remove(passwd_ino); |
643 | } | ||
644 | securityfs_remove(dir_ino); | 639 | securityfs_remove(dir_ino); |
645 | if (secondary == 1) { | 640 | if (secondary == 1) { |
646 | mod_unreg_security(MY_NAME, &seclvl_ops); | 641 | mod_unreg_security(MY_NAME, &seclvl_ops); |
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c index 34195b748608..b2d5db20ec8c 100644 --- a/sound/arm/aaci.c +++ b/sound/arm/aaci.c | |||
@@ -650,7 +650,7 @@ static int aaci_do_resume(snd_card_t *card, unsigned int state) | |||
650 | return 0; | 650 | return 0; |
651 | } | 651 | } |
652 | 652 | ||
653 | static int aaci_suspend(struct amba_device *dev, u32 state) | 653 | static int aaci_suspend(struct amba_device *dev, pm_message_t state) |
654 | { | 654 | { |
655 | snd_card_t *card = amba_get_drvdata(dev); | 655 | snd_card_t *card = amba_get_drvdata(dev); |
656 | return card ? aaci_do_suspend(card) : 0; | 656 | return card ? aaci_do_suspend(card) : 0; |
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index 3daeecb9eb0e..cd313af6ebcf 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c | |||
@@ -228,11 +228,11 @@ typedef struct snd_rme32 { | |||
228 | } rme32_t; | 228 | } rme32_t; |
229 | 229 | ||
230 | static struct pci_device_id snd_rme32_ids[] = { | 230 | static struct pci_device_id snd_rme32_ids[] = { |
231 | {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_DIGI32, | 231 | {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32, |
232 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, | 232 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, |
233 | {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_DIGI32_8, | 233 | {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8, |
234 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, | 234 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, |
235 | {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_DIGI32_PRO, | 235 | {PCI_VENDOR_ID_XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_PRO, |
236 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, | 236 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0,}, |
237 | {0,} | 237 | {0,} |
238 | }; | 238 | }; |
@@ -240,7 +240,7 @@ static struct pci_device_id snd_rme32_ids[] = { | |||
240 | MODULE_DEVICE_TABLE(pci, snd_rme32_ids); | 240 | MODULE_DEVICE_TABLE(pci, snd_rme32_ids); |
241 | 241 | ||
242 | #define RME32_ISWORKING(rme32) ((rme32)->wcreg & RME32_WCR_START) | 242 | #define RME32_ISWORKING(rme32) ((rme32)->wcreg & RME32_WCR_START) |
243 | #define RME32_PRO_WITH_8414(rme32) ((rme32)->pci->device == PCI_DEVICE_ID_DIGI32_PRO && (rme32)->rev == RME32_PRO_REVISION_WITH_8414) | 243 | #define RME32_PRO_WITH_8414(rme32) ((rme32)->pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO && (rme32)->rev == RME32_PRO_REVISION_WITH_8414) |
244 | 244 | ||
245 | static int snd_rme32_playback_prepare(snd_pcm_substream_t * substream); | 245 | static int snd_rme32_playback_prepare(snd_pcm_substream_t * substream); |
246 | 246 | ||
@@ -527,21 +527,21 @@ static int snd_rme32_playback_setrate(rme32_t * rme32, int rate) | |||
527 | RME32_WCR_FREQ_1; | 527 | RME32_WCR_FREQ_1; |
528 | break; | 528 | break; |
529 | case 64000: | 529 | case 64000: |
530 | if (rme32->pci->device != PCI_DEVICE_ID_DIGI32_PRO) | 530 | if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO) |
531 | return -EINVAL; | 531 | return -EINVAL; |
532 | rme32->wcreg |= RME32_WCR_DS_BM; | 532 | rme32->wcreg |= RME32_WCR_DS_BM; |
533 | rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) & | 533 | rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) & |
534 | ~RME32_WCR_FREQ_1; | 534 | ~RME32_WCR_FREQ_1; |
535 | break; | 535 | break; |
536 | case 88200: | 536 | case 88200: |
537 | if (rme32->pci->device != PCI_DEVICE_ID_DIGI32_PRO) | 537 | if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO) |
538 | return -EINVAL; | 538 | return -EINVAL; |
539 | rme32->wcreg |= RME32_WCR_DS_BM; | 539 | rme32->wcreg |= RME32_WCR_DS_BM; |
540 | rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_1) & | 540 | rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_1) & |
541 | ~RME32_WCR_FREQ_0; | 541 | ~RME32_WCR_FREQ_0; |
542 | break; | 542 | break; |
543 | case 96000: | 543 | case 96000: |
544 | if (rme32->pci->device != PCI_DEVICE_ID_DIGI32_PRO) | 544 | if (rme32->pci->device != PCI_DEVICE_ID_RME_DIGI32_PRO) |
545 | return -EINVAL; | 545 | return -EINVAL; |
546 | rme32->wcreg |= RME32_WCR_DS_BM; | 546 | rme32->wcreg |= RME32_WCR_DS_BM; |
547 | rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) | | 547 | rme32->wcreg = (rme32->wcreg | RME32_WCR_FREQ_0) | |
@@ -881,7 +881,7 @@ static int snd_rme32_playback_spdif_open(snd_pcm_substream_t * substream) | |||
881 | runtime->hw = snd_rme32_spdif_fd_info; | 881 | runtime->hw = snd_rme32_spdif_fd_info; |
882 | else | 882 | else |
883 | runtime->hw = snd_rme32_spdif_info; | 883 | runtime->hw = snd_rme32_spdif_info; |
884 | if (rme32->pci->device == PCI_DEVICE_ID_DIGI32_PRO) { | 884 | if (rme32->pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO) { |
885 | runtime->hw.rates |= SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000; | 885 | runtime->hw.rates |= SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000; |
886 | runtime->hw.rate_max = 96000; | 886 | runtime->hw.rate_max = 96000; |
887 | } | 887 | } |
@@ -1408,8 +1408,8 @@ static int __devinit snd_rme32_create(rme32_t * rme32) | |||
1408 | } | 1408 | } |
1409 | 1409 | ||
1410 | /* set up ALSA pcm device for ADAT */ | 1410 | /* set up ALSA pcm device for ADAT */ |
1411 | if ((pci->device == PCI_DEVICE_ID_DIGI32) || | 1411 | if ((pci->device == PCI_DEVICE_ID_RME_DIGI32) || |
1412 | (pci->device == PCI_DEVICE_ID_DIGI32_PRO)) { | 1412 | (pci->device == PCI_DEVICE_ID_RME_DIGI32_PRO)) { |
1413 | /* ADAT is not available on DIGI32 and DIGI32 Pro */ | 1413 | /* ADAT is not available on DIGI32 and DIGI32 Pro */ |
1414 | rme32->adat_pcm = NULL; | 1414 | rme32->adat_pcm = NULL; |
1415 | } | 1415 | } |
@@ -1639,11 +1639,11 @@ snd_rme32_info_inputtype_control(snd_kcontrol_t * kcontrol, | |||
1639 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1639 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1640 | uinfo->count = 1; | 1640 | uinfo->count = 1; |
1641 | switch (rme32->pci->device) { | 1641 | switch (rme32->pci->device) { |
1642 | case PCI_DEVICE_ID_DIGI32: | 1642 | case PCI_DEVICE_ID_RME_DIGI32: |
1643 | case PCI_DEVICE_ID_DIGI32_8: | 1643 | case PCI_DEVICE_ID_RME_DIGI32_8: |
1644 | uinfo->value.enumerated.items = 3; | 1644 | uinfo->value.enumerated.items = 3; |
1645 | break; | 1645 | break; |
1646 | case PCI_DEVICE_ID_DIGI32_PRO: | 1646 | case PCI_DEVICE_ID_RME_DIGI32_PRO: |
1647 | uinfo->value.enumerated.items = 4; | 1647 | uinfo->value.enumerated.items = 4; |
1648 | break; | 1648 | break; |
1649 | default: | 1649 | default: |
@@ -1670,11 +1670,11 @@ snd_rme32_get_inputtype_control(snd_kcontrol_t * kcontrol, | |||
1670 | ucontrol->value.enumerated.item[0] = snd_rme32_getinputtype(rme32); | 1670 | ucontrol->value.enumerated.item[0] = snd_rme32_getinputtype(rme32); |
1671 | 1671 | ||
1672 | switch (rme32->pci->device) { | 1672 | switch (rme32->pci->device) { |
1673 | case PCI_DEVICE_ID_DIGI32: | 1673 | case PCI_DEVICE_ID_RME_DIGI32: |
1674 | case PCI_DEVICE_ID_DIGI32_8: | 1674 | case PCI_DEVICE_ID_RME_DIGI32_8: |
1675 | items = 3; | 1675 | items = 3; |
1676 | break; | 1676 | break; |
1677 | case PCI_DEVICE_ID_DIGI32_PRO: | 1677 | case PCI_DEVICE_ID_RME_DIGI32_PRO: |
1678 | items = 4; | 1678 | items = 4; |
1679 | break; | 1679 | break; |
1680 | default: | 1680 | default: |
@@ -1697,11 +1697,11 @@ snd_rme32_put_inputtype_control(snd_kcontrol_t * kcontrol, | |||
1697 | int change, items = 3; | 1697 | int change, items = 3; |
1698 | 1698 | ||
1699 | switch (rme32->pci->device) { | 1699 | switch (rme32->pci->device) { |
1700 | case PCI_DEVICE_ID_DIGI32: | 1700 | case PCI_DEVICE_ID_RME_DIGI32: |
1701 | case PCI_DEVICE_ID_DIGI32_8: | 1701 | case PCI_DEVICE_ID_RME_DIGI32_8: |
1702 | items = 3; | 1702 | items = 3; |
1703 | break; | 1703 | break; |
1704 | case PCI_DEVICE_ID_DIGI32_PRO: | 1704 | case PCI_DEVICE_ID_RME_DIGI32_PRO: |
1705 | items = 4; | 1705 | items = 4; |
1706 | break; | 1706 | break; |
1707 | default: | 1707 | default: |
@@ -1982,13 +1982,13 @@ snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) | |||
1982 | 1982 | ||
1983 | strcpy(card->driver, "Digi32"); | 1983 | strcpy(card->driver, "Digi32"); |
1984 | switch (rme32->pci->device) { | 1984 | switch (rme32->pci->device) { |
1985 | case PCI_DEVICE_ID_DIGI32: | 1985 | case PCI_DEVICE_ID_RME_DIGI32: |
1986 | strcpy(card->shortname, "RME Digi32"); | 1986 | strcpy(card->shortname, "RME Digi32"); |
1987 | break; | 1987 | break; |
1988 | case PCI_DEVICE_ID_DIGI32_8: | 1988 | case PCI_DEVICE_ID_RME_DIGI32_8: |
1989 | strcpy(card->shortname, "RME Digi32/8"); | 1989 | strcpy(card->shortname, "RME Digi32/8"); |
1990 | break; | 1990 | break; |
1991 | case PCI_DEVICE_ID_DIGI32_PRO: | 1991 | case PCI_DEVICE_ID_RME_DIGI32_PRO: |
1992 | strcpy(card->shortname, "RME Digi32 PRO"); | 1992 | strcpy(card->shortname, "RME Digi32 PRO"); |
1993 | break; | 1993 | break; |
1994 | } | 1994 | } |
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c index 9983b66dc564..c495cae78dbf 100644 --- a/sound/pci/rme96.c +++ b/sound/pci/rme96.c | |||
@@ -233,13 +233,13 @@ typedef struct snd_rme96 { | |||
233 | } rme96_t; | 233 | } rme96_t; |
234 | 234 | ||
235 | static struct pci_device_id snd_rme96_ids[] = { | 235 | static struct pci_device_id snd_rme96_ids[] = { |
236 | { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_DIGI96, | 236 | { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96, |
237 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, | 237 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, |
238 | { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_DIGI96_8, | 238 | { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8, |
239 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, | 239 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, |
240 | { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_DIGI96_8_PRO, | 240 | { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO, |
241 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, | 241 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, |
242 | { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST, | 242 | { PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST, |
243 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, | 243 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, |
244 | { 0, } | 244 | { 0, } |
245 | }; | 245 | }; |
@@ -248,12 +248,12 @@ MODULE_DEVICE_TABLE(pci, snd_rme96_ids); | |||
248 | 248 | ||
249 | #define RME96_ISPLAYING(rme96) ((rme96)->wcreg & RME96_WCR_START) | 249 | #define RME96_ISPLAYING(rme96) ((rme96)->wcreg & RME96_WCR_START) |
250 | #define RME96_ISRECORDING(rme96) ((rme96)->wcreg & RME96_WCR_START_2) | 250 | #define RME96_ISRECORDING(rme96) ((rme96)->wcreg & RME96_WCR_START_2) |
251 | #define RME96_HAS_ANALOG_IN(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST) | 251 | #define RME96_HAS_ANALOG_IN(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST) |
252 | #define RME96_HAS_ANALOG_OUT(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PRO || \ | 252 | #define RME96_HAS_ANALOG_OUT(rme96) ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PRO || \ |
253 | (rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST) | 253 | (rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST) |
254 | #define RME96_DAC_IS_1852(rme96) (RME96_HAS_ANALOG_OUT(rme96) && (rme96)->rev >= 4) | 254 | #define RME96_DAC_IS_1852(rme96) (RME96_HAS_ANALOG_OUT(rme96) && (rme96)->rev >= 4) |
255 | #define RME96_DAC_IS_1855(rme96) (((rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST && (rme96)->rev < 4) || \ | 255 | #define RME96_DAC_IS_1855(rme96) (((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && (rme96)->rev < 4) || \ |
256 | ((rme96)->pci->device == PCI_DEVICE_ID_DIGI96_8_PRO && (rme96)->rev == 2)) | 256 | ((rme96)->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PRO && (rme96)->rev == 2)) |
257 | #define RME96_185X_MAX_OUT(rme96) ((1 << (RME96_DAC_IS_1852(rme96) ? RME96_AD1852_VOL_BITS : RME96_AD1855_VOL_BITS)) - 1) | 257 | #define RME96_185X_MAX_OUT(rme96) ((1 << (RME96_DAC_IS_1852(rme96) ? RME96_AD1852_VOL_BITS : RME96_AD1855_VOL_BITS)) - 1) |
258 | 258 | ||
259 | static int | 259 | static int |
@@ -830,9 +830,9 @@ snd_rme96_setinputtype(rme96_t *rme96, | |||
830 | RME96_WCR_INP_1; | 830 | RME96_WCR_INP_1; |
831 | break; | 831 | break; |
832 | case RME96_INPUT_XLR: | 832 | case RME96_INPUT_XLR: |
833 | if ((rme96->pci->device != PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST && | 833 | if ((rme96->pci->device != PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && |
834 | rme96->pci->device != PCI_DEVICE_ID_DIGI96_8_PRO) || | 834 | rme96->pci->device != PCI_DEVICE_ID_RME_DIGI96_8_PRO) || |
835 | (rme96->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST && | 835 | (rme96->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && |
836 | rme96->rev > 4)) | 836 | rme96->rev > 4)) |
837 | { | 837 | { |
838 | /* Only Digi96/8 PRO and Digi96/8 PAD supports XLR */ | 838 | /* Only Digi96/8 PRO and Digi96/8 PAD supports XLR */ |
@@ -1598,7 +1598,7 @@ snd_rme96_create(rme96_t *rme96) | |||
1598 | rme96->spdif_pcm->info_flags = 0; | 1598 | rme96->spdif_pcm->info_flags = 0; |
1599 | 1599 | ||
1600 | /* set up ALSA pcm device for ADAT */ | 1600 | /* set up ALSA pcm device for ADAT */ |
1601 | if (pci->device == PCI_DEVICE_ID_DIGI96) { | 1601 | if (pci->device == PCI_DEVICE_ID_RME_DIGI96) { |
1602 | /* ADAT is not available on the base model */ | 1602 | /* ADAT is not available on the base model */ |
1603 | rme96->adat_pcm = NULL; | 1603 | rme96->adat_pcm = NULL; |
1604 | } else { | 1604 | } else { |
@@ -1858,14 +1858,14 @@ snd_rme96_info_inputtype_control(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * | |||
1858 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 1858 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
1859 | uinfo->count = 1; | 1859 | uinfo->count = 1; |
1860 | switch (rme96->pci->device) { | 1860 | switch (rme96->pci->device) { |
1861 | case PCI_DEVICE_ID_DIGI96: | 1861 | case PCI_DEVICE_ID_RME_DIGI96: |
1862 | case PCI_DEVICE_ID_DIGI96_8: | 1862 | case PCI_DEVICE_ID_RME_DIGI96_8: |
1863 | uinfo->value.enumerated.items = 3; | 1863 | uinfo->value.enumerated.items = 3; |
1864 | break; | 1864 | break; |
1865 | case PCI_DEVICE_ID_DIGI96_8_PRO: | 1865 | case PCI_DEVICE_ID_RME_DIGI96_8_PRO: |
1866 | uinfo->value.enumerated.items = 4; | 1866 | uinfo->value.enumerated.items = 4; |
1867 | break; | 1867 | break; |
1868 | case PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST: | 1868 | case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: |
1869 | if (rme96->rev > 4) { | 1869 | if (rme96->rev > 4) { |
1870 | /* PST */ | 1870 | /* PST */ |
1871 | uinfo->value.enumerated.items = 4; | 1871 | uinfo->value.enumerated.items = 4; |
@@ -1895,14 +1895,14 @@ snd_rme96_get_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1895 | ucontrol->value.enumerated.item[0] = snd_rme96_getinputtype(rme96); | 1895 | ucontrol->value.enumerated.item[0] = snd_rme96_getinputtype(rme96); |
1896 | 1896 | ||
1897 | switch (rme96->pci->device) { | 1897 | switch (rme96->pci->device) { |
1898 | case PCI_DEVICE_ID_DIGI96: | 1898 | case PCI_DEVICE_ID_RME_DIGI96: |
1899 | case PCI_DEVICE_ID_DIGI96_8: | 1899 | case PCI_DEVICE_ID_RME_DIGI96_8: |
1900 | items = 3; | 1900 | items = 3; |
1901 | break; | 1901 | break; |
1902 | case PCI_DEVICE_ID_DIGI96_8_PRO: | 1902 | case PCI_DEVICE_ID_RME_DIGI96_8_PRO: |
1903 | items = 4; | 1903 | items = 4; |
1904 | break; | 1904 | break; |
1905 | case PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST: | 1905 | case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: |
1906 | if (rme96->rev > 4) { | 1906 | if (rme96->rev > 4) { |
1907 | /* for handling PST case, (INPUT_ANALOG is moved to INPUT_XLR */ | 1907 | /* for handling PST case, (INPUT_ANALOG is moved to INPUT_XLR */ |
1908 | if (ucontrol->value.enumerated.item[0] == RME96_INPUT_ANALOG) { | 1908 | if (ucontrol->value.enumerated.item[0] == RME96_INPUT_ANALOG) { |
@@ -1932,14 +1932,14 @@ snd_rme96_put_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1932 | int change, items = 3; | 1932 | int change, items = 3; |
1933 | 1933 | ||
1934 | switch (rme96->pci->device) { | 1934 | switch (rme96->pci->device) { |
1935 | case PCI_DEVICE_ID_DIGI96: | 1935 | case PCI_DEVICE_ID_RME_DIGI96: |
1936 | case PCI_DEVICE_ID_DIGI96_8: | 1936 | case PCI_DEVICE_ID_RME_DIGI96_8: |
1937 | items = 3; | 1937 | items = 3; |
1938 | break; | 1938 | break; |
1939 | case PCI_DEVICE_ID_DIGI96_8_PRO: | 1939 | case PCI_DEVICE_ID_RME_DIGI96_8_PRO: |
1940 | items = 4; | 1940 | items = 4; |
1941 | break; | 1941 | break; |
1942 | case PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST: | 1942 | case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: |
1943 | if (rme96->rev > 4) { | 1943 | if (rme96->rev > 4) { |
1944 | items = 4; | 1944 | items = 4; |
1945 | } else { | 1945 | } else { |
@@ -1953,7 +1953,7 @@ snd_rme96_put_inputtype_control(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t | |||
1953 | val = ucontrol->value.enumerated.item[0] % items; | 1953 | val = ucontrol->value.enumerated.item[0] % items; |
1954 | 1954 | ||
1955 | /* special case for PST */ | 1955 | /* special case for PST */ |
1956 | if (rme96->pci->device == PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST && rme96->rev > 4) { | 1956 | if (rme96->pci->device == PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST && rme96->rev > 4) { |
1957 | if (val == RME96_INPUT_XLR) { | 1957 | if (val == RME96_INPUT_XLR) { |
1958 | val = RME96_INPUT_ANALOG; | 1958 | val = RME96_INPUT_ANALOG; |
1959 | } | 1959 | } |
@@ -2375,16 +2375,16 @@ snd_rme96_probe(struct pci_dev *pci, | |||
2375 | 2375 | ||
2376 | strcpy(card->driver, "Digi96"); | 2376 | strcpy(card->driver, "Digi96"); |
2377 | switch (rme96->pci->device) { | 2377 | switch (rme96->pci->device) { |
2378 | case PCI_DEVICE_ID_DIGI96: | 2378 | case PCI_DEVICE_ID_RME_DIGI96: |
2379 | strcpy(card->shortname, "RME Digi96"); | 2379 | strcpy(card->shortname, "RME Digi96"); |
2380 | break; | 2380 | break; |
2381 | case PCI_DEVICE_ID_DIGI96_8: | 2381 | case PCI_DEVICE_ID_RME_DIGI96_8: |
2382 | strcpy(card->shortname, "RME Digi96/8"); | 2382 | strcpy(card->shortname, "RME Digi96/8"); |
2383 | break; | 2383 | break; |
2384 | case PCI_DEVICE_ID_DIGI96_8_PRO: | 2384 | case PCI_DEVICE_ID_RME_DIGI96_8_PRO: |
2385 | strcpy(card->shortname, "RME Digi96/8 PRO"); | 2385 | strcpy(card->shortname, "RME Digi96/8 PRO"); |
2386 | break; | 2386 | break; |
2387 | case PCI_DEVICE_ID_DIGI96_8_PAD_OR_PST: | 2387 | case PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST: |
2388 | pci_read_config_byte(rme96->pci, 8, &val); | 2388 | pci_read_config_byte(rme96->pci, 8, &val); |
2389 | if (val < 5) { | 2389 | if (val < 5) { |
2390 | strcpy(card->shortname, "RME Digi96/8 PAD"); | 2390 | strcpy(card->shortname, "RME Digi96/8 PAD"); |
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 2fb27c4e951f..f4361c518e46 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c | |||
@@ -173,7 +173,7 @@ static cs4231_t *cs4231_list; | |||
173 | 173 | ||
174 | #define CS4231_GLOBALIRQ 0x01 /* IRQ is active */ | 174 | #define CS4231_GLOBALIRQ 0x01 /* IRQ is active */ |
175 | 175 | ||
176 | /* definitions for codec irq status */ | 176 | /* definitions for codec irq status - CS4231_IRQ_STATUS */ |
177 | 177 | ||
178 | #define CS4231_PLAYBACK_IRQ 0x10 | 178 | #define CS4231_PLAYBACK_IRQ 0x10 |
179 | #define CS4231_RECORD_IRQ 0x20 | 179 | #define CS4231_RECORD_IRQ 0x20 |
@@ -402,7 +402,7 @@ static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg, | |||
402 | udelay(100); | 402 | udelay(100); |
403 | #ifdef CONFIG_SND_DEBUG | 403 | #ifdef CONFIG_SND_DEBUG |
404 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) | 404 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) |
405 | snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | 405 | snd_printdd("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); |
406 | #endif | 406 | #endif |
407 | if (chip->calibrate_mute) { | 407 | if (chip->calibrate_mute) { |
408 | chip->image[reg] &= mask; | 408 | chip->image[reg] &= mask; |
@@ -425,6 +425,10 @@ static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char val | |||
425 | timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); | 425 | timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); |
426 | timeout--) | 426 | timeout--) |
427 | udelay(100); | 427 | udelay(100); |
428 | #ifdef CONFIG_SND_DEBUG | ||
429 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) | ||
430 | snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | ||
431 | #endif | ||
428 | __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); | 432 | __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); |
429 | __cs4231_writeb(chip, value, CS4231P(chip, REG)); | 433 | __cs4231_writeb(chip, value, CS4231P(chip, REG)); |
430 | mb(); | 434 | mb(); |
@@ -440,15 +444,12 @@ static void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char valu | |||
440 | udelay(100); | 444 | udelay(100); |
441 | #ifdef CONFIG_SND_DEBUG | 445 | #ifdef CONFIG_SND_DEBUG |
442 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) | 446 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) |
443 | snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); | 447 | snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); |
444 | #endif | 448 | #endif |
445 | __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); | 449 | __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); |
446 | __cs4231_writeb(chip, value, CS4231P(chip, REG)); | 450 | __cs4231_writeb(chip, value, CS4231P(chip, REG)); |
447 | chip->image[reg] = value; | 451 | chip->image[reg] = value; |
448 | mb(); | 452 | mb(); |
449 | #if 0 | ||
450 | printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value); | ||
451 | #endif | ||
452 | } | 453 | } |
453 | 454 | ||
454 | static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg) | 455 | static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg) |
@@ -462,61 +463,14 @@ static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg) | |||
462 | udelay(100); | 463 | udelay(100); |
463 | #ifdef CONFIG_SND_DEBUG | 464 | #ifdef CONFIG_SND_DEBUG |
464 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) | 465 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) |
465 | snd_printk("in: auto calibration time out - reg = 0x%x\n", reg); | 466 | snd_printdd("in: auto calibration time out - reg = 0x%x\n", reg); |
466 | #endif | 467 | #endif |
467 | __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); | 468 | __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); |
468 | mb(); | 469 | mb(); |
469 | ret = __cs4231_readb(chip, CS4231P(chip, REG)); | 470 | ret = __cs4231_readb(chip, CS4231P(chip, REG)); |
470 | #if 0 | ||
471 | printk("codec in - reg 0x%x = 0x%x\n", chip->mce_bit | reg, ret); | ||
472 | #endif | ||
473 | return ret; | 471 | return ret; |
474 | } | 472 | } |
475 | 473 | ||
476 | #if 0 | ||
477 | |||
478 | static void snd_cs4231_debug(cs4231_t *chip) | ||
479 | { | ||
480 | printk("CS4231 REGS: INDEX = 0x%02x ", | ||
481 | __cs4231_readb(chip, CS4231P(chip, REGSEL))); | ||
482 | printk(" STATUS = 0x%02x\n", | ||
483 | __cs4231_readb(chip, CS4231P(chip, STATUS))); | ||
484 | printk(" 0x00: left input = 0x%02x ", snd_cs4231_in(chip, 0x00)); | ||
485 | printk(" 0x10: alt 1 (CFIG 2) = 0x%02x\n", snd_cs4231_in(chip, 0x10)); | ||
486 | printk(" 0x01: right input = 0x%02x ", snd_cs4231_in(chip, 0x01)); | ||
487 | printk(" 0x11: alt 2 (CFIG 3) = 0x%02x\n", snd_cs4231_in(chip, 0x11)); | ||
488 | printk(" 0x02: GF1 left input = 0x%02x ", snd_cs4231_in(chip, 0x02)); | ||
489 | printk(" 0x12: left line in = 0x%02x\n", snd_cs4231_in(chip, 0x12)); | ||
490 | printk(" 0x03: GF1 right input = 0x%02x ", snd_cs4231_in(chip, 0x03)); | ||
491 | printk(" 0x13: right line in = 0x%02x\n", snd_cs4231_in(chip, 0x13)); | ||
492 | printk(" 0x04: CD left input = 0x%02x ", snd_cs4231_in(chip, 0x04)); | ||
493 | printk(" 0x14: timer low = 0x%02x\n", snd_cs4231_in(chip, 0x14)); | ||
494 | printk(" 0x05: CD right input = 0x%02x ", snd_cs4231_in(chip, 0x05)); | ||
495 | printk(" 0x15: timer high = 0x%02x\n", snd_cs4231_in(chip, 0x15)); | ||
496 | printk(" 0x06: left output = 0x%02x ", snd_cs4231_in(chip, 0x06)); | ||
497 | printk(" 0x16: left MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x16)); | ||
498 | printk(" 0x07: right output = 0x%02x ", snd_cs4231_in(chip, 0x07)); | ||
499 | printk(" 0x17: right MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x17)); | ||
500 | printk(" 0x08: playback format = 0x%02x ", snd_cs4231_in(chip, 0x08)); | ||
501 | printk(" 0x18: IRQ status = 0x%02x\n", snd_cs4231_in(chip, 0x18)); | ||
502 | printk(" 0x09: iface (CFIG 1) = 0x%02x ", snd_cs4231_in(chip, 0x09)); | ||
503 | printk(" 0x19: left line out = 0x%02x\n", snd_cs4231_in(chip, 0x19)); | ||
504 | printk(" 0x0a: pin control = 0x%02x ", snd_cs4231_in(chip, 0x0a)); | ||
505 | printk(" 0x1a: mono control = 0x%02x\n", snd_cs4231_in(chip, 0x1a)); | ||
506 | printk(" 0x0b: init & status = 0x%02x ", snd_cs4231_in(chip, 0x0b)); | ||
507 | printk(" 0x1b: right line out = 0x%02x\n", snd_cs4231_in(chip, 0x1b)); | ||
508 | printk(" 0x0c: revision & mode = 0x%02x ", snd_cs4231_in(chip, 0x0c)); | ||
509 | printk(" 0x1c: record format = 0x%02x\n", snd_cs4231_in(chip, 0x1c)); | ||
510 | printk(" 0x0d: loopback = 0x%02x ", snd_cs4231_in(chip, 0x0d)); | ||
511 | printk(" 0x1d: var freq (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x1d)); | ||
512 | printk(" 0x0e: ply upr count = 0x%02x ", snd_cs4231_in(chip, 0x0e)); | ||
513 | printk(" 0x1e: rec upr count = 0x%02x\n", snd_cs4231_in(chip, 0x1e)); | ||
514 | printk(" 0x0f: ply lwr count = 0x%02x ", snd_cs4231_in(chip, 0x0f)); | ||
515 | printk(" 0x1f: rec lwr count = 0x%02x\n", snd_cs4231_in(chip, 0x1f)); | ||
516 | } | ||
517 | |||
518 | #endif | ||
519 | |||
520 | /* | 474 | /* |
521 | * CS4231 detection / MCE routines | 475 | * CS4231 detection / MCE routines |
522 | */ | 476 | */ |
@@ -528,11 +482,12 @@ static void snd_cs4231_busy_wait(cs4231_t *chip) | |||
528 | /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */ | 482 | /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */ |
529 | for (timeout = 5; timeout > 0; timeout--) | 483 | for (timeout = 5; timeout > 0; timeout--) |
530 | __cs4231_readb(chip, CS4231P(chip, REGSEL)); | 484 | __cs4231_readb(chip, CS4231P(chip, REGSEL)); |
485 | |||
531 | /* end of cleanup sequence */ | 486 | /* end of cleanup sequence */ |
532 | for (timeout = 250; | 487 | for (timeout = 500; |
533 | timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); | 488 | timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); |
534 | timeout--) | 489 | timeout--) |
535 | udelay(100); | 490 | udelay(1000); |
536 | } | 491 | } |
537 | 492 | ||
538 | static void snd_cs4231_mce_up(cs4231_t *chip) | 493 | static void snd_cs4231_mce_up(cs4231_t *chip) |
@@ -545,12 +500,12 @@ static void snd_cs4231_mce_up(cs4231_t *chip) | |||
545 | udelay(100); | 500 | udelay(100); |
546 | #ifdef CONFIG_SND_DEBUG | 501 | #ifdef CONFIG_SND_DEBUG |
547 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) | 502 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) |
548 | snd_printk("mce_up - auto calibration time out (0)\n"); | 503 | snd_printdd("mce_up - auto calibration time out (0)\n"); |
549 | #endif | 504 | #endif |
550 | chip->mce_bit |= CS4231_MCE; | 505 | chip->mce_bit |= CS4231_MCE; |
551 | timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL)); | 506 | timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL)); |
552 | if (timeout == 0x80) | 507 | if (timeout == 0x80) |
553 | snd_printk("mce_up [%p]: serious init problem - codec still busy\n", chip->port); | 508 | snd_printdd("mce_up [%p]: serious init problem - codec still busy\n", chip->port); |
554 | if (!(timeout & CS4231_MCE)) | 509 | if (!(timeout & CS4231_MCE)) |
555 | __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL)); | 510 | __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL)); |
556 | spin_unlock_irqrestore(&chip->lock, flags); | 511 | spin_unlock_irqrestore(&chip->lock, flags); |
@@ -563,18 +518,15 @@ static void snd_cs4231_mce_down(cs4231_t *chip) | |||
563 | 518 | ||
564 | spin_lock_irqsave(&chip->lock, flags); | 519 | spin_lock_irqsave(&chip->lock, flags); |
565 | snd_cs4231_busy_wait(chip); | 520 | snd_cs4231_busy_wait(chip); |
566 | #if 0 | ||
567 | printk("(1) timeout = %i\n", timeout); | ||
568 | #endif | ||
569 | #ifdef CONFIG_SND_DEBUG | 521 | #ifdef CONFIG_SND_DEBUG |
570 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) | 522 | if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) |
571 | snd_printk("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL)); | 523 | snd_printdd("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL)); |
572 | #endif | 524 | #endif |
573 | chip->mce_bit &= ~CS4231_MCE; | 525 | chip->mce_bit &= ~CS4231_MCE; |
574 | timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL)); | 526 | timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL)); |
575 | __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL)); | 527 | __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL)); |
576 | if (timeout == 0x80) | 528 | if (timeout == 0x80) |
577 | snd_printk("mce_down [%p]: serious init problem - codec still busy\n", chip->port); | 529 | snd_printdd("mce_down [%p]: serious init problem - codec still busy\n", chip->port); |
578 | if ((timeout & CS4231_MCE) == 0) { | 530 | if ((timeout & CS4231_MCE) == 0) { |
579 | spin_unlock_irqrestore(&chip->lock, flags); | 531 | spin_unlock_irqrestore(&chip->lock, flags); |
580 | return; | 532 | return; |
@@ -590,9 +542,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip) | |||
590 | spin_unlock_irqrestore(&chip->lock, flags); | 542 | spin_unlock_irqrestore(&chip->lock, flags); |
591 | return; | 543 | return; |
592 | } | 544 | } |
593 | #if 0 | 545 | |
594 | printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies); | ||
595 | #endif | ||
596 | /* in 10ms increments, check condition, up to 250ms */ | 546 | /* in 10ms increments, check condition, up to 250ms */ |
597 | timeout = 25; | 547 | timeout = 25; |
598 | while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) { | 548 | while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) { |
@@ -604,9 +554,7 @@ static void snd_cs4231_mce_down(cs4231_t *chip) | |||
604 | msleep(10); | 554 | msleep(10); |
605 | spin_lock_irqsave(&chip->lock, flags); | 555 | spin_lock_irqsave(&chip->lock, flags); |
606 | } | 556 | } |
607 | #if 0 | 557 | |
608 | printk("(3) jiffies = %li\n", jiffies); | ||
609 | #endif | ||
610 | /* in 10ms increments, check condition, up to 100ms */ | 558 | /* in 10ms increments, check condition, up to 100ms */ |
611 | timeout = 10; | 559 | timeout = 10; |
612 | while (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) { | 560 | while (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) { |
@@ -619,54 +567,58 @@ static void snd_cs4231_mce_down(cs4231_t *chip) | |||
619 | spin_lock_irqsave(&chip->lock, flags); | 567 | spin_lock_irqsave(&chip->lock, flags); |
620 | } | 568 | } |
621 | spin_unlock_irqrestore(&chip->lock, flags); | 569 | spin_unlock_irqrestore(&chip->lock, flags); |
622 | #if 0 | ||
623 | printk("(4) jiffies = %li\n", jiffies); | ||
624 | snd_printk("mce_down - exit = 0x%x\n", __cs4231_readb(chip, CS4231P(chip, REGSEL))); | ||
625 | #endif | ||
626 | } | 570 | } |
627 | 571 | ||
628 | #if 0 /* Unused for now... */ | ||
629 | static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size) | ||
630 | { | ||
631 | switch (format & 0xe0) { | ||
632 | case CS4231_LINEAR_16: | ||
633 | case CS4231_LINEAR_16_BIG: | ||
634 | size >>= 1; | ||
635 | break; | ||
636 | case CS4231_ADPCM_16: | ||
637 | return size >> 2; | ||
638 | } | ||
639 | if (format & CS4231_STEREO) | ||
640 | size >>= 1; | ||
641 | return size; | ||
642 | } | ||
643 | #endif | ||
644 | |||
645 | #ifdef EBUS_SUPPORT | 572 | #ifdef EBUS_SUPPORT |
646 | static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent) | 573 | static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent) |
647 | { | 574 | { |
648 | snd_pcm_runtime_t *runtime = substream->runtime; | 575 | snd_pcm_runtime_t *runtime = substream->runtime; |
649 | 576 | ||
650 | while (1) { | 577 | while (1) { |
651 | unsigned int dma_size = snd_pcm_lib_period_bytes(substream); | 578 | unsigned int period_size = snd_pcm_lib_period_bytes(substream); |
652 | unsigned int offset = dma_size * (*periods_sent); | 579 | unsigned int offset = period_size * (*periods_sent); |
653 | 580 | ||
654 | if (dma_size >= (1 << 24)) | 581 | if (period_size >= (1 << 24)) |
655 | BUG(); | 582 | BUG(); |
656 | 583 | ||
657 | if (ebus_dma_request(p, runtime->dma_addr + offset, dma_size)) | 584 | if (ebus_dma_request(p, runtime->dma_addr + offset, period_size)) |
658 | return; | 585 | return; |
659 | #if 0 | ||
660 | printk("ebus_advance: Sent period %u (size[%x] offset[%x])\n", | ||
661 | (*periods_sent), dma_size, offset); | ||
662 | #endif | ||
663 | (*periods_sent) = ((*periods_sent) + 1) % runtime->periods; | 586 | (*periods_sent) = ((*periods_sent) + 1) % runtime->periods; |
664 | } | 587 | } |
665 | } | 588 | } |
666 | #endif | 589 | #endif |
667 | 590 | ||
668 | static void cs4231_dma_trigger(cs4231_t *chip, unsigned int what, int on) | 591 | #ifdef SBUS_SUPPORT |
592 | static void snd_cs4231_sbus_advance_dma(snd_pcm_substream_t *substream, unsigned int *periods_sent) | ||
593 | { | ||
594 | cs4231_t *chip = snd_pcm_substream_chip(substream); | ||
595 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
596 | |||
597 | unsigned int period_size = snd_pcm_lib_period_bytes(substream); | ||
598 | unsigned int offset = period_size * (*periods_sent % runtime->periods); | ||
599 | |||
600 | if (runtime->period_size > 0xffff + 1) | ||
601 | BUG(); | ||
602 | |||
603 | switch (substream->stream) { | ||
604 | case SNDRV_PCM_STREAM_PLAYBACK: | ||
605 | sbus_writel(runtime->dma_addr + offset, chip->port + APCPNVA); | ||
606 | sbus_writel(period_size, chip->port + APCPNC); | ||
607 | break; | ||
608 | case SNDRV_PCM_STREAM_CAPTURE: | ||
609 | sbus_writel(runtime->dma_addr + offset, chip->port + APCCNVA); | ||
610 | sbus_writel(period_size, chip->port + APCCNC); | ||
611 | break; | ||
612 | } | ||
613 | |||
614 | (*periods_sent) = (*periods_sent + 1) % runtime->periods; | ||
615 | } | ||
616 | #endif | ||
617 | |||
618 | static void cs4231_dma_trigger(snd_pcm_substream_t *substream, unsigned int what, int on) | ||
669 | { | 619 | { |
620 | cs4231_t *chip = snd_pcm_substream_chip(substream); | ||
621 | |||
670 | #ifdef EBUS_SUPPORT | 622 | #ifdef EBUS_SUPPORT |
671 | if (chip->flags & CS4231_FLAG_EBUS) { | 623 | if (chip->flags & CS4231_FLAG_EBUS) { |
672 | if (what & CS4231_PLAYBACK_ENABLE) { | 624 | if (what & CS4231_PLAYBACK_ENABLE) { |
@@ -694,6 +646,60 @@ static void cs4231_dma_trigger(cs4231_t *chip, unsigned int what, int on) | |||
694 | } else { | 646 | } else { |
695 | #endif | 647 | #endif |
696 | #ifdef SBUS_SUPPORT | 648 | #ifdef SBUS_SUPPORT |
649 | u32 csr = sbus_readl(chip->port + APCCSR); | ||
650 | /* I don't know why, but on sbus the period counter must | ||
651 | * only start counting after the first period is sent. | ||
652 | * Therefore this dummy thing. | ||
653 | */ | ||
654 | unsigned int dummy = 0; | ||
655 | |||
656 | switch (what) { | ||
657 | case CS4231_PLAYBACK_ENABLE: | ||
658 | if (on) { | ||
659 | csr &= ~APC_XINT_PLAY; | ||
660 | sbus_writel(csr, chip->port + APCCSR); | ||
661 | |||
662 | csr &= ~APC_PPAUSE; | ||
663 | sbus_writel(csr, chip->port + APCCSR); | ||
664 | |||
665 | snd_cs4231_sbus_advance_dma(substream, &dummy); | ||
666 | |||
667 | csr |= APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | | ||
668 | APC_XINT_PLAY | APC_XINT_EMPT | APC_XINT_GENL | | ||
669 | APC_XINT_PENA | APC_PDMA_READY; | ||
670 | sbus_writel(csr, chip->port + APCCSR); | ||
671 | } else { | ||
672 | csr |= APC_PPAUSE; | ||
673 | sbus_writel(csr, chip->port + APCCSR); | ||
674 | |||
675 | csr &= ~APC_PDMA_READY; | ||
676 | sbus_writel(csr, chip->port + APCCSR); | ||
677 | } | ||
678 | break; | ||
679 | case CS4231_RECORD_ENABLE: | ||
680 | if (on) { | ||
681 | csr &= ~APC_XINT_CAPT; | ||
682 | sbus_writel(csr, chip->port + APCCSR); | ||
683 | |||
684 | csr &= ~APC_CPAUSE; | ||
685 | sbus_writel(csr, chip->port + APCCSR); | ||
686 | |||
687 | snd_cs4231_sbus_advance_dma(substream, &dummy); | ||
688 | |||
689 | csr |= APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | | ||
690 | APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL | | ||
691 | APC_CDMA_READY; | ||
692 | |||
693 | sbus_writel(csr, chip->port + APCCSR); | ||
694 | } else { | ||
695 | csr |= APC_CPAUSE; | ||
696 | sbus_writel(csr, chip->port + APCCSR); | ||
697 | |||
698 | csr &= ~APC_CDMA_READY; | ||
699 | sbus_writel(csr, chip->port + APCCSR); | ||
700 | } | ||
701 | break; | ||
702 | } | ||
697 | #endif | 703 | #endif |
698 | #ifdef EBUS_SUPPORT | 704 | #ifdef EBUS_SUPPORT |
699 | } | 705 | } |
@@ -725,25 +731,12 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd) | |||
725 | } | 731 | } |
726 | } | 732 | } |
727 | 733 | ||
728 | #if 0 | ||
729 | printk("TRIGGER: what[%x] on(%d)\n", | ||
730 | what, (cmd == SNDRV_PCM_TRIGGER_START)); | ||
731 | #endif | ||
732 | |||
733 | spin_lock_irqsave(&chip->lock, flags); | 734 | spin_lock_irqsave(&chip->lock, flags); |
734 | if (cmd == SNDRV_PCM_TRIGGER_START) { | 735 | if (cmd == SNDRV_PCM_TRIGGER_START) { |
735 | cs4231_dma_trigger(chip, what, 1); | 736 | cs4231_dma_trigger(substream, what, 1); |
736 | chip->image[CS4231_IFACE_CTRL] |= what; | 737 | chip->image[CS4231_IFACE_CTRL] |= what; |
737 | if (what & CS4231_PLAYBACK_ENABLE) { | ||
738 | snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, 0xff); | ||
739 | snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, 0xff); | ||
740 | } | ||
741 | if (what & CS4231_RECORD_ENABLE) { | ||
742 | snd_cs4231_out(chip, CS4231_REC_LWR_CNT, 0xff); | ||
743 | snd_cs4231_out(chip, CS4231_REC_UPR_CNT, 0xff); | ||
744 | } | ||
745 | } else { | 738 | } else { |
746 | cs4231_dma_trigger(chip, what, 0); | 739 | cs4231_dma_trigger(substream, what, 0); |
747 | chip->image[CS4231_IFACE_CTRL] &= ~what; | 740 | chip->image[CS4231_IFACE_CTRL] &= ~what; |
748 | } | 741 | } |
749 | snd_cs4231_out(chip, CS4231_IFACE_CTRL, | 742 | snd_cs4231_out(chip, CS4231_IFACE_CTRL, |
@@ -755,9 +748,7 @@ static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd) | |||
755 | result = -EINVAL; | 748 | result = -EINVAL; |
756 | break; | 749 | break; |
757 | } | 750 | } |
758 | #if 0 | 751 | |
759 | snd_cs4231_debug(chip); | ||
760 | #endif | ||
761 | return result; | 752 | return result; |
762 | } | 753 | } |
763 | 754 | ||
@@ -790,9 +781,6 @@ static unsigned char snd_cs4231_get_format(cs4231_t *chip, int format, int chann | |||
790 | } | 781 | } |
791 | if (channels > 1) | 782 | if (channels > 1) |
792 | rformat |= CS4231_STEREO; | 783 | rformat |= CS4231_STEREO; |
793 | #if 0 | ||
794 | snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode); | ||
795 | #endif | ||
796 | return rformat; | 784 | return rformat; |
797 | } | 785 | } |
798 | 786 | ||
@@ -944,7 +932,7 @@ static void snd_cs4231_init(cs4231_t *chip) | |||
944 | snd_cs4231_mce_down(chip); | 932 | snd_cs4231_mce_down(chip); |
945 | 933 | ||
946 | #ifdef SNDRV_DEBUG_MCE | 934 | #ifdef SNDRV_DEBUG_MCE |
947 | snd_printk("init: (1)\n"); | 935 | snd_printdd("init: (1)\n"); |
948 | #endif | 936 | #endif |
949 | snd_cs4231_mce_up(chip); | 937 | snd_cs4231_mce_up(chip); |
950 | spin_lock_irqsave(&chip->lock, flags); | 938 | spin_lock_irqsave(&chip->lock, flags); |
@@ -957,7 +945,7 @@ static void snd_cs4231_init(cs4231_t *chip) | |||
957 | snd_cs4231_mce_down(chip); | 945 | snd_cs4231_mce_down(chip); |
958 | 946 | ||
959 | #ifdef SNDRV_DEBUG_MCE | 947 | #ifdef SNDRV_DEBUG_MCE |
960 | snd_printk("init: (2)\n"); | 948 | snd_printdd("init: (2)\n"); |
961 | #endif | 949 | #endif |
962 | 950 | ||
963 | snd_cs4231_mce_up(chip); | 951 | snd_cs4231_mce_up(chip); |
@@ -967,7 +955,7 @@ static void snd_cs4231_init(cs4231_t *chip) | |||
967 | snd_cs4231_mce_down(chip); | 955 | snd_cs4231_mce_down(chip); |
968 | 956 | ||
969 | #ifdef SNDRV_DEBUG_MCE | 957 | #ifdef SNDRV_DEBUG_MCE |
970 | snd_printk("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]); | 958 | snd_printdd("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]); |
971 | #endif | 959 | #endif |
972 | 960 | ||
973 | spin_lock_irqsave(&chip->lock, flags); | 961 | spin_lock_irqsave(&chip->lock, flags); |
@@ -981,7 +969,7 @@ static void snd_cs4231_init(cs4231_t *chip) | |||
981 | snd_cs4231_mce_down(chip); | 969 | snd_cs4231_mce_down(chip); |
982 | 970 | ||
983 | #ifdef SNDRV_DEBUG_MCE | 971 | #ifdef SNDRV_DEBUG_MCE |
984 | snd_printk("init: (4)\n"); | 972 | snd_printdd("init: (4)\n"); |
985 | #endif | 973 | #endif |
986 | 974 | ||
987 | snd_cs4231_mce_up(chip); | 975 | snd_cs4231_mce_up(chip); |
@@ -991,7 +979,7 @@ static void snd_cs4231_init(cs4231_t *chip) | |||
991 | snd_cs4231_mce_down(chip); | 979 | snd_cs4231_mce_down(chip); |
992 | 980 | ||
993 | #ifdef SNDRV_DEBUG_MCE | 981 | #ifdef SNDRV_DEBUG_MCE |
994 | snd_printk("init: (5)\n"); | 982 | snd_printdd("init: (5)\n"); |
995 | #endif | 983 | #endif |
996 | } | 984 | } |
997 | 985 | ||
@@ -1022,6 +1010,7 @@ static int snd_cs4231_open(cs4231_t *chip, unsigned int mode) | |||
1022 | CS4231_RECORD_IRQ | | 1010 | CS4231_RECORD_IRQ | |
1023 | CS4231_TIMER_IRQ); | 1011 | CS4231_TIMER_IRQ); |
1024 | snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); | 1012 | snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); |
1013 | |||
1025 | spin_unlock_irqrestore(&chip->lock, flags); | 1014 | spin_unlock_irqrestore(&chip->lock, flags); |
1026 | 1015 | ||
1027 | chip->mode = mode; | 1016 | chip->mode = mode; |
@@ -1136,11 +1125,21 @@ static int snd_cs4231_playback_hw_free(snd_pcm_substream_t *substream) | |||
1136 | static int snd_cs4231_playback_prepare(snd_pcm_substream_t *substream) | 1125 | static int snd_cs4231_playback_prepare(snd_pcm_substream_t *substream) |
1137 | { | 1126 | { |
1138 | cs4231_t *chip = snd_pcm_substream_chip(substream); | 1127 | cs4231_t *chip = snd_pcm_substream_chip(substream); |
1128 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
1139 | unsigned long flags; | 1129 | unsigned long flags; |
1140 | 1130 | ||
1141 | spin_lock_irqsave(&chip->lock, flags); | 1131 | spin_lock_irqsave(&chip->lock, flags); |
1132 | |||
1142 | chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | | 1133 | chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | |
1143 | CS4231_PLAYBACK_PIO); | 1134 | CS4231_PLAYBACK_PIO); |
1135 | |||
1136 | if (runtime->period_size > 0xffff + 1) | ||
1137 | BUG(); | ||
1138 | |||
1139 | snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, (runtime->period_size - 1) & 0x00ff); | ||
1140 | snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff); | ||
1141 | chip->p_periods_sent = 0; | ||
1142 | |||
1144 | spin_unlock_irqrestore(&chip->lock, flags); | 1143 | spin_unlock_irqrestore(&chip->lock, flags); |
1145 | 1144 | ||
1146 | return 0; | 1145 | return 0; |
@@ -1172,12 +1171,16 @@ static int snd_cs4231_capture_hw_free(snd_pcm_substream_t *substream) | |||
1172 | static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream) | 1171 | static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream) |
1173 | { | 1172 | { |
1174 | cs4231_t *chip = snd_pcm_substream_chip(substream); | 1173 | cs4231_t *chip = snd_pcm_substream_chip(substream); |
1174 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
1175 | unsigned long flags; | 1175 | unsigned long flags; |
1176 | 1176 | ||
1177 | spin_lock_irqsave(&chip->lock, flags); | 1177 | spin_lock_irqsave(&chip->lock, flags); |
1178 | chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | | 1178 | chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | |
1179 | CS4231_RECORD_PIO); | 1179 | CS4231_RECORD_PIO); |
1180 | 1180 | ||
1181 | snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) & 0x00ff); | ||
1182 | snd_cs4231_out(chip, CS4231_REC_LWR_CNT, (runtime->period_size - 1) >> 8 & 0x00ff); | ||
1183 | |||
1181 | spin_unlock_irqrestore(&chip->lock, flags); | 1184 | spin_unlock_irqrestore(&chip->lock, flags); |
1182 | 1185 | ||
1183 | return 0; | 1186 | return 0; |
@@ -1196,53 +1199,61 @@ static void snd_cs4231_overrange(cs4231_t *chip) | |||
1196 | chip->capture_substream->runtime->overrange++; | 1199 | chip->capture_substream->runtime->overrange++; |
1197 | } | 1200 | } |
1198 | 1201 | ||
1199 | static void snd_cs4231_generic_interrupt(cs4231_t *chip) | 1202 | static irqreturn_t snd_cs4231_generic_interrupt(cs4231_t *chip) |
1200 | { | 1203 | { |
1201 | unsigned long flags; | 1204 | unsigned long flags; |
1202 | unsigned char status; | 1205 | unsigned char status; |
1203 | 1206 | ||
1207 | /*This is IRQ is not raised by the cs4231*/ | ||
1208 | if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ)) | ||
1209 | return IRQ_NONE; | ||
1210 | |||
1204 | status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); | 1211 | status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); |
1205 | if (!status) | ||
1206 | return; | ||
1207 | 1212 | ||
1208 | if (status & CS4231_TIMER_IRQ) { | 1213 | if (status & CS4231_TIMER_IRQ) { |
1209 | if (chip->timer) | 1214 | if (chip->timer) |
1210 | snd_timer_interrupt(chip->timer, chip->timer->sticks); | 1215 | snd_timer_interrupt(chip->timer, chip->timer->sticks); |
1211 | } | 1216 | } |
1212 | if (status & CS4231_PLAYBACK_IRQ) | 1217 | |
1213 | snd_pcm_period_elapsed(chip->playback_substream); | 1218 | if (status & CS4231_RECORD_IRQ) |
1214 | if (status & CS4231_RECORD_IRQ) { | ||
1215 | snd_cs4231_overrange(chip); | 1219 | snd_cs4231_overrange(chip); |
1216 | snd_pcm_period_elapsed(chip->capture_substream); | ||
1217 | } | ||
1218 | 1220 | ||
1219 | /* ACK the CS4231 interrupt. */ | 1221 | /* ACK the CS4231 interrupt. */ |
1220 | spin_lock_irqsave(&chip->lock, flags); | 1222 | spin_lock_irqsave(&chip->lock, flags); |
1221 | snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); | 1223 | snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0); |
1222 | spin_unlock_irqrestore(&chip->lock, flags); | 1224 | spin_unlock_irqrestore(&chip->lock, flags); |
1225 | |||
1226 | return 0; | ||
1223 | } | 1227 | } |
1224 | 1228 | ||
1225 | #ifdef SBUS_SUPPORT | 1229 | #ifdef SBUS_SUPPORT |
1226 | static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 1230 | static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
1227 | { | 1231 | { |
1228 | cs4231_t *chip = dev_id; | 1232 | cs4231_t *chip = dev_id; |
1229 | u32 csr; | ||
1230 | |||
1231 | csr = sbus_readl(chip->port + APCCSR); | ||
1232 | if (!(csr & (APC_INT_PENDING | | ||
1233 | APC_PLAY_INT | | ||
1234 | APC_CAPT_INT | | ||
1235 | APC_GENL_INT | | ||
1236 | APC_XINT_PEMP | | ||
1237 | APC_XINT_CEMP))) | ||
1238 | return IRQ_NONE; | ||
1239 | 1233 | ||
1240 | /* ACK the APC interrupt. */ | 1234 | /* ACK the APC interrupt. */ |
1235 | u32 csr = sbus_readl(chip->port + APCCSR); | ||
1236 | |||
1241 | sbus_writel(csr, chip->port + APCCSR); | 1237 | sbus_writel(csr, chip->port + APCCSR); |
1242 | 1238 | ||
1243 | snd_cs4231_generic_interrupt(chip); | 1239 | if ((chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) && |
1240 | (csr & APC_PLAY_INT) && | ||
1241 | (csr & APC_XINT_PNVA) && | ||
1242 | !(csr & APC_XINT_EMPT)) { | ||
1243 | snd_cs4231_sbus_advance_dma(chip->playback_substream, | ||
1244 | &chip->p_periods_sent); | ||
1245 | snd_pcm_period_elapsed(chip->playback_substream); | ||
1246 | } | ||
1244 | 1247 | ||
1245 | return IRQ_HANDLED; | 1248 | if ((chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) && |
1249 | (csr & APC_CAPT_INT) && | ||
1250 | (csr & APC_XINT_CNVA)) { | ||
1251 | snd_cs4231_sbus_advance_dma(chip->capture_substream, | ||
1252 | &chip->c_periods_sent); | ||
1253 | snd_pcm_period_elapsed(chip->capture_substream); | ||
1254 | } | ||
1255 | |||
1256 | return snd_cs4231_generic_interrupt(chip); | ||
1246 | } | 1257 | } |
1247 | #endif | 1258 | #endif |
1248 | 1259 | ||
@@ -1290,7 +1301,8 @@ static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substr | |||
1290 | #ifdef EBUS_SUPPORT | 1301 | #ifdef EBUS_SUPPORT |
1291 | } | 1302 | } |
1292 | #endif | 1303 | #endif |
1293 | ptr += (period_bytes - residue); | 1304 | ptr += period_bytes - residue; |
1305 | |||
1294 | return bytes_to_frames(substream->runtime, ptr); | 1306 | return bytes_to_frames(substream->runtime, ptr); |
1295 | } | 1307 | } |
1296 | 1308 | ||
@@ -1314,7 +1326,7 @@ static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substr | |||
1314 | #ifdef EBUS_SUPPORT | 1326 | #ifdef EBUS_SUPPORT |
1315 | } | 1327 | } |
1316 | #endif | 1328 | #endif |
1317 | ptr += (period_bytes - residue); | 1329 | ptr += period_bytes - residue; |
1318 | return bytes_to_frames(substream->runtime, ptr); | 1330 | return bytes_to_frames(substream->runtime, ptr); |
1319 | } | 1331 | } |
1320 | 1332 | ||
@@ -1328,9 +1340,6 @@ static int snd_cs4231_probe(cs4231_t *chip) | |||
1328 | int i, id, vers; | 1340 | int i, id, vers; |
1329 | unsigned char *ptr; | 1341 | unsigned char *ptr; |
1330 | 1342 | ||
1331 | #if 0 | ||
1332 | snd_cs4231_debug(chip); | ||
1333 | #endif | ||
1334 | id = vers = 0; | 1343 | id = vers = 0; |
1335 | for (i = 0; i < 50; i++) { | 1344 | for (i = 0; i < 50; i++) { |
1336 | mb(); | 1345 | mb(); |
@@ -1985,13 +1994,13 @@ static int __init snd_cs4231_sbus_create(snd_card_t *card, | |||
1985 | chip->port = sbus_ioremap(&sdev->resource[0], 0, | 1994 | chip->port = sbus_ioremap(&sdev->resource[0], 0, |
1986 | chip->regs_size, "cs4231"); | 1995 | chip->regs_size, "cs4231"); |
1987 | if (!chip->port) { | 1996 | if (!chip->port) { |
1988 | snd_printk("cs4231-%d: Unable to map chip registers.\n", dev); | 1997 | snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); |
1989 | return -EIO; | 1998 | return -EIO; |
1990 | } | 1999 | } |
1991 | 2000 | ||
1992 | if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, | 2001 | if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, |
1993 | SA_SHIRQ, "cs4231", chip)) { | 2002 | SA_SHIRQ, "cs4231", chip)) { |
1994 | snd_printk("cs4231-%d: Unable to grab SBUS IRQ %s\n", | 2003 | snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %s\n", |
1995 | dev, | 2004 | dev, |
1996 | __irq_itoa(sdev->irqs[0])); | 2005 | __irq_itoa(sdev->irqs[0])); |
1997 | snd_cs4231_sbus_free(chip); | 2006 | snd_cs4231_sbus_free(chip); |
@@ -2113,29 +2122,29 @@ static int __init snd_cs4231_ebus_create(snd_card_t *card, | |||
2113 | chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10); | 2122 | chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10); |
2114 | if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) { | 2123 | if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) { |
2115 | snd_cs4231_ebus_free(chip); | 2124 | snd_cs4231_ebus_free(chip); |
2116 | snd_printk("cs4231-%d: Unable to map chip registers.\n", dev); | 2125 | snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); |
2117 | return -EIO; | 2126 | return -EIO; |
2118 | } | 2127 | } |
2119 | 2128 | ||
2120 | if (ebus_dma_register(&chip->eb2c)) { | 2129 | if (ebus_dma_register(&chip->eb2c)) { |
2121 | snd_cs4231_ebus_free(chip); | 2130 | snd_cs4231_ebus_free(chip); |
2122 | snd_printk("cs4231-%d: Unable to register EBUS capture DMA\n", dev); | 2131 | snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev); |
2123 | return -EBUSY; | 2132 | return -EBUSY; |
2124 | } | 2133 | } |
2125 | if (ebus_dma_irq_enable(&chip->eb2c, 1)) { | 2134 | if (ebus_dma_irq_enable(&chip->eb2c, 1)) { |
2126 | snd_cs4231_ebus_free(chip); | 2135 | snd_cs4231_ebus_free(chip); |
2127 | snd_printk("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev); | 2136 | snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev); |
2128 | return -EBUSY; | 2137 | return -EBUSY; |
2129 | } | 2138 | } |
2130 | 2139 | ||
2131 | if (ebus_dma_register(&chip->eb2p)) { | 2140 | if (ebus_dma_register(&chip->eb2p)) { |
2132 | snd_cs4231_ebus_free(chip); | 2141 | snd_cs4231_ebus_free(chip); |
2133 | snd_printk("cs4231-%d: Unable to register EBUS play DMA\n", dev); | 2142 | snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev); |
2134 | return -EBUSY; | 2143 | return -EBUSY; |
2135 | } | 2144 | } |
2136 | if (ebus_dma_irq_enable(&chip->eb2p, 1)) { | 2145 | if (ebus_dma_irq_enable(&chip->eb2p, 1)) { |
2137 | snd_cs4231_ebus_free(chip); | 2146 | snd_cs4231_ebus_free(chip); |
2138 | snd_printk("cs4231-%d: Unable to enable EBUS play IRQ\n", dev); | 2147 | snd_printdd("cs4231-%d: Unable to enable EBUS play IRQ\n", dev); |
2139 | return -EBUSY; | 2148 | return -EBUSY; |
2140 | } | 2149 | } |
2141 | 2150 | ||