diff options
249 files changed, 6439 insertions, 8056 deletions
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 73060819ed99..438277800103 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX | |||
@@ -159,8 +159,6 @@ hayes-esp.txt | |||
159 | - info on using the Hayes ESP serial driver. | 159 | - info on using the Hayes ESP serial driver. |
160 | highuid.txt | 160 | highuid.txt |
161 | - notes on the change from 16 bit to 32 bit user/group IDs. | 161 | - notes on the change from 16 bit to 32 bit user/group IDs. |
162 | hpet.txt | ||
163 | - High Precision Event Timer Driver for Linux. | ||
164 | timers/ | 162 | timers/ |
165 | - info on the timer related topics | 163 | - info on the timer related topics |
166 | hw_random.txt | 164 | hw_random.txt |
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 3d2d0c29f027..cc8093c15cf5 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -287,14 +287,6 @@ Who: Glauber Costa <gcosta@redhat.com> | |||
287 | 287 | ||
288 | --------------------------- | 288 | --------------------------- |
289 | 289 | ||
290 | What: old style serial driver for ColdFire (CONFIG_SERIAL_COLDFIRE) | ||
291 | When: 2.6.28 | ||
292 | Why: This driver still uses the old interface and has been replaced | ||
293 | by CONFIG_SERIAL_MCF. | ||
294 | Who: Sebastian Siewior <sebastian@breakpoint.cc> | ||
295 | |||
296 | --------------------------- | ||
297 | |||
298 | What: /sys/o2cb symlink | 290 | What: /sys/o2cb symlink |
299 | When: January 2010 | 291 | When: January 2010 |
300 | Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb | 292 | Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb |
diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt index 74484e696405..eb154ef36c2a 100644 --- a/Documentation/filesystems/ext4.txt +++ b/Documentation/filesystems/ext4.txt | |||
@@ -223,6 +223,11 @@ errors=remount-ro(*) Remount the filesystem read-only on an error. | |||
223 | errors=continue Keep going on a filesystem error. | 223 | errors=continue Keep going on a filesystem error. |
224 | errors=panic Panic and halt the machine if an error occurs. | 224 | errors=panic Panic and halt the machine if an error occurs. |
225 | 225 | ||
226 | data_err=ignore(*) Just print an error message if an error occurs | ||
227 | in a file data buffer in ordered mode. | ||
228 | data_err=abort Abort the journal if an error occurs in a file | ||
229 | data buffer in ordered mode. | ||
230 | |||
226 | grpid Give objects the same group ID as their creator. | 231 | grpid Give objects the same group ID as their creator. |
227 | bsdgroups | 232 | bsdgroups |
228 | 233 | ||
diff --git a/Documentation/timers/00-INDEX b/Documentation/timers/00-INDEX new file mode 100644 index 000000000000..397dc35e1323 --- /dev/null +++ b/Documentation/timers/00-INDEX | |||
@@ -0,0 +1,10 @@ | |||
1 | 00-INDEX | ||
2 | - this file | ||
3 | highres.txt | ||
4 | - High resolution timers and dynamic ticks design notes | ||
5 | hpet.txt | ||
6 | - High Precision Event Timer Driver for Linux | ||
7 | hrtimers.txt | ||
8 | - subsystem for high-resolution kernel timers | ||
9 | timer_stats.txt | ||
10 | - timer usage statistics | ||
diff --git a/Documentation/hpet.txt b/Documentation/timers/hpet.txt index 6ad52d9dad6c..e7c09abcfab4 100644 --- a/Documentation/hpet.txt +++ b/Documentation/timers/hpet.txt | |||
@@ -1,21 +1,32 @@ | |||
1 | High Precision Event Timer Driver for Linux | 1 | High Precision Event Timer Driver for Linux |
2 | 2 | ||
3 | The High Precision Event Timer (HPET) hardware is the future replacement | 3 | The High Precision Event Timer (HPET) hardware follows a specification |
4 | for the 8254 and Real Time Clock (RTC) periodic timer functionality. | 4 | by Intel and Microsoft which can be found at |
5 | Each HPET can have up to 32 timers. It is possible to configure the | 5 | |
6 | first two timers as legacy replacements for 8254 and RTC periodic timers. | 6 | http://www.intel.com/technology/architecture/hpetspec.htm |
7 | A specification done by Intel and Microsoft can be found at | 7 | |
8 | <http://www.intel.com/technology/architecture/hpetspec.htm>. | 8 | Each HPET has one fixed-rate counter (at 10+ MHz, hence "High Precision") |
9 | and up to 32 comparators. Normally three or more comparators are provided, | ||
10 | each of which can generate oneshot interupts and at least one of which has | ||
11 | additional hardware to support periodic interrupts. The comparators are | ||
12 | also called "timers", which can be misleading since usually timers are | ||
13 | independent of each other ... these share a counter, complicating resets. | ||
14 | |||
15 | HPET devices can support two interrupt routing modes. In one mode, the | ||
16 | comparators are additional interrupt sources with no particular system | ||
17 | role. Many x86 BIOS writers don't route HPET interrupts at all, which | ||
18 | prevents use of that mode. They support the other "legacy replacement" | ||
19 | mode where the first two comparators block interrupts from 8254 timers | ||
20 | and from the RTC. | ||
9 | 21 | ||
10 | The driver supports detection of HPET driver allocation and initialization | 22 | The driver supports detection of HPET driver allocation and initialization |
11 | of the HPET before the driver module_init routine is called. This enables | 23 | of the HPET before the driver module_init routine is called. This enables |
12 | platform code which uses timer 0 or 1 as the main timer to intercept HPET | 24 | platform code which uses timer 0 or 1 as the main timer to intercept HPET |
13 | initialization. An example of this initialization can be found in | 25 | initialization. An example of this initialization can be found in |
14 | arch/i386/kernel/time_hpet.c. | 26 | arch/x86/kernel/hpet.c. |
15 | 27 | ||
16 | The driver provides two APIs which are very similar to the API found in | 28 | The driver provides a userspace API which resembles the API found in the |
17 | the rtc.c driver. There is a user space API and a kernel space API. | 29 | RTC driver framework. An example user space program is provided below. |
18 | An example user space program is provided below. | ||
19 | 30 | ||
20 | #include <stdio.h> | 31 | #include <stdio.h> |
21 | #include <stdlib.h> | 32 | #include <stdlib.h> |
@@ -286,15 +297,3 @@ out: | |||
286 | 297 | ||
287 | return; | 298 | return; |
288 | } | 299 | } |
289 | |||
290 | The kernel API has three interfaces exported from the driver: | ||
291 | |||
292 | hpet_register(struct hpet_task *tp, int periodic) | ||
293 | hpet_unregister(struct hpet_task *tp) | ||
294 | hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg) | ||
295 | |||
296 | The kernel module using this interface fills in the ht_func and ht_data | ||
297 | members of the hpet_task structure before calling hpet_register. | ||
298 | hpet_control simply vectors to the hpet_ioctl routine and has the same | ||
299 | commands and respective arguments as the user API. hpet_unregister | ||
300 | is used to terminate usage of the HPET timer reserved by hpet_register. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 8bf72d378332..74b808205312 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -73,6 +73,7 @@ L: Mailing list that is relevant to this area | |||
73 | W: Web-page with status/info | 73 | W: Web-page with status/info |
74 | T: SCM tree type and location. Type is one of: git, hg, quilt. | 74 | T: SCM tree type and location. Type is one of: git, hg, quilt. |
75 | S: Status, one of the following: | 75 | S: Status, one of the following: |
76 | F: Applicable files and/or directories | ||
76 | 77 | ||
77 | Supported: Someone is actually paid to look after this. | 78 | Supported: Someone is actually paid to look after this. |
78 | Maintained: Someone actually looks after it. | 79 | Maintained: Someone actually looks after it. |
@@ -102,14 +103,14 @@ M: dave@thedillows.org | |||
102 | L: netdev@vger.kernel.org | 103 | L: netdev@vger.kernel.org |
103 | S: Maintained | 104 | S: Maintained |
104 | 105 | ||
105 | 3W-XXXX ATA-RAID CONTROLLER DRIVER | 106 | 3W-9XXX SATA-RAID CONTROLLER DRIVER |
106 | P: Adam Radford | 107 | P: Adam Radford |
107 | M: linuxraid@amcc.com | 108 | M: linuxraid@amcc.com |
108 | L: linux-scsi@vger.kernel.org | 109 | L: linux-scsi@vger.kernel.org |
109 | W: http://www.amcc.com | 110 | W: http://www.amcc.com |
110 | S: Supported | 111 | S: Supported |
111 | 112 | ||
112 | 3W-9XXX SATA-RAID CONTROLLER DRIVER | 113 | 3W-XXXX ATA-RAID CONTROLLER DRIVER |
113 | P: Adam Radford | 114 | P: Adam Radford |
114 | M: linuxraid@amcc.com | 115 | M: linuxraid@amcc.com |
115 | L: linux-scsi@vger.kernel.org | 116 | L: linux-scsi@vger.kernel.org |
@@ -163,16 +164,11 @@ M: A2232@gmx.net | |||
163 | L: linux-m68k@lists.linux-m68k.org | 164 | L: linux-m68k@lists.linux-m68k.org |
164 | S: Maintained | 165 | S: Maintained |
165 | 166 | ||
166 | AFS FILESYSTEM & AF_RXRPC SOCKET DOMAIN | 167 | AACRAID SCSI RAID DRIVER |
167 | P: David Howells | 168 | P: Adaptec OEM Raid Solutions |
168 | M: dhowells@redhat.com | 169 | M: aacraid@adaptec.com |
169 | L: linux-afs@lists.infradead.org | 170 | L: linux-scsi@vger.kernel.org |
170 | S: Supported | 171 | W: http://www.adaptec.com/ |
171 | |||
172 | AIO | ||
173 | P: Benjamin LaHaise | ||
174 | M: bcrl@kvack.org | ||
175 | L: linux-aio@kvack.org | ||
176 | S: Supported | 172 | S: Supported |
177 | 173 | ||
178 | ABIT UGURU 1,2 HARDWARE MONITOR DRIVER | 174 | ABIT UGURU 1,2 HARDWARE MONITOR DRIVER |
@@ -193,27 +189,6 @@ M: jes@trained-monkey.org | |||
193 | L: linux-acenic@sunsite.dk | 189 | L: linux-acenic@sunsite.dk |
194 | S: Maintained | 190 | S: Maintained |
195 | 191 | ||
196 | IPS SCSI RAID DRIVER | ||
197 | P: Adaptec OEM Raid Solutions | ||
198 | M: aacraid@adaptec.com | ||
199 | L: linux-scsi@vger.kernel.org | ||
200 | W: http://www.adaptec.com/ | ||
201 | S: Maintained | ||
202 | |||
203 | DPT_I2O SCSI RAID DRIVER | ||
204 | P: Adaptec OEM Raid Solutions | ||
205 | M: aacraid@adaptec.com | ||
206 | L: linux-scsi@vger.kernel.org | ||
207 | W: http://www.adaptec.com/ | ||
208 | S: Maintained | ||
209 | |||
210 | AACRAID SCSI RAID DRIVER | ||
211 | P: Adaptec OEM Raid Solutions | ||
212 | M: aacraid@adaptec.com | ||
213 | L: linux-scsi@vger.kernel.org | ||
214 | W: http://www.adaptec.com/ | ||
215 | S: Supported | ||
216 | |||
217 | ACER WMI LAPTOP EXTRAS | 192 | ACER WMI LAPTOP EXTRAS |
218 | P: Carlos Corbacho | 193 | P: Carlos Corbacho |
219 | M: carlos@strangeworlds.co.uk | 194 | M: carlos@strangeworlds.co.uk |
@@ -327,6 +302,12 @@ P: Roman Zippel | |||
327 | M: zippel@linux-m68k.org | 302 | M: zippel@linux-m68k.org |
328 | S: Maintained | 303 | S: Maintained |
329 | 304 | ||
305 | AFS FILESYSTEM & AF_RXRPC SOCKET DOMAIN | ||
306 | P: David Howells | ||
307 | M: dhowells@redhat.com | ||
308 | L: linux-afs@lists.infradead.org | ||
309 | S: Supported | ||
310 | |||
330 | AGPGART DRIVER | 311 | AGPGART DRIVER |
331 | P: David Airlie | 312 | P: David Airlie |
332 | M: airlied@linux.ie | 313 | M: airlied@linux.ie |
@@ -345,6 +326,12 @@ M: hare@suse.de | |||
345 | L: linux-scsi@vger.kernel.org | 326 | L: linux-scsi@vger.kernel.org |
346 | S: Maintained | 327 | S: Maintained |
347 | 328 | ||
329 | AIO | ||
330 | P: Benjamin LaHaise | ||
331 | M: bcrl@kvack.org | ||
332 | L: linux-aio@kvack.org | ||
333 | S: Supported | ||
334 | |||
348 | ALCATEL SPEEDTOUCH USB DRIVER | 335 | ALCATEL SPEEDTOUCH USB DRIVER |
349 | P: Duncan Sands | 336 | P: Duncan Sands |
350 | M: duncan.sands@free.fr | 337 | M: duncan.sands@free.fr |
@@ -737,7 +724,7 @@ L: linux-kernel@vger.kernel.org | |||
737 | W: http://sourceforge.net/projects/xscaleiop | 724 | W: http://sourceforge.net/projects/xscaleiop |
738 | S: Supported | 725 | S: Supported |
739 | 726 | ||
740 | ATA OVER ETHERNET DRIVER | 727 | ATA OVER ETHERNET (AOE) DRIVER |
741 | P: Ed L. Cashin | 728 | P: Ed L. Cashin |
742 | M: ecashin@coraid.com | 729 | M: ecashin@coraid.com |
743 | W: http://www.coraid.com/support/linux | 730 | W: http://www.coraid.com/support/linux |
@@ -870,11 +857,48 @@ L: linux-hams@vger.kernel.org | |||
870 | W: http://www.linux-ax25.org/ | 857 | W: http://www.linux-ax25.org/ |
871 | S: Maintained | 858 | S: Maintained |
872 | 859 | ||
860 | B43 WIRELESS DRIVER | ||
861 | P: Michael Buesch | ||
862 | M: mb@bu3sch.de | ||
863 | P: Stefano Brivio | ||
864 | M: stefano.brivio@polimi.it | ||
865 | L: linux-wireless@vger.kernel.org | ||
866 | W: http://linuxwireless.org/en/users/Drivers/b43 | ||
867 | S: Maintained | ||
868 | |||
869 | B43LEGACY WIRELESS DRIVER | ||
870 | P: Larry Finger | ||
871 | M: Larry.Finger@lwfinger.net | ||
872 | P: Stefano Brivio | ||
873 | M: stefano.brivio@polimi.it | ||
874 | L: linux-wireless@vger.kernel.org | ||
875 | W: http://linuxwireless.org/en/users/Drivers/b43 | ||
876 | S: Maintained | ||
877 | |||
873 | BACKLIGHT CLASS/SUBSYSTEM | 878 | BACKLIGHT CLASS/SUBSYSTEM |
874 | P: Richard Purdie | 879 | P: Richard Purdie |
875 | M: rpurdie@rpsys.net | 880 | M: rpurdie@rpsys.net |
876 | S: Maintained | 881 | S: Maintained |
877 | 882 | ||
883 | BAYCOM/HDLCDRV DRIVERS FOR AX.25 | ||
884 | P: Thomas Sailer | ||
885 | M: t.sailer@alumni.ethz.ch | ||
886 | L: linux-hams@vger.kernel.org | ||
887 | W: http://www.baycom.org/~tom/ham/ham.html | ||
888 | S: Maintained | ||
889 | |||
890 | BEFS FILE SYSTEM | ||
891 | P: Sergey S. Kostyliov | ||
892 | M: rathamahata@php4.ru | ||
893 | L: linux-kernel@vger.kernel.org | ||
894 | S: Maintained | ||
895 | |||
896 | BFS FILE SYSTEM | ||
897 | P: Tigran A. Aivazian | ||
898 | M: tigran@aivazian.fsnet.co.uk | ||
899 | L: linux-kernel@vger.kernel.org | ||
900 | S: Maintained | ||
901 | |||
878 | BLACKFIN ARCHITECTURE | 902 | BLACKFIN ARCHITECTURE |
879 | P: Bryan Wu | 903 | P: Bryan Wu |
880 | M: cooloney@kernel.org | 904 | M: cooloney@kernel.org |
@@ -910,43 +934,6 @@ L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only) | |||
910 | W: http://blackfin.uclinux.org | 934 | W: http://blackfin.uclinux.org |
911 | S: Supported | 935 | S: Supported |
912 | 936 | ||
913 | BAYCOM/HDLCDRV DRIVERS FOR AX.25 | ||
914 | P: Thomas Sailer | ||
915 | M: t.sailer@alumni.ethz.ch | ||
916 | L: linux-hams@vger.kernel.org | ||
917 | W: http://www.baycom.org/~tom/ham/ham.html | ||
918 | S: Maintained | ||
919 | |||
920 | B43 WIRELESS DRIVER | ||
921 | P: Michael Buesch | ||
922 | M: mb@bu3sch.de | ||
923 | P: Stefano Brivio | ||
924 | M: stefano.brivio@polimi.it | ||
925 | L: linux-wireless@vger.kernel.org | ||
926 | W: http://linuxwireless.org/en/users/Drivers/b43 | ||
927 | S: Maintained | ||
928 | |||
929 | B43LEGACY WIRELESS DRIVER | ||
930 | P: Larry Finger | ||
931 | M: Larry.Finger@lwfinger.net | ||
932 | P: Stefano Brivio | ||
933 | M: stefano.brivio@polimi.it | ||
934 | L: linux-wireless@vger.kernel.org | ||
935 | W: http://linuxwireless.org/en/users/Drivers/b43 | ||
936 | S: Maintained | ||
937 | |||
938 | BEFS FILE SYSTEM | ||
939 | P: Sergey S. Kostyliov | ||
940 | M: rathamahata@php4.ru | ||
941 | L: linux-kernel@vger.kernel.org | ||
942 | S: Maintained | ||
943 | |||
944 | BFS FILE SYSTEM | ||
945 | P: Tigran A. Aivazian | ||
946 | M: tigran@aivazian.fsnet.co.uk | ||
947 | L: linux-kernel@vger.kernel.org | ||
948 | S: Maintained | ||
949 | |||
950 | BLACKFIN I2C TWI DRIVER | 937 | BLACKFIN I2C TWI DRIVER |
951 | P: Sonic Zhang | 938 | P: Sonic Zhang |
952 | M: sonic.zhang@analog.com | 939 | M: sonic.zhang@analog.com |
@@ -1040,15 +1027,6 @@ M: corbet@lwn.net | |||
1040 | L: video4linux-list@redhat.com | 1027 | L: video4linux-list@redhat.com |
1041 | S: Maintained | 1028 | S: Maintained |
1042 | 1029 | ||
1043 | CAN NETWORK LAYER | ||
1044 | P: Urs Thuermann | ||
1045 | M: urs.thuermann@volkswagen.de | ||
1046 | P: Oliver Hartkopp | ||
1047 | M: oliver.hartkopp@volkswagen.de | ||
1048 | L: socketcan-core@lists.berlios.de (subscribers-only) | ||
1049 | W: http://developer.berlios.de/projects/socketcan/ | ||
1050 | S: Maintained | ||
1051 | |||
1052 | CALGARY x86-64 IOMMU | 1030 | CALGARY x86-64 IOMMU |
1053 | P: Muli Ben-Yehuda | 1031 | P: Muli Ben-Yehuda |
1054 | M: muli@il.ibm.com | 1032 | M: muli@il.ibm.com |
@@ -1058,6 +1036,15 @@ L: linux-kernel@vger.kernel.org | |||
1058 | L: discuss@x86-64.org | 1036 | L: discuss@x86-64.org |
1059 | S: Maintained | 1037 | S: Maintained |
1060 | 1038 | ||
1039 | CAN NETWORK LAYER | ||
1040 | P: Urs Thuermann | ||
1041 | M: urs.thuermann@volkswagen.de | ||
1042 | P: Oliver Hartkopp | ||
1043 | M: oliver.hartkopp@volkswagen.de | ||
1044 | L: socketcan-core@lists.berlios.de (subscribers-only) | ||
1045 | W: http://developer.berlios.de/projects/socketcan/ | ||
1046 | S: Maintained | ||
1047 | |||
1061 | CELL BROADBAND ENGINE ARCHITECTURE | 1048 | CELL BROADBAND ENGINE ARCHITECTURE |
1062 | P: Arnd Bergmann | 1049 | P: Arnd Bergmann |
1063 | M: arnd@arndb.de | 1050 | M: arnd@arndb.de |
@@ -1066,13 +1053,6 @@ L: cbe-oss-dev@ozlabs.org | |||
1066 | W: http://www.ibm.com/developerworks/power/cell/ | 1053 | W: http://www.ibm.com/developerworks/power/cell/ |
1067 | S: Supported | 1054 | S: Supported |
1068 | 1055 | ||
1069 | CISCO 10G ETHERNET DRIVER | ||
1070 | P: Scott Feldman | ||
1071 | M: scofeldm@cisco.com | ||
1072 | P: Joe Eykholt | ||
1073 | M: jeykholt@cisco.com | ||
1074 | S: Supported | ||
1075 | |||
1076 | CFAG12864B LCD DRIVER | 1056 | CFAG12864B LCD DRIVER |
1077 | P: Miguel Ojeda Sandonis | 1057 | P: Miguel Ojeda Sandonis |
1078 | M: miguel.ojeda.sandonis@gmail.com | 1058 | M: miguel.ojeda.sandonis@gmail.com |
@@ -1104,19 +1084,11 @@ P: Joel Schopp | |||
1104 | M: jschopp@austin.ibm.com | 1084 | M: jschopp@austin.ibm.com |
1105 | S: Supported | 1085 | S: Supported |
1106 | 1086 | ||
1107 | COMMON INTERNET FILE SYSTEM (CIFS) | 1087 | CISCO 10G ETHERNET DRIVER |
1108 | P: Steve French | 1088 | P: Scott Feldman |
1109 | M: sfrench@samba.org | 1089 | M: scofeldm@cisco.com |
1110 | L: linux-cifs-client@lists.samba.org | 1090 | P: Joe Eykholt |
1111 | L: samba-technical@lists.samba.org | 1091 | M: jeykholt@cisco.com |
1112 | W: http://linux-cifs.samba.org/ | ||
1113 | T: git kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git | ||
1114 | S: Supported | ||
1115 | |||
1116 | CONFIGFS | ||
1117 | P: Joel Becker | ||
1118 | M: joel.becker@oracle.com | ||
1119 | L: linux-kernel@vger.kernel.org | ||
1120 | S: Supported | 1092 | S: Supported |
1121 | 1093 | ||
1122 | CIRRUS LOGIC EP93XX ETHERNET DRIVER | 1094 | CIRRUS LOGIC EP93XX ETHERNET DRIVER |
@@ -1152,6 +1124,15 @@ L: codalist@coda.cs.cmu.edu | |||
1152 | W: http://www.coda.cs.cmu.edu/ | 1124 | W: http://www.coda.cs.cmu.edu/ |
1153 | S: Maintained | 1125 | S: Maintained |
1154 | 1126 | ||
1127 | COMMON INTERNET FILE SYSTEM (CIFS) | ||
1128 | P: Steve French | ||
1129 | M: sfrench@samba.org | ||
1130 | L: linux-cifs-client@lists.samba.org | ||
1131 | L: samba-technical@lists.samba.org | ||
1132 | W: http://linux-cifs.samba.org/ | ||
1133 | T: git kernel.org:/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git | ||
1134 | S: Supported | ||
1135 | |||
1155 | COMPACTPCI HOTPLUG CORE | 1136 | COMPACTPCI HOTPLUG CORE |
1156 | P: Scott Murray | 1137 | P: Scott Murray |
1157 | M: scottm@somanetworks.com | 1138 | M: scottm@somanetworks.com |
@@ -1191,6 +1172,12 @@ L: accessrunner-general@lists.sourceforge.net | |||
1191 | W: http://accessrunner.sourceforge.net/ | 1172 | W: http://accessrunner.sourceforge.net/ |
1192 | S: Maintained | 1173 | S: Maintained |
1193 | 1174 | ||
1175 | CONFIGFS | ||
1176 | P: Joel Becker | ||
1177 | M: joel.becker@oracle.com | ||
1178 | L: linux-kernel@vger.kernel.org | ||
1179 | S: Supported | ||
1180 | |||
1194 | CONTROL GROUPS (CGROUPS) | 1181 | CONTROL GROUPS (CGROUPS) |
1195 | P: Paul Menage | 1182 | P: Paul Menage |
1196 | M: menage@google.com | 1183 | M: menage@google.com |
@@ -1314,6 +1301,20 @@ W: http://www.qsl.net/dl1bke/ | |||
1314 | L: linux-hams@vger.kernel.org | 1301 | L: linux-hams@vger.kernel.org |
1315 | S: Maintained | 1302 | S: Maintained |
1316 | 1303 | ||
1304 | DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER | ||
1305 | P: Tobias Ringstrom | ||
1306 | M: tori@unhappy.mine.nu | ||
1307 | L: netdev@vger.kernel.org | ||
1308 | S: Maintained | ||
1309 | |||
1310 | DC390/AM53C974 SCSI driver | ||
1311 | P: Kurt Garloff | ||
1312 | M: garloff@suse.de | ||
1313 | W: http://www.garloff.de/kurt/linux/dc390/ | ||
1314 | P: Guennadi Liakhovetski | ||
1315 | M: g.liakhovetski@gmx.de | ||
1316 | S: Maintained | ||
1317 | |||
1317 | DC395x SCSI driver | 1318 | DC395x SCSI driver |
1318 | P: Oliver Neukum | 1319 | P: Oliver Neukum |
1319 | M: oliver@neukum.name | 1320 | M: oliver@neukum.name |
@@ -1326,14 +1327,6 @@ L: dc395x@twibble.org | |||
1326 | L: http://lists.twibble.org/mailman/listinfo/dc395x/ | 1327 | L: http://lists.twibble.org/mailman/listinfo/dc395x/ |
1327 | S: Maintained | 1328 | S: Maintained |
1328 | 1329 | ||
1329 | DC390/AM53C974 SCSI driver | ||
1330 | P: Kurt Garloff | ||
1331 | M: garloff@suse.de | ||
1332 | W: http://www.garloff.de/kurt/linux/dc390/ | ||
1333 | P: Guennadi Liakhovetski | ||
1334 | M: g.liakhovetski@gmx.de | ||
1335 | S: Maintained | ||
1336 | |||
1337 | DCCP PROTOCOL | 1330 | DCCP PROTOCOL |
1338 | P: Arnaldo Carvalho de Melo | 1331 | P: Arnaldo Carvalho de Melo |
1339 | M: acme@ghostprotocols.net | 1332 | M: acme@ghostprotocols.net |
@@ -1364,12 +1357,6 @@ P: Doug Warzecha | |||
1364 | M: Douglas_Warzecha@dell.com | 1357 | M: Douglas_Warzecha@dell.com |
1365 | S: Maintained | 1358 | S: Maintained |
1366 | 1359 | ||
1367 | DEVICE-MAPPER (LVM) | ||
1368 | P: Alasdair Kergon | ||
1369 | L: dm-devel@redhat.com | ||
1370 | W: http://sources.redhat.com/dm | ||
1371 | S: Maintained | ||
1372 | |||
1373 | DEVICE NUMBER REGISTRY | 1360 | DEVICE NUMBER REGISTRY |
1374 | P: Torben Mathiasen | 1361 | P: Torben Mathiasen |
1375 | M: device@lanana.org | 1362 | M: device@lanana.org |
@@ -1377,6 +1364,12 @@ W: http://lanana.org/docs/device-list/index.html | |||
1377 | L: linux-kernel@vger.kernel.org | 1364 | L: linux-kernel@vger.kernel.org |
1378 | S: Maintained | 1365 | S: Maintained |
1379 | 1366 | ||
1367 | DEVICE-MAPPER (LVM) | ||
1368 | P: Alasdair Kergon | ||
1369 | L: dm-devel@redhat.com | ||
1370 | W: http://sources.redhat.com/dm | ||
1371 | S: Maintained | ||
1372 | |||
1380 | DIGI INTL. EPCA DRIVER | 1373 | DIGI INTL. EPCA DRIVER |
1381 | P: Digi International, Inc | 1374 | P: Digi International, Inc |
1382 | M: Eng.Linux@digi.com | 1375 | M: Eng.Linux@digi.com |
@@ -1384,7 +1377,7 @@ L: Eng.Linux@digi.com | |||
1384 | W: http://www.digi.com | 1377 | W: http://www.digi.com |
1385 | S: Orphan | 1378 | S: Orphan |
1386 | 1379 | ||
1387 | DIRECTORY NOTIFICATION | 1380 | DIRECTORY NOTIFICATION (DNOTIFY) |
1388 | P: Stephen Rothwell | 1381 | P: Stephen Rothwell |
1389 | M: sfr@canb.auug.org.au | 1382 | M: sfr@canb.auug.org.au |
1390 | L: linux-kernel@vger.kernel.org | 1383 | L: linux-kernel@vger.kernel.org |
@@ -1398,13 +1391,13 @@ W: http://www.win.tue.nl/~aeb/linux/zip/zip-1.html | |||
1398 | W: http://www.win.tue.nl/~aeb/partitions/partition_types-1.html | 1391 | W: http://www.win.tue.nl/~aeb/partitions/partition_types-1.html |
1399 | S: Maintained | 1392 | S: Maintained |
1400 | 1393 | ||
1401 | DISKQUOTA: | 1394 | DISKQUOTA |
1402 | P: Jan Kara | 1395 | P: Jan Kara |
1403 | M: jack@suse.cz | 1396 | M: jack@suse.cz |
1404 | L: linux-kernel@vger.kernel.org | 1397 | L: linux-kernel@vger.kernel.org |
1405 | S: Maintained | 1398 | S: Maintained |
1406 | 1399 | ||
1407 | DISTRIBUTED LOCK MANAGER | 1400 | DISTRIBUTED LOCK MANAGER (DLM) |
1408 | P: Christine Caulfield | 1401 | P: Christine Caulfield |
1409 | M: ccaulfie@redhat.com | 1402 | M: ccaulfie@redhat.com |
1410 | P: David Teigland | 1403 | P: David Teigland |
@@ -1414,12 +1407,6 @@ W: http://sources.redhat.com/cluster/ | |||
1414 | T: git kernel.org:/pub/scm/linux/kernel/git/teigland/dlm.git | 1407 | T: git kernel.org:/pub/scm/linux/kernel/git/teigland/dlm.git |
1415 | S: Supported | 1408 | S: Supported |
1416 | 1409 | ||
1417 | DAVICOM FAST ETHERNET (DMFE) NETWORK DRIVER | ||
1418 | P: Tobias Ringstrom | ||
1419 | M: tori@unhappy.mine.nu | ||
1420 | L: netdev@vger.kernel.org | ||
1421 | S: Maintained | ||
1422 | |||
1423 | DMA GENERIC OFFLOAD ENGINE SUBSYSTEM | 1410 | DMA GENERIC OFFLOAD ENGINE SUBSYSTEM |
1424 | P: Maciej Sosnowski | 1411 | P: Maciej Sosnowski |
1425 | M: maciej.sosnowski@intel.com | 1412 | M: maciej.sosnowski@intel.com |
@@ -1459,6 +1446,13 @@ M: jrv@vanzandt.mv.com | |||
1459 | L: blinux-list@redhat.com | 1446 | L: blinux-list@redhat.com |
1460 | S: Maintained | 1447 | S: Maintained |
1461 | 1448 | ||
1449 | DPT_I2O SCSI RAID DRIVER | ||
1450 | P: Adaptec OEM Raid Solutions | ||
1451 | M: aacraid@adaptec.com | ||
1452 | L: linux-scsi@vger.kernel.org | ||
1453 | W: http://www.adaptec.com/ | ||
1454 | S: Maintained | ||
1455 | |||
1462 | DRIVER CORE, KOBJECTS, AND SYSFS | 1456 | DRIVER CORE, KOBJECTS, AND SYSFS |
1463 | P: Greg Kroah-Hartman | 1457 | P: Greg Kroah-Hartman |
1464 | M: gregkh@suse.de | 1458 | M: gregkh@suse.de |
@@ -1607,7 +1601,7 @@ EFS FILESYSTEM | |||
1607 | W: http://aeschi.ch.eu.org/efs/ | 1601 | W: http://aeschi.ch.eu.org/efs/ |
1608 | S: Orphan | 1602 | S: Orphan |
1609 | 1603 | ||
1610 | EHCA (IBM GX bus InfiniBand adapter) DRIVER: | 1604 | EHCA (IBM GX bus InfiniBand adapter) DRIVER |
1611 | P: Hoang-Nam Nguyen | 1605 | P: Hoang-Nam Nguyen |
1612 | M: hnguyen@de.ibm.com | 1606 | M: hnguyen@de.ibm.com |
1613 | P: Christoph Raisch | 1607 | P: Christoph Raisch |
@@ -1687,6 +1681,42 @@ P: Akinobu Mita | |||
1687 | M: akinobu.mita@gmail.com | 1681 | M: akinobu.mita@gmail.com |
1688 | S: Supported | 1682 | S: Supported |
1689 | 1683 | ||
1684 | FILE LOCKING (flock() and fcntl()/lockf()) | ||
1685 | P: Matthew Wilcox | ||
1686 | M: matthew@wil.cx | ||
1687 | L: linux-fsdevel@vger.kernel.org | ||
1688 | S: Maintained | ||
1689 | |||
1690 | FILESYSTEMS (VFS and infrastructure) | ||
1691 | P: Alexander Viro | ||
1692 | M: viro@zeniv.linux.org.uk | ||
1693 | L: linux-fsdevel@vger.kernel.org | ||
1694 | S: Maintained | ||
1695 | |||
1696 | FIREWIRE SUBSYSTEM (drivers/firewire, <linux/firewire*.h>) | ||
1697 | P: Kristian Hoegsberg, Stefan Richter | ||
1698 | M: krh@redhat.com, stefanr@s5r6.in-berlin.de | ||
1699 | L: linux1394-devel@lists.sourceforge.net | ||
1700 | W: http://www.linux1394.org/ | ||
1701 | T: git kernel.org:/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git | ||
1702 | S: Maintained | ||
1703 | |||
1704 | FIRMWARE LOADER (request_firmware) | ||
1705 | L: linux-kernel@vger.kernel.org | ||
1706 | S: Orphan | ||
1707 | |||
1708 | FPU EMULATOR | ||
1709 | P: Bill Metzenthen | ||
1710 | M: billm@suburbia.net | ||
1711 | W: http://suburbia.net/~billm/floating-point/emulator/ | ||
1712 | S: Maintained | ||
1713 | |||
1714 | FRAME RELAY DLCI/FRAD (Sangoma drivers too) | ||
1715 | P: Mike McLagan | ||
1716 | M: mike.mclagan@linux.org | ||
1717 | L: netdev@vger.kernel.org | ||
1718 | S: Maintained | ||
1719 | |||
1690 | FRAMEBUFFER LAYER | 1720 | FRAMEBUFFER LAYER |
1691 | P: Antonino Daplas | 1721 | P: Antonino Daplas |
1692 | M: adaplas@gmail.com | 1722 | M: adaplas@gmail.com |
@@ -1752,42 +1782,6 @@ L: alsa-devel@alsa-project.org | |||
1752 | L: linuxppc-dev@ozlabs.org | 1782 | L: linuxppc-dev@ozlabs.org |
1753 | S: Supported | 1783 | S: Supported |
1754 | 1784 | ||
1755 | FILE LOCKING (flock() and fcntl()/lockf()) | ||
1756 | P: Matthew Wilcox | ||
1757 | M: matthew@wil.cx | ||
1758 | L: linux-fsdevel@vger.kernel.org | ||
1759 | S: Maintained | ||
1760 | |||
1761 | FILESYSTEMS (VFS and infrastructure) | ||
1762 | P: Alexander Viro | ||
1763 | M: viro@zeniv.linux.org.uk | ||
1764 | L: linux-fsdevel@vger.kernel.org | ||
1765 | S: Maintained | ||
1766 | |||
1767 | FIREWIRE SUBSYSTEM (drivers/firewire, <linux/firewire*.h>) | ||
1768 | P: Kristian Hoegsberg, Stefan Richter | ||
1769 | M: krh@redhat.com, stefanr@s5r6.in-berlin.de | ||
1770 | L: linux1394-devel@lists.sourceforge.net | ||
1771 | W: http://www.linux1394.org/ | ||
1772 | T: git kernel.org:/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git | ||
1773 | S: Maintained | ||
1774 | |||
1775 | FIRMWARE LOADER (request_firmware) | ||
1776 | L: linux-kernel@vger.kernel.org | ||
1777 | S: Orphan | ||
1778 | |||
1779 | FPU EMULATOR | ||
1780 | P: Bill Metzenthen | ||
1781 | M: billm@suburbia.net | ||
1782 | W: http://suburbia.net/~billm/floating-point/emulator/ | ||
1783 | S: Maintained | ||
1784 | |||
1785 | FRAME RELAY DLCI/FRAD (Sangoma drivers too) | ||
1786 | P: Mike McLagan | ||
1787 | M: mike.mclagan@linux.org | ||
1788 | L: netdev@vger.kernel.org | ||
1789 | S: Maintained | ||
1790 | |||
1791 | FREEVXFS FILESYSTEM | 1785 | FREEVXFS FILESYSTEM |
1792 | P: Christoph Hellwig | 1786 | P: Christoph Hellwig |
1793 | M: hch@infradead.org | 1787 | M: hch@infradead.org |
@@ -1859,6 +1853,13 @@ L: gigaset307x-common@lists.sourceforge.net | |||
1859 | W: http://gigaset307x.sourceforge.net/ | 1853 | W: http://gigaset307x.sourceforge.net/ |
1860 | S: Maintained | 1854 | S: Maintained |
1861 | 1855 | ||
1856 | HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER | ||
1857 | P: Robert Love | ||
1858 | M: rlove@rlove.org | ||
1859 | M: linux-kernel@vger.kernel.org | ||
1860 | W: http://www.kernel.org/pub/linux/kernel/people/rml/hdaps/ | ||
1861 | S: Maintained | ||
1862 | |||
1862 | HARDWARE MONITORING | 1863 | HARDWARE MONITORING |
1863 | L: lm-sensors@lm-sensors.org | 1864 | L: lm-sensors@lm-sensors.org |
1864 | W: http://www.lm-sensors.org/ | 1865 | W: http://www.lm-sensors.org/ |
@@ -1867,13 +1868,6 @@ S: Orphan | |||
1867 | HARDWARE RANDOM NUMBER GENERATOR CORE | 1868 | HARDWARE RANDOM NUMBER GENERATOR CORE |
1868 | S: Orphan | 1869 | S: Orphan |
1869 | 1870 | ||
1870 | HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER | ||
1871 | P: Robert Love | ||
1872 | M: rlove@rlove.org | ||
1873 | M: linux-kernel@vger.kernel.org | ||
1874 | W: http://www.kernel.org/pub/linux/kernel/people/rml/hdaps/ | ||
1875 | S: Maintained | ||
1876 | |||
1877 | HARMONY SOUND DRIVER | 1871 | HARMONY SOUND DRIVER |
1878 | P: Kyle McMartin | 1872 | P: Kyle McMartin |
1879 | M: kyle@mcmartin.ca | 1873 | M: kyle@mcmartin.ca |
@@ -1887,6 +1881,24 @@ L: linux-kernel@vger.kernel.org | |||
1887 | W: http://www.nyx.net/~arobinso | 1881 | W: http://www.nyx.net/~arobinso |
1888 | S: Maintained | 1882 | S: Maintained |
1889 | 1883 | ||
1884 | HEWLETT-PACKARD FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA | ||
1885 | P: Chirag Kantharia | ||
1886 | M: chirag.kantharia@hp.com | ||
1887 | L: iss_storagedev@hp.com | ||
1888 | S: Maintained | ||
1889 | |||
1890 | HEWLETT-PACKARD SMART2 RAID DRIVER | ||
1891 | P: Chirag Kantharia | ||
1892 | M: chirag.kantharia@hp.com | ||
1893 | L: iss_storagedev@hp.com | ||
1894 | S: Maintained | ||
1895 | |||
1896 | HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss) | ||
1897 | P: Mike Miller | ||
1898 | M: mike.miller@hp.com | ||
1899 | L: iss_storagedev@hp.com | ||
1900 | S: Supported | ||
1901 | |||
1890 | HFS FILESYSTEM | 1902 | HFS FILESYSTEM |
1891 | P: Roman Zippel | 1903 | P: Roman Zippel |
1892 | M: zippel@linux-m68k.org | 1904 | M: zippel@linux-m68k.org |
@@ -1900,6 +1912,14 @@ L: linux-nvidia@lists.surfsouth.com | |||
1900 | W: http://drama.obuda.kando.hu/~fero/cgi-bin/hgafb.shtml | 1912 | W: http://drama.obuda.kando.hu/~fero/cgi-bin/hgafb.shtml |
1901 | S: Maintained | 1913 | S: Maintained |
1902 | 1914 | ||
1915 | HIBERNATION (aka Software Suspend, aka swsusp) | ||
1916 | P: Pavel Machek | ||
1917 | M: pavel@suse.cz | ||
1918 | P: Rafael J. Wysocki | ||
1919 | M: rjw@sisk.pl | ||
1920 | L: linux-pm@lists.linux-foundation.org | ||
1921 | S: Supported | ||
1922 | |||
1903 | HID CORE LAYER | 1923 | HID CORE LAYER |
1904 | P: Jiri Kosina | 1924 | P: Jiri Kosina |
1905 | M: jkosina@suse.cz | 1925 | M: jkosina@suse.cz |
@@ -1932,24 +1952,6 @@ M: jes@trained-monkey.org | |||
1932 | L: linux-hippi@sunsite.dk | 1952 | L: linux-hippi@sunsite.dk |
1933 | S: Maintained | 1953 | S: Maintained |
1934 | 1954 | ||
1935 | HEWLETT-PACKARD FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA | ||
1936 | P: Chirag Kantharia | ||
1937 | M: chirag.kantharia@hp.com | ||
1938 | L: iss_storagedev@hp.com | ||
1939 | S: Maintained | ||
1940 | |||
1941 | HEWLETT-PACKARD SMART2 RAID DRIVER | ||
1942 | P: Chirag Kantharia | ||
1943 | M: chirag.kantharia@hp.com | ||
1944 | L: iss_storagedev@hp.com | ||
1945 | S: Maintained | ||
1946 | |||
1947 | HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss) | ||
1948 | P: Mike Miller | ||
1949 | M: mike.miller@hp.com | ||
1950 | L: iss_storagedev@hp.com | ||
1951 | S: Supported | ||
1952 | |||
1953 | HOST AP DRIVER | 1955 | HOST AP DRIVER |
1954 | P: Jouni Malinen | 1956 | P: Jouni Malinen |
1955 | M: j@w1.fi | 1957 | M: j@w1.fi |
@@ -1958,16 +1960,16 @@ L: linux-wireless@vger.kernel.org | |||
1958 | W: http://hostap.epitest.fi/ | 1960 | W: http://hostap.epitest.fi/ |
1959 | S: Maintained | 1961 | S: Maintained |
1960 | 1962 | ||
1961 | HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series | ||
1962 | P: Jaroslav Kysela | ||
1963 | M: perex@perex.cz | ||
1964 | S: Maintained | ||
1965 | |||
1966 | HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER | 1963 | HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER |
1967 | P: Carlos Corbacho | 1964 | P: Carlos Corbacho |
1968 | M: carlos@strangeworlds.co.uk | 1965 | M: carlos@strangeworlds.co.uk |
1969 | S: Odd Fixes | 1966 | S: Odd Fixes |
1970 | 1967 | ||
1968 | HP100: Driver for HP 10/100 Mbit/s Voice Grade Network Adapter Series | ||
1969 | P: Jaroslav Kysela | ||
1970 | M: perex@perex.cz | ||
1971 | S: Maintained | ||
1972 | |||
1971 | HPET: High Precision Event Timers driver (drivers/char/hpet.c) | 1973 | HPET: High Precision Event Timers driver (drivers/char/hpet.c) |
1972 | P: Clemens Ladisch | 1974 | P: Clemens Ladisch |
1973 | M: clemens@ladisch.de | 1975 | M: clemens@ladisch.de |
@@ -2047,14 +2049,6 @@ W: http://www.ia64-linux.org/ | |||
2047 | T: git kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git | 2049 | T: git kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git |
2048 | S: Maintained | 2050 | S: Maintained |
2049 | 2051 | ||
2050 | SN-IA64 (Itanium) SUB-PLATFORM | ||
2051 | P: Jes Sorensen | ||
2052 | M: jes@sgi.com | ||
2053 | L: linux-altix@sgi.com | ||
2054 | L: linux-ia64@vger.kernel.org | ||
2055 | W: http://www.sgi.com/altix | ||
2056 | S: Maintained | ||
2057 | |||
2058 | IBM MCA SCSI SUBSYSTEM DRIVER | 2052 | IBM MCA SCSI SUBSYSTEM DRIVER |
2059 | P: Michael Lang | 2053 | P: Michael Lang |
2060 | M: langa2@kph.uni-mainz.de | 2054 | M: langa2@kph.uni-mainz.de |
@@ -2138,14 +2132,6 @@ W: http://www.openib.org/ | |||
2138 | T: git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git | 2132 | T: git kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git |
2139 | S: Supported | 2133 | S: Supported |
2140 | 2134 | ||
2141 | INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS | ||
2142 | P: Dmitry Torokhov | ||
2143 | M: dmitry.torokhov@gmail.com | ||
2144 | M: dtor@mail.ru | ||
2145 | L: linux-input@vger.kernel.org | ||
2146 | T: git kernel.org:/pub/scm/linux/kernel/git/dtor/input.git | ||
2147 | S: Maintained | ||
2148 | |||
2149 | INOTIFY | 2135 | INOTIFY |
2150 | P: John McCutchan | 2136 | P: John McCutchan |
2151 | M: ttb@tentacle.dhs.org | 2137 | M: ttb@tentacle.dhs.org |
@@ -2154,6 +2140,14 @@ M: rml@novell.com | |||
2154 | L: linux-kernel@vger.kernel.org | 2140 | L: linux-kernel@vger.kernel.org |
2155 | S: Maintained | 2141 | S: Maintained |
2156 | 2142 | ||
2143 | INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS | ||
2144 | P: Dmitry Torokhov | ||
2145 | M: dmitry.torokhov@gmail.com | ||
2146 | M: dtor@mail.ru | ||
2147 | L: linux-input@vger.kernel.org | ||
2148 | T: git kernel.org:/pub/scm/linux/kernel/git/dtor/input.git | ||
2149 | S: Maintained | ||
2150 | |||
2157 | INTEL FRAMEBUFFER DRIVER (excluding 810 and 815) | 2151 | INTEL FRAMEBUFFER DRIVER (excluding 810 and 815) |
2158 | P: Sylvain Meyer | 2152 | P: Sylvain Meyer |
2159 | M: sylvain.meyer@worldonline.fr | 2153 | M: sylvain.meyer@worldonline.fr |
@@ -2258,7 +2252,7 @@ M: pfg@sgi.com | |||
2258 | L: linux-mips@linux-mips.org | 2252 | L: linux-mips@linux-mips.org |
2259 | S: Maintained | 2253 | S: Maintained |
2260 | 2254 | ||
2261 | IP MASQUERADING: | 2255 | IP MASQUERADING |
2262 | P: Juanjo Ciarlante | 2256 | P: Juanjo Ciarlante |
2263 | M: jjciarla@raiz.uncu.edu.ar | 2257 | M: jjciarla@raiz.uncu.edu.ar |
2264 | S: Maintained | 2258 | S: Maintained |
@@ -2273,7 +2267,7 @@ M: jesse@icplus.com.tw | |||
2273 | L: netdev@vger.kernel.org | 2267 | L: netdev@vger.kernel.org |
2274 | S: Maintained | 2268 | S: Maintained |
2275 | 2269 | ||
2276 | IPATH DRIVER: | 2270 | IPATH DRIVER |
2277 | P: Ralph Campbell | 2271 | P: Ralph Campbell |
2278 | M: infinipath@qlogic.com | 2272 | M: infinipath@qlogic.com |
2279 | L: general@lists.openfabrics.org | 2273 | L: general@lists.openfabrics.org |
@@ -2287,13 +2281,25 @@ L: openipmi-developer@lists.sourceforge.net | |||
2287 | W: http://openipmi.sourceforge.net/ | 2281 | W: http://openipmi.sourceforge.net/ |
2288 | S: Supported | 2282 | S: Supported |
2289 | 2283 | ||
2290 | IPX NETWORK LAYER | 2284 | IPS SCSI RAID DRIVER |
2291 | P: Arnaldo Carvalho de Melo | 2285 | P: Adaptec OEM Raid Solutions |
2292 | M: acme@ghostprotocols.net | 2286 | M: aacraid@adaptec.com |
2287 | L: linux-scsi@vger.kernel.org | ||
2288 | W: http://www.adaptec.com/ | ||
2289 | S: Maintained | ||
2290 | |||
2291 | IPVS | ||
2292 | P: Wensong Zhang | ||
2293 | M: wensong@linux-vs.org | ||
2294 | P: Simon Horman | ||
2295 | M: horms@verge.net.au | ||
2296 | P: Julian Anastasov | ||
2297 | M: ja@ssi.bg | ||
2293 | L: netdev@vger.kernel.org | 2298 | L: netdev@vger.kernel.org |
2299 | L: lvs-devel@vger.kernel.org | ||
2294 | S: Maintained | 2300 | S: Maintained |
2295 | 2301 | ||
2296 | IPWIRELES DRIVER | 2302 | IPWIRELESS DRIVER |
2297 | P: Jiri Kosina | 2303 | P: Jiri Kosina |
2298 | M: jkosina@suse.cz | 2304 | M: jkosina@suse.cz |
2299 | P: David Sterba | 2305 | P: David Sterba |
@@ -2301,6 +2307,12 @@ M: dsterba@suse.cz | |||
2301 | S: Maintained | 2307 | S: Maintained |
2302 | T: git://git.kernel.org/pub/scm/linux/kernel/git/jikos/ipwireless_cs.git | 2308 | T: git://git.kernel.org/pub/scm/linux/kernel/git/jikos/ipwireless_cs.git |
2303 | 2309 | ||
2310 | IPX NETWORK LAYER | ||
2311 | P: Arnaldo Carvalho de Melo | ||
2312 | M: acme@ghostprotocols.net | ||
2313 | L: netdev@vger.kernel.org | ||
2314 | S: Maintained | ||
2315 | |||
2304 | IRDA SUBSYSTEM | 2316 | IRDA SUBSYSTEM |
2305 | P: Samuel Ortiz | 2317 | P: Samuel Ortiz |
2306 | M: samuel@sortiz.org | 2318 | M: samuel@sortiz.org |
@@ -2308,6 +2320,11 @@ L: irda-users@lists.sourceforge.net (subscribers-only) | |||
2308 | W: http://irda.sourceforge.net/ | 2320 | W: http://irda.sourceforge.net/ |
2309 | S: Maintained | 2321 | S: Maintained |
2310 | 2322 | ||
2323 | ISAPNP | ||
2324 | P: Jaroslav Kysela | ||
2325 | M: perex@perex.cz | ||
2326 | S: Maintained | ||
2327 | |||
2311 | ISCSI | 2328 | ISCSI |
2312 | P: Mike Christie | 2329 | P: Mike Christie |
2313 | M: michaelc@cs.wisc.edu | 2330 | M: michaelc@cs.wisc.edu |
@@ -2316,11 +2333,6 @@ W: www.open-iscsi.org | |||
2316 | T: git kernel.org:/pub/scm/linux/kernel/mnc/linux-2.6-iscsi.git | 2333 | T: git kernel.org:/pub/scm/linux/kernel/mnc/linux-2.6-iscsi.git |
2317 | S: Maintained | 2334 | S: Maintained |
2318 | 2335 | ||
2319 | ISAPNP | ||
2320 | P: Jaroslav Kysela | ||
2321 | M: perex@perex.cz | ||
2322 | S: Maintained | ||
2323 | |||
2324 | ISDN SUBSYSTEM | 2336 | ISDN SUBSYSTEM |
2325 | P: Karsten Keil | 2337 | P: Karsten Keil |
2326 | M: kkeil@suse.de | 2338 | M: kkeil@suse.de |
@@ -2345,6 +2357,14 @@ L: video4linux-list@redhat.com | |||
2345 | W: http://www.ivtvdriver.org | 2357 | W: http://www.ivtvdriver.org |
2346 | S: Maintained | 2358 | S: Maintained |
2347 | 2359 | ||
2360 | JFS FILESYSTEM | ||
2361 | P: Dave Kleikamp | ||
2362 | M: shaggy@austin.ibm.com | ||
2363 | L: jfs-discussion@lists.sourceforge.net | ||
2364 | W: http://jfs.sourceforge.net/ | ||
2365 | T: git kernel.org:/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git | ||
2366 | S: Supported | ||
2367 | |||
2348 | JME NETWORK DRIVER | 2368 | JME NETWORK DRIVER |
2349 | P: Guo-Fu Tseng | 2369 | P: Guo-Fu Tseng |
2350 | M: cooldavid@cooldavid.org | 2370 | M: cooldavid@cooldavid.org |
@@ -2358,24 +2378,6 @@ L: linux-mtd@lists.infradead.org | |||
2358 | W: http://www.linux-mtd.infradead.org/doc/jffs2.html | 2378 | W: http://www.linux-mtd.infradead.org/doc/jffs2.html |
2359 | S: Maintained | 2379 | S: Maintained |
2360 | 2380 | ||
2361 | UBI FILE SYSTEM (UBIFS) | ||
2362 | P: Artem Bityutskiy | ||
2363 | M: dedekind@infradead.org | ||
2364 | P: Adrian Hunter | ||
2365 | M: ext-adrian.hunter@nokia.com | ||
2366 | L: linux-mtd@lists.infradead.org | ||
2367 | T: git git://git.infradead.org/~dedekind/ubifs-2.6.git | ||
2368 | W: http://www.linux-mtd.infradead.org/doc/ubifs.html | ||
2369 | S: Maintained | ||
2370 | |||
2371 | JFS FILESYSTEM | ||
2372 | P: Dave Kleikamp | ||
2373 | M: shaggy@austin.ibm.com | ||
2374 | L: jfs-discussion@lists.sourceforge.net | ||
2375 | W: http://jfs.sourceforge.net/ | ||
2376 | T: git kernel.org:/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git | ||
2377 | S: Supported | ||
2378 | |||
2379 | JOURNALLING LAYER FOR BLOCK DEVICES (JBD) | 2381 | JOURNALLING LAYER FOR BLOCK DEVICES (JBD) |
2380 | P: Stephen Tweedie, Andrew Morton | 2382 | P: Stephen Tweedie, Andrew Morton |
2381 | M: sct@redhat.com, akpm@linux-foundation.org | 2383 | M: sct@redhat.com, akpm@linux-foundation.org |
@@ -2612,11 +2614,6 @@ W: http://www.pasemi.com/ | |||
2612 | L: linuxppc-dev@ozlabs.org | 2614 | L: linuxppc-dev@ozlabs.org |
2613 | S: Supported | 2615 | S: Supported |
2614 | 2616 | ||
2615 | LLC (802.2) | ||
2616 | P: Arnaldo Carvalho de Melo | ||
2617 | M: acme@ghostprotocols.net | ||
2618 | S: Maintained | ||
2619 | |||
2620 | LINUX SECURITY MODULE (LSM) FRAMEWORK | 2617 | LINUX SECURITY MODULE (LSM) FRAMEWORK |
2621 | P: Chris Wright | 2618 | P: Chris Wright |
2622 | M: chrisw@sous-sol.org | 2619 | M: chrisw@sous-sol.org |
@@ -2624,6 +2621,11 @@ L: linux-security-module@vger.kernel.org | |||
2624 | T: git kernel.org:/pub/scm/linux/kernel/git/chrisw/lsm-2.6.git | 2621 | T: git kernel.org:/pub/scm/linux/kernel/git/chrisw/lsm-2.6.git |
2625 | S: Supported | 2622 | S: Supported |
2626 | 2623 | ||
2624 | LLC (802.2) | ||
2625 | P: Arnaldo Carvalho de Melo | ||
2626 | M: acme@ghostprotocols.net | ||
2627 | S: Maintained | ||
2628 | |||
2627 | LM83 HARDWARE MONITOR DRIVER | 2629 | LM83 HARDWARE MONITOR DRIVER |
2628 | P: Jean Delvare | 2630 | P: Jean Delvare |
2629 | M: khali@linux-fr.org | 2631 | M: khali@linux-fr.org |
@@ -2724,14 +2726,6 @@ M: kaber@trash.net | |||
2724 | L: netdev@vger.kernel.org | 2726 | L: netdev@vger.kernel.org |
2725 | S: Maintained | 2727 | S: Maintained |
2726 | 2728 | ||
2727 | MARVELL YUKON / SYSKONNECT DRIVER | ||
2728 | P: Mirko Lindner | ||
2729 | M: mlindner@syskonnect.de | ||
2730 | P: Ralph Roesler | ||
2731 | M: rroesler@syskonnect.de | ||
2732 | W: http://www.syskonnect.com | ||
2733 | S: Supported | ||
2734 | |||
2735 | MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7 | 2729 | MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7 |
2736 | P: Michael Kerrisk | 2730 | P: Michael Kerrisk |
2737 | M: mtk.manpages@gmail.com | 2731 | M: mtk.manpages@gmail.com |
@@ -2751,6 +2745,14 @@ M: buytenh@marvell.com | |||
2751 | L: netdev@vger.kernel.org | 2745 | L: netdev@vger.kernel.org |
2752 | S: Supported | 2746 | S: Supported |
2753 | 2747 | ||
2748 | MARVELL YUKON / SYSKONNECT DRIVER | ||
2749 | P: Mirko Lindner | ||
2750 | M: mlindner@syskonnect.de | ||
2751 | P: Ralph Roesler | ||
2752 | M: rroesler@syskonnect.de | ||
2753 | W: http://www.syskonnect.com | ||
2754 | S: Supported | ||
2755 | |||
2754 | MATROX FRAMEBUFFER DRIVER | 2756 | MATROX FRAMEBUFFER DRIVER |
2755 | P: Petr Vandrovec | 2757 | P: Petr Vandrovec |
2756 | M: vandrove@vc.cvut.cz | 2758 | M: vandrove@vc.cvut.cz |
@@ -2787,15 +2789,6 @@ L: linux-mm@kvack.org | |||
2787 | L: linux-kernel@vger.kernel.org | 2789 | L: linux-kernel@vger.kernel.org |
2788 | S: Maintained | 2790 | S: Maintained |
2789 | 2791 | ||
2790 | MEI MN10300/AM33 PORT | ||
2791 | P: David Howells | ||
2792 | M: dhowells@redhat.com | ||
2793 | P: Koichi Yasutake | ||
2794 | M: yasutake.koichi@jp.panasonic.com | ||
2795 | L: linux-am33-list@redhat.com (moderated for non-subscribers) | ||
2796 | W: ftp://ftp.redhat.com/pub/redhat/gnupro/AM33/ | ||
2797 | S: Maintained | ||
2798 | |||
2799 | MEMORY TECHNOLOGY DEVICES (MTD) | 2792 | MEMORY TECHNOLOGY DEVICES (MTD) |
2800 | P: David Woodhouse | 2793 | P: David Woodhouse |
2801 | M: dwmw2@infradead.org | 2794 | M: dwmw2@infradead.org |
@@ -2804,14 +2797,6 @@ L: linux-mtd@lists.infradead.org | |||
2804 | T: git git://git.infradead.org/mtd-2.6.git | 2797 | T: git git://git.infradead.org/mtd-2.6.git |
2805 | S: Maintained | 2798 | S: Maintained |
2806 | 2799 | ||
2807 | UNSORTED BLOCK IMAGES (UBI) | ||
2808 | P: Artem Bityutskiy | ||
2809 | M: dedekind@infradead.org | ||
2810 | W: http://www.linux-mtd.infradead.org/ | ||
2811 | L: linux-mtd@lists.infradead.org | ||
2812 | T: git git://git.infradead.org/~dedekind/ubi-2.6.git | ||
2813 | S: Maintained | ||
2814 | |||
2815 | MICROTEK X6 SCANNER | 2800 | MICROTEK X6 SCANNER |
2816 | P: Oliver Neukum | 2801 | P: Oliver Neukum |
2817 | M: oliver@neukum.name | 2802 | M: oliver@neukum.name |
@@ -3043,17 +3028,6 @@ L: netdev@vger.kernel.org | |||
3043 | W: http://www.netxen.com | 3028 | W: http://www.netxen.com |
3044 | S: Supported | 3029 | S: Supported |
3045 | 3030 | ||
3046 | IPVS | ||
3047 | P: Wensong Zhang | ||
3048 | M: wensong@linux-vs.org | ||
3049 | P: Simon Horman | ||
3050 | M: horms@verge.net.au | ||
3051 | P: Julian Anastasov | ||
3052 | M: ja@ssi.bg | ||
3053 | L: netdev@vger.kernel.org | ||
3054 | L: lvs-devel@vger.kernel.org | ||
3055 | S: Maintained | ||
3056 | |||
3057 | NFS, SUNRPC, AND LOCKD CLIENTS | 3031 | NFS, SUNRPC, AND LOCKD CLIENTS |
3058 | P: Trond Myklebust | 3032 | P: Trond Myklebust |
3059 | M: Trond.Myklebust@netapp.com | 3033 | M: Trond.Myklebust@netapp.com |
@@ -3099,22 +3073,6 @@ M: adaplas@gmail.com | |||
3099 | L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) | 3073 | L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) |
3100 | S: Maintained | 3074 | S: Maintained |
3101 | 3075 | ||
3102 | OPENCORES I2C BUS DRIVER | ||
3103 | P: Peter Korsgaard | ||
3104 | M: jacmet@sunsite.dk | ||
3105 | L: i2c@lm-sensors.org | ||
3106 | S: Maintained | ||
3107 | |||
3108 | ORACLE CLUSTER FILESYSTEM 2 (OCFS2) | ||
3109 | P: Mark Fasheh | ||
3110 | M: mfasheh@suse.com | ||
3111 | P: Joel Becker | ||
3112 | M: joel.becker@oracle.com | ||
3113 | L: ocfs2-devel@oss.oracle.com (moderated for non-subscribers) | ||
3114 | W: http://oss.oracle.com/projects/ocfs2/ | ||
3115 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2.git | ||
3116 | S: Supported | ||
3117 | |||
3118 | OMFS FILESYSTEM | 3076 | OMFS FILESYSTEM |
3119 | P: Bob Copeland | 3077 | P: Bob Copeland |
3120 | M: me@bobcopeland.com | 3078 | M: me@bobcopeland.com |
@@ -3150,12 +3108,28 @@ L: osst-users@lists.sourceforge.net | |||
3150 | L: linux-scsi@vger.kernel.org | 3108 | L: linux-scsi@vger.kernel.org |
3151 | S: Maintained | 3109 | S: Maintained |
3152 | 3110 | ||
3111 | OPENCORES I2C BUS DRIVER | ||
3112 | P: Peter Korsgaard | ||
3113 | M: jacmet@sunsite.dk | ||
3114 | L: i2c@lm-sensors.org | ||
3115 | S: Maintained | ||
3116 | |||
3153 | OPROFILE | 3117 | OPROFILE |
3154 | P: Robert Richter | 3118 | P: Robert Richter |
3155 | M: robert.richter@amd.com | 3119 | M: robert.richter@amd.com |
3156 | L: oprofile-list@lists.sf.net | 3120 | L: oprofile-list@lists.sf.net |
3157 | S: Maintained | 3121 | S: Maintained |
3158 | 3122 | ||
3123 | ORACLE CLUSTER FILESYSTEM 2 (OCFS2) | ||
3124 | P: Mark Fasheh | ||
3125 | M: mfasheh@suse.com | ||
3126 | P: Joel Becker | ||
3127 | M: joel.becker@oracle.com | ||
3128 | L: ocfs2-devel@oss.oracle.com (moderated for non-subscribers) | ||
3129 | W: http://oss.oracle.com/projects/ocfs2/ | ||
3130 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2.git | ||
3131 | S: Supported | ||
3132 | |||
3159 | ORINOCO DRIVER | 3133 | ORINOCO DRIVER |
3160 | P: Pavel Roskin | 3134 | P: Pavel Roskin |
3161 | M: proski@gnu.org | 3135 | M: proski@gnu.org |
@@ -3167,6 +3141,14 @@ L: orinoco-devel@lists.sourceforge.net | |||
3167 | W: http://www.nongnu.org/orinoco/ | 3141 | W: http://www.nongnu.org/orinoco/ |
3168 | S: Maintained | 3142 | S: Maintained |
3169 | 3143 | ||
3144 | P54 WIRELESS DRIVER | ||
3145 | P: Michael Wu | ||
3146 | M: flamingice@sourmilk.net | ||
3147 | L: linux-wireless@vger.kernel.org | ||
3148 | W: http://prism54.org | ||
3149 | T: git kernel.org:/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git | ||
3150 | S: Maintained | ||
3151 | |||
3170 | PA SEMI ETHERNET DRIVER | 3152 | PA SEMI ETHERNET DRIVER |
3171 | P: Olof Johansson | 3153 | P: Olof Johansson |
3172 | M: olof@lixom.net | 3154 | M: olof@lixom.net |
@@ -3179,10 +3161,32 @@ M: olof@lixom.net | |||
3179 | L: i2c@lm-sensors.org | 3161 | L: i2c@lm-sensors.org |
3180 | S: Maintained | 3162 | S: Maintained |
3181 | 3163 | ||
3164 | PANASONIC MN10300/AM33 PORT | ||
3165 | P: David Howells | ||
3166 | M: dhowells@redhat.com | ||
3167 | P: Koichi Yasutake | ||
3168 | M: yasutake.koichi@jp.panasonic.com | ||
3169 | L: linux-am33-list@redhat.com (moderated for non-subscribers) | ||
3170 | W: ftp://ftp.redhat.com/pub/redhat/gnupro/AM33/ | ||
3171 | S: Maintained | ||
3172 | |||
3182 | PARALLEL PORT SUPPORT | 3173 | PARALLEL PORT SUPPORT |
3183 | L: linux-parport@lists.infradead.org (subscribers-only) | 3174 | L: linux-parport@lists.infradead.org (subscribers-only) |
3184 | S: Orphan | 3175 | S: Orphan |
3185 | 3176 | ||
3177 | PARAVIRT_OPS INTERFACE | ||
3178 | P: Jeremy Fitzhardinge | ||
3179 | M: jeremy@xensource.com | ||
3180 | P: Chris Wright | ||
3181 | M: chrisw@sous-sol.org | ||
3182 | P: Zachary Amsden | ||
3183 | M: zach@vmware.com | ||
3184 | P: Rusty Russell | ||
3185 | M: rusty@rustcorp.com.au | ||
3186 | L: virtualization@lists.osdl.org | ||
3187 | L: linux-kernel@vger.kernel.org | ||
3188 | S: Supported | ||
3189 | |||
3186 | PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES | 3190 | PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES |
3187 | P: Tim Waugh | 3191 | P: Tim Waugh |
3188 | M: tim@cyberelk.net | 3192 | M: tim@cyberelk.net |
@@ -3202,19 +3206,6 @@ W: http://www.parisc-linux.org/ | |||
3202 | T: git kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6.git | 3206 | T: git kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6.git |
3203 | S: Maintained | 3207 | S: Maintained |
3204 | 3208 | ||
3205 | PARAVIRT_OPS INTERFACE | ||
3206 | P: Jeremy Fitzhardinge | ||
3207 | M: jeremy@xensource.com | ||
3208 | P: Chris Wright | ||
3209 | M: chrisw@sous-sol.org | ||
3210 | P: Zachary Amsden | ||
3211 | M: zach@vmware.com | ||
3212 | P: Rusty Russell | ||
3213 | M: rusty@rustcorp.com.au | ||
3214 | L: virtualization@lists.osdl.org | ||
3215 | L: linux-kernel@vger.kernel.org | ||
3216 | S: Supported | ||
3217 | |||
3218 | PC87360 HARDWARE MONITORING DRIVER | 3209 | PC87360 HARDWARE MONITORING DRIVER |
3219 | P: Jim Cromie | 3210 | P: Jim Cromie |
3220 | M: jim.cromie@gmail.com | 3211 | M: jim.cromie@gmail.com |
@@ -3344,14 +3335,6 @@ L: kpreempt-tech@lists.sourceforge.net | |||
3344 | W: ftp://ftp.kernel.org/pub/linux/kernel/people/rml/preempt-kernel | 3335 | W: ftp://ftp.kernel.org/pub/linux/kernel/people/rml/preempt-kernel |
3345 | S: Supported | 3336 | S: Supported |
3346 | 3337 | ||
3347 | P54 WIRELESS DRIVER | ||
3348 | P: Michael Wu | ||
3349 | M: flamingice@sourmilk.net | ||
3350 | L: linux-wireless@vger.kernel.org | ||
3351 | W: http://prism54.org | ||
3352 | T: git kernel.org:/pub/scm/linux/kernel/git/mwu/mac80211-drivers.git | ||
3353 | S: Maintained | ||
3354 | |||
3355 | PRISM54 WIRELESS DRIVER | 3338 | PRISM54 WIRELESS DRIVER |
3356 | P: Luis R. Rodriguez | 3339 | P: Luis R. Rodriguez |
3357 | M: mcgrof@gmail.com | 3340 | M: mcgrof@gmail.com |
@@ -3442,13 +3425,7 @@ M: paulus@samba.org | |||
3442 | L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) | 3425 | L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers) |
3443 | S: Maintained | 3426 | S: Maintained |
3444 | 3427 | ||
3445 | RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER | 3428 | RALINK RT2X00 WIRELESS LAN DRIVER |
3446 | P: Corey Thomas | ||
3447 | M: coreythomas@charter.net | ||
3448 | L: linux-wireless@vger.kernel.org | ||
3449 | S: Maintained | ||
3450 | |||
3451 | RALINK RT2X00 WLAN DRIVER | ||
3452 | P: rt2x00 project | 3429 | P: rt2x00 project |
3453 | L: linux-wireless@vger.kernel.org | 3430 | L: linux-wireless@vger.kernel.org |
3454 | L: rt2400-devel@lists.sourceforge.net | 3431 | L: rt2400-devel@lists.sourceforge.net |
@@ -3473,6 +3450,18 @@ M: mporter@kernel.crashing.org | |||
3473 | L: linux-kernel@vger.kernel.org | 3450 | L: linux-kernel@vger.kernel.org |
3474 | S: Maintained | 3451 | S: Maintained |
3475 | 3452 | ||
3453 | RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER | ||
3454 | P: Corey Thomas | ||
3455 | M: coreythomas@charter.net | ||
3456 | L: linux-wireless@vger.kernel.org | ||
3457 | S: Maintained | ||
3458 | |||
3459 | RCUTORTURE MODULE | ||
3460 | P: Josh Triplett | ||
3461 | M: josh@freedesktop.org | ||
3462 | L: linux-kernel@vger.kernel.org | ||
3463 | S: Maintained | ||
3464 | |||
3476 | RDC R-321X SoC | 3465 | RDC R-321X SoC |
3477 | P: Florian Fainelli | 3466 | P: Florian Fainelli |
3478 | M: florian.fainelli@telecomint.eu | 3467 | M: florian.fainelli@telecomint.eu |
@@ -3492,12 +3481,6 @@ W: http://www.rdrop.com/users/paulmck/rclock/ | |||
3492 | L: linux-kernel@vger.kernel.org | 3481 | L: linux-kernel@vger.kernel.org |
3493 | S: Supported | 3482 | S: Supported |
3494 | 3483 | ||
3495 | RCUTORTURE MODULE | ||
3496 | P: Josh Triplett | ||
3497 | M: josh@freedesktop.org | ||
3498 | L: linux-kernel@vger.kernel.org | ||
3499 | S: Maintained | ||
3500 | |||
3501 | REAL TIME CLOCK DRIVER | 3484 | REAL TIME CLOCK DRIVER |
3502 | P: Paul Gortmaker | 3485 | P: Paul Gortmaker |
3503 | M: p_gortmaker@yahoo.com | 3486 | M: p_gortmaker@yahoo.com |
@@ -3521,6 +3504,9 @@ L: netdev@vger.kernel.org | |||
3521 | S: Maintained | 3504 | S: Maintained |
3522 | F: net/rfkill | 3505 | F: net/rfkill |
3523 | 3506 | ||
3507 | RISCOM8 DRIVER | ||
3508 | S: Orphan | ||
3509 | |||
3524 | ROCKETPORT DRIVER | 3510 | ROCKETPORT DRIVER |
3525 | P: Comtrol Corp. | 3511 | P: Comtrol Corp. |
3526 | W: http://www.comtrol.com | 3512 | W: http://www.comtrol.com |
@@ -3533,9 +3519,6 @@ L: linux-hams@vger.kernel.org | |||
3533 | W: http://www.linux-ax25.org/ | 3519 | W: http://www.linux-ax25.org/ |
3534 | S: Maintained | 3520 | S: Maintained |
3535 | 3521 | ||
3536 | RISCOM8 DRIVER | ||
3537 | S: Orphan | ||
3538 | |||
3539 | RTL818X WIRELESS DRIVER | 3522 | RTL818X WIRELESS DRIVER |
3540 | P: Michael Wu | 3523 | P: Michael Wu |
3541 | M: flamingice@sourmilk.net | 3524 | M: flamingice@sourmilk.net |
@@ -3675,6 +3658,12 @@ M: saschasommer@freenet.de | |||
3675 | L: sdricohcs-devel@lists.sourceforge.net (subscribers-only) | 3658 | L: sdricohcs-devel@lists.sourceforge.net (subscribers-only) |
3676 | S: Maintained | 3659 | S: Maintained |
3677 | 3660 | ||
3661 | SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER | ||
3662 | P: Pierre Ossman | ||
3663 | M: drzeus-sdhci@drzeus.cx | ||
3664 | L: sdhci-devel@list.drzeus.cx | ||
3665 | S: Maintained | ||
3666 | |||
3678 | SECURITY CONTACT | 3667 | SECURITY CONTACT |
3679 | P: Security Officers | 3668 | P: Security Officers |
3680 | M: security@kernel.org | 3669 | M: security@kernel.org |
@@ -3698,19 +3687,13 @@ P: Jiri Slaby | |||
3698 | M: jirislaby@gmail.com | 3687 | M: jirislaby@gmail.com |
3699 | S: Maintained | 3688 | S: Maintained |
3700 | 3689 | ||
3701 | SERIAL ATA (SATA) SUBSYSTEM: | 3690 | SERIAL ATA (SATA) SUBSYSTEM |
3702 | P: Jeff Garzik | 3691 | P: Jeff Garzik |
3703 | M: jgarzik@pobox.com | 3692 | M: jgarzik@pobox.com |
3704 | L: linux-ide@vger.kernel.org | 3693 | L: linux-ide@vger.kernel.org |
3705 | T: git kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git | 3694 | T: git kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git |
3706 | S: Supported | 3695 | S: Supported |
3707 | 3696 | ||
3708 | SGI SN-IA64 (Altix) SERIAL CONSOLE DRIVER | ||
3709 | P: Pat Gefre | ||
3710 | M: pfg@sgi.com | ||
3711 | L: linux-ia64@vger.kernel.org | ||
3712 | S: Supported | ||
3713 | |||
3714 | SFC NETWORK DRIVER | 3697 | SFC NETWORK DRIVER |
3715 | P: Steve Hodgson | 3698 | P: Steve Hodgson |
3716 | P: Ben Hutchings | 3699 | P: Ben Hutchings |
@@ -3718,6 +3701,17 @@ P: Robert Stonehouse | |||
3718 | M: linux-net-drivers@solarflare.com | 3701 | M: linux-net-drivers@solarflare.com |
3719 | S: Supported | 3702 | S: Supported |
3720 | 3703 | ||
3704 | SGI GRU DRIVER | ||
3705 | P: Jack Steiner | ||
3706 | M: steiner@sgi.com | ||
3707 | S: Maintained | ||
3708 | |||
3709 | SGI SN-IA64 (Altix) SERIAL CONSOLE DRIVER | ||
3710 | P: Pat Gefre | ||
3711 | M: pfg@sgi.com | ||
3712 | L: linux-ia64@vger.kernel.org | ||
3713 | S: Supported | ||
3714 | |||
3721 | SGI VISUAL WORKSTATION 320 AND 540 | 3715 | SGI VISUAL WORKSTATION 320 AND 540 |
3722 | P: Andrey Panin | 3716 | P: Andrey Panin |
3723 | M: pazke@donpac.ru | 3717 | M: pazke@donpac.ru |
@@ -3725,16 +3719,24 @@ L: linux-visws-devel@lists.sf.net | |||
3725 | W: http://linux-visws.sf.net | 3719 | W: http://linux-visws.sf.net |
3726 | S: Maintained for 2.6. | 3720 | S: Maintained for 2.6. |
3727 | 3721 | ||
3728 | SGI GRU DRIVER | ||
3729 | P: Jack Steiner | ||
3730 | M: steiner@sgi.com | ||
3731 | S: Maintained | ||
3732 | |||
3733 | SGI XP/XPC/XPNET DRIVER | 3722 | SGI XP/XPC/XPNET DRIVER |
3734 | P: Dean Nelson | 3723 | P: Dean Nelson |
3735 | M: dcn@sgi.com | 3724 | M: dcn@sgi.com |
3736 | S: Maintained | 3725 | S: Maintained |
3737 | 3726 | ||
3727 | SHARP LH SUPPORT (LH7952X & LH7A40X) | ||
3728 | P: Marc Singer | ||
3729 | M: elf@buici.com | ||
3730 | W: http://projects.buici.com/arm | ||
3731 | L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) | ||
3732 | S: Maintained | ||
3733 | |||
3734 | SHPC HOTPLUG DRIVER | ||
3735 | P: Kristen Carlson Accardi | ||
3736 | M: kristen.c.accardi@intel.com | ||
3737 | L: linux-pci@vger.kernel.org | ||
3738 | S: Supported | ||
3739 | |||
3738 | SIMTEC EB110ATX (Chalice CATS) | 3740 | SIMTEC EB110ATX (Chalice CATS) |
3739 | P: Ben Dooks | 3741 | P: Ben Dooks |
3740 | P: Vincent Sanders | 3742 | P: Vincent Sanders |
@@ -3780,6 +3782,12 @@ M: thomas@winischhofer.net | |||
3780 | W: http://www.winischhofer.at/linuxsisusbvga.shtml | 3782 | W: http://www.winischhofer.at/linuxsisusbvga.shtml |
3781 | S: Maintained | 3783 | S: Maintained |
3782 | 3784 | ||
3785 | SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS | ||
3786 | P: Stephen Hemminger | ||
3787 | M: shemminger@linux-foundation.org | ||
3788 | L: netdev@vger.kernel.org | ||
3789 | S: Maintained | ||
3790 | |||
3783 | SLAB ALLOCATOR | 3791 | SLAB ALLOCATOR |
3784 | P: Christoph Lameter | 3792 | P: Christoph Lameter |
3785 | M: cl@linux-foundation.org | 3793 | M: cl@linux-foundation.org |
@@ -3806,12 +3814,25 @@ P: Ben Nizette | |||
3806 | M: bn@niasdigital.com | 3814 | M: bn@niasdigital.com |
3807 | S: Maintained | 3815 | S: Maintained |
3808 | 3816 | ||
3817 | SN-IA64 (Itanium) SUB-PLATFORM | ||
3818 | P: Jes Sorensen | ||
3819 | M: jes@sgi.com | ||
3820 | L: linux-altix@sgi.com | ||
3821 | L: linux-ia64@vger.kernel.org | ||
3822 | W: http://www.sgi.com/altix | ||
3823 | S: Maintained | ||
3824 | |||
3809 | SOC-CAMERA V4L2 SUBSYSTEM | 3825 | SOC-CAMERA V4L2 SUBSYSTEM |
3810 | P: Guennadi Liakhovetski | 3826 | P: Guennadi Liakhovetski |
3811 | M: g.liakhovetski@gmx.de | 3827 | M: g.liakhovetski@gmx.de |
3812 | L: video4linux-list@redhat.com | 3828 | L: video4linux-list@redhat.com |
3813 | S: Maintained | 3829 | S: Maintained |
3814 | 3830 | ||
3831 | SOEKRIS NET48XX LED SUPPORT | ||
3832 | P: Chris Boot | ||
3833 | M: bootc@bootc.net | ||
3834 | S: Maintained | ||
3835 | |||
3815 | SOFTWARE RAID (Multiple Disks) SUPPORT | 3836 | SOFTWARE RAID (Multiple Disks) SUPPORT |
3816 | P: Ingo Molnar | 3837 | P: Ingo Molnar |
3817 | M: mingo@redhat.com | 3838 | M: mingo@redhat.com |
@@ -3820,24 +3841,6 @@ M: neilb@suse.de | |||
3820 | L: linux-raid@vger.kernel.org | 3841 | L: linux-raid@vger.kernel.org |
3821 | S: Supported | 3842 | S: Supported |
3822 | 3843 | ||
3823 | HIBERNATION (aka Software Suspend, aka swsusp): | ||
3824 | P: Pavel Machek | ||
3825 | M: pavel@suse.cz | ||
3826 | P: Rafael J. Wysocki | ||
3827 | M: rjw@sisk.pl | ||
3828 | L: linux-pm@lists.linux-foundation.org | ||
3829 | S: Supported | ||
3830 | |||
3831 | SUSPEND TO RAM: | ||
3832 | P: Len Brown | ||
3833 | M: len.brown@intel.com | ||
3834 | P: Pavel Machek | ||
3835 | M: pavel@suse.cz | ||
3836 | P: Rafael J. Wysocki | ||
3837 | M: rjw@sisk.pl | ||
3838 | L: linux-pm@lists.linux-foundation.org | ||
3839 | S: Supported | ||
3840 | |||
3841 | SONIC NETWORK DRIVER | 3844 | SONIC NETWORK DRIVER |
3842 | P: Thomas Bogendoerfer | 3845 | P: Thomas Bogendoerfer |
3843 | M: tsbogend@alpha.franken.de | 3846 | M: tsbogend@alpha.franken.de |
@@ -3882,59 +3885,7 @@ L: alsa-devel@alsa-project.org (subscribers-only) | |||
3882 | W: http://alsa-project.org/main/index.php/ASoC | 3885 | W: http://alsa-project.org/main/index.php/ASoC |
3883 | S: Supported | 3886 | S: Supported |
3884 | 3887 | ||
3885 | SPI SUBSYSTEM | 3888 | SPARC (sparc32) |
3886 | P: David Brownell | ||
3887 | M: dbrownell@users.sourceforge.net | ||
3888 | L: spi-devel-general@lists.sourceforge.net | ||
3889 | S: Maintained | ||
3890 | |||
3891 | SPU FILE SYSTEM | ||
3892 | P: Jeremy Kerr | ||
3893 | M: jk@ozlabs.org | ||
3894 | L: linuxppc-dev@ozlabs.org | ||
3895 | L: cbe-oss-dev@ozlabs.org | ||
3896 | W: http://www.ibm.com/developerworks/power/cell/ | ||
3897 | S: Supported | ||
3898 | |||
3899 | STABLE BRANCH: | ||
3900 | P: Greg Kroah-Hartman | ||
3901 | M: greg@kroah.com | ||
3902 | P: Chris Wright | ||
3903 | M: chrisw@sous-sol.org | ||
3904 | L: stable@kernel.org | ||
3905 | S: Maintained | ||
3906 | |||
3907 | SHARP LH SUPPORT (LH7952X & LH7A40X) | ||
3908 | P: Marc Singer | ||
3909 | M: elf@buici.com | ||
3910 | W: http://projects.buici.com/arm | ||
3911 | L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only) | ||
3912 | S: Maintained | ||
3913 | |||
3914 | SHPC HOTPLUG DRIVER | ||
3915 | P: Kristen Carlson Accardi | ||
3916 | M: kristen.c.accardi@intel.com | ||
3917 | L: linux-pci@vger.kernel.org | ||
3918 | S: Supported | ||
3919 | |||
3920 | SECURE DIGITAL HOST CONTROLLER INTERFACE DRIVER | ||
3921 | P: Pierre Ossman | ||
3922 | M: drzeus-sdhci@drzeus.cx | ||
3923 | L: sdhci-devel@list.drzeus.cx | ||
3924 | S: Maintained | ||
3925 | |||
3926 | SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS | ||
3927 | P: Stephen Hemminger | ||
3928 | M: shemminger@linux-foundation.org | ||
3929 | L: netdev@vger.kernel.org | ||
3930 | S: Maintained | ||
3931 | |||
3932 | SOEKRIS NET48XX LED SUPPORT | ||
3933 | P: Chris Boot | ||
3934 | M: bootc@bootc.net | ||
3935 | S: Maintained | ||
3936 | |||
3937 | SPARC (sparc32): | ||
3938 | P: William L. Irwin | 3889 | P: William L. Irwin |
3939 | M: wli@holomorphy.com | 3890 | M: wli@holomorphy.com |
3940 | L: sparclinux@vger.kernel.org | 3891 | L: sparclinux@vger.kernel.org |
@@ -3946,6 +3897,12 @@ M: R.E.Wolff@BitWizard.nl | |||
3946 | L: linux-kernel@vger.kernel.org ? | 3897 | L: linux-kernel@vger.kernel.org ? |
3947 | S: Supported | 3898 | S: Supported |
3948 | 3899 | ||
3900 | SPI SUBSYSTEM | ||
3901 | P: David Brownell | ||
3902 | M: dbrownell@users.sourceforge.net | ||
3903 | L: spi-devel-general@lists.sourceforge.net | ||
3904 | S: Maintained | ||
3905 | |||
3949 | SPIDERNET NETWORK DRIVER for CELL | 3906 | SPIDERNET NETWORK DRIVER for CELL |
3950 | P: Ishizaki Kou | 3907 | P: Ishizaki Kou |
3951 | M: kou.ishizaki@toshiba.co.jp | 3908 | M: kou.ishizaki@toshiba.co.jp |
@@ -3954,12 +3911,28 @@ M: jens@de.ibm.com | |||
3954 | L: netdev@vger.kernel.org | 3911 | L: netdev@vger.kernel.org |
3955 | S: Supported | 3912 | S: Supported |
3956 | 3913 | ||
3914 | SPU FILE SYSTEM | ||
3915 | P: Jeremy Kerr | ||
3916 | M: jk@ozlabs.org | ||
3917 | L: linuxppc-dev@ozlabs.org | ||
3918 | L: cbe-oss-dev@ozlabs.org | ||
3919 | W: http://www.ibm.com/developerworks/power/cell/ | ||
3920 | S: Supported | ||
3921 | |||
3957 | SRM (Alpha) environment access | 3922 | SRM (Alpha) environment access |
3958 | P: Jan-Benedict Glaw | 3923 | P: Jan-Benedict Glaw |
3959 | M: jbglaw@lug-owl.de | 3924 | M: jbglaw@lug-owl.de |
3960 | L: linux-kernel@vger.kernel.org | 3925 | L: linux-kernel@vger.kernel.org |
3961 | S: Maintained | 3926 | S: Maintained |
3962 | 3927 | ||
3928 | STABLE BRANCH: | ||
3929 | P: Greg Kroah-Hartman | ||
3930 | M: greg@kroah.com | ||
3931 | P: Chris Wright | ||
3932 | M: chrisw@sous-sol.org | ||
3933 | L: stable@kernel.org | ||
3934 | S: Maintained | ||
3935 | |||
3963 | STARFIRE/DURALAN NETWORK DRIVER | 3936 | STARFIRE/DURALAN NETWORK DRIVER |
3964 | P: Ion Badulescu | 3937 | P: Ion Badulescu |
3965 | M: ionut@cs.columbia.edu | 3938 | M: ionut@cs.columbia.edu |
@@ -3975,6 +3948,12 @@ M: laredo@gnu.org | |||
3975 | W: http://www.stradis.com/ | 3948 | W: http://www.stradis.com/ |
3976 | S: Maintained | 3949 | S: Maintained |
3977 | 3950 | ||
3951 | SUN3/3X | ||
3952 | P: Sam Creasey | ||
3953 | M: sammy@sammy.net | ||
3954 | W: http://sammy.net/sun3/ | ||
3955 | S: Maintained | ||
3956 | |||
3978 | SUPERH | 3957 | SUPERH |
3979 | P: Paul Mundt | 3958 | P: Paul Mundt |
3980 | M: lethal@linux-sh.org | 3959 | M: lethal@linux-sh.org |
@@ -3983,11 +3962,15 @@ W: http://www.linux-sh.org | |||
3983 | T: git kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6.git | 3962 | T: git kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6.git |
3984 | S: Supported | 3963 | S: Supported |
3985 | 3964 | ||
3986 | SUN3/3X | 3965 | SUSPEND TO RAM |
3987 | P: Sam Creasey | 3966 | P: Len Brown |
3988 | M: sammy@sammy.net | 3967 | M: len.brown@intel.com |
3989 | W: http://sammy.net/sun3/ | 3968 | P: Pavel Machek |
3990 | S: Maintained | 3969 | M: pavel@suse.cz |
3970 | P: Rafael J. Wysocki | ||
3971 | M: rjw@sisk.pl | ||
3972 | L: linux-pm@lists.linux-foundation.org | ||
3973 | S: Supported | ||
3991 | 3974 | ||
3992 | SVGA HANDLING | 3975 | SVGA HANDLING |
3993 | P: Martin Mares | 3976 | P: Martin Mares |
@@ -4033,7 +4016,7 @@ P: Mark Gross | |||
4033 | M: mark.gross@intel.com | 4016 | M: mark.gross@intel.com |
4034 | S: Supported | 4017 | S: Supported |
4035 | 4018 | ||
4036 | TENSILICA XTENSA PORT (xtensa): | 4019 | TENSILICA XTENSA PORT (xtensa) |
4037 | P: Chris Zankel | 4020 | P: Chris Zankel |
4038 | M: chris@zankel.net | 4021 | M: chris@zankel.net |
4039 | S: Maintained | 4022 | S: Maintained |
@@ -4147,6 +4130,16 @@ M: ballabio_dario@emc.com | |||
4147 | L: linux-scsi@vger.kernel.org | 4130 | L: linux-scsi@vger.kernel.org |
4148 | S: Maintained | 4131 | S: Maintained |
4149 | 4132 | ||
4133 | UBI FILE SYSTEM (UBIFS) | ||
4134 | P: Artem Bityutskiy | ||
4135 | M: dedekind@infradead.org | ||
4136 | P: Adrian Hunter | ||
4137 | M: ext-adrian.hunter@nokia.com | ||
4138 | L: linux-mtd@lists.infradead.org | ||
4139 | T: git git://git.infradead.org/~dedekind/ubifs-2.6.git | ||
4140 | W: http://www.linux-mtd.infradead.org/doc/ubifs.html | ||
4141 | S: Maintained | ||
4142 | |||
4150 | UCLINUX (AND M68KNOMMU) | 4143 | UCLINUX (AND M68KNOMMU) |
4151 | P: Greg Ungerer | 4144 | P: Greg Ungerer |
4152 | M: gerg@uclinux.org | 4145 | M: gerg@uclinux.org |
@@ -4172,7 +4165,7 @@ M: dushistov@mail.ru | |||
4172 | L: linux-kernel@vger.kernel.org | 4165 | L: linux-kernel@vger.kernel.org |
4173 | S: Maintained | 4166 | S: Maintained |
4174 | 4167 | ||
4175 | UltraSPARC (sparc64): | 4168 | UltraSPARC (sparc64) |
4176 | P: David S. Miller | 4169 | P: David S. Miller |
4177 | M: davem@davemloft.net | 4170 | M: davem@davemloft.net |
4178 | L: sparclinux@vger.kernel.org | 4171 | L: sparclinux@vger.kernel.org |
@@ -4186,6 +4179,14 @@ L: linux-kernel@vger.kernel.org | |||
4186 | W: http://www.kernel.dk | 4179 | W: http://www.kernel.dk |
4187 | S: Maintained | 4180 | S: Maintained |
4188 | 4181 | ||
4182 | UNSORTED BLOCK IMAGES (UBI) | ||
4183 | P: Artem Bityutskiy | ||
4184 | M: dedekind@infradead.org | ||
4185 | W: http://www.linux-mtd.infradead.org/ | ||
4186 | L: linux-mtd@lists.infradead.org | ||
4187 | T: git git://git.infradead.org/~dedekind/ubi-2.6.git | ||
4188 | S: Maintained | ||
4189 | |||
4189 | USB ACM DRIVER | 4190 | USB ACM DRIVER |
4190 | P: Oliver Neukum | 4191 | P: Oliver Neukum |
4191 | M: oliver@neukum.name | 4192 | M: oliver@neukum.name |
@@ -4455,7 +4456,7 @@ L: video4linux-list@redhat.com | |||
4455 | W: http://royale.zerezo.com/zr364xx/ | 4456 | W: http://royale.zerezo.com/zr364xx/ |
4456 | S: Maintained | 4457 | S: Maintained |
4457 | 4458 | ||
4458 | USER-MODE LINUX | 4459 | USER-MODE LINUX (UML) |
4459 | P: Jeff Dike | 4460 | P: Jeff Dike |
4460 | M: jdike@addtoit.com | 4461 | M: jdike@addtoit.com |
4461 | L: user-mode-linux-devel@lists.sourceforge.net | 4462 | L: user-mode-linux-devel@lists.sourceforge.net |
@@ -4479,7 +4480,7 @@ W: http://kernel.org/~kzak/util-linux-ng/ | |||
4479 | T: git://git.kernel.org/pub/scm/utils/util-linux-ng/util-linux-ng.git | 4480 | T: git://git.kernel.org/pub/scm/utils/util-linux-ng/util-linux-ng.git |
4480 | S: Maintained | 4481 | S: Maintained |
4481 | 4482 | ||
4482 | VFAT/FAT/MSDOS FILESYSTEM: | 4483 | VFAT/FAT/MSDOS FILESYSTEM |
4483 | P: OGAWA Hirofumi | 4484 | P: OGAWA Hirofumi |
4484 | M: hirofumi@mail.parknet.co.jp | 4485 | M: hirofumi@mail.parknet.co.jp |
4485 | L: linux-kernel@vger.kernel.org | 4486 | L: linux-kernel@vger.kernel.org |
@@ -4502,7 +4503,7 @@ M: romieu@fr.zoreil.com | |||
4502 | L: netdev@vger.kernel.org | 4503 | L: netdev@vger.kernel.org |
4503 | S: Maintained | 4504 | S: Maintained |
4504 | 4505 | ||
4505 | VIDEO FOR LINUX | 4506 | VIDEO FOR LINUX (V4L) |
4506 | P: Mauro Carvalho Chehab | 4507 | P: Mauro Carvalho Chehab |
4507 | M: mchehab@infradead.org | 4508 | M: mchehab@infradead.org |
4508 | M: v4l-dvb-maintainer@linuxtv.org | 4509 | M: v4l-dvb-maintainer@linuxtv.org |
@@ -4608,6 +4609,17 @@ M: eis@baty.hanse.de | |||
4608 | L: linux-x25@vger.kernel.org | 4609 | L: linux-x25@vger.kernel.org |
4609 | S: Maintained | 4610 | S: Maintained |
4610 | 4611 | ||
4612 | X86 ARCHITECTURE (32-BIT AND 64-BIT) | ||
4613 | P: Thomas Gleixner | ||
4614 | M: tglx@linutronix.de | ||
4615 | P: Ingo Molnar | ||
4616 | M: mingo@redhat.com | ||
4617 | P: H. Peter Anvin | ||
4618 | M: hpa@zytor.com | ||
4619 | L: linux-kernel@vger.kernel.org | ||
4620 | T: git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git | ||
4621 | S: Maintained | ||
4622 | |||
4611 | XEN HYPERVISOR INTERFACE | 4623 | XEN HYPERVISOR INTERFACE |
4612 | P: Jeremy Fitzhardinge | 4624 | P: Jeremy Fitzhardinge |
4613 | M: jeremy@xensource.com | 4625 | M: jeremy@xensource.com |
@@ -4639,17 +4651,6 @@ M: jacmet@sunsite.dk | |||
4639 | L: linux-serial@vger.kernel.org | 4651 | L: linux-serial@vger.kernel.org |
4640 | S: Maintained | 4652 | S: Maintained |
4641 | 4653 | ||
4642 | X86 ARCHITECTURE (32-BIT AND 64-BIT) | ||
4643 | P: Thomas Gleixner | ||
4644 | M: tglx@linutronix.de | ||
4645 | P: Ingo Molnar | ||
4646 | M: mingo@redhat.com | ||
4647 | P: H. Peter Anvin | ||
4648 | M: hpa@zytor.com | ||
4649 | L: linux-kernel@vger.kernel.org | ||
4650 | T: git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git | ||
4651 | S: Maintained | ||
4652 | |||
4653 | YAM DRIVER FOR AX.25 | 4654 | YAM DRIVER FOR AX.25 |
4654 | P: Jean-Paul Roubelat | 4655 | P: Jean-Paul Roubelat |
4655 | M: jpr@f6fbb.org | 4656 | M: jpr@f6fbb.org |
diff --git a/arch/Kconfig b/arch/Kconfig index 364c6dadde0a..0267babe5eb9 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
@@ -13,6 +13,20 @@ config OPROFILE | |||
13 | 13 | ||
14 | If unsure, say N. | 14 | If unsure, say N. |
15 | 15 | ||
16 | config OPROFILE_IBS | ||
17 | bool "OProfile AMD IBS support (EXPERIMENTAL)" | ||
18 | default n | ||
19 | depends on OPROFILE && SMP && X86 | ||
20 | help | ||
21 | Instruction-Based Sampling (IBS) is a new profiling | ||
22 | technique that provides rich, precise program performance | ||
23 | information. IBS is introduced by AMD Family10h processors | ||
24 | (AMD Opteron Quad-Core processor “Barcelona”) to overcome | ||
25 | the limitations of conventional performance counter | ||
26 | sampling. | ||
27 | |||
28 | If unsure, say N. | ||
29 | |||
16 | config HAVE_OPROFILE | 30 | config HAVE_OPROFILE |
17 | def_bool n | 31 | def_bool n |
18 | 32 | ||
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 1bec55d63ef6..ee35226c44e9 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig | |||
@@ -5,6 +5,7 @@ | |||
5 | config ALPHA | 5 | config ALPHA |
6 | bool | 6 | bool |
7 | default y | 7 | default y |
8 | select HAVE_AOUT | ||
8 | select HAVE_IDE | 9 | select HAVE_IDE |
9 | select HAVE_OPROFILE | 10 | select HAVE_OPROFILE |
10 | help | 11 | help |
@@ -68,9 +69,6 @@ config AUTO_IRQ_AFFINITY | |||
68 | depends on SMP | 69 | depends on SMP |
69 | default y | 70 | default y |
70 | 71 | ||
71 | config ARCH_SUPPORTS_AOUT | ||
72 | def_bool y | ||
73 | |||
74 | source "init/Kconfig" | 72 | source "init/Kconfig" |
75 | 73 | ||
76 | 74 | ||
diff --git a/arch/alpha/include/asm/statfs.h b/arch/alpha/include/asm/statfs.h index ad15830baefe..de35cd438a10 100644 --- a/arch/alpha/include/asm/statfs.h +++ b/arch/alpha/include/asm/statfs.h | |||
@@ -1,6 +1,10 @@ | |||
1 | #ifndef _ALPHA_STATFS_H | 1 | #ifndef _ALPHA_STATFS_H |
2 | #define _ALPHA_STATFS_H | 2 | #define _ALPHA_STATFS_H |
3 | 3 | ||
4 | /* Alpha is the only 64-bit platform with 32-bit statfs. And doesn't | ||
5 | even seem to implement statfs64 */ | ||
6 | #define __statfs_word __u32 | ||
7 | |||
4 | #include <asm-generic/statfs.h> | 8 | #include <asm-generic/statfs.h> |
5 | 9 | ||
6 | #endif | 10 | #endif |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index efeed65b4a66..4853f9df37bd 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -8,6 +8,7 @@ mainmenu "Linux Kernel Configuration" | |||
8 | config ARM | 8 | config ARM |
9 | bool | 9 | bool |
10 | default y | 10 | default y |
11 | select HAVE_AOUT | ||
11 | select HAVE_IDE | 12 | select HAVE_IDE |
12 | select RTC_LIB | 13 | select RTC_LIB |
13 | select SYS_SUPPORTS_APM_EMULATION | 14 | select SYS_SUPPORTS_APM_EMULATION |
@@ -140,9 +141,6 @@ config GENERIC_CALIBRATE_DELAY | |||
140 | bool | 141 | bool |
141 | default y | 142 | default y |
142 | 143 | ||
143 | config ARCH_SUPPORTS_AOUT | ||
144 | def_bool y | ||
145 | |||
146 | config ARCH_MAY_HAVE_PC_FDC | 144 | config ARCH_MAY_HAVE_PC_FDC |
147 | bool | 145 | bool |
148 | 146 | ||
diff --git a/arch/arm/include/asm/statfs.h b/arch/arm/include/asm/statfs.h index a02e6a8c3d70..079447c05ba7 100644 --- a/arch/arm/include/asm/statfs.h +++ b/arch/arm/include/asm/statfs.h | |||
@@ -1,42 +1,12 @@ | |||
1 | #ifndef _ASMARM_STATFS_H | 1 | #ifndef _ASMARM_STATFS_H |
2 | #define _ASMARM_STATFS_H | 2 | #define _ASMARM_STATFS_H |
3 | 3 | ||
4 | #ifndef __KERNEL_STRICT_NAMES | ||
5 | # include <linux/types.h> | ||
6 | typedef __kernel_fsid_t fsid_t; | ||
7 | #endif | ||
8 | |||
9 | struct statfs { | ||
10 | __u32 f_type; | ||
11 | __u32 f_bsize; | ||
12 | __u32 f_blocks; | ||
13 | __u32 f_bfree; | ||
14 | __u32 f_bavail; | ||
15 | __u32 f_files; | ||
16 | __u32 f_ffree; | ||
17 | __kernel_fsid_t f_fsid; | ||
18 | __u32 f_namelen; | ||
19 | __u32 f_frsize; | ||
20 | __u32 f_spare[5]; | ||
21 | }; | ||
22 | |||
23 | /* | 4 | /* |
24 | * With EABI there is 4 bytes of padding added to this structure. | 5 | * With EABI there is 4 bytes of padding added to this structure. |
25 | * Let's pack it so the padding goes away to simplify dual ABI support. | 6 | * Let's pack it so the padding goes away to simplify dual ABI support. |
26 | * Note that user space does NOT have to pack this structure. | 7 | * Note that user space does NOT have to pack this structure. |
27 | */ | 8 | */ |
28 | struct statfs64 { | 9 | #define ARCH_PACK_STATFS64 __attribute__((packed,aligned(4))) |
29 | __u32 f_type; | ||
30 | __u32 f_bsize; | ||
31 | __u64 f_blocks; | ||
32 | __u64 f_bfree; | ||
33 | __u64 f_bavail; | ||
34 | __u64 f_files; | ||
35 | __u64 f_ffree; | ||
36 | __kernel_fsid_t f_fsid; | ||
37 | __u32 f_namelen; | ||
38 | __u32 f_frsize; | ||
39 | __u32 f_spare[5]; | ||
40 | } __attribute__ ((packed,aligned(4))); | ||
41 | 10 | ||
11 | #include <asm-generic/statfs.h> | ||
42 | #endif | 12 | #endif |
diff --git a/arch/avr32/include/asm/a.out.h b/arch/avr32/include/asm/a.out.h deleted file mode 100644 index e46375a34a72..000000000000 --- a/arch/avr32/include/asm/a.out.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | #ifndef __ASM_AVR32_A_OUT_H | ||
2 | #define __ASM_AVR32_A_OUT_H | ||
3 | |||
4 | struct exec | ||
5 | { | ||
6 | unsigned long a_info; /* Use macros N_MAGIC, etc for access */ | ||
7 | unsigned a_text; /* length of text, in bytes */ | ||
8 | unsigned a_data; /* length of data, in bytes */ | ||
9 | unsigned a_bss; /* length of uninitialized data area for file, in bytes */ | ||
10 | unsigned a_syms; /* length of symbol table data in file, in bytes */ | ||
11 | unsigned a_entry; /* start address */ | ||
12 | unsigned a_trsize; /* length of relocation info for text, in bytes */ | ||
13 | unsigned a_drsize; /* length of relocation info for data, in bytes */ | ||
14 | }; | ||
15 | |||
16 | #define N_TRSIZE(a) ((a).a_trsize) | ||
17 | #define N_DRSIZE(a) ((a).a_drsize) | ||
18 | #define N_SYMSIZE(a) ((a).a_syms) | ||
19 | |||
20 | #endif /* __ASM_AVR32_A_OUT_H */ | ||
diff --git a/arch/blackfin/include/asm/a.out.h b/arch/blackfin/include/asm/a.out.h deleted file mode 100644 index 6c3d652ebd33..000000000000 --- a/arch/blackfin/include/asm/a.out.h +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | #ifndef __BFIN_A_OUT_H__ | ||
2 | #define __BFIN_A_OUT_H__ | ||
3 | |||
4 | struct exec { | ||
5 | unsigned long a_info; /* Use macros N_MAGIC, etc for access */ | ||
6 | unsigned a_text; /* length of text, in bytes */ | ||
7 | unsigned a_data; /* length of data, in bytes */ | ||
8 | unsigned a_bss; /* length of uninitialized data area for file, in bytes */ | ||
9 | unsigned a_syms; /* length of symbol table data in file, in bytes */ | ||
10 | unsigned a_entry; /* start address */ | ||
11 | unsigned a_trsize; /* length of relocation info for text, in bytes */ | ||
12 | unsigned a_drsize; /* length of relocation info for data, in bytes */ | ||
13 | }; | ||
14 | |||
15 | #define N_TRSIZE(a) ((a).a_trsize) | ||
16 | #define N_DRSIZE(a) ((a).a_drsize) | ||
17 | #define N_SYMSIZE(a) ((a).a_syms) | ||
18 | |||
19 | #endif /* __BFIN_A_OUT_H__ */ | ||
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 93229b3d6e3e..339293d677cc 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c | |||
@@ -117,15 +117,14 @@ int request_dma(unsigned int channel, char *device_id) | |||
117 | 117 | ||
118 | #ifdef CONFIG_BF54x | 118 | #ifdef CONFIG_BF54x |
119 | if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) { | 119 | if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) { |
120 | if (strncmp(device_id, "BFIN_UART", 9) == 0) { | 120 | unsigned int per_map; |
121 | dma_ch[channel].regs->peripheral_map &= 0x0FFF; | 121 | per_map = dma_ch[channel].regs->peripheral_map & 0xFFF; |
122 | dma_ch[channel].regs->peripheral_map |= | 122 | if (strncmp(device_id, "BFIN_UART", 9) == 0) |
123 | dma_ch[channel].regs->peripheral_map = per_map | | ||
123 | ((channel - CH_UART2_RX + 0xC)<<12); | 124 | ((channel - CH_UART2_RX + 0xC)<<12); |
124 | } else { | 125 | else |
125 | dma_ch[channel].regs->peripheral_map &= 0x0FFF; | 126 | dma_ch[channel].regs->peripheral_map = per_map | |
126 | dma_ch[channel].regs->peripheral_map |= | ||
127 | ((channel - CH_UART2_RX + 0x6)<<12); | 127 | ((channel - CH_UART2_RX + 0x6)<<12); |
128 | } | ||
129 | } | 128 | } |
130 | #endif | 129 | #endif |
131 | 130 | ||
diff --git a/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h index 2526b6ed6faa..75722d6008b0 100644 --- a/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h +++ b/arch/blackfin/mach-bf527/include/mach/bfin_serial_5xx.h | |||
@@ -78,6 +78,9 @@ | |||
78 | # define CONFIG_UART1_RTS_PIN -1 | 78 | # define CONFIG_UART1_RTS_PIN -1 |
79 | # endif | 79 | # endif |
80 | #endif | 80 | #endif |
81 | |||
82 | #define BFIN_UART_TX_FIFO_SIZE 2 | ||
83 | |||
81 | /* | 84 | /* |
82 | * The pin configuration is different from schematic | 85 | * The pin configuration is different from schematic |
83 | */ | 86 | */ |
@@ -119,7 +122,6 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart) | |||
119 | bfin_write16(uart->port.membase + OFFSET_LSR, -1); | 122 | bfin_write16(uart->port.membase + OFFSET_LSR, -1); |
120 | } | 123 | } |
121 | 124 | ||
122 | struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS]; | ||
123 | struct bfin_serial_res { | 125 | struct bfin_serial_res { |
124 | unsigned long uart_base_addr; | 126 | unsigned long uart_base_addr; |
125 | int uart_irq; | 127 | int uart_irq; |
@@ -164,8 +166,6 @@ struct bfin_serial_res bfin_serial_resource[] = { | |||
164 | #endif | 166 | #endif |
165 | }; | 167 | }; |
166 | 168 | ||
167 | int nr_ports = ARRAY_SIZE(bfin_serial_resource); | ||
168 | |||
169 | #define DRIVER_NAME "bfin-uart" | 169 | #define DRIVER_NAME "bfin-uart" |
170 | 170 | ||
171 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) | 171 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) |
diff --git a/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h index ebf592b59aab..815bfe5dd1a9 100644 --- a/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h +++ b/arch/blackfin/mach-bf533/include/mach/bfin_serial_5xx.h | |||
@@ -69,6 +69,8 @@ | |||
69 | # endif | 69 | # endif |
70 | #endif | 70 | #endif |
71 | 71 | ||
72 | #define BFIN_UART_TX_FIFO_SIZE 2 | ||
73 | |||
72 | struct bfin_serial_port { | 74 | struct bfin_serial_port { |
73 | struct uart_port port; | 75 | struct uart_port port; |
74 | unsigned int old_status; | 76 | unsigned int old_status; |
@@ -111,7 +113,6 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart) | |||
111 | bfin_write16(uart->port.membase + OFFSET_LSR, -1); | 113 | bfin_write16(uart->port.membase + OFFSET_LSR, -1); |
112 | } | 114 | } |
113 | 115 | ||
114 | struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS]; | ||
115 | struct bfin_serial_res { | 116 | struct bfin_serial_res { |
116 | unsigned long uart_base_addr; | 117 | unsigned long uart_base_addr; |
117 | int uart_irq; | 118 | int uart_irq; |
@@ -142,7 +143,6 @@ struct bfin_serial_res bfin_serial_resource[] = { | |||
142 | 143 | ||
143 | #define DRIVER_NAME "bfin-uart" | 144 | #define DRIVER_NAME "bfin-uart" |
144 | 145 | ||
145 | int nr_ports = BFIN_UART_NR_PORTS; | ||
146 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) | 146 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) |
147 | { | 147 | { |
148 | 148 | ||
diff --git a/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h index 1bf56ffa22f9..b3f87e1d16a2 100644 --- a/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h +++ b/arch/blackfin/mach-bf537/include/mach/bfin_serial_5xx.h | |||
@@ -78,6 +78,9 @@ | |||
78 | # define CONFIG_UART1_RTS_PIN -1 | 78 | # define CONFIG_UART1_RTS_PIN -1 |
79 | # endif | 79 | # endif |
80 | #endif | 80 | #endif |
81 | |||
82 | #define BFIN_UART_TX_FIFO_SIZE 2 | ||
83 | |||
81 | /* | 84 | /* |
82 | * The pin configuration is different from schematic | 85 | * The pin configuration is different from schematic |
83 | */ | 86 | */ |
@@ -119,7 +122,6 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart) | |||
119 | bfin_write16(uart->port.membase + OFFSET_LSR, -1); | 122 | bfin_write16(uart->port.membase + OFFSET_LSR, -1); |
120 | } | 123 | } |
121 | 124 | ||
122 | struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS]; | ||
123 | struct bfin_serial_res { | 125 | struct bfin_serial_res { |
124 | unsigned long uart_base_addr; | 126 | unsigned long uart_base_addr; |
125 | int uart_irq; | 127 | int uart_irq; |
@@ -164,8 +166,6 @@ struct bfin_serial_res bfin_serial_resource[] = { | |||
164 | #endif | 166 | #endif |
165 | }; | 167 | }; |
166 | 168 | ||
167 | int nr_ports = ARRAY_SIZE(bfin_serial_resource); | ||
168 | |||
169 | #define DRIVER_NAME "bfin-uart" | 169 | #define DRIVER_NAME "bfin-uart" |
170 | 170 | ||
171 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) | 171 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) |
diff --git a/arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h index 5e29446a8e03..e4cf35e7ab9f 100644 --- a/arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h +++ b/arch/blackfin/mach-bf548/include/mach/bfin_serial_5xx.h | |||
@@ -82,6 +82,9 @@ | |||
82 | # define CONFIG_UART1_RTS_PIN -1 | 82 | # define CONFIG_UART1_RTS_PIN -1 |
83 | # endif | 83 | # endif |
84 | #endif | 84 | #endif |
85 | |||
86 | #define BFIN_UART_TX_FIFO_SIZE 2 | ||
87 | |||
85 | /* | 88 | /* |
86 | * The pin configuration is different from schematic | 89 | * The pin configuration is different from schematic |
87 | */ | 90 | */ |
@@ -105,7 +108,6 @@ struct bfin_serial_port { | |||
105 | #endif | 108 | #endif |
106 | }; | 109 | }; |
107 | 110 | ||
108 | struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS]; | ||
109 | struct bfin_serial_res { | 111 | struct bfin_serial_res { |
110 | unsigned long uart_base_addr; | 112 | unsigned long uart_base_addr; |
111 | int uart_irq; | 113 | int uart_irq; |
@@ -170,8 +172,6 @@ struct bfin_serial_res bfin_serial_resource[] = { | |||
170 | #endif | 172 | #endif |
171 | }; | 173 | }; |
172 | 174 | ||
173 | int nr_ports = ARRAY_SIZE(bfin_serial_resource); | ||
174 | |||
175 | #define DRIVER_NAME "bfin-uart" | 175 | #define DRIVER_NAME "bfin-uart" |
176 | 176 | ||
177 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) | 177 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) |
diff --git a/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h b/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h index 8aa02780e642..e0ce0c1843d4 100644 --- a/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h +++ b/arch/blackfin/mach-bf561/include/mach/bfin_serial_5xx.h | |||
@@ -69,6 +69,8 @@ | |||
69 | # endif | 69 | # endif |
70 | #endif | 70 | #endif |
71 | 71 | ||
72 | #define BFIN_UART_TX_FIFO_SIZE 2 | ||
73 | |||
72 | struct bfin_serial_port { | 74 | struct bfin_serial_port { |
73 | struct uart_port port; | 75 | struct uart_port port; |
74 | unsigned int old_status; | 76 | unsigned int old_status; |
@@ -111,7 +113,6 @@ static inline void UART_CLEAR_LSR(struct bfin_serial_port *uart) | |||
111 | bfin_write16(uart->port.membase + OFFSET_LSR, -1); | 113 | bfin_write16(uart->port.membase + OFFSET_LSR, -1); |
112 | } | 114 | } |
113 | 115 | ||
114 | struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS]; | ||
115 | struct bfin_serial_res { | 116 | struct bfin_serial_res { |
116 | unsigned long uart_base_addr; | 117 | unsigned long uart_base_addr; |
117 | int uart_irq; | 118 | int uart_irq; |
@@ -142,7 +143,6 @@ struct bfin_serial_res bfin_serial_resource[] = { | |||
142 | 143 | ||
143 | #define DRIVER_NAME "bfin-uart" | 144 | #define DRIVER_NAME "bfin-uart" |
144 | 145 | ||
145 | int nr_ports = BFIN_UART_NR_PORTS; | ||
146 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) | 146 | static void bfin_serial_hw_init(struct bfin_serial_port *uart) |
147 | { | 147 | { |
148 | 148 | ||
diff --git a/arch/cris/arch-v10/boot/tools/build.c b/arch/cris/arch-v10/boot/tools/build.c index 2f9bbb26d603..c8adef364160 100644 --- a/arch/cris/arch-v10/boot/tools/build.c +++ b/arch/cris/arch-v10/boot/tools/build.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <sys/sysmacros.h> | 30 | #include <sys/sysmacros.h> |
31 | #include <unistd.h> /* contains read/write */ | 31 | #include <unistd.h> /* contains read/write */ |
32 | #include <fcntl.h> | 32 | #include <fcntl.h> |
33 | #include <linux/a.out.h> | ||
34 | #include <errno.h> | 33 | #include <errno.h> |
35 | 34 | ||
36 | #define MINIX_HEADER 32 | 35 | #define MINIX_HEADER 32 |
diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig index 396ab059efa3..107cb5bb9f39 100644 --- a/arch/h8300/Kconfig +++ b/arch/h8300/Kconfig | |||
@@ -66,9 +66,6 @@ config TIME_LOW_RES | |||
66 | bool | 66 | bool |
67 | default y | 67 | default y |
68 | 68 | ||
69 | config ARCH_SUPPORTS_AOUT | ||
70 | def_bool y | ||
71 | |||
72 | config NO_IOPORT | 69 | config NO_IOPORT |
73 | def_bool y | 70 | def_bool y |
74 | 71 | ||
diff --git a/arch/h8300/include/asm/a.out.h b/arch/h8300/include/asm/a.out.h deleted file mode 100644 index ded780f0a492..000000000000 --- a/arch/h8300/include/asm/a.out.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | #ifndef __H8300_A_OUT_H__ | ||
2 | #define __H8300_A_OUT_H__ | ||
3 | |||
4 | struct exec | ||
5 | { | ||
6 | unsigned long a_info; /* Use macros N_MAGIC, etc for access */ | ||
7 | unsigned a_text; /* length of text, in bytes */ | ||
8 | unsigned a_data; /* length of data, in bytes */ | ||
9 | unsigned a_bss; /* length of uninitialized data area for file, in bytes */ | ||
10 | unsigned a_syms; /* length of symbol table data in file, in bytes */ | ||
11 | unsigned a_entry; /* start address */ | ||
12 | unsigned a_trsize; /* length of relocation info for text, in bytes */ | ||
13 | unsigned a_drsize; /* length of relocation info for data, in bytes */ | ||
14 | }; | ||
15 | |||
16 | #define N_TRSIZE(a) ((a).a_trsize) | ||
17 | #define N_DRSIZE(a) ((a).a_drsize) | ||
18 | #define N_SYMSIZE(a) ((a).a_syms) | ||
19 | |||
20 | #endif /* __H8300_A_OUT_H__ */ | ||
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index dfbe7ab9ffe2..a8ef654a5a0b 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/ptrace.h> | 34 | #include <linux/ptrace.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/user.h> | 36 | #include <linux/user.h> |
37 | #include <linux/a.out.h> | ||
38 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
39 | #include <linux/reboot.h> | 38 | #include <linux/reboot.h> |
40 | #include <linux/fs.h> | 39 | #include <linux/fs.h> |
diff --git a/arch/ia64/include/asm/a.out.h b/arch/ia64/include/asm/a.out.h deleted file mode 100644 index 193dcfb67596..000000000000 --- a/arch/ia64/include/asm/a.out.h +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | #ifndef _ASM_IA64_A_OUT_H | ||
2 | #define _ASM_IA64_A_OUT_H | ||
3 | |||
4 | /* | ||
5 | * No a.out format has been (or should be) defined so this file is | ||
6 | * just a dummy that allows us to get binfmt_elf compiled. It | ||
7 | * probably would be better to clean up binfmt_elf.c so it does not | ||
8 | * necessarily depend on there being a.out support. | ||
9 | * | ||
10 | * Modified 1998-2002 | ||
11 | * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co. | ||
12 | */ | ||
13 | |||
14 | #include <linux/types.h> | ||
15 | |||
16 | struct exec { | ||
17 | unsigned long a_info; | ||
18 | unsigned long a_text; | ||
19 | unsigned long a_data; | ||
20 | unsigned long a_bss; | ||
21 | unsigned long a_entry; | ||
22 | }; | ||
23 | |||
24 | #define N_TXTADDR(x) 0 | ||
25 | #define N_DATADDR(x) 0 | ||
26 | #define N_BSSADDR(x) 0 | ||
27 | #define N_DRSIZE(x) 0 | ||
28 | #define N_TRSIZE(x) 0 | ||
29 | #define N_SYMSIZE(x) 0 | ||
30 | #define N_TXTOFF(x) 0 | ||
31 | |||
32 | #endif /* _ASM_IA64_A_OUT_H */ | ||
diff --git a/arch/ia64/include/asm/statfs.h b/arch/ia64/include/asm/statfs.h index 811097974f31..1e589669de56 100644 --- a/arch/ia64/include/asm/statfs.h +++ b/arch/ia64/include/asm/statfs.h | |||
@@ -8,55 +8,13 @@ | |||
8 | * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co | 8 | * David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #ifndef __KERNEL_STRICT_NAMES | ||
12 | # include <linux/types.h> | ||
13 | typedef __kernel_fsid_t fsid_t; | ||
14 | #endif | ||
15 | |||
16 | /* | 11 | /* |
17 | * This is ugly --- we're already 64-bit, so just duplicate the definitions | 12 | * We need compat_statfs64 to be packed, because the i386 ABI won't |
13 | * add padding at the end to bring it to a multiple of 8 bytes, but | ||
14 | * the IA64 ABI will. | ||
18 | */ | 15 | */ |
19 | struct statfs { | 16 | #define ARCH_PACK_COMPAT_STATFS64 __attribute__((packed,aligned(4))) |
20 | long f_type; | ||
21 | long f_bsize; | ||
22 | long f_blocks; | ||
23 | long f_bfree; | ||
24 | long f_bavail; | ||
25 | long f_files; | ||
26 | long f_ffree; | ||
27 | __kernel_fsid_t f_fsid; | ||
28 | long f_namelen; | ||
29 | long f_frsize; | ||
30 | long f_spare[5]; | ||
31 | }; | ||
32 | |||
33 | |||
34 | struct statfs64 { | ||
35 | long f_type; | ||
36 | long f_bsize; | ||
37 | long f_blocks; | ||
38 | long f_bfree; | ||
39 | long f_bavail; | ||
40 | long f_files; | ||
41 | long f_ffree; | ||
42 | __kernel_fsid_t f_fsid; | ||
43 | long f_namelen; | ||
44 | long f_frsize; | ||
45 | long f_spare[5]; | ||
46 | }; | ||
47 | 17 | ||
48 | struct compat_statfs64 { | 18 | #include <asm-generic/statfs.h> |
49 | __u32 f_type; | ||
50 | __u32 f_bsize; | ||
51 | __u64 f_blocks; | ||
52 | __u64 f_bfree; | ||
53 | __u64 f_bavail; | ||
54 | __u64 f_files; | ||
55 | __u64 f_ffree; | ||
56 | __kernel_fsid_t f_fsid; | ||
57 | __u32 f_namelen; | ||
58 | __u32 f_frsize; | ||
59 | __u32 f_spare[5]; | ||
60 | } __attribute__((packed)); | ||
61 | 19 | ||
62 | #endif /* _ASM_IA64_STATFS_H */ | 20 | #endif /* _ASM_IA64_STATFS_H */ |
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 200100ea7610..f482a9098e32 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
22 | #include <linux/kexec.h> | 22 | #include <linux/kexec.h> |
23 | 23 | ||
24 | #include <asm/a.out.h> | ||
25 | #include <asm/dma.h> | 24 | #include <asm/dma.h> |
26 | #include <asm/ia32.h> | 25 | #include <asm/ia32.h> |
27 | #include <asm/io.h> | 26 | #include <asm/io.h> |
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig index f57113f1f892..00289c178f89 100644 --- a/arch/m32r/Kconfig +++ b/arch/m32r/Kconfig | |||
@@ -36,9 +36,6 @@ config NO_IOPORT | |||
36 | config NO_DMA | 36 | config NO_DMA |
37 | def_bool y | 37 | def_bool y |
38 | 38 | ||
39 | config ARCH_SUPPORTS_AOUT | ||
40 | def_bool y | ||
41 | |||
42 | config HZ | 39 | config HZ |
43 | int | 40 | int |
44 | default 100 | 41 | default 100 |
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig index 8c5e1de68fcb..41e5bf02e230 100644 --- a/arch/m68k/Kconfig +++ b/arch/m68k/Kconfig | |||
@@ -5,6 +5,7 @@ | |||
5 | config M68K | 5 | config M68K |
6 | bool | 6 | bool |
7 | default y | 7 | default y |
8 | select HAVE_AOUT | ||
8 | select HAVE_IDE | 9 | select HAVE_IDE |
9 | 10 | ||
10 | config MMU | 11 | config MMU |
@@ -53,9 +54,6 @@ config NO_IOPORT | |||
53 | config NO_DMA | 54 | config NO_DMA |
54 | def_bool SUN3 | 55 | def_bool SUN3 |
55 | 56 | ||
56 | config ARCH_SUPPORTS_AOUT | ||
57 | def_bool y | ||
58 | |||
59 | config HZ | 57 | config HZ |
60 | int | 58 | int |
61 | default 100 | 59 | default 100 |
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index 2e7515e8db98..0a8998315e5e 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig | |||
@@ -73,9 +73,6 @@ config GENERIC_CLOCKEVENTS | |||
73 | config NO_IOPORT | 73 | config NO_IOPORT |
74 | def_bool y | 74 | def_bool y |
75 | 75 | ||
76 | config ARCH_SUPPORTS_AOUT | ||
77 | def_bool y | ||
78 | |||
79 | source "init/Kconfig" | 76 | source "init/Kconfig" |
80 | 77 | ||
81 | menu "Processor type and features" | 78 | menu "Processor type and features" |
diff --git a/arch/m68knommu/include/asm/a.out.h b/arch/m68knommu/include/asm/a.out.h deleted file mode 100644 index ce18ef99de04..000000000000 --- a/arch/m68knommu/include/asm/a.out.h +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | #include <asm-m68k/a.out.h> | ||
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c index 47502d5ec19f..3f2d7745f31e 100644 --- a/arch/m68knommu/kernel/process.c +++ b/arch/m68knommu/kernel/process.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/ptrace.h> | 25 | #include <linux/ptrace.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/user.h> | 27 | #include <linux/user.h> |
28 | #include <linux/a.out.h> | ||
29 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
30 | #include <linux/reboot.h> | 29 | #include <linux/reboot.h> |
31 | #include <linux/fs.h> | 30 | #include <linux/fs.h> |
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c index 46f8f9d0c408..5d5d56bcd0ef 100644 --- a/arch/m68knommu/kernel/traps.c +++ b/arch/m68knommu/kernel/traps.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
25 | #include <linux/a.out.h> | ||
26 | #include <linux/user.h> | 25 | #include <linux/user.h> |
27 | #include <linux/string.h> | 26 | #include <linux/string.h> |
28 | #include <linux/linkage.h> | 27 | #include <linux/linkage.h> |
diff --git a/arch/mips/include/asm/a.out.h b/arch/mips/include/asm/a.out.h deleted file mode 100644 index cad8371422ab..000000000000 --- a/arch/mips/include/asm/a.out.h +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 1994 - 1999, 2003 by Ralf Baechle | ||
7 | */ | ||
8 | #ifndef _ASM_A_OUT_H | ||
9 | #define _ASM_A_OUT_H | ||
10 | |||
11 | #ifdef __KERNEL__ | ||
12 | |||
13 | |||
14 | #endif | ||
15 | |||
16 | struct exec | ||
17 | { | ||
18 | unsigned long a_info; /* Use macros N_MAGIC, etc for access */ | ||
19 | unsigned a_text; /* length of text, in bytes */ | ||
20 | unsigned a_data; /* length of data, in bytes */ | ||
21 | unsigned a_bss; /* length of uninitialized data area for | ||
22 | file, in bytes */ | ||
23 | unsigned a_syms; /* length of symbol table data in file, | ||
24 | in bytes */ | ||
25 | unsigned a_entry; /* start address */ | ||
26 | unsigned a_trsize; /* length of relocation info for text, in | ||
27 | bytes */ | ||
28 | unsigned a_drsize; /* length of relocation info for data, in bytes */ | ||
29 | }; | ||
30 | |||
31 | #define N_TRSIZE(a) ((a).a_trsize) | ||
32 | #define N_DRSIZE(a) ((a).a_drsize) | ||
33 | #define N_SYMSIZE(a) ((a).a_syms) | ||
34 | |||
35 | #endif /* _ASM_A_OUT_H */ | ||
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 22fc19bbe87f..ca2e4026ad20 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/personality.h> | 22 | #include <linux/personality.h> |
23 | #include <linux/sys.h> | 23 | #include <linux/sys.h> |
24 | #include <linux/user.h> | 24 | #include <linux/user.h> |
25 | #include <linux/a.out.h> | ||
26 | #include <linux/init.h> | 25 | #include <linux/init.h> |
27 | #include <linux/completion.h> | 26 | #include <linux/completion.h> |
28 | #include <linux/kallsyms.h> | 27 | #include <linux/kallsyms.h> |
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 343015a2f418..37970d9b2186 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | 7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. |
8 | * Copyright (C) 2001 MIPS Technologies, Inc. | 8 | * Copyright (C) 2001 MIPS Technologies, Inc. |
9 | */ | 9 | */ |
10 | #include <linux/a.out.h> | ||
11 | #include <linux/capability.h> | 10 | #include <linux/capability.h> |
12 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
13 | #include <linux/linkage.h> | 12 | #include <linux/linkage.h> |
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index e856218da90d..dd557c9cf001 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig | |||
@@ -53,9 +53,6 @@ config QUICKLIST | |||
53 | config ARCH_HAS_ILOG2_U32 | 53 | config ARCH_HAS_ILOG2_U32 |
54 | def_bool y | 54 | def_bool y |
55 | 55 | ||
56 | config ARCH_SUPPORTS_AOUT | ||
57 | def_bool n | ||
58 | |||
59 | # Use the generic interrupt handling code in kernel/irq/ | 56 | # Use the generic interrupt handling code in kernel/irq/ |
60 | config GENERIC_HARDIRQS | 57 | config GENERIC_HARDIRQS |
61 | def_bool y | 58 | def_bool y |
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index a7d4fd353c2b..8313fccced5e 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig | |||
@@ -76,9 +76,6 @@ config IRQ_PER_CPU | |||
76 | bool | 76 | bool |
77 | default y | 77 | default y |
78 | 78 | ||
79 | config ARCH_SUPPORTS_AOUT | ||
80 | def_bool y | ||
81 | |||
82 | # unless you want to implement ACPI on PA-RISC ... ;-) | 79 | # unless you want to implement ACPI on PA-RISC ... ;-) |
83 | config PM | 80 | config PM |
84 | bool | 81 | bool |
diff --git a/arch/powerpc/include/asm/a.out.h b/arch/powerpc/include/asm/a.out.h deleted file mode 100644 index 89cead6b176e..000000000000 --- a/arch/powerpc/include/asm/a.out.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | #ifndef _ASM_POWERPC_A_OUT_H | ||
2 | #define _ASM_POWERPC_A_OUT_H | ||
3 | |||
4 | struct exec | ||
5 | { | ||
6 | unsigned long a_info; /* Use macros N_MAGIC, etc for access */ | ||
7 | unsigned a_text; /* length of text, in bytes */ | ||
8 | unsigned a_data; /* length of data, in bytes */ | ||
9 | unsigned a_bss; /* length of uninitialized data area for file, in bytes */ | ||
10 | unsigned a_syms; /* length of symbol table data in file, in bytes */ | ||
11 | unsigned a_entry; /* start address */ | ||
12 | unsigned a_trsize; /* length of relocation info for text, in bytes */ | ||
13 | unsigned a_drsize; /* length of relocation info for data, in bytes */ | ||
14 | }; | ||
15 | |||
16 | #define N_TRSIZE(a) ((a).a_trsize) | ||
17 | #define N_DRSIZE(a) ((a).a_drsize) | ||
18 | #define N_SYMSIZE(a) ((a).a_syms) | ||
19 | |||
20 | #endif /* _ASM_POWERPC_A_OUT_H */ | ||
diff --git a/arch/powerpc/include/asm/statfs.h b/arch/powerpc/include/asm/statfs.h index 67024026c10d..5244834583a4 100644 --- a/arch/powerpc/include/asm/statfs.h +++ b/arch/powerpc/include/asm/statfs.h | |||
@@ -1,60 +1,6 @@ | |||
1 | #ifndef _ASM_POWERPC_STATFS_H | 1 | #ifndef _ASM_POWERPC_STATFS_H |
2 | #define _ASM_POWERPC_STATFS_H | 2 | #define _ASM_POWERPC_STATFS_H |
3 | 3 | ||
4 | /* For ppc32 we just use the generic definitions, not so simple on ppc64 */ | ||
5 | |||
6 | #ifndef __powerpc64__ | ||
7 | #include <asm-generic/statfs.h> | 4 | #include <asm-generic/statfs.h> |
8 | #else | ||
9 | |||
10 | #ifndef __KERNEL_STRICT_NAMES | ||
11 | #include <linux/types.h> | ||
12 | typedef __kernel_fsid_t fsid_t; | ||
13 | #endif | ||
14 | |||
15 | /* | ||
16 | * We're already 64-bit, so duplicate the definition | ||
17 | */ | ||
18 | struct statfs { | ||
19 | long f_type; | ||
20 | long f_bsize; | ||
21 | long f_blocks; | ||
22 | long f_bfree; | ||
23 | long f_bavail; | ||
24 | long f_files; | ||
25 | long f_ffree; | ||
26 | __kernel_fsid_t f_fsid; | ||
27 | long f_namelen; | ||
28 | long f_frsize; | ||
29 | long f_spare[5]; | ||
30 | }; | ||
31 | |||
32 | struct statfs64 { | ||
33 | long f_type; | ||
34 | long f_bsize; | ||
35 | long f_blocks; | ||
36 | long f_bfree; | ||
37 | long f_bavail; | ||
38 | long f_files; | ||
39 | long f_ffree; | ||
40 | __kernel_fsid_t f_fsid; | ||
41 | long f_namelen; | ||
42 | long f_frsize; | ||
43 | long f_spare[5]; | ||
44 | }; | ||
45 | 5 | ||
46 | struct compat_statfs64 { | ||
47 | __u32 f_type; | ||
48 | __u32 f_bsize; | ||
49 | __u64 f_blocks; | ||
50 | __u64 f_bfree; | ||
51 | __u64 f_bavail; | ||
52 | __u64 f_files; | ||
53 | __u64 f_ffree; | ||
54 | __kernel_fsid_t f_fsid; | ||
55 | __u32 f_namelen; | ||
56 | __u32 f_frsize; | ||
57 | __u32 f_spare[5]; | ||
58 | }; | ||
59 | #endif /* ! __powerpc64__ */ | ||
60 | #endif | 6 | #endif |
diff --git a/arch/powerpc/kernel/softemu8xx.c b/arch/powerpc/kernel/softemu8xx.c index c906c4bf6835..23c8c5e7dc4d 100644 --- a/arch/powerpc/kernel/softemu8xx.c +++ b/arch/powerpc/kernel/softemu8xx.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/ptrace.h> | 23 | #include <linux/ptrace.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/user.h> | 25 | #include <linux/user.h> |
26 | #include <linux/a.out.h> | ||
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
28 | 27 | ||
29 | #include <asm/pgtable.h> | 28 | #include <asm/pgtable.h> |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 81ccb8dd1a54..f5def6cf5cd6 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/ptrace.h> | 23 | #include <linux/ptrace.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/user.h> | 25 | #include <linux/user.h> |
26 | #include <linux/a.out.h> | ||
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
28 | #include <linux/init.h> | 27 | #include <linux/init.h> |
29 | #include <linux/module.h> | 28 | #include <linux/module.h> |
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 1ba7ce5aafae..272d79a8d289 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/ptrace.h> | 17 | #include <linux/ptrace.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/user.h> | 19 | #include <linux/user.h> |
20 | #include <linux/a.out.h> | ||
21 | #include <linux/tty.h> | 20 | #include <linux/tty.h> |
22 | #include <linux/major.h> | 21 | #include <linux/major.h> |
23 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 364714757cf1..d4c61c3c9669 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/ptrace.h> | 23 | #include <linux/ptrace.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/user.h> | 25 | #include <linux/user.h> |
26 | #include <linux/a.out.h> | ||
27 | #include <linux/tty.h> | 26 | #include <linux/tty.h> |
28 | #include <linux/string.h> | 27 | #include <linux/string.h> |
29 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 88ccf3a08a9c..82c14d203d8b 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/ptrace.h> | 33 | #include <linux/ptrace.h> |
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <linux/user.h> | 35 | #include <linux/user.h> |
36 | #include <linux/a.out.h> | ||
37 | #include <linux/tty.h> | 36 | #include <linux/tty.h> |
38 | #include <linux/string.h> | 37 | #include <linux/string.h> |
39 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 7b01d67b4e48..ec341707e41b 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/unistd.h> | 25 | #include <linux/unistd.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/user.h> | 27 | #include <linux/user.h> |
28 | #include <linux/a.out.h> | ||
29 | #include <linux/tty.h> | 28 | #include <linux/tty.h> |
30 | #include <linux/major.h> | 29 | #include <linux/major.h> |
31 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
diff --git a/arch/s390/include/asm/statfs.h b/arch/s390/include/asm/statfs.h index 099a45579190..06cc70307ece 100644 --- a/arch/s390/include/asm/statfs.h +++ b/arch/s390/include/asm/statfs.h | |||
@@ -12,19 +12,16 @@ | |||
12 | #ifndef __s390x__ | 12 | #ifndef __s390x__ |
13 | #include <asm-generic/statfs.h> | 13 | #include <asm-generic/statfs.h> |
14 | #else | 14 | #else |
15 | /* | ||
16 | * We can't use <asm-generic/statfs.h> because in 64-bit mode | ||
17 | * we mix ints of different sizes in our struct statfs. | ||
18 | */ | ||
15 | 19 | ||
16 | #ifndef __KERNEL_STRICT_NAMES | 20 | #ifndef __KERNEL_STRICT_NAMES |
17 | |||
18 | #include <linux/types.h> | 21 | #include <linux/types.h> |
19 | |||
20 | typedef __kernel_fsid_t fsid_t; | 22 | typedef __kernel_fsid_t fsid_t; |
21 | |||
22 | #endif | 23 | #endif |
23 | 24 | ||
24 | /* | ||
25 | * This is ugly -- we're already 64-bit clean, so just duplicate the | ||
26 | * definitions. | ||
27 | */ | ||
28 | struct statfs { | 25 | struct statfs { |
29 | int f_type; | 26 | int f_type; |
30 | int f_bsize; | 27 | int f_bsize; |
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index 2ba7183bc1f0..2d2769d766ec 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild | |||
@@ -15,8 +15,6 @@ header-y += signal_32.h | |||
15 | header-y += signal_64.h | 15 | header-y += signal_64.h |
16 | header-y += stat_32.h | 16 | header-y += stat_32.h |
17 | header-y += stat_64.h | 17 | header-y += stat_64.h |
18 | header-y += statfs_32.h | ||
19 | header-y += statfs_64.h | ||
20 | header-y += unistd_32.h | 18 | header-y += unistd_32.h |
21 | header-y += unistd_64.h | 19 | header-y += unistd_64.h |
22 | 20 | ||
diff --git a/arch/sparc/include/asm/serial.h b/arch/sparc/include/asm/serial.h new file mode 100644 index 000000000000..f90d61c28059 --- /dev/null +++ b/arch/sparc/include/asm/serial.h | |||
@@ -0,0 +1,6 @@ | |||
1 | #ifndef __SPARC_SERIAL_H | ||
2 | #define __SPARC_SERIAL_H | ||
3 | |||
4 | #define BASE_BAUD ( 1843200 / 16 ) | ||
5 | |||
6 | #endif /* __SPARC_SERIAL_H */ | ||
diff --git a/arch/sparc/include/asm/statfs.h b/arch/sparc/include/asm/statfs.h index 5e937a73743d..55e607ad461d 100644 --- a/arch/sparc/include/asm/statfs.h +++ b/arch/sparc/include/asm/statfs.h | |||
@@ -1,8 +1,6 @@ | |||
1 | #ifndef ___ASM_SPARC_STATFS_H | 1 | #ifndef ___ASM_SPARC_STATFS_H |
2 | #define ___ASM_SPARC_STATFS_H | 2 | #define ___ASM_SPARC_STATFS_H |
3 | #if defined(__sparc__) && defined(__arch64__) | 3 | |
4 | #include <asm/statfs_64.h> | 4 | #include <asm-generic/statfs.h> |
5 | #else | 5 | |
6 | #include <asm/statfs_32.h> | ||
7 | #endif | ||
8 | #endif | 6 | #endif |
diff --git a/arch/sparc/include/asm/statfs_32.h b/arch/sparc/include/asm/statfs_32.h deleted file mode 100644 index 304520fa8863..000000000000 --- a/arch/sparc/include/asm/statfs_32.h +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #ifndef _SPARC_STATFS_H | ||
2 | #define _SPARC_STATFS_H | ||
3 | |||
4 | #include <asm-generic/statfs.h> | ||
5 | |||
6 | #endif | ||
diff --git a/arch/sparc/include/asm/statfs_64.h b/arch/sparc/include/asm/statfs_64.h deleted file mode 100644 index 79b3c890a5fa..000000000000 --- a/arch/sparc/include/asm/statfs_64.h +++ /dev/null | |||
@@ -1,54 +0,0 @@ | |||
1 | #ifndef _SPARC64_STATFS_H | ||
2 | #define _SPARC64_STATFS_H | ||
3 | |||
4 | #ifndef __KERNEL_STRICT_NAMES | ||
5 | |||
6 | #include <linux/types.h> | ||
7 | |||
8 | typedef __kernel_fsid_t fsid_t; | ||
9 | |||
10 | #endif | ||
11 | |||
12 | struct statfs { | ||
13 | long f_type; | ||
14 | long f_bsize; | ||
15 | long f_blocks; | ||
16 | long f_bfree; | ||
17 | long f_bavail; | ||
18 | long f_files; | ||
19 | long f_ffree; | ||
20 | __kernel_fsid_t f_fsid; | ||
21 | long f_namelen; | ||
22 | long f_frsize; | ||
23 | long f_spare[5]; | ||
24 | }; | ||
25 | |||
26 | struct statfs64 { | ||
27 | long f_type; | ||
28 | long f_bsize; | ||
29 | long f_blocks; | ||
30 | long f_bfree; | ||
31 | long f_bavail; | ||
32 | long f_files; | ||
33 | long f_ffree; | ||
34 | __kernel_fsid_t f_fsid; | ||
35 | long f_namelen; | ||
36 | long f_frsize; | ||
37 | long f_spare[5]; | ||
38 | }; | ||
39 | |||
40 | struct compat_statfs64 { | ||
41 | __u32 f_type; | ||
42 | __u32 f_bsize; | ||
43 | __u64 f_blocks; | ||
44 | __u64 f_bfree; | ||
45 | __u64 f_bavail; | ||
46 | __u64 f_files; | ||
47 | __u64 f_ffree; | ||
48 | __kernel_fsid_t f_fsid; | ||
49 | __u32 f_namelen; | ||
50 | __u32 f_frsize; | ||
51 | __u32 f_spare[5]; | ||
52 | }; | ||
53 | |||
54 | #endif | ||
diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index e09edfa560da..1f57c113df6d 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 | |||
@@ -9,8 +9,9 @@ config UML_X86 | |||
9 | default y | 9 | default y |
10 | 10 | ||
11 | config X86_32 | 11 | config X86_32 |
12 | bool | 12 | bool |
13 | default y | 13 | default y |
14 | select HAVE_AOUT | ||
14 | 15 | ||
15 | config RWSEM_XCHGADD_ALGORITHM | 16 | config RWSEM_XCHGADD_ALGORITHM |
16 | def_bool y | 17 | def_bool y |
@@ -42,6 +43,3 @@ config ARCH_REUSE_HOST_VSYSCALL_AREA | |||
42 | config GENERIC_HWEIGHT | 43 | config GENERIC_HWEIGHT |
43 | bool | 44 | bool |
44 | default y | 45 | default y |
45 | |||
46 | config ARCH_SUPPORTS_AOUT | ||
47 | def_bool y | ||
diff --git a/arch/um/Kconfig.x86_64 b/arch/um/Kconfig.x86_64 index 5696e7b374b3..40b3407cfe16 100644 --- a/arch/um/Kconfig.x86_64 +++ b/arch/um/Kconfig.x86_64 | |||
@@ -37,6 +37,3 @@ config SMP_BROKEN | |||
37 | config GENERIC_HWEIGHT | 37 | config GENERIC_HWEIGHT |
38 | bool | 38 | bool |
39 | default y | 39 | default y |
40 | |||
41 | config ARCH_SUPPORTS_AOUT | ||
42 | def_bool y | ||
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index d741f35d7b3a..14a102e877d6 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
@@ -275,6 +275,8 @@ int line_ioctl(struct tty_struct *tty, struct file * file, | |||
275 | case TIOCGLTC: | 275 | case TIOCGLTC: |
276 | case TIOCSLTC: | 276 | case TIOCSLTC: |
277 | #endif | 277 | #endif |
278 | /* Note: these are out of date as we now have TCGETS2 etc but this | ||
279 | whole lot should probably go away */ | ||
278 | case TCGETS: | 280 | case TCGETS: |
279 | case TCSETSF: | 281 | case TCSETSF: |
280 | case TCSETSW: | 282 | case TCSETSW: |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index fc8351f374fd..f65c2744d573 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -18,6 +18,7 @@ config X86_64 | |||
18 | ### Arch settings | 18 | ### Arch settings |
19 | config X86 | 19 | config X86 |
20 | def_bool y | 20 | def_bool y |
21 | select HAVE_AOUT if X86_32 | ||
21 | select HAVE_UNSTABLE_SCHED_CLOCK | 22 | select HAVE_UNSTABLE_SCHED_CLOCK |
22 | select HAVE_IDE | 23 | select HAVE_IDE |
23 | select HAVE_OPROFILE | 24 | select HAVE_OPROFILE |
@@ -152,9 +153,6 @@ config AUDIT_ARCH | |||
152 | bool | 153 | bool |
153 | default X86_64 | 154 | default X86_64 |
154 | 155 | ||
155 | config ARCH_SUPPORTS_AOUT | ||
156 | def_bool y | ||
157 | |||
158 | config ARCH_SUPPORTS_OPTIMIZED_INLINING | 156 | config ARCH_SUPPORTS_OPTIMIZED_INLINING |
159 | def_bool y | 157 | def_bool y |
160 | 158 | ||
@@ -1885,7 +1883,7 @@ config IA32_EMULATION | |||
1885 | 1883 | ||
1886 | config IA32_AOUT | 1884 | config IA32_AOUT |
1887 | tristate "IA32 a.out support" | 1885 | tristate "IA32 a.out support" |
1888 | depends on IA32_EMULATION && ARCH_SUPPORTS_AOUT | 1886 | depends on IA32_EMULATION |
1889 | help | 1887 | help |
1890 | Support old a.out binaries in the 32bit emulation. | 1888 | Support old a.out binaries in the 32bit emulation. |
1891 | 1889 | ||
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index c5f101360520..0b7c4a3f0651 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu | |||
@@ -38,8 +38,7 @@ config M386 | |||
38 | - "Crusoe" for the Transmeta Crusoe series. | 38 | - "Crusoe" for the Transmeta Crusoe series. |
39 | - "Efficeon" for the Transmeta Efficeon series. | 39 | - "Efficeon" for the Transmeta Efficeon series. |
40 | - "Winchip-C6" for original IDT Winchip. | 40 | - "Winchip-C6" for original IDT Winchip. |
41 | - "Winchip-2" for IDT Winchip 2. | 41 | - "Winchip-2" for IDT Winchips with 3dNow! capabilities. |
42 | - "Winchip-2A" for IDT Winchips with 3dNow! capabilities. | ||
43 | - "GeodeGX1" for Geode GX1 (Cyrix MediaGX). | 42 | - "GeodeGX1" for Geode GX1 (Cyrix MediaGX). |
44 | - "Geode GX/LX" For AMD Geode GX and LX processors. | 43 | - "Geode GX/LX" For AMD Geode GX and LX processors. |
45 | - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3. | 44 | - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3. |
@@ -194,19 +193,11 @@ config MWINCHIPC6 | |||
194 | treat this chip as a 586TSC with some extended instructions | 193 | treat this chip as a 586TSC with some extended instructions |
195 | and alignment requirements. | 194 | and alignment requirements. |
196 | 195 | ||
197 | config MWINCHIP2 | ||
198 | bool "Winchip-2" | ||
199 | depends on X86_32 | ||
200 | help | ||
201 | Select this for an IDT Winchip-2. Linux and GCC | ||
202 | treat this chip as a 586TSC with some extended instructions | ||
203 | and alignment requirements. | ||
204 | |||
205 | config MWINCHIP3D | 196 | config MWINCHIP3D |
206 | bool "Winchip-2A/Winchip-3" | 197 | bool "Winchip-2/Winchip-2A/Winchip-3" |
207 | depends on X86_32 | 198 | depends on X86_32 |
208 | help | 199 | help |
209 | Select this for an IDT Winchip-2A or 3. Linux and GCC | 200 | Select this for an IDT Winchip-2, 2A or 3. Linux and GCC |
210 | treat this chip as a 586TSC with some extended instructions | 201 | treat this chip as a 586TSC with some extended instructions |
211 | and alignment requirements. Also enable out of order memory | 202 | and alignment requirements. Also enable out of order memory |
212 | stores for this CPU, which can increase performance of some | 203 | stores for this CPU, which can increase performance of some |
@@ -318,7 +309,7 @@ config X86_L1_CACHE_SHIFT | |||
318 | int | 309 | int |
319 | default "7" if MPENTIUM4 || X86_GENERIC || GENERIC_CPU || MPSC | 310 | default "7" if MPENTIUM4 || X86_GENERIC || GENERIC_CPU || MPSC |
320 | default "4" if X86_ELAN || M486 || M386 || MGEODEGX1 | 311 | default "4" if X86_ELAN || M486 || M386 || MGEODEGX1 |
321 | default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX | 312 | default "5" if MWINCHIP3D || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX |
322 | default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MVIAC7 | 313 | default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MVIAC7 |
323 | 314 | ||
324 | config X86_XADD | 315 | config X86_XADD |
@@ -360,7 +351,7 @@ config X86_POPAD_OK | |||
360 | 351 | ||
361 | config X86_ALIGNMENT_16 | 352 | config X86_ALIGNMENT_16 |
362 | def_bool y | 353 | def_bool y |
363 | depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1 | 354 | depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1 |
364 | 355 | ||
365 | config X86_INTEL_USERCOPY | 356 | config X86_INTEL_USERCOPY |
366 | def_bool y | 357 | def_bool y |
@@ -368,7 +359,7 @@ config X86_INTEL_USERCOPY | |||
368 | 359 | ||
369 | config X86_USE_PPRO_CHECKSUM | 360 | config X86_USE_PPRO_CHECKSUM |
370 | def_bool y | 361 | def_bool y |
371 | depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX || MCORE2 | 362 | depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX || MCORE2 |
372 | 363 | ||
373 | config X86_USE_3DNOW | 364 | config X86_USE_3DNOW |
374 | def_bool y | 365 | def_bool y |
@@ -376,7 +367,7 @@ config X86_USE_3DNOW | |||
376 | 367 | ||
377 | config X86_OOSTORE | 368 | config X86_OOSTORE |
378 | def_bool y | 369 | def_bool y |
379 | depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR | 370 | depends on (MWINCHIP3D || MWINCHIPC6) && MTRR |
380 | 371 | ||
381 | # | 372 | # |
382 | # P6_NOPs are a relatively minor optimization that require a family >= | 373 | # P6_NOPs are a relatively minor optimization that require a family >= |
@@ -396,7 +387,7 @@ config X86_P6_NOP | |||
396 | 387 | ||
397 | config X86_TSC | 388 | config X86_TSC |
398 | def_bool y | 389 | def_bool y |
399 | depends on ((MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ) || X86_64 | 390 | depends on ((MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ) || X86_64 |
400 | 391 | ||
401 | config X86_CMPXCHG64 | 392 | config X86_CMPXCHG64 |
402 | def_bool y | 393 | def_bool y |
@@ -406,7 +397,7 @@ config X86_CMPXCHG64 | |||
406 | # generates cmov. | 397 | # generates cmov. |
407 | config X86_CMOV | 398 | config X86_CMOV |
408 | def_bool y | 399 | def_bool y |
409 | depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || X86_64) | 400 | depends on (MK8 || MK7 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64) |
410 | 401 | ||
411 | config X86_MINIMUM_CPU_FAMILY | 402 | config X86_MINIMUM_CPU_FAMILY |
412 | int | 403 | int |
@@ -417,7 +408,7 @@ config X86_MINIMUM_CPU_FAMILY | |||
417 | 408 | ||
418 | config X86_DEBUGCTLMSR | 409 | config X86_DEBUGCTLMSR |
419 | def_bool y | 410 | def_bool y |
420 | depends on !(MK6 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) | 411 | depends on !(MK6 || MWINCHIPC6 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) |
421 | 412 | ||
422 | menuconfig PROCESSOR_SELECT | 413 | menuconfig PROCESSOR_SELECT |
423 | bool "Supported processor vendors" if EMBEDDED | 414 | bool "Supported processor vendors" if EMBEDDED |
diff --git a/arch/x86/Makefile_32.cpu b/arch/x86/Makefile_32.cpu index b72b4f753113..80177ec052f0 100644 --- a/arch/x86/Makefile_32.cpu +++ b/arch/x86/Makefile_32.cpu | |||
@@ -28,7 +28,6 @@ cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8,-march=athlon) | |||
28 | cflags-$(CONFIG_MCRUSOE) += -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 | 28 | cflags-$(CONFIG_MCRUSOE) += -march=i686 $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 |
29 | cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call tune,pentium3) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 | 29 | cflags-$(CONFIG_MEFFICEON) += -march=i686 $(call tune,pentium3) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 |
30 | cflags-$(CONFIG_MWINCHIPC6) += $(call cc-option,-march=winchip-c6,-march=i586) | 30 | cflags-$(CONFIG_MWINCHIPC6) += $(call cc-option,-march=winchip-c6,-march=i586) |
31 | cflags-$(CONFIG_MWINCHIP2) += $(call cc-option,-march=winchip2,-march=i586) | ||
32 | cflags-$(CONFIG_MWINCHIP3D) += $(call cc-option,-march=winchip2,-march=i586) | 31 | cflags-$(CONFIG_MWINCHIP3D) += $(call cc-option,-march=winchip2,-march=i586) |
33 | cflags-$(CONFIG_MCYRIXIII) += $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 | 32 | cflags-$(CONFIG_MCYRIXIII) += $(call cc-option,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 |
34 | cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686) | 33 | cflags-$(CONFIG_MVIAC3_2) += $(call cc-option,-march=c3-2,-march=i686) |
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig index ca226ca31288..52d0359719d7 100644 --- a/arch/x86/configs/i386_defconfig +++ b/arch/x86/configs/i386_defconfig | |||
@@ -213,7 +213,6 @@ CONFIG_M686=y | |||
213 | # CONFIG_MCRUSOE is not set | 213 | # CONFIG_MCRUSOE is not set |
214 | # CONFIG_MEFFICEON is not set | 214 | # CONFIG_MEFFICEON is not set |
215 | # CONFIG_MWINCHIPC6 is not set | 215 | # CONFIG_MWINCHIPC6 is not set |
216 | # CONFIG_MWINCHIP2 is not set | ||
217 | # CONFIG_MWINCHIP3D is not set | 216 | # CONFIG_MWINCHIP3D is not set |
218 | # CONFIG_MGEODEGX1 is not set | 217 | # CONFIG_MGEODEGX1 is not set |
219 | # CONFIG_MGEODE_LX is not set | 218 | # CONFIG_MGEODE_LX is not set |
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig index 2c4b1c771e28..f0a03d7a7d63 100644 --- a/arch/x86/configs/x86_64_defconfig +++ b/arch/x86/configs/x86_64_defconfig | |||
@@ -210,7 +210,6 @@ CONFIG_X86_PC=y | |||
210 | # CONFIG_MCRUSOE is not set | 210 | # CONFIG_MCRUSOE is not set |
211 | # CONFIG_MEFFICEON is not set | 211 | # CONFIG_MEFFICEON is not set |
212 | # CONFIG_MWINCHIPC6 is not set | 212 | # CONFIG_MWINCHIPC6 is not set |
213 | # CONFIG_MWINCHIP2 is not set | ||
214 | # CONFIG_MWINCHIP3D is not set | 213 | # CONFIG_MWINCHIP3D is not set |
215 | # CONFIG_MGEODEGX1 is not set | 214 | # CONFIG_MGEODEGX1 is not set |
216 | # CONFIG_MGEODE_LX is not set | 215 | # CONFIG_MGEODE_LX is not set |
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index ffc1bb4fed7d..eb4314768bf7 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S | |||
@@ -39,11 +39,11 @@ | |||
39 | .endm | 39 | .endm |
40 | 40 | ||
41 | /* clobbers %eax */ | 41 | /* clobbers %eax */ |
42 | .macro CLEAR_RREGS | 42 | .macro CLEAR_RREGS _r9=rax |
43 | xorl %eax,%eax | 43 | xorl %eax,%eax |
44 | movq %rax,R11(%rsp) | 44 | movq %rax,R11(%rsp) |
45 | movq %rax,R10(%rsp) | 45 | movq %rax,R10(%rsp) |
46 | movq %rax,R9(%rsp) | 46 | movq %\_r9,R9(%rsp) |
47 | movq %rax,R8(%rsp) | 47 | movq %rax,R8(%rsp) |
48 | .endm | 48 | .endm |
49 | 49 | ||
@@ -52,11 +52,10 @@ | |||
52 | * We don't reload %eax because syscall_trace_enter() returned | 52 | * We don't reload %eax because syscall_trace_enter() returned |
53 | * the value it wants us to use in the table lookup. | 53 | * the value it wants us to use in the table lookup. |
54 | */ | 54 | */ |
55 | .macro LOAD_ARGS32 offset | 55 | .macro LOAD_ARGS32 offset, _r9=0 |
56 | movl \offset(%rsp),%r11d | 56 | .if \_r9 |
57 | movl \offset+8(%rsp),%r10d | ||
58 | movl \offset+16(%rsp),%r9d | 57 | movl \offset+16(%rsp),%r9d |
59 | movl \offset+24(%rsp),%r8d | 58 | .endif |
60 | movl \offset+40(%rsp),%ecx | 59 | movl \offset+40(%rsp),%ecx |
61 | movl \offset+48(%rsp),%edx | 60 | movl \offset+48(%rsp),%edx |
62 | movl \offset+56(%rsp),%esi | 61 | movl \offset+56(%rsp),%esi |
@@ -145,7 +144,7 @@ ENTRY(ia32_sysenter_target) | |||
145 | SAVE_ARGS 0,0,1 | 144 | SAVE_ARGS 0,0,1 |
146 | /* no need to do an access_ok check here because rbp has been | 145 | /* no need to do an access_ok check here because rbp has been |
147 | 32bit zero extended */ | 146 | 32bit zero extended */ |
148 | 1: movl (%rbp),%r9d | 147 | 1: movl (%rbp),%ebp |
149 | .section __ex_table,"a" | 148 | .section __ex_table,"a" |
150 | .quad 1b,ia32_badarg | 149 | .quad 1b,ia32_badarg |
151 | .previous | 150 | .previous |
@@ -157,7 +156,7 @@ ENTRY(ia32_sysenter_target) | |||
157 | cmpl $(IA32_NR_syscalls-1),%eax | 156 | cmpl $(IA32_NR_syscalls-1),%eax |
158 | ja ia32_badsys | 157 | ja ia32_badsys |
159 | sysenter_do_call: | 158 | sysenter_do_call: |
160 | IA32_ARG_FIXUP 1 | 159 | IA32_ARG_FIXUP |
161 | sysenter_dispatch: | 160 | sysenter_dispatch: |
162 | call *ia32_sys_call_table(,%rax,8) | 161 | call *ia32_sys_call_table(,%rax,8) |
163 | movq %rax,RAX-ARGOFFSET(%rsp) | 162 | movq %rax,RAX-ARGOFFSET(%rsp) |
@@ -234,20 +233,17 @@ sysexit_audit: | |||
234 | #endif | 233 | #endif |
235 | 234 | ||
236 | sysenter_tracesys: | 235 | sysenter_tracesys: |
237 | xchgl %r9d,%ebp | ||
238 | #ifdef CONFIG_AUDITSYSCALL | 236 | #ifdef CONFIG_AUDITSYSCALL |
239 | testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10) | 237 | testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10) |
240 | jz sysenter_auditsys | 238 | jz sysenter_auditsys |
241 | #endif | 239 | #endif |
242 | SAVE_REST | 240 | SAVE_REST |
243 | CLEAR_RREGS | 241 | CLEAR_RREGS |
244 | movq %r9,R9(%rsp) | ||
245 | movq $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */ | 242 | movq $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */ |
246 | movq %rsp,%rdi /* &pt_regs -> arg1 */ | 243 | movq %rsp,%rdi /* &pt_regs -> arg1 */ |
247 | call syscall_trace_enter | 244 | call syscall_trace_enter |
248 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ | 245 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ |
249 | RESTORE_REST | 246 | RESTORE_REST |
250 | xchgl %ebp,%r9d | ||
251 | cmpl $(IA32_NR_syscalls-1),%eax | 247 | cmpl $(IA32_NR_syscalls-1),%eax |
252 | ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ | 248 | ja int_ret_from_sys_call /* sysenter_tracesys has set RAX(%rsp) */ |
253 | jmp sysenter_do_call | 249 | jmp sysenter_do_call |
@@ -314,9 +310,9 @@ ENTRY(ia32_cstar_target) | |||
314 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) | 310 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) |
315 | CFI_REMEMBER_STATE | 311 | CFI_REMEMBER_STATE |
316 | jnz cstar_tracesys | 312 | jnz cstar_tracesys |
317 | cstar_do_call: | ||
318 | cmpl $IA32_NR_syscalls-1,%eax | 313 | cmpl $IA32_NR_syscalls-1,%eax |
319 | ja ia32_badsys | 314 | ja ia32_badsys |
315 | cstar_do_call: | ||
320 | IA32_ARG_FIXUP 1 | 316 | IA32_ARG_FIXUP 1 |
321 | cstar_dispatch: | 317 | cstar_dispatch: |
322 | call *ia32_sys_call_table(,%rax,8) | 318 | call *ia32_sys_call_table(,%rax,8) |
@@ -357,15 +353,13 @@ cstar_tracesys: | |||
357 | #endif | 353 | #endif |
358 | xchgl %r9d,%ebp | 354 | xchgl %r9d,%ebp |
359 | SAVE_REST | 355 | SAVE_REST |
360 | CLEAR_RREGS | 356 | CLEAR_RREGS r9 |
361 | movq %r9,R9(%rsp) | ||
362 | movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */ | 357 | movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */ |
363 | movq %rsp,%rdi /* &pt_regs -> arg1 */ | 358 | movq %rsp,%rdi /* &pt_regs -> arg1 */ |
364 | call syscall_trace_enter | 359 | call syscall_trace_enter |
365 | LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */ | 360 | LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */ |
366 | RESTORE_REST | 361 | RESTORE_REST |
367 | xchgl %ebp,%r9d | 362 | xchgl %ebp,%r9d |
368 | movl RSP-ARGOFFSET(%rsp), %r8d | ||
369 | cmpl $(IA32_NR_syscalls-1),%eax | 363 | cmpl $(IA32_NR_syscalls-1),%eax |
370 | ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ | 364 | ja int_ret_from_sys_call /* cstar_tracesys has set RAX(%rsp) */ |
371 | jmp cstar_do_call | 365 | jmp cstar_do_call |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 5098585f87ce..0d41f0343dc0 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -23,7 +23,7 @@ CFLAGS_hpet.o := $(nostackp) | |||
23 | CFLAGS_tsc.o := $(nostackp) | 23 | CFLAGS_tsc.o := $(nostackp) |
24 | 24 | ||
25 | obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o | 25 | obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o |
26 | obj-y += traps_$(BITS).o irq_$(BITS).o | 26 | obj-y += traps.o irq_$(BITS).o dumpstack_$(BITS).o |
27 | obj-y += time_$(BITS).o ioport.o ldt.o | 27 | obj-y += time_$(BITS).o ioport.o ldt.o |
28 | obj-y += setup.o i8259.o irqinit_$(BITS).o setup_percpu.o | 28 | obj-y += setup.o i8259.o irqinit_$(BITS).o setup_percpu.o |
29 | obj-$(CONFIG_X86_VISWS) += visws_quirks.o | 29 | obj-$(CONFIG_X86_VISWS) += visws_quirks.o |
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index fb04e49776ba..a84ac7b570e6 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
@@ -444,7 +444,7 @@ void __init alternative_instructions(void) | |||
444 | _text, _etext); | 444 | _text, _etext); |
445 | 445 | ||
446 | /* Only switch to UP mode if we don't immediately boot others */ | 446 | /* Only switch to UP mode if we don't immediately boot others */ |
447 | if (num_possible_cpus() == 1 || setup_max_cpus <= 1) | 447 | if (num_present_cpus() == 1 || setup_max_cpus <= 1) |
448 | alternatives_smp_switch(0); | 448 | alternatives_smp_switch(0); |
449 | } | 449 | } |
450 | #endif | 450 | #endif |
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index a91c57cb666a..21c831d96af3 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c | |||
@@ -295,6 +295,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) | |||
295 | * | 295 | * |
296 | * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and | 296 | * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and |
297 | * MCE interrupts are supported. Thus MCE offset must be set to 0. | 297 | * MCE interrupts are supported. Thus MCE offset must be set to 0. |
298 | * | ||
299 | * If mask=1, the LVT entry does not generate interrupts while mask=0 | ||
300 | * enables the vector. See also the BKDGs. | ||
298 | */ | 301 | */ |
299 | 302 | ||
300 | #define APIC_EILVT_LVTOFF_MCE 0 | 303 | #define APIC_EILVT_LVTOFF_MCE 0 |
@@ -319,6 +322,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) | |||
319 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); | 322 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); |
320 | return APIC_EILVT_LVTOFF_IBS; | 323 | return APIC_EILVT_LVTOFF_IBS; |
321 | } | 324 | } |
325 | EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs); | ||
322 | 326 | ||
323 | /* | 327 | /* |
324 | * Program the next event, relative to now | 328 | * Program the next event, relative to now |
diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 53898b65a6ae..94ddb69ae15e 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c | |||
@@ -307,6 +307,9 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) | |||
307 | * | 307 | * |
308 | * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and | 308 | * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and |
309 | * MCE interrupts are supported. Thus MCE offset must be set to 0. | 309 | * MCE interrupts are supported. Thus MCE offset must be set to 0. |
310 | * | ||
311 | * If mask=1, the LVT entry does not generate interrupts while mask=0 | ||
312 | * enables the vector. See also the BKDGs. | ||
310 | */ | 313 | */ |
311 | 314 | ||
312 | #define APIC_EILVT_LVTOFF_MCE 0 | 315 | #define APIC_EILVT_LVTOFF_MCE 0 |
@@ -331,6 +334,7 @@ u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) | |||
331 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); | 334 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); |
332 | return APIC_EILVT_LVTOFF_IBS; | 335 | return APIC_EILVT_LVTOFF_IBS; |
333 | } | 336 | } |
337 | EXPORT_SYMBOL_GPL(setup_APIC_eilvt_ibs); | ||
334 | 338 | ||
335 | /* | 339 | /* |
336 | * Program the next event, relative to now | 340 | * Program the next event, relative to now |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index fb789dd9e691..25581dcb280e 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -124,18 +124,25 @@ static inline int flag_is_changeable_p(u32 flag) | |||
124 | { | 124 | { |
125 | u32 f1, f2; | 125 | u32 f1, f2; |
126 | 126 | ||
127 | asm("pushfl\n\t" | 127 | /* |
128 | "pushfl\n\t" | 128 | * Cyrix and IDT cpus allow disabling of CPUID |
129 | "popl %0\n\t" | 129 | * so the code below may return different results |
130 | "movl %0,%1\n\t" | 130 | * when it is executed before and after enabling |
131 | "xorl %2,%0\n\t" | 131 | * the CPUID. Add "volatile" to not allow gcc to |
132 | "pushl %0\n\t" | 132 | * optimize the subsequent calls to this function. |
133 | "popfl\n\t" | 133 | */ |
134 | "pushfl\n\t" | 134 | asm volatile ("pushfl\n\t" |
135 | "popl %0\n\t" | 135 | "pushfl\n\t" |
136 | "popfl\n\t" | 136 | "popl %0\n\t" |
137 | : "=&r" (f1), "=&r" (f2) | 137 | "movl %0,%1\n\t" |
138 | : "ir" (flag)); | 138 | "xorl %2,%0\n\t" |
139 | "pushl %0\n\t" | ||
140 | "popfl\n\t" | ||
141 | "pushfl\n\t" | ||
142 | "popl %0\n\t" | ||
143 | "popfl\n\t" | ||
144 | : "=&r" (f1), "=&r" (f2) | ||
145 | : "ir" (flag)); | ||
139 | 146 | ||
140 | return ((f1^f2) & flag) != 0; | 147 | return ((f1^f2) & flag) != 0; |
141 | } | 148 | } |
@@ -719,12 +726,24 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) | |||
719 | #endif | 726 | #endif |
720 | } | 727 | } |
721 | 728 | ||
729 | #ifdef CONFIG_X86_64 | ||
730 | static void vgetcpu_set_mode(void) | ||
731 | { | ||
732 | if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP)) | ||
733 | vgetcpu_mode = VGETCPU_RDTSCP; | ||
734 | else | ||
735 | vgetcpu_mode = VGETCPU_LSL; | ||
736 | } | ||
737 | #endif | ||
738 | |||
722 | void __init identify_boot_cpu(void) | 739 | void __init identify_boot_cpu(void) |
723 | { | 740 | { |
724 | identify_cpu(&boot_cpu_data); | 741 | identify_cpu(&boot_cpu_data); |
725 | #ifdef CONFIG_X86_32 | 742 | #ifdef CONFIG_X86_32 |
726 | sysenter_setup(); | 743 | sysenter_setup(); |
727 | enable_sep_cpu(); | 744 | enable_sep_cpu(); |
745 | #else | ||
746 | vgetcpu_set_mode(); | ||
728 | #endif | 747 | #endif |
729 | } | 748 | } |
730 | 749 | ||
@@ -797,7 +816,7 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) | |||
797 | else if (c->cpuid_level >= 0) | 816 | else if (c->cpuid_level >= 0) |
798 | vendor = c->x86_vendor_id; | 817 | vendor = c->x86_vendor_id; |
799 | 818 | ||
800 | if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor))) | 819 | if (vendor && !strstr(c->x86_model_id, vendor)) |
801 | printk(KERN_CONT "%s ", vendor); | 820 | printk(KERN_CONT "%s ", vendor); |
802 | 821 | ||
803 | if (c->x86_model_id[0]) | 822 | if (c->x86_model_id[0]) |
diff --git a/arch/x86/kernel/doublefault_32.c b/arch/x86/kernel/doublefault_32.c index 395acb12b0d1..b4f14c6c09d9 100644 --- a/arch/x86/kernel/doublefault_32.c +++ b/arch/x86/kernel/doublefault_32.c | |||
@@ -66,6 +66,6 @@ struct tss_struct doublefault_tss __cacheline_aligned = { | |||
66 | .ds = __USER_DS, | 66 | .ds = __USER_DS, |
67 | .fs = __KERNEL_PERCPU, | 67 | .fs = __KERNEL_PERCPU, |
68 | 68 | ||
69 | .__cr3 = __phys_addr_const((unsigned long)swapper_pg_dir) | 69 | .__cr3 = __pa_nodebug(swapper_pg_dir), |
70 | } | 70 | } |
71 | }; | 71 | }; |
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c new file mode 100644 index 000000000000..201ee359a1a9 --- /dev/null +++ b/arch/x86/kernel/dumpstack_32.c | |||
@@ -0,0 +1,447 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
3 | * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs | ||
4 | */ | ||
5 | #include <linux/kallsyms.h> | ||
6 | #include <linux/kprobes.h> | ||
7 | #include <linux/uaccess.h> | ||
8 | #include <linux/utsname.h> | ||
9 | #include <linux/hardirq.h> | ||
10 | #include <linux/kdebug.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/ptrace.h> | ||
13 | #include <linux/kexec.h> | ||
14 | #include <linux/bug.h> | ||
15 | #include <linux/nmi.h> | ||
16 | |||
17 | #include <asm/stacktrace.h> | ||
18 | |||
19 | #define STACKSLOTS_PER_LINE 8 | ||
20 | #define get_bp(bp) asm("movl %%ebp, %0" : "=r" (bp) :) | ||
21 | |||
22 | int panic_on_unrecovered_nmi; | ||
23 | int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE; | ||
24 | static unsigned int code_bytes = 64; | ||
25 | static int die_counter; | ||
26 | |||
27 | void printk_address(unsigned long address, int reliable) | ||
28 | { | ||
29 | printk(" [<%p>] %s%pS\n", (void *) address, | ||
30 | reliable ? "" : "? ", (void *) address); | ||
31 | } | ||
32 | |||
33 | static inline int valid_stack_ptr(struct thread_info *tinfo, | ||
34 | void *p, unsigned int size, void *end) | ||
35 | { | ||
36 | void *t = tinfo; | ||
37 | if (end) { | ||
38 | if (p < end && p >= (end-THREAD_SIZE)) | ||
39 | return 1; | ||
40 | else | ||
41 | return 0; | ||
42 | } | ||
43 | return p > t && p < t + THREAD_SIZE - size; | ||
44 | } | ||
45 | |||
46 | /* The form of the top of the frame on the stack */ | ||
47 | struct stack_frame { | ||
48 | struct stack_frame *next_frame; | ||
49 | unsigned long return_address; | ||
50 | }; | ||
51 | |||
52 | static inline unsigned long | ||
53 | print_context_stack(struct thread_info *tinfo, | ||
54 | unsigned long *stack, unsigned long bp, | ||
55 | const struct stacktrace_ops *ops, void *data, | ||
56 | unsigned long *end) | ||
57 | { | ||
58 | struct stack_frame *frame = (struct stack_frame *)bp; | ||
59 | |||
60 | while (valid_stack_ptr(tinfo, stack, sizeof(*stack), end)) { | ||
61 | unsigned long addr; | ||
62 | |||
63 | addr = *stack; | ||
64 | if (__kernel_text_address(addr)) { | ||
65 | if ((unsigned long) stack == bp + sizeof(long)) { | ||
66 | ops->address(data, addr, 1); | ||
67 | frame = frame->next_frame; | ||
68 | bp = (unsigned long) frame; | ||
69 | } else { | ||
70 | ops->address(data, addr, bp == 0); | ||
71 | } | ||
72 | } | ||
73 | stack++; | ||
74 | } | ||
75 | return bp; | ||
76 | } | ||
77 | |||
78 | void dump_trace(struct task_struct *task, struct pt_regs *regs, | ||
79 | unsigned long *stack, unsigned long bp, | ||
80 | const struct stacktrace_ops *ops, void *data) | ||
81 | { | ||
82 | if (!task) | ||
83 | task = current; | ||
84 | |||
85 | if (!stack) { | ||
86 | unsigned long dummy; | ||
87 | stack = &dummy; | ||
88 | if (task && task != current) | ||
89 | stack = (unsigned long *)task->thread.sp; | ||
90 | } | ||
91 | |||
92 | #ifdef CONFIG_FRAME_POINTER | ||
93 | if (!bp) { | ||
94 | if (task == current) { | ||
95 | /* Grab bp right from our regs */ | ||
96 | get_bp(bp); | ||
97 | } else { | ||
98 | /* bp is the last reg pushed by switch_to */ | ||
99 | bp = *(unsigned long *) task->thread.sp; | ||
100 | } | ||
101 | } | ||
102 | #endif | ||
103 | |||
104 | for (;;) { | ||
105 | struct thread_info *context; | ||
106 | |||
107 | context = (struct thread_info *) | ||
108 | ((unsigned long)stack & (~(THREAD_SIZE - 1))); | ||
109 | bp = print_context_stack(context, stack, bp, ops, data, NULL); | ||
110 | |||
111 | stack = (unsigned long *)context->previous_esp; | ||
112 | if (!stack) | ||
113 | break; | ||
114 | if (ops->stack(data, "IRQ") < 0) | ||
115 | break; | ||
116 | touch_nmi_watchdog(); | ||
117 | } | ||
118 | } | ||
119 | EXPORT_SYMBOL(dump_trace); | ||
120 | |||
121 | static void | ||
122 | print_trace_warning_symbol(void *data, char *msg, unsigned long symbol) | ||
123 | { | ||
124 | printk(data); | ||
125 | print_symbol(msg, symbol); | ||
126 | printk("\n"); | ||
127 | } | ||
128 | |||
129 | static void print_trace_warning(void *data, char *msg) | ||
130 | { | ||
131 | printk("%s%s\n", (char *)data, msg); | ||
132 | } | ||
133 | |||
134 | static int print_trace_stack(void *data, char *name) | ||
135 | { | ||
136 | printk("%s <%s> ", (char *)data, name); | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * Print one address/symbol entries per line. | ||
142 | */ | ||
143 | static void print_trace_address(void *data, unsigned long addr, int reliable) | ||
144 | { | ||
145 | touch_nmi_watchdog(); | ||
146 | printk(data); | ||
147 | printk_address(addr, reliable); | ||
148 | } | ||
149 | |||
150 | static const struct stacktrace_ops print_trace_ops = { | ||
151 | .warning = print_trace_warning, | ||
152 | .warning_symbol = print_trace_warning_symbol, | ||
153 | .stack = print_trace_stack, | ||
154 | .address = print_trace_address, | ||
155 | }; | ||
156 | |||
157 | static void | ||
158 | show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, | ||
159 | unsigned long *stack, unsigned long bp, char *log_lvl) | ||
160 | { | ||
161 | printk("%sCall Trace:\n", log_lvl); | ||
162 | dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl); | ||
163 | } | ||
164 | |||
165 | void show_trace(struct task_struct *task, struct pt_regs *regs, | ||
166 | unsigned long *stack, unsigned long bp) | ||
167 | { | ||
168 | show_trace_log_lvl(task, regs, stack, bp, ""); | ||
169 | } | ||
170 | |||
171 | static void | ||
172 | show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, | ||
173 | unsigned long *sp, unsigned long bp, char *log_lvl) | ||
174 | { | ||
175 | unsigned long *stack; | ||
176 | int i; | ||
177 | |||
178 | if (sp == NULL) { | ||
179 | if (task) | ||
180 | sp = (unsigned long *)task->thread.sp; | ||
181 | else | ||
182 | sp = (unsigned long *)&sp; | ||
183 | } | ||
184 | |||
185 | stack = sp; | ||
186 | for (i = 0; i < kstack_depth_to_print; i++) { | ||
187 | if (kstack_end(stack)) | ||
188 | break; | ||
189 | if (i && ((i % STACKSLOTS_PER_LINE) == 0)) | ||
190 | printk("\n%s", log_lvl); | ||
191 | printk(" %08lx", *stack++); | ||
192 | touch_nmi_watchdog(); | ||
193 | } | ||
194 | printk("\n"); | ||
195 | show_trace_log_lvl(task, regs, sp, bp, log_lvl); | ||
196 | } | ||
197 | |||
198 | void show_stack(struct task_struct *task, unsigned long *sp) | ||
199 | { | ||
200 | show_stack_log_lvl(task, NULL, sp, 0, ""); | ||
201 | } | ||
202 | |||
203 | /* | ||
204 | * The architecture-independent dump_stack generator | ||
205 | */ | ||
206 | void dump_stack(void) | ||
207 | { | ||
208 | unsigned long bp = 0; | ||
209 | unsigned long stack; | ||
210 | |||
211 | #ifdef CONFIG_FRAME_POINTER | ||
212 | if (!bp) | ||
213 | get_bp(bp); | ||
214 | #endif | ||
215 | |||
216 | printk("Pid: %d, comm: %.20s %s %s %.*s\n", | ||
217 | current->pid, current->comm, print_tainted(), | ||
218 | init_utsname()->release, | ||
219 | (int)strcspn(init_utsname()->version, " "), | ||
220 | init_utsname()->version); | ||
221 | show_trace(NULL, NULL, &stack, bp); | ||
222 | } | ||
223 | |||
224 | EXPORT_SYMBOL(dump_stack); | ||
225 | |||
226 | void show_registers(struct pt_regs *regs) | ||
227 | { | ||
228 | int i; | ||
229 | |||
230 | print_modules(); | ||
231 | __show_regs(regs, 0); | ||
232 | |||
233 | printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)\n", | ||
234 | TASK_COMM_LEN, current->comm, task_pid_nr(current), | ||
235 | current_thread_info(), current, task_thread_info(current)); | ||
236 | /* | ||
237 | * When in-kernel, we also print out the stack and code at the | ||
238 | * time of the fault.. | ||
239 | */ | ||
240 | if (!user_mode_vm(regs)) { | ||
241 | unsigned int code_prologue = code_bytes * 43 / 64; | ||
242 | unsigned int code_len = code_bytes; | ||
243 | unsigned char c; | ||
244 | u8 *ip; | ||
245 | |||
246 | printk(KERN_EMERG "Stack:\n"); | ||
247 | show_stack_log_lvl(NULL, regs, ®s->sp, | ||
248 | 0, KERN_EMERG); | ||
249 | |||
250 | printk(KERN_EMERG "Code: "); | ||
251 | |||
252 | ip = (u8 *)regs->ip - code_prologue; | ||
253 | if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { | ||
254 | /* try starting at IP */ | ||
255 | ip = (u8 *)regs->ip; | ||
256 | code_len = code_len - code_prologue + 1; | ||
257 | } | ||
258 | for (i = 0; i < code_len; i++, ip++) { | ||
259 | if (ip < (u8 *)PAGE_OFFSET || | ||
260 | probe_kernel_address(ip, c)) { | ||
261 | printk(" Bad EIP value."); | ||
262 | break; | ||
263 | } | ||
264 | if (ip == (u8 *)regs->ip) | ||
265 | printk("<%02x> ", c); | ||
266 | else | ||
267 | printk("%02x ", c); | ||
268 | } | ||
269 | } | ||
270 | printk("\n"); | ||
271 | } | ||
272 | |||
273 | int is_valid_bugaddr(unsigned long ip) | ||
274 | { | ||
275 | unsigned short ud2; | ||
276 | |||
277 | if (ip < PAGE_OFFSET) | ||
278 | return 0; | ||
279 | if (probe_kernel_address((unsigned short *)ip, ud2)) | ||
280 | return 0; | ||
281 | |||
282 | return ud2 == 0x0b0f; | ||
283 | } | ||
284 | |||
285 | static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED; | ||
286 | static int die_owner = -1; | ||
287 | static unsigned int die_nest_count; | ||
288 | |||
289 | unsigned __kprobes long oops_begin(void) | ||
290 | { | ||
291 | unsigned long flags; | ||
292 | |||
293 | oops_enter(); | ||
294 | |||
295 | if (die_owner != raw_smp_processor_id()) { | ||
296 | console_verbose(); | ||
297 | raw_local_irq_save(flags); | ||
298 | __raw_spin_lock(&die_lock); | ||
299 | die_owner = smp_processor_id(); | ||
300 | die_nest_count = 0; | ||
301 | bust_spinlocks(1); | ||
302 | } else { | ||
303 | raw_local_irq_save(flags); | ||
304 | } | ||
305 | die_nest_count++; | ||
306 | return flags; | ||
307 | } | ||
308 | |||
309 | void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr) | ||
310 | { | ||
311 | bust_spinlocks(0); | ||
312 | die_owner = -1; | ||
313 | add_taint(TAINT_DIE); | ||
314 | __raw_spin_unlock(&die_lock); | ||
315 | raw_local_irq_restore(flags); | ||
316 | |||
317 | if (!regs) | ||
318 | return; | ||
319 | |||
320 | if (kexec_should_crash(current)) | ||
321 | crash_kexec(regs); | ||
322 | if (in_interrupt()) | ||
323 | panic("Fatal exception in interrupt"); | ||
324 | if (panic_on_oops) | ||
325 | panic("Fatal exception"); | ||
326 | oops_exit(); | ||
327 | do_exit(signr); | ||
328 | } | ||
329 | |||
330 | int __kprobes __die(const char *str, struct pt_regs *regs, long err) | ||
331 | { | ||
332 | unsigned short ss; | ||
333 | unsigned long sp; | ||
334 | |||
335 | printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter); | ||
336 | #ifdef CONFIG_PREEMPT | ||
337 | printk("PREEMPT "); | ||
338 | #endif | ||
339 | #ifdef CONFIG_SMP | ||
340 | printk("SMP "); | ||
341 | #endif | ||
342 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
343 | printk("DEBUG_PAGEALLOC"); | ||
344 | #endif | ||
345 | printk("\n"); | ||
346 | if (notify_die(DIE_OOPS, str, regs, err, | ||
347 | current->thread.trap_no, SIGSEGV) == NOTIFY_STOP) | ||
348 | return 1; | ||
349 | |||
350 | show_registers(regs); | ||
351 | /* Executive summary in case the oops scrolled away */ | ||
352 | sp = (unsigned long) (®s->sp); | ||
353 | savesegment(ss, ss); | ||
354 | if (user_mode(regs)) { | ||
355 | sp = regs->sp; | ||
356 | ss = regs->ss & 0xffff; | ||
357 | } | ||
358 | printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip); | ||
359 | print_symbol("%s", regs->ip); | ||
360 | printk(" SS:ESP %04x:%08lx\n", ss, sp); | ||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | /* | ||
365 | * This is gone through when something in the kernel has done something bad | ||
366 | * and is about to be terminated: | ||
367 | */ | ||
368 | void die(const char *str, struct pt_regs *regs, long err) | ||
369 | { | ||
370 | unsigned long flags = oops_begin(); | ||
371 | |||
372 | if (die_nest_count < 3) { | ||
373 | report_bug(regs->ip, regs); | ||
374 | |||
375 | if (__die(str, regs, err)) | ||
376 | regs = NULL; | ||
377 | } else { | ||
378 | printk(KERN_EMERG "Recursive die() failure, output suppressed\n"); | ||
379 | } | ||
380 | |||
381 | oops_end(flags, regs, SIGSEGV); | ||
382 | } | ||
383 | |||
384 | static DEFINE_SPINLOCK(nmi_print_lock); | ||
385 | |||
386 | void notrace __kprobes | ||
387 | die_nmi(char *str, struct pt_regs *regs, int do_panic) | ||
388 | { | ||
389 | if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP) | ||
390 | return; | ||
391 | |||
392 | spin_lock(&nmi_print_lock); | ||
393 | /* | ||
394 | * We are in trouble anyway, lets at least try | ||
395 | * to get a message out: | ||
396 | */ | ||
397 | bust_spinlocks(1); | ||
398 | printk(KERN_EMERG "%s", str); | ||
399 | printk(" on CPU%d, ip %08lx, registers:\n", | ||
400 | smp_processor_id(), regs->ip); | ||
401 | show_registers(regs); | ||
402 | if (do_panic) | ||
403 | panic("Non maskable interrupt"); | ||
404 | console_silent(); | ||
405 | spin_unlock(&nmi_print_lock); | ||
406 | bust_spinlocks(0); | ||
407 | |||
408 | /* | ||
409 | * If we are in kernel we are probably nested up pretty bad | ||
410 | * and might aswell get out now while we still can: | ||
411 | */ | ||
412 | if (!user_mode_vm(regs)) { | ||
413 | current->thread.trap_no = 2; | ||
414 | crash_kexec(regs); | ||
415 | } | ||
416 | |||
417 | do_exit(SIGSEGV); | ||
418 | } | ||
419 | |||
420 | static int __init oops_setup(char *s) | ||
421 | { | ||
422 | if (!s) | ||
423 | return -EINVAL; | ||
424 | if (!strcmp(s, "panic")) | ||
425 | panic_on_oops = 1; | ||
426 | return 0; | ||
427 | } | ||
428 | early_param("oops", oops_setup); | ||
429 | |||
430 | static int __init kstack_setup(char *s) | ||
431 | { | ||
432 | if (!s) | ||
433 | return -EINVAL; | ||
434 | kstack_depth_to_print = simple_strtoul(s, NULL, 0); | ||
435 | return 0; | ||
436 | } | ||
437 | early_param("kstack", kstack_setup); | ||
438 | |||
439 | static int __init code_bytes_setup(char *s) | ||
440 | { | ||
441 | code_bytes = simple_strtoul(s, NULL, 0); | ||
442 | if (code_bytes > 8192) | ||
443 | code_bytes = 8192; | ||
444 | |||
445 | return 1; | ||
446 | } | ||
447 | __setup("code_bytes=", code_bytes_setup); | ||
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c new file mode 100644 index 000000000000..086cc8118e39 --- /dev/null +++ b/arch/x86/kernel/dumpstack_64.c | |||
@@ -0,0 +1,573 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
3 | * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs | ||
4 | */ | ||
5 | #include <linux/kallsyms.h> | ||
6 | #include <linux/kprobes.h> | ||
7 | #include <linux/uaccess.h> | ||
8 | #include <linux/utsname.h> | ||
9 | #include <linux/hardirq.h> | ||
10 | #include <linux/kdebug.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/ptrace.h> | ||
13 | #include <linux/kexec.h> | ||
14 | #include <linux/bug.h> | ||
15 | #include <linux/nmi.h> | ||
16 | |||
17 | #include <asm/stacktrace.h> | ||
18 | |||
19 | #define STACKSLOTS_PER_LINE 4 | ||
20 | #define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :) | ||
21 | |||
22 | int panic_on_unrecovered_nmi; | ||
23 | int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE; | ||
24 | static unsigned int code_bytes = 64; | ||
25 | static int die_counter; | ||
26 | |||
27 | void printk_address(unsigned long address, int reliable) | ||
28 | { | ||
29 | printk(" [<%p>] %s%pS\n", (void *) address, | ||
30 | reliable ? "" : "? ", (void *) address); | ||
31 | } | ||
32 | |||
33 | static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, | ||
34 | unsigned *usedp, char **idp) | ||
35 | { | ||
36 | static char ids[][8] = { | ||
37 | [DEBUG_STACK - 1] = "#DB", | ||
38 | [NMI_STACK - 1] = "NMI", | ||
39 | [DOUBLEFAULT_STACK - 1] = "#DF", | ||
40 | [STACKFAULT_STACK - 1] = "#SS", | ||
41 | [MCE_STACK - 1] = "#MC", | ||
42 | #if DEBUG_STKSZ > EXCEPTION_STKSZ | ||
43 | [N_EXCEPTION_STACKS ... | ||
44 | N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]" | ||
45 | #endif | ||
46 | }; | ||
47 | unsigned k; | ||
48 | |||
49 | /* | ||
50 | * Iterate over all exception stacks, and figure out whether | ||
51 | * 'stack' is in one of them: | ||
52 | */ | ||
53 | for (k = 0; k < N_EXCEPTION_STACKS; k++) { | ||
54 | unsigned long end = per_cpu(orig_ist, cpu).ist[k]; | ||
55 | /* | ||
56 | * Is 'stack' above this exception frame's end? | ||
57 | * If yes then skip to the next frame. | ||
58 | */ | ||
59 | if (stack >= end) | ||
60 | continue; | ||
61 | /* | ||
62 | * Is 'stack' above this exception frame's start address? | ||
63 | * If yes then we found the right frame. | ||
64 | */ | ||
65 | if (stack >= end - EXCEPTION_STKSZ) { | ||
66 | /* | ||
67 | * Make sure we only iterate through an exception | ||
68 | * stack once. If it comes up for the second time | ||
69 | * then there's something wrong going on - just | ||
70 | * break out and return NULL: | ||
71 | */ | ||
72 | if (*usedp & (1U << k)) | ||
73 | break; | ||
74 | *usedp |= 1U << k; | ||
75 | *idp = ids[k]; | ||
76 | return (unsigned long *)end; | ||
77 | } | ||
78 | /* | ||
79 | * If this is a debug stack, and if it has a larger size than | ||
80 | * the usual exception stacks, then 'stack' might still | ||
81 | * be within the lower portion of the debug stack: | ||
82 | */ | ||
83 | #if DEBUG_STKSZ > EXCEPTION_STKSZ | ||
84 | if (k == DEBUG_STACK - 1 && stack >= end - DEBUG_STKSZ) { | ||
85 | unsigned j = N_EXCEPTION_STACKS - 1; | ||
86 | |||
87 | /* | ||
88 | * Black magic. A large debug stack is composed of | ||
89 | * multiple exception stack entries, which we | ||
90 | * iterate through now. Dont look: | ||
91 | */ | ||
92 | do { | ||
93 | ++j; | ||
94 | end -= EXCEPTION_STKSZ; | ||
95 | ids[j][4] = '1' + (j - N_EXCEPTION_STACKS); | ||
96 | } while (stack < end - EXCEPTION_STKSZ); | ||
97 | if (*usedp & (1U << j)) | ||
98 | break; | ||
99 | *usedp |= 1U << j; | ||
100 | *idp = ids[j]; | ||
101 | return (unsigned long *)end; | ||
102 | } | ||
103 | #endif | ||
104 | } | ||
105 | return NULL; | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * x86-64 can have up to three kernel stacks: | ||
110 | * process stack | ||
111 | * interrupt stack | ||
112 | * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack | ||
113 | */ | ||
114 | |||
115 | static inline int valid_stack_ptr(struct thread_info *tinfo, | ||
116 | void *p, unsigned int size, void *end) | ||
117 | { | ||
118 | void *t = tinfo; | ||
119 | if (end) { | ||
120 | if (p < end && p >= (end-THREAD_SIZE)) | ||
121 | return 1; | ||
122 | else | ||
123 | return 0; | ||
124 | } | ||
125 | return p > t && p < t + THREAD_SIZE - size; | ||
126 | } | ||
127 | |||
128 | /* The form of the top of the frame on the stack */ | ||
129 | struct stack_frame { | ||
130 | struct stack_frame *next_frame; | ||
131 | unsigned long return_address; | ||
132 | }; | ||
133 | |||
134 | static inline unsigned long | ||
135 | print_context_stack(struct thread_info *tinfo, | ||
136 | unsigned long *stack, unsigned long bp, | ||
137 | const struct stacktrace_ops *ops, void *data, | ||
138 | unsigned long *end) | ||
139 | { | ||
140 | struct stack_frame *frame = (struct stack_frame *)bp; | ||
141 | |||
142 | while (valid_stack_ptr(tinfo, stack, sizeof(*stack), end)) { | ||
143 | unsigned long addr; | ||
144 | |||
145 | addr = *stack; | ||
146 | if (__kernel_text_address(addr)) { | ||
147 | if ((unsigned long) stack == bp + sizeof(long)) { | ||
148 | ops->address(data, addr, 1); | ||
149 | frame = frame->next_frame; | ||
150 | bp = (unsigned long) frame; | ||
151 | } else { | ||
152 | ops->address(data, addr, bp == 0); | ||
153 | } | ||
154 | } | ||
155 | stack++; | ||
156 | } | ||
157 | return bp; | ||
158 | } | ||
159 | |||
160 | void dump_trace(struct task_struct *task, struct pt_regs *regs, | ||
161 | unsigned long *stack, unsigned long bp, | ||
162 | const struct stacktrace_ops *ops, void *data) | ||
163 | { | ||
164 | const unsigned cpu = get_cpu(); | ||
165 | unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; | ||
166 | unsigned used = 0; | ||
167 | struct thread_info *tinfo; | ||
168 | |||
169 | if (!task) | ||
170 | task = current; | ||
171 | |||
172 | if (!stack) { | ||
173 | unsigned long dummy; | ||
174 | stack = &dummy; | ||
175 | if (task && task != current) | ||
176 | stack = (unsigned long *)task->thread.sp; | ||
177 | } | ||
178 | |||
179 | #ifdef CONFIG_FRAME_POINTER | ||
180 | if (!bp) { | ||
181 | if (task == current) { | ||
182 | /* Grab bp right from our regs */ | ||
183 | get_bp(bp); | ||
184 | } else { | ||
185 | /* bp is the last reg pushed by switch_to */ | ||
186 | bp = *(unsigned long *) task->thread.sp; | ||
187 | } | ||
188 | } | ||
189 | #endif | ||
190 | |||
191 | /* | ||
192 | * Print function call entries in all stacks, starting at the | ||
193 | * current stack address. If the stacks consist of nested | ||
194 | * exceptions | ||
195 | */ | ||
196 | tinfo = task_thread_info(task); | ||
197 | for (;;) { | ||
198 | char *id; | ||
199 | unsigned long *estack_end; | ||
200 | estack_end = in_exception_stack(cpu, (unsigned long)stack, | ||
201 | &used, &id); | ||
202 | |||
203 | if (estack_end) { | ||
204 | if (ops->stack(data, id) < 0) | ||
205 | break; | ||
206 | |||
207 | bp = print_context_stack(tinfo, stack, bp, ops, | ||
208 | data, estack_end); | ||
209 | ops->stack(data, "<EOE>"); | ||
210 | /* | ||
211 | * We link to the next stack via the | ||
212 | * second-to-last pointer (index -2 to end) in the | ||
213 | * exception stack: | ||
214 | */ | ||
215 | stack = (unsigned long *) estack_end[-2]; | ||
216 | continue; | ||
217 | } | ||
218 | if (irqstack_end) { | ||
219 | unsigned long *irqstack; | ||
220 | irqstack = irqstack_end - | ||
221 | (IRQSTACKSIZE - 64) / sizeof(*irqstack); | ||
222 | |||
223 | if (stack >= irqstack && stack < irqstack_end) { | ||
224 | if (ops->stack(data, "IRQ") < 0) | ||
225 | break; | ||
226 | bp = print_context_stack(tinfo, stack, bp, | ||
227 | ops, data, irqstack_end); | ||
228 | /* | ||
229 | * We link to the next stack (which would be | ||
230 | * the process stack normally) the last | ||
231 | * pointer (index -1 to end) in the IRQ stack: | ||
232 | */ | ||
233 | stack = (unsigned long *) (irqstack_end[-1]); | ||
234 | irqstack_end = NULL; | ||
235 | ops->stack(data, "EOI"); | ||
236 | continue; | ||
237 | } | ||
238 | } | ||
239 | break; | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | * This handles the process stack: | ||
244 | */ | ||
245 | bp = print_context_stack(tinfo, stack, bp, ops, data, NULL); | ||
246 | put_cpu(); | ||
247 | } | ||
248 | EXPORT_SYMBOL(dump_trace); | ||
249 | |||
250 | static void | ||
251 | print_trace_warning_symbol(void *data, char *msg, unsigned long symbol) | ||
252 | { | ||
253 | printk(data); | ||
254 | print_symbol(msg, symbol); | ||
255 | printk("\n"); | ||
256 | } | ||
257 | |||
258 | static void print_trace_warning(void *data, char *msg) | ||
259 | { | ||
260 | printk("%s%s\n", (char *)data, msg); | ||
261 | } | ||
262 | |||
263 | static int print_trace_stack(void *data, char *name) | ||
264 | { | ||
265 | printk("%s <%s> ", (char *)data, name); | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | /* | ||
270 | * Print one address/symbol entries per line. | ||
271 | */ | ||
272 | static void print_trace_address(void *data, unsigned long addr, int reliable) | ||
273 | { | ||
274 | touch_nmi_watchdog(); | ||
275 | printk(data); | ||
276 | printk_address(addr, reliable); | ||
277 | } | ||
278 | |||
279 | static const struct stacktrace_ops print_trace_ops = { | ||
280 | .warning = print_trace_warning, | ||
281 | .warning_symbol = print_trace_warning_symbol, | ||
282 | .stack = print_trace_stack, | ||
283 | .address = print_trace_address, | ||
284 | }; | ||
285 | |||
286 | static void | ||
287 | show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, | ||
288 | unsigned long *stack, unsigned long bp, char *log_lvl) | ||
289 | { | ||
290 | printk("%sCall Trace:\n", log_lvl); | ||
291 | dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl); | ||
292 | } | ||
293 | |||
294 | void show_trace(struct task_struct *task, struct pt_regs *regs, | ||
295 | unsigned long *stack, unsigned long bp) | ||
296 | { | ||
297 | show_trace_log_lvl(task, regs, stack, bp, ""); | ||
298 | } | ||
299 | |||
300 | static void | ||
301 | show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, | ||
302 | unsigned long *sp, unsigned long bp, char *log_lvl) | ||
303 | { | ||
304 | unsigned long *stack; | ||
305 | int i; | ||
306 | const int cpu = smp_processor_id(); | ||
307 | unsigned long *irqstack_end = | ||
308 | (unsigned long *) (cpu_pda(cpu)->irqstackptr); | ||
309 | unsigned long *irqstack = | ||
310 | (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE); | ||
311 | |||
312 | /* | ||
313 | * debugging aid: "show_stack(NULL, NULL);" prints the | ||
314 | * back trace for this cpu. | ||
315 | */ | ||
316 | |||
317 | if (sp == NULL) { | ||
318 | if (task) | ||
319 | sp = (unsigned long *)task->thread.sp; | ||
320 | else | ||
321 | sp = (unsigned long *)&sp; | ||
322 | } | ||
323 | |||
324 | stack = sp; | ||
325 | for (i = 0; i < kstack_depth_to_print; i++) { | ||
326 | if (stack >= irqstack && stack <= irqstack_end) { | ||
327 | if (stack == irqstack_end) { | ||
328 | stack = (unsigned long *) (irqstack_end[-1]); | ||
329 | printk(" <EOI> "); | ||
330 | } | ||
331 | } else { | ||
332 | if (((long) stack & (THREAD_SIZE-1)) == 0) | ||
333 | break; | ||
334 | } | ||
335 | if (i && ((i % STACKSLOTS_PER_LINE) == 0)) | ||
336 | printk("\n%s", log_lvl); | ||
337 | printk(" %016lx", *stack++); | ||
338 | touch_nmi_watchdog(); | ||
339 | } | ||
340 | printk("\n"); | ||
341 | show_trace_log_lvl(task, regs, sp, bp, log_lvl); | ||
342 | } | ||
343 | |||
344 | void show_stack(struct task_struct *task, unsigned long *sp) | ||
345 | { | ||
346 | show_stack_log_lvl(task, NULL, sp, 0, ""); | ||
347 | } | ||
348 | |||
349 | /* | ||
350 | * The architecture-independent dump_stack generator | ||
351 | */ | ||
352 | void dump_stack(void) | ||
353 | { | ||
354 | unsigned long bp = 0; | ||
355 | unsigned long stack; | ||
356 | |||
357 | #ifdef CONFIG_FRAME_POINTER | ||
358 | if (!bp) | ||
359 | get_bp(bp); | ||
360 | #endif | ||
361 | |||
362 | printk("Pid: %d, comm: %.20s %s %s %.*s\n", | ||
363 | current->pid, current->comm, print_tainted(), | ||
364 | init_utsname()->release, | ||
365 | (int)strcspn(init_utsname()->version, " "), | ||
366 | init_utsname()->version); | ||
367 | show_trace(NULL, NULL, &stack, bp); | ||
368 | } | ||
369 | EXPORT_SYMBOL(dump_stack); | ||
370 | |||
371 | void show_registers(struct pt_regs *regs) | ||
372 | { | ||
373 | int i; | ||
374 | unsigned long sp; | ||
375 | const int cpu = smp_processor_id(); | ||
376 | struct task_struct *cur = cpu_pda(cpu)->pcurrent; | ||
377 | |||
378 | sp = regs->sp; | ||
379 | printk("CPU %d ", cpu); | ||
380 | __show_regs(regs, 1); | ||
381 | printk("Process %s (pid: %d, threadinfo %p, task %p)\n", | ||
382 | cur->comm, cur->pid, task_thread_info(cur), cur); | ||
383 | |||
384 | /* | ||
385 | * When in-kernel, we also print out the stack and code at the | ||
386 | * time of the fault.. | ||
387 | */ | ||
388 | if (!user_mode(regs)) { | ||
389 | unsigned int code_prologue = code_bytes * 43 / 64; | ||
390 | unsigned int code_len = code_bytes; | ||
391 | unsigned char c; | ||
392 | u8 *ip; | ||
393 | |||
394 | printk(KERN_EMERG "Stack:\n"); | ||
395 | show_stack_log_lvl(NULL, regs, (unsigned long *)sp, | ||
396 | regs->bp, KERN_EMERG); | ||
397 | |||
398 | printk(KERN_EMERG "Code: "); | ||
399 | |||
400 | ip = (u8 *)regs->ip - code_prologue; | ||
401 | if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { | ||
402 | /* try starting at IP */ | ||
403 | ip = (u8 *)regs->ip; | ||
404 | code_len = code_len - code_prologue + 1; | ||
405 | } | ||
406 | for (i = 0; i < code_len; i++, ip++) { | ||
407 | if (ip < (u8 *)PAGE_OFFSET || | ||
408 | probe_kernel_address(ip, c)) { | ||
409 | printk(" Bad RIP value."); | ||
410 | break; | ||
411 | } | ||
412 | if (ip == (u8 *)regs->ip) | ||
413 | printk("<%02x> ", c); | ||
414 | else | ||
415 | printk("%02x ", c); | ||
416 | } | ||
417 | } | ||
418 | printk("\n"); | ||
419 | } | ||
420 | |||
421 | int is_valid_bugaddr(unsigned long ip) | ||
422 | { | ||
423 | unsigned short ud2; | ||
424 | |||
425 | if (__copy_from_user(&ud2, (const void __user *) ip, sizeof(ud2))) | ||
426 | return 0; | ||
427 | |||
428 | return ud2 == 0x0b0f; | ||
429 | } | ||
430 | |||
431 | static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED; | ||
432 | static int die_owner = -1; | ||
433 | static unsigned int die_nest_count; | ||
434 | |||
435 | unsigned __kprobes long oops_begin(void) | ||
436 | { | ||
437 | int cpu; | ||
438 | unsigned long flags; | ||
439 | |||
440 | oops_enter(); | ||
441 | |||
442 | /* racy, but better than risking deadlock. */ | ||
443 | raw_local_irq_save(flags); | ||
444 | cpu = smp_processor_id(); | ||
445 | if (!__raw_spin_trylock(&die_lock)) { | ||
446 | if (cpu == die_owner) | ||
447 | /* nested oops. should stop eventually */; | ||
448 | else | ||
449 | __raw_spin_lock(&die_lock); | ||
450 | } | ||
451 | die_nest_count++; | ||
452 | die_owner = cpu; | ||
453 | console_verbose(); | ||
454 | bust_spinlocks(1); | ||
455 | return flags; | ||
456 | } | ||
457 | |||
458 | void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr) | ||
459 | { | ||
460 | die_owner = -1; | ||
461 | bust_spinlocks(0); | ||
462 | die_nest_count--; | ||
463 | if (!die_nest_count) | ||
464 | /* Nest count reaches zero, release the lock. */ | ||
465 | __raw_spin_unlock(&die_lock); | ||
466 | raw_local_irq_restore(flags); | ||
467 | if (!regs) { | ||
468 | oops_exit(); | ||
469 | return; | ||
470 | } | ||
471 | if (in_interrupt()) | ||
472 | panic("Fatal exception in interrupt"); | ||
473 | if (panic_on_oops) | ||
474 | panic("Fatal exception"); | ||
475 | oops_exit(); | ||
476 | do_exit(signr); | ||
477 | } | ||
478 | |||
479 | int __kprobes __die(const char *str, struct pt_regs *regs, long err) | ||
480 | { | ||
481 | printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter); | ||
482 | #ifdef CONFIG_PREEMPT | ||
483 | printk("PREEMPT "); | ||
484 | #endif | ||
485 | #ifdef CONFIG_SMP | ||
486 | printk("SMP "); | ||
487 | #endif | ||
488 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
489 | printk("DEBUG_PAGEALLOC"); | ||
490 | #endif | ||
491 | printk("\n"); | ||
492 | if (notify_die(DIE_OOPS, str, regs, err, | ||
493 | current->thread.trap_no, SIGSEGV) == NOTIFY_STOP) | ||
494 | return 1; | ||
495 | |||
496 | show_registers(regs); | ||
497 | add_taint(TAINT_DIE); | ||
498 | /* Executive summary in case the oops scrolled away */ | ||
499 | printk(KERN_ALERT "RIP "); | ||
500 | printk_address(regs->ip, 1); | ||
501 | printk(" RSP <%016lx>\n", regs->sp); | ||
502 | if (kexec_should_crash(current)) | ||
503 | crash_kexec(regs); | ||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | void die(const char *str, struct pt_regs *regs, long err) | ||
508 | { | ||
509 | unsigned long flags = oops_begin(); | ||
510 | |||
511 | if (!user_mode(regs)) | ||
512 | report_bug(regs->ip, regs); | ||
513 | |||
514 | if (__die(str, regs, err)) | ||
515 | regs = NULL; | ||
516 | oops_end(flags, regs, SIGSEGV); | ||
517 | } | ||
518 | |||
519 | notrace __kprobes void | ||
520 | die_nmi(char *str, struct pt_regs *regs, int do_panic) | ||
521 | { | ||
522 | unsigned long flags; | ||
523 | |||
524 | if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP) | ||
525 | return; | ||
526 | |||
527 | flags = oops_begin(); | ||
528 | /* | ||
529 | * We are in trouble anyway, lets at least try | ||
530 | * to get a message out. | ||
531 | */ | ||
532 | printk(KERN_EMERG "%s", str); | ||
533 | printk(" on CPU%d, ip %08lx, registers:\n", | ||
534 | smp_processor_id(), regs->ip); | ||
535 | show_registers(regs); | ||
536 | if (kexec_should_crash(current)) | ||
537 | crash_kexec(regs); | ||
538 | if (do_panic || panic_on_oops) | ||
539 | panic("Non maskable interrupt"); | ||
540 | oops_end(flags, NULL, SIGBUS); | ||
541 | nmi_exit(); | ||
542 | local_irq_enable(); | ||
543 | do_exit(SIGBUS); | ||
544 | } | ||
545 | |||
546 | static int __init oops_setup(char *s) | ||
547 | { | ||
548 | if (!s) | ||
549 | return -EINVAL; | ||
550 | if (!strcmp(s, "panic")) | ||
551 | panic_on_oops = 1; | ||
552 | return 0; | ||
553 | } | ||
554 | early_param("oops", oops_setup); | ||
555 | |||
556 | static int __init kstack_setup(char *s) | ||
557 | { | ||
558 | if (!s) | ||
559 | return -EINVAL; | ||
560 | kstack_depth_to_print = simple_strtoul(s, NULL, 0); | ||
561 | return 0; | ||
562 | } | ||
563 | early_param("kstack", kstack_setup); | ||
564 | |||
565 | static int __init code_bytes_setup(char *s) | ||
566 | { | ||
567 | code_bytes = simple_strtoul(s, NULL, 0); | ||
568 | if (code_bytes > 8192) | ||
569 | code_bytes = 8192; | ||
570 | |||
571 | return 1; | ||
572 | } | ||
573 | __setup("code_bytes=", code_bytes_setup); | ||
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 109792bc7cfa..b21fbfaffe39 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -730,6 +730,7 @@ error_code: | |||
730 | movl $(__USER_DS), %ecx | 730 | movl $(__USER_DS), %ecx |
731 | movl %ecx, %ds | 731 | movl %ecx, %ds |
732 | movl %ecx, %es | 732 | movl %ecx, %es |
733 | TRACE_IRQS_OFF | ||
733 | movl %esp,%eax # pt_regs pointer | 734 | movl %esp,%eax # pt_regs pointer |
734 | call *%edi | 735 | call *%edi |
735 | jmp ret_from_exception | 736 | jmp ret_from_exception |
@@ -760,20 +761,9 @@ ENTRY(device_not_available) | |||
760 | RING0_INT_FRAME | 761 | RING0_INT_FRAME |
761 | pushl $-1 # mark this as an int | 762 | pushl $-1 # mark this as an int |
762 | CFI_ADJUST_CFA_OFFSET 4 | 763 | CFI_ADJUST_CFA_OFFSET 4 |
763 | SAVE_ALL | 764 | pushl $do_device_not_available |
764 | GET_CR0_INTO_EAX | ||
765 | testl $0x4, %eax # EM (math emulation bit) | ||
766 | jne device_not_available_emulate | ||
767 | preempt_stop(CLBR_ANY) | ||
768 | call math_state_restore | ||
769 | jmp ret_from_exception | ||
770 | device_not_available_emulate: | ||
771 | pushl $0 # temporary storage for ORIG_EIP | ||
772 | CFI_ADJUST_CFA_OFFSET 4 | 765 | CFI_ADJUST_CFA_OFFSET 4 |
773 | call math_emulate | 766 | jmp error_code |
774 | addl $4, %esp | ||
775 | CFI_ADJUST_CFA_OFFSET -4 | ||
776 | jmp ret_from_exception | ||
777 | CFI_ENDPROC | 767 | CFI_ENDPROC |
778 | END(device_not_available) | 768 | END(device_not_available) |
779 | 769 | ||
@@ -814,6 +804,7 @@ debug_stack_correct: | |||
814 | pushl $-1 # mark this as an int | 804 | pushl $-1 # mark this as an int |
815 | CFI_ADJUST_CFA_OFFSET 4 | 805 | CFI_ADJUST_CFA_OFFSET 4 |
816 | SAVE_ALL | 806 | SAVE_ALL |
807 | TRACE_IRQS_OFF | ||
817 | xorl %edx,%edx # error code 0 | 808 | xorl %edx,%edx # error code 0 |
818 | movl %esp,%eax # pt_regs pointer | 809 | movl %esp,%eax # pt_regs pointer |
819 | call do_debug | 810 | call do_debug |
@@ -858,6 +849,7 @@ nmi_stack_correct: | |||
858 | pushl %eax | 849 | pushl %eax |
859 | CFI_ADJUST_CFA_OFFSET 4 | 850 | CFI_ADJUST_CFA_OFFSET 4 |
860 | SAVE_ALL | 851 | SAVE_ALL |
852 | TRACE_IRQS_OFF | ||
861 | xorl %edx,%edx # zero error code | 853 | xorl %edx,%edx # zero error code |
862 | movl %esp,%eax # pt_regs pointer | 854 | movl %esp,%eax # pt_regs pointer |
863 | call do_nmi | 855 | call do_nmi |
@@ -898,6 +890,7 @@ nmi_espfix_stack: | |||
898 | pushl %eax | 890 | pushl %eax |
899 | CFI_ADJUST_CFA_OFFSET 4 | 891 | CFI_ADJUST_CFA_OFFSET 4 |
900 | SAVE_ALL | 892 | SAVE_ALL |
893 | TRACE_IRQS_OFF | ||
901 | FIXUP_ESPFIX_STACK # %eax == %esp | 894 | FIXUP_ESPFIX_STACK # %eax == %esp |
902 | xorl %edx,%edx # zero error code | 895 | xorl %edx,%edx # zero error code |
903 | call do_nmi | 896 | call do_nmi |
@@ -928,6 +921,7 @@ KPROBE_ENTRY(int3) | |||
928 | pushl $-1 # mark this as an int | 921 | pushl $-1 # mark this as an int |
929 | CFI_ADJUST_CFA_OFFSET 4 | 922 | CFI_ADJUST_CFA_OFFSET 4 |
930 | SAVE_ALL | 923 | SAVE_ALL |
924 | TRACE_IRQS_OFF | ||
931 | xorl %edx,%edx # zero error code | 925 | xorl %edx,%edx # zero error code |
932 | movl %esp,%eax # pt_regs pointer | 926 | movl %esp,%eax # pt_regs pointer |
933 | call do_int3 | 927 | call do_int3 |
@@ -1030,7 +1024,7 @@ ENTRY(machine_check) | |||
1030 | RING0_INT_FRAME | 1024 | RING0_INT_FRAME |
1031 | pushl $0 | 1025 | pushl $0 |
1032 | CFI_ADJUST_CFA_OFFSET 4 | 1026 | CFI_ADJUST_CFA_OFFSET 4 |
1033 | pushl machine_check_vector | 1027 | pushl $do_machine_check |
1034 | CFI_ADJUST_CFA_OFFSET 4 | 1028 | CFI_ADJUST_CFA_OFFSET 4 |
1035 | jmp error_code | 1029 | jmp error_code |
1036 | CFI_ENDPROC | 1030 | CFI_ENDPROC |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index cf3a0b2d0059..1db6ce4314e1 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -667,6 +667,13 @@ END(stub_rt_sigreturn) | |||
667 | SAVE_ARGS | 667 | SAVE_ARGS |
668 | leaq -ARGOFFSET(%rsp),%rdi # arg1 for handler | 668 | leaq -ARGOFFSET(%rsp),%rdi # arg1 for handler |
669 | pushq %rbp | 669 | pushq %rbp |
670 | /* | ||
671 | * Save rbp twice: One is for marking the stack frame, as usual, and the | ||
672 | * other, to fill pt_regs properly. This is because bx comes right | ||
673 | * before the last saved register in that structure, and not bp. If the | ||
674 | * base pointer were in the place bx is today, this would not be needed. | ||
675 | */ | ||
676 | movq %rbp, -8(%rsp) | ||
670 | CFI_ADJUST_CFA_OFFSET 8 | 677 | CFI_ADJUST_CFA_OFFSET 8 |
671 | CFI_REL_OFFSET rbp, 0 | 678 | CFI_REL_OFFSET rbp, 0 |
672 | movq %rsp,%rbp | 679 | movq %rsp,%rbp |
@@ -932,6 +939,9 @@ END(spurious_interrupt) | |||
932 | .if \ist | 939 | .if \ist |
933 | movq %gs:pda_data_offset, %rbp | 940 | movq %gs:pda_data_offset, %rbp |
934 | .endif | 941 | .endif |
942 | .if \irqtrace | ||
943 | TRACE_IRQS_OFF | ||
944 | .endif | ||
935 | movq %rsp,%rdi | 945 | movq %rsp,%rdi |
936 | movq ORIG_RAX(%rsp),%rsi | 946 | movq ORIG_RAX(%rsp),%rsi |
937 | movq $-1,ORIG_RAX(%rsp) | 947 | movq $-1,ORIG_RAX(%rsp) |
@@ -1058,7 +1068,8 @@ KPROBE_ENTRY(error_entry) | |||
1058 | je error_kernelspace | 1068 | je error_kernelspace |
1059 | error_swapgs: | 1069 | error_swapgs: |
1060 | SWAPGS | 1070 | SWAPGS |
1061 | error_sti: | 1071 | error_sti: |
1072 | TRACE_IRQS_OFF | ||
1062 | movq %rdi,RDI(%rsp) | 1073 | movq %rdi,RDI(%rsp) |
1063 | CFI_REL_OFFSET rdi,RDI | 1074 | CFI_REL_OFFSET rdi,RDI |
1064 | movq %rsp,%rdi | 1075 | movq %rsp,%rdi |
@@ -1232,7 +1243,7 @@ ENTRY(simd_coprocessor_error) | |||
1232 | END(simd_coprocessor_error) | 1243 | END(simd_coprocessor_error) |
1233 | 1244 | ||
1234 | ENTRY(device_not_available) | 1245 | ENTRY(device_not_available) |
1235 | zeroentry math_state_restore | 1246 | zeroentry do_device_not_available |
1236 | END(device_not_available) | 1247 | END(device_not_available) |
1237 | 1248 | ||
1238 | /* runs on exception stack */ | 1249 | /* runs on exception stack */ |
diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/es7000_32.c index 849e5cd485b8..f454c78fcef6 100644 --- a/arch/x86/kernel/es7000_32.c +++ b/arch/x86/kernel/es7000_32.c | |||
@@ -109,6 +109,7 @@ struct oem_table { | |||
109 | }; | 109 | }; |
110 | 110 | ||
111 | extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); | 111 | extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); |
112 | extern void unmap_unisys_acpi_oem_table(unsigned long oem_addr); | ||
112 | #endif | 113 | #endif |
113 | 114 | ||
114 | struct mip_reg { | 115 | struct mip_reg { |
@@ -243,21 +244,38 @@ parse_unisys_oem (char *oemptr) | |||
243 | } | 244 | } |
244 | 245 | ||
245 | #ifdef CONFIG_ACPI | 246 | #ifdef CONFIG_ACPI |
246 | int __init | 247 | static unsigned long oem_addrX; |
247 | find_unisys_acpi_oem_table(unsigned long *oem_addr) | 248 | static unsigned long oem_size; |
249 | int __init find_unisys_acpi_oem_table(unsigned long *oem_addr) | ||
248 | { | 250 | { |
249 | struct acpi_table_header *header = NULL; | 251 | struct acpi_table_header *header = NULL; |
250 | int i = 0; | 252 | int i = 0; |
251 | while (ACPI_SUCCESS(acpi_get_table("OEM1", i++, &header))) { | 253 | acpi_size tbl_size; |
254 | |||
255 | while (ACPI_SUCCESS(acpi_get_table_with_size("OEM1", i++, &header, &tbl_size))) { | ||
252 | if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) { | 256 | if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) { |
253 | struct oem_table *t = (struct oem_table *)header; | 257 | struct oem_table *t = (struct oem_table *)header; |
254 | *oem_addr = (unsigned long)__acpi_map_table(t->OEMTableAddr, | 258 | |
255 | t->OEMTableSize); | 259 | oem_addrX = t->OEMTableAddr; |
260 | oem_size = t->OEMTableSize; | ||
261 | early_acpi_os_unmap_memory(header, tbl_size); | ||
262 | |||
263 | *oem_addr = (unsigned long)__acpi_map_table(oem_addrX, | ||
264 | oem_size); | ||
256 | return 0; | 265 | return 0; |
257 | } | 266 | } |
267 | early_acpi_os_unmap_memory(header, tbl_size); | ||
258 | } | 268 | } |
259 | return -1; | 269 | return -1; |
260 | } | 270 | } |
271 | |||
272 | void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr) | ||
273 | { | ||
274 | if (!oem_addr) | ||
275 | return; | ||
276 | |||
277 | __acpi_unmap_table((char *)oem_addr, oem_size); | ||
278 | } | ||
261 | #endif | 279 | #endif |
262 | 280 | ||
263 | static void | 281 | static void |
diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/genx2apic_uv_x.c index ae2ffc8a400c..33581d94a90e 100644 --- a/arch/x86/kernel/genx2apic_uv_x.c +++ b/arch/x86/kernel/genx2apic_uv_x.c | |||
@@ -114,7 +114,7 @@ static void uv_send_IPI_one(int cpu, int vector) | |||
114 | unsigned long val, apicid, lapicid; | 114 | unsigned long val, apicid, lapicid; |
115 | int pnode; | 115 | int pnode; |
116 | 116 | ||
117 | apicid = per_cpu(x86_cpu_to_apicid, cpu); /* ZZZ - cache node-local ? */ | 117 | apicid = per_cpu(x86_cpu_to_apicid, cpu); |
118 | lapicid = apicid & 0x3f; /* ZZZ macro needed */ | 118 | lapicid = apicid & 0x3f; /* ZZZ macro needed */ |
119 | pnode = uv_apicid_to_pnode(apicid); | 119 | pnode = uv_apicid_to_pnode(apicid); |
120 | val = | 120 | val = |
@@ -202,12 +202,10 @@ static unsigned int phys_pkg_id(int index_msb) | |||
202 | return uv_read_apic_id() >> index_msb; | 202 | return uv_read_apic_id() >> index_msb; |
203 | } | 203 | } |
204 | 204 | ||
205 | #ifdef ZZZ /* Needs x2apic patch */ | ||
206 | static void uv_send_IPI_self(int vector) | 205 | static void uv_send_IPI_self(int vector) |
207 | { | 206 | { |
208 | apic_write(APIC_SELF_IPI, vector); | 207 | apic_write(APIC_SELF_IPI, vector); |
209 | } | 208 | } |
210 | #endif | ||
211 | 209 | ||
212 | struct genapic apic_x2apic_uv_x = { | 210 | struct genapic apic_x2apic_uv_x = { |
213 | .name = "UV large system", | 211 | .name = "UV large system", |
@@ -215,15 +213,15 @@ struct genapic apic_x2apic_uv_x = { | |||
215 | .int_delivery_mode = dest_Fixed, | 213 | .int_delivery_mode = dest_Fixed, |
216 | .int_dest_mode = (APIC_DEST_PHYSICAL != 0), | 214 | .int_dest_mode = (APIC_DEST_PHYSICAL != 0), |
217 | .target_cpus = uv_target_cpus, | 215 | .target_cpus = uv_target_cpus, |
218 | .vector_allocation_domain = uv_vector_allocation_domain,/* Fixme ZZZ */ | 216 | .vector_allocation_domain = uv_vector_allocation_domain, |
219 | .apic_id_registered = uv_apic_id_registered, | 217 | .apic_id_registered = uv_apic_id_registered, |
220 | .init_apic_ldr = uv_init_apic_ldr, | 218 | .init_apic_ldr = uv_init_apic_ldr, |
221 | .send_IPI_all = uv_send_IPI_all, | 219 | .send_IPI_all = uv_send_IPI_all, |
222 | .send_IPI_allbutself = uv_send_IPI_allbutself, | 220 | .send_IPI_allbutself = uv_send_IPI_allbutself, |
223 | .send_IPI_mask = uv_send_IPI_mask, | 221 | .send_IPI_mask = uv_send_IPI_mask, |
224 | /* ZZZ.send_IPI_self = uv_send_IPI_self, */ | 222 | .send_IPI_self = uv_send_IPI_self, |
225 | .cpu_mask_to_apicid = uv_cpu_mask_to_apicid, | 223 | .cpu_mask_to_apicid = uv_cpu_mask_to_apicid, |
226 | .phys_pkg_id = phys_pkg_id, /* Fixme ZZZ */ | 224 | .phys_pkg_id = phys_pkg_id, |
227 | .get_apic_id = get_apic_id, | 225 | .get_apic_id = get_apic_id, |
228 | .set_apic_id = set_apic_id, | 226 | .set_apic_id = set_apic_id, |
229 | .apic_id_mask = (0xFFFFFFFFu), | 227 | .apic_id_mask = (0xFFFFFFFFu), |
@@ -286,12 +284,13 @@ static __init void map_low_mmrs(void) | |||
286 | 284 | ||
287 | enum map_type {map_wb, map_uc}; | 285 | enum map_type {map_wb, map_uc}; |
288 | 286 | ||
289 | static __init void map_high(char *id, unsigned long base, int shift, enum map_type map_type) | 287 | static __init void map_high(char *id, unsigned long base, int shift, |
288 | int max_pnode, enum map_type map_type) | ||
290 | { | 289 | { |
291 | unsigned long bytes, paddr; | 290 | unsigned long bytes, paddr; |
292 | 291 | ||
293 | paddr = base << shift; | 292 | paddr = base << shift; |
294 | bytes = (1UL << shift); | 293 | bytes = (1UL << shift) * (max_pnode + 1); |
295 | printk(KERN_INFO "UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr, | 294 | printk(KERN_INFO "UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr, |
296 | paddr + bytes); | 295 | paddr + bytes); |
297 | if (map_type == map_uc) | 296 | if (map_type == map_uc) |
@@ -307,7 +306,7 @@ static __init void map_gru_high(int max_pnode) | |||
307 | 306 | ||
308 | gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR); | 307 | gru.v = uv_read_local_mmr(UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR); |
309 | if (gru.s.enable) | 308 | if (gru.s.enable) |
310 | map_high("GRU", gru.s.base, shift, map_wb); | 309 | map_high("GRU", gru.s.base, shift, max_pnode, map_wb); |
311 | } | 310 | } |
312 | 311 | ||
313 | static __init void map_config_high(int max_pnode) | 312 | static __init void map_config_high(int max_pnode) |
@@ -317,7 +316,7 @@ static __init void map_config_high(int max_pnode) | |||
317 | 316 | ||
318 | cfg.v = uv_read_local_mmr(UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR); | 317 | cfg.v = uv_read_local_mmr(UVH_RH_GAM_CFG_OVERLAY_CONFIG_MMR); |
319 | if (cfg.s.enable) | 318 | if (cfg.s.enable) |
320 | map_high("CONFIG", cfg.s.base, shift, map_uc); | 319 | map_high("CONFIG", cfg.s.base, shift, max_pnode, map_uc); |
321 | } | 320 | } |
322 | 321 | ||
323 | static __init void map_mmr_high(int max_pnode) | 322 | static __init void map_mmr_high(int max_pnode) |
@@ -327,7 +326,7 @@ static __init void map_mmr_high(int max_pnode) | |||
327 | 326 | ||
328 | mmr.v = uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR); | 327 | mmr.v = uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR); |
329 | if (mmr.s.enable) | 328 | if (mmr.s.enable) |
330 | map_high("MMR", mmr.s.base, shift, map_uc); | 329 | map_high("MMR", mmr.s.base, shift, max_pnode, map_uc); |
331 | } | 330 | } |
332 | 331 | ||
333 | static __init void map_mmioh_high(int max_pnode) | 332 | static __init void map_mmioh_high(int max_pnode) |
@@ -337,7 +336,7 @@ static __init void map_mmioh_high(int max_pnode) | |||
337 | 336 | ||
338 | mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR); | 337 | mmioh.v = uv_read_local_mmr(UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_MMR); |
339 | if (mmioh.s.enable) | 338 | if (mmioh.s.enable) |
340 | map_high("MMIOH", mmioh.s.base, shift, map_uc); | 339 | map_high("MMIOH", mmioh.s.base, shift, max_pnode, map_uc); |
341 | } | 340 | } |
342 | 341 | ||
343 | static __init void uv_rtc_init(void) | 342 | static __init void uv_rtc_init(void) |
diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/head.c index 3e66bd364a9d..1dcb0f13897e 100644 --- a/arch/x86/kernel/head.c +++ b/arch/x86/kernel/head.c | |||
@@ -35,6 +35,7 @@ void __init reserve_ebda_region(void) | |||
35 | 35 | ||
36 | /* start of EBDA area */ | 36 | /* start of EBDA area */ |
37 | ebda_addr = get_bios_ebda(); | 37 | ebda_addr = get_bios_ebda(); |
38 | printk(KERN_INFO "BIOS EBDA/lowmem at: %08x/%08x\n", ebda_addr, lowmem); | ||
38 | 39 | ||
39 | /* Fixup: bios puts an EBDA in the top 64K segment */ | 40 | /* Fixup: bios puts an EBDA in the top 64K segment */ |
40 | /* of conventional memory, but does not adjust lowmem. */ | 41 | /* of conventional memory, but does not adjust lowmem. */ |
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 73deaffadd03..acf62fc233da 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c | |||
@@ -115,13 +115,17 @@ static void hpet_reserve_platform_timers(unsigned long id) | |||
115 | hd.hd_phys_address = hpet_address; | 115 | hd.hd_phys_address = hpet_address; |
116 | hd.hd_address = hpet; | 116 | hd.hd_address = hpet; |
117 | hd.hd_nirqs = nrtimers; | 117 | hd.hd_nirqs = nrtimers; |
118 | hd.hd_flags = HPET_DATA_PLATFORM; | ||
119 | hpet_reserve_timer(&hd, 0); | 118 | hpet_reserve_timer(&hd, 0); |
120 | 119 | ||
121 | #ifdef CONFIG_HPET_EMULATE_RTC | 120 | #ifdef CONFIG_HPET_EMULATE_RTC |
122 | hpet_reserve_timer(&hd, 1); | 121 | hpet_reserve_timer(&hd, 1); |
123 | #endif | 122 | #endif |
124 | 123 | ||
124 | /* | ||
125 | * NOTE that hd_irq[] reflects IOAPIC input pins (LEGACY_8254 | ||
126 | * is wrong for i8259!) not the output IRQ. Many BIOS writers | ||
127 | * don't bother configuring *any* comparator interrupts. | ||
128 | */ | ||
125 | hd.hd_irq[0] = HPET_LEGACY_8254; | 129 | hd.hd_irq[0] = HPET_LEGACY_8254; |
126 | hd.hd_irq[1] = HPET_LEGACY_RTC; | 130 | hd.hd_irq[1] = HPET_LEGACY_RTC; |
127 | 131 | ||
diff --git a/arch/x86/kernel/irqinit_64.c b/arch/x86/kernel/irqinit_64.c index 1f26fd9ec4f4..5b5be9d43c2a 100644 --- a/arch/x86/kernel/irqinit_64.c +++ b/arch/x86/kernel/irqinit_64.c | |||
@@ -135,7 +135,7 @@ DEFINE_PER_CPU(vector_irq_t, vector_irq) = { | |||
135 | [IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1 | 135 | [IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1 |
136 | }; | 136 | }; |
137 | 137 | ||
138 | static void __init init_ISA_irqs (void) | 138 | void __init init_ISA_irqs(void) |
139 | { | 139 | { |
140 | int i; | 140 | int i; |
141 | 141 | ||
@@ -164,22 +164,8 @@ static void __init init_ISA_irqs (void) | |||
164 | 164 | ||
165 | void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ"))); | 165 | void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ"))); |
166 | 166 | ||
167 | void __init native_init_IRQ(void) | 167 | static void __init smp_intr_init(void) |
168 | { | 168 | { |
169 | int i; | ||
170 | |||
171 | init_ISA_irqs(); | ||
172 | /* | ||
173 | * Cover the whole vector space, no vector can escape | ||
174 | * us. (some of these will be overridden and become | ||
175 | * 'special' SMP interrupts) | ||
176 | */ | ||
177 | for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) { | ||
178 | int vector = FIRST_EXTERNAL_VECTOR + i; | ||
179 | if (vector != IA32_SYSCALL_VECTOR) | ||
180 | set_intr_gate(vector, interrupt[i]); | ||
181 | } | ||
182 | |||
183 | #ifdef CONFIG_SMP | 169 | #ifdef CONFIG_SMP |
184 | /* | 170 | /* |
185 | * The reschedule interrupt is a CPU-to-CPU reschedule-helper | 171 | * The reschedule interrupt is a CPU-to-CPU reschedule-helper |
@@ -207,6 +193,12 @@ void __init native_init_IRQ(void) | |||
207 | /* Low priority IPI to cleanup after moving an irq */ | 193 | /* Low priority IPI to cleanup after moving an irq */ |
208 | set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt); | 194 | set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt); |
209 | #endif | 195 | #endif |
196 | } | ||
197 | |||
198 | static void __init apic_intr_init(void) | ||
199 | { | ||
200 | smp_intr_init(); | ||
201 | |||
210 | alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); | 202 | alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); |
211 | alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt); | 203 | alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt); |
212 | 204 | ||
@@ -216,6 +208,25 @@ void __init native_init_IRQ(void) | |||
216 | /* IPI vectors for APIC spurious and error interrupts */ | 208 | /* IPI vectors for APIC spurious and error interrupts */ |
217 | alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); | 209 | alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); |
218 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); | 210 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); |
211 | } | ||
212 | |||
213 | void __init native_init_IRQ(void) | ||
214 | { | ||
215 | int i; | ||
216 | |||
217 | init_ISA_irqs(); | ||
218 | /* | ||
219 | * Cover the whole vector space, no vector can escape | ||
220 | * us. (some of these will be overridden and become | ||
221 | * 'special' SMP interrupts) | ||
222 | */ | ||
223 | for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) { | ||
224 | int vector = FIRST_EXTERNAL_VECTOR + i; | ||
225 | if (vector != IA32_SYSCALL_VECTOR) | ||
226 | set_intr_gate(vector, interrupt[i]); | ||
227 | } | ||
228 | |||
229 | apic_intr_init(); | ||
219 | 230 | ||
220 | if (!acpi_ioapic) | 231 | if (!acpi_ioapic) |
221 | setup_irq(2, &irq2); | 232 | setup_irq(2, &irq2); |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 922c14058f97..0a1302fe6d45 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -123,7 +123,7 @@ void cpu_idle(void) | |||
123 | } | 123 | } |
124 | } | 124 | } |
125 | 125 | ||
126 | void __show_registers(struct pt_regs *regs, int all) | 126 | void __show_regs(struct pt_regs *regs, int all) |
127 | { | 127 | { |
128 | unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; | 128 | unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; |
129 | unsigned long d0, d1, d2, d3, d6, d7; | 129 | unsigned long d0, d1, d2, d3, d6, d7; |
@@ -189,7 +189,7 @@ void __show_registers(struct pt_regs *regs, int all) | |||
189 | 189 | ||
190 | void show_regs(struct pt_regs *regs) | 190 | void show_regs(struct pt_regs *regs) |
191 | { | 191 | { |
192 | __show_registers(regs, 1); | 192 | __show_regs(regs, 1); |
193 | show_trace(NULL, regs, ®s->sp, regs->bp); | 193 | show_trace(NULL, regs, ®s->sp, regs->bp); |
194 | } | 194 | } |
195 | 195 | ||
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index ca80394ef5b8..cd8c0ed02b7e 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -136,7 +136,7 @@ void cpu_idle(void) | |||
136 | } | 136 | } |
137 | 137 | ||
138 | /* Prints also some state that isn't saved in the pt_regs */ | 138 | /* Prints also some state that isn't saved in the pt_regs */ |
139 | void __show_regs(struct pt_regs *regs) | 139 | void __show_regs(struct pt_regs *regs, int all) |
140 | { | 140 | { |
141 | unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs; | 141 | unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L, fs, gs, shadowgs; |
142 | unsigned long d0, d1, d2, d3, d6, d7; | 142 | unsigned long d0, d1, d2, d3, d6, d7; |
@@ -175,6 +175,9 @@ void __show_regs(struct pt_regs *regs) | |||
175 | rdmsrl(MSR_GS_BASE, gs); | 175 | rdmsrl(MSR_GS_BASE, gs); |
176 | rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); | 176 | rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); |
177 | 177 | ||
178 | if (!all) | ||
179 | return; | ||
180 | |||
178 | cr0 = read_cr0(); | 181 | cr0 = read_cr0(); |
179 | cr2 = read_cr2(); | 182 | cr2 = read_cr2(); |
180 | cr3 = read_cr3(); | 183 | cr3 = read_cr3(); |
@@ -200,7 +203,7 @@ void __show_regs(struct pt_regs *regs) | |||
200 | void show_regs(struct pt_regs *regs) | 203 | void show_regs(struct pt_regs *regs) |
201 | { | 204 | { |
202 | printk(KERN_INFO "CPU %d:", smp_processor_id()); | 205 | printk(KERN_INFO "CPU %d:", smp_processor_id()); |
203 | __show_regs(regs); | 206 | __show_regs(regs, 1); |
204 | show_trace(NULL, regs, (void *)(regs + 1), regs->bp); | 207 | show_trace(NULL, regs, (void *)(regs + 1), regs->bp); |
205 | } | 208 | } |
206 | 209 | ||
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index d13858818100..f6a11b9b1f98 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c | |||
@@ -354,9 +354,27 @@ static void ati_force_hpet_resume(void) | |||
354 | printk(KERN_DEBUG "Force enabled HPET at resume\n"); | 354 | printk(KERN_DEBUG "Force enabled HPET at resume\n"); |
355 | } | 355 | } |
356 | 356 | ||
357 | static u32 ati_ixp4x0_rev(struct pci_dev *dev) | ||
358 | { | ||
359 | u32 d; | ||
360 | u8 b; | ||
361 | |||
362 | pci_read_config_byte(dev, 0xac, &b); | ||
363 | b &= ~(1<<5); | ||
364 | pci_write_config_byte(dev, 0xac, b); | ||
365 | pci_read_config_dword(dev, 0x70, &d); | ||
366 | d |= 1<<8; | ||
367 | pci_write_config_dword(dev, 0x70, d); | ||
368 | pci_read_config_dword(dev, 0x8, &d); | ||
369 | d &= 0xff; | ||
370 | dev_printk(KERN_DEBUG, &dev->dev, "SB4X0 revision 0x%x\n", d); | ||
371 | return d; | ||
372 | } | ||
373 | |||
357 | static void ati_force_enable_hpet(struct pci_dev *dev) | 374 | static void ati_force_enable_hpet(struct pci_dev *dev) |
358 | { | 375 | { |
359 | u32 uninitialized_var(val); | 376 | u32 d, val; |
377 | u8 b; | ||
360 | 378 | ||
361 | if (hpet_address || force_hpet_address) | 379 | if (hpet_address || force_hpet_address) |
362 | return; | 380 | return; |
@@ -366,14 +384,33 @@ static void ati_force_enable_hpet(struct pci_dev *dev) | |||
366 | return; | 384 | return; |
367 | } | 385 | } |
368 | 386 | ||
387 | d = ati_ixp4x0_rev(dev); | ||
388 | if (d < 0x82) | ||
389 | return; | ||
390 | |||
391 | /* base address */ | ||
369 | pci_write_config_dword(dev, 0x14, 0xfed00000); | 392 | pci_write_config_dword(dev, 0x14, 0xfed00000); |
370 | pci_read_config_dword(dev, 0x14, &val); | 393 | pci_read_config_dword(dev, 0x14, &val); |
394 | |||
395 | /* enable interrupt */ | ||
396 | outb(0x72, 0xcd6); b = inb(0xcd7); | ||
397 | b |= 0x1; | ||
398 | outb(0x72, 0xcd6); outb(b, 0xcd7); | ||
399 | outb(0x72, 0xcd6); b = inb(0xcd7); | ||
400 | if (!(b & 0x1)) | ||
401 | return; | ||
402 | pci_read_config_dword(dev, 0x64, &d); | ||
403 | d |= (1<<10); | ||
404 | pci_write_config_dword(dev, 0x64, d); | ||
405 | pci_read_config_dword(dev, 0x64, &d); | ||
406 | if (!(d & (1<<10))) | ||
407 | return; | ||
408 | |||
371 | force_hpet_address = val; | 409 | force_hpet_address = val; |
372 | force_hpet_resume_type = ATI_FORCE_HPET_RESUME; | 410 | force_hpet_resume_type = ATI_FORCE_HPET_RESUME; |
373 | dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n", | 411 | dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n", |
374 | force_hpet_address); | 412 | force_hpet_address); |
375 | cached_dev = dev; | 413 | cached_dev = dev; |
376 | return; | ||
377 | } | 414 | } |
378 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS, | 415 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS, |
379 | ati_force_enable_hpet); | 416 | ati_force_enable_hpet); |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 21b8e0a59780..2255782e8d4b 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -302,7 +302,7 @@ static void __init relocate_initrd(void) | |||
302 | if (clen > MAX_MAP_CHUNK-slop) | 302 | if (clen > MAX_MAP_CHUNK-slop) |
303 | clen = MAX_MAP_CHUNK-slop; | 303 | clen = MAX_MAP_CHUNK-slop; |
304 | mapaddr = ramdisk_image & PAGE_MASK; | 304 | mapaddr = ramdisk_image & PAGE_MASK; |
305 | p = early_ioremap(mapaddr, clen+slop); | 305 | p = early_memremap(mapaddr, clen+slop); |
306 | memcpy(q, p+slop, clen); | 306 | memcpy(q, p+slop, clen); |
307 | early_iounmap(p, clen+slop); | 307 | early_iounmap(p, clen+slop); |
308 | q += clen; | 308 | q += clen; |
@@ -379,7 +379,7 @@ static void __init parse_setup_data(void) | |||
379 | return; | 379 | return; |
380 | pa_data = boot_params.hdr.setup_data; | 380 | pa_data = boot_params.hdr.setup_data; |
381 | while (pa_data) { | 381 | while (pa_data) { |
382 | data = early_ioremap(pa_data, PAGE_SIZE); | 382 | data = early_memremap(pa_data, PAGE_SIZE); |
383 | switch (data->type) { | 383 | switch (data->type) { |
384 | case SETUP_E820_EXT: | 384 | case SETUP_E820_EXT: |
385 | parse_e820_ext(data, pa_data); | 385 | parse_e820_ext(data, pa_data); |
@@ -402,7 +402,7 @@ static void __init e820_reserve_setup_data(void) | |||
402 | return; | 402 | return; |
403 | pa_data = boot_params.hdr.setup_data; | 403 | pa_data = boot_params.hdr.setup_data; |
404 | while (pa_data) { | 404 | while (pa_data) { |
405 | data = early_ioremap(pa_data, sizeof(*data)); | 405 | data = early_memremap(pa_data, sizeof(*data)); |
406 | e820_update_range(pa_data, sizeof(*data)+data->len, | 406 | e820_update_range(pa_data, sizeof(*data)+data->len, |
407 | E820_RAM, E820_RESERVED_KERN); | 407 | E820_RAM, E820_RESERVED_KERN); |
408 | found = 1; | 408 | found = 1; |
@@ -428,7 +428,7 @@ static void __init reserve_early_setup_data(void) | |||
428 | return; | 428 | return; |
429 | pa_data = boot_params.hdr.setup_data; | 429 | pa_data = boot_params.hdr.setup_data; |
430 | while (pa_data) { | 430 | while (pa_data) { |
431 | data = early_ioremap(pa_data, sizeof(*data)); | 431 | data = early_memremap(pa_data, sizeof(*data)); |
432 | sprintf(buf, "setup data %x", data->type); | 432 | sprintf(buf, "setup data %x", data->type); |
433 | reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf); | 433 | reserve_early(pa_data, pa_data+sizeof(*data)+data->len, buf); |
434 | pa_data = data->next; | 434 | pa_data = data->next; |
@@ -998,6 +998,8 @@ void __init setup_arch(char **cmdline_p) | |||
998 | */ | 998 | */ |
999 | acpi_boot_table_init(); | 999 | acpi_boot_table_init(); |
1000 | 1000 | ||
1001 | early_acpi_boot_init(); | ||
1002 | |||
1001 | #ifdef CONFIG_ACPI_NUMA | 1003 | #ifdef CONFIG_ACPI_NUMA |
1002 | /* | 1004 | /* |
1003 | * Parse SRAT to discover nodes. | 1005 | * Parse SRAT to discover nodes. |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 76b6f50978f7..8c3aca7cb343 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -334,14 +334,17 @@ static void __cpuinit start_secondary(void *unused) | |||
334 | * does not change while we are assigning vectors to cpus. Holding | 334 | * does not change while we are assigning vectors to cpus. Holding |
335 | * this lock ensures we don't half assign or remove an irq from a cpu. | 335 | * this lock ensures we don't half assign or remove an irq from a cpu. |
336 | */ | 336 | */ |
337 | ipi_call_lock_irq(); | 337 | ipi_call_lock(); |
338 | lock_vector_lock(); | 338 | lock_vector_lock(); |
339 | __setup_vector_irq(smp_processor_id()); | 339 | __setup_vector_irq(smp_processor_id()); |
340 | cpu_set(smp_processor_id(), cpu_online_map); | 340 | cpu_set(smp_processor_id(), cpu_online_map); |
341 | unlock_vector_lock(); | 341 | unlock_vector_lock(); |
342 | ipi_call_unlock_irq(); | 342 | ipi_call_unlock(); |
343 | per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; | 343 | per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; |
344 | 344 | ||
345 | /* enable local interrupts */ | ||
346 | local_irq_enable(); | ||
347 | |||
345 | setup_secondary_clock(); | 348 | setup_secondary_clock(); |
346 | 349 | ||
347 | wmb(); | 350 | wmb(); |
@@ -596,10 +599,12 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip) | |||
596 | * Give the other CPU some time to accept the IPI. | 599 | * Give the other CPU some time to accept the IPI. |
597 | */ | 600 | */ |
598 | udelay(200); | 601 | udelay(200); |
599 | maxlvt = lapic_get_maxlvt(); | 602 | if (APIC_INTEGRATED(apic_version[phys_apicid])) { |
600 | if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ | 603 | maxlvt = lapic_get_maxlvt(); |
601 | apic_write(APIC_ESR, 0); | 604 | if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ |
602 | accept_status = (apic_read(APIC_ESR) & 0xEF); | 605 | apic_write(APIC_ESR, 0); |
606 | accept_status = (apic_read(APIC_ESR) & 0xEF); | ||
607 | } | ||
603 | pr_debug("NMI sent.\n"); | 608 | pr_debug("NMI sent.\n"); |
604 | 609 | ||
605 | if (send_status) | 610 | if (send_status) |
@@ -1256,39 +1261,6 @@ void __init native_smp_cpus_done(unsigned int max_cpus) | |||
1256 | check_nmi_watchdog(); | 1261 | check_nmi_watchdog(); |
1257 | } | 1262 | } |
1258 | 1263 | ||
1259 | #ifdef CONFIG_HOTPLUG_CPU | ||
1260 | |||
1261 | static void remove_siblinginfo(int cpu) | ||
1262 | { | ||
1263 | int sibling; | ||
1264 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
1265 | |||
1266 | for_each_cpu_mask_nr(sibling, per_cpu(cpu_core_map, cpu)) { | ||
1267 | cpu_clear(cpu, per_cpu(cpu_core_map, sibling)); | ||
1268 | /*/ | ||
1269 | * last thread sibling in this cpu core going down | ||
1270 | */ | ||
1271 | if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) | ||
1272 | cpu_data(sibling).booted_cores--; | ||
1273 | } | ||
1274 | |||
1275 | for_each_cpu_mask_nr(sibling, per_cpu(cpu_sibling_map, cpu)) | ||
1276 | cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling)); | ||
1277 | cpus_clear(per_cpu(cpu_sibling_map, cpu)); | ||
1278 | cpus_clear(per_cpu(cpu_core_map, cpu)); | ||
1279 | c->phys_proc_id = 0; | ||
1280 | c->cpu_core_id = 0; | ||
1281 | cpu_clear(cpu, cpu_sibling_setup_map); | ||
1282 | } | ||
1283 | |||
1284 | static int additional_cpus __initdata = -1; | ||
1285 | |||
1286 | static __init int setup_additional_cpus(char *s) | ||
1287 | { | ||
1288 | return s && get_option(&s, &additional_cpus) ? 0 : -EINVAL; | ||
1289 | } | ||
1290 | early_param("additional_cpus", setup_additional_cpus); | ||
1291 | |||
1292 | /* | 1264 | /* |
1293 | * cpu_possible_map should be static, it cannot change as cpu's | 1265 | * cpu_possible_map should be static, it cannot change as cpu's |
1294 | * are onlined, or offlined. The reason is per-cpu data-structures | 1266 | * are onlined, or offlined. The reason is per-cpu data-structures |
@@ -1308,21 +1280,13 @@ early_param("additional_cpus", setup_additional_cpus); | |||
1308 | */ | 1280 | */ |
1309 | __init void prefill_possible_map(void) | 1281 | __init void prefill_possible_map(void) |
1310 | { | 1282 | { |
1311 | int i; | 1283 | int i, possible; |
1312 | int possible; | ||
1313 | 1284 | ||
1314 | /* no processor from mptable or madt */ | 1285 | /* no processor from mptable or madt */ |
1315 | if (!num_processors) | 1286 | if (!num_processors) |
1316 | num_processors = 1; | 1287 | num_processors = 1; |
1317 | 1288 | ||
1318 | if (additional_cpus == -1) { | 1289 | possible = num_processors + disabled_cpus; |
1319 | if (disabled_cpus > 0) | ||
1320 | additional_cpus = disabled_cpus; | ||
1321 | else | ||
1322 | additional_cpus = 0; | ||
1323 | } | ||
1324 | |||
1325 | possible = num_processors + additional_cpus; | ||
1326 | if (possible > NR_CPUS) | 1290 | if (possible > NR_CPUS) |
1327 | possible = NR_CPUS; | 1291 | possible = NR_CPUS; |
1328 | 1292 | ||
@@ -1335,6 +1299,31 @@ __init void prefill_possible_map(void) | |||
1335 | nr_cpu_ids = possible; | 1299 | nr_cpu_ids = possible; |
1336 | } | 1300 | } |
1337 | 1301 | ||
1302 | #ifdef CONFIG_HOTPLUG_CPU | ||
1303 | |||
1304 | static void remove_siblinginfo(int cpu) | ||
1305 | { | ||
1306 | int sibling; | ||
1307 | struct cpuinfo_x86 *c = &cpu_data(cpu); | ||
1308 | |||
1309 | for_each_cpu_mask_nr(sibling, per_cpu(cpu_core_map, cpu)) { | ||
1310 | cpu_clear(cpu, per_cpu(cpu_core_map, sibling)); | ||
1311 | /*/ | ||
1312 | * last thread sibling in this cpu core going down | ||
1313 | */ | ||
1314 | if (cpus_weight(per_cpu(cpu_sibling_map, cpu)) == 1) | ||
1315 | cpu_data(sibling).booted_cores--; | ||
1316 | } | ||
1317 | |||
1318 | for_each_cpu_mask_nr(sibling, per_cpu(cpu_sibling_map, cpu)) | ||
1319 | cpu_clear(cpu, per_cpu(cpu_sibling_map, sibling)); | ||
1320 | cpus_clear(per_cpu(cpu_sibling_map, cpu)); | ||
1321 | cpus_clear(per_cpu(cpu_core_map, cpu)); | ||
1322 | c->phys_proc_id = 0; | ||
1323 | c->cpu_core_id = 0; | ||
1324 | cpu_clear(cpu, cpu_sibling_setup_map); | ||
1325 | } | ||
1326 | |||
1338 | static void __ref remove_cpu_from_maps(int cpu) | 1327 | static void __ref remove_cpu_from_maps(int cpu) |
1339 | { | 1328 | { |
1340 | cpu_clear(cpu, cpu_online_map); | 1329 | cpu_clear(cpu, cpu_online_map); |
diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c index bbecf8b6bf96..77b400f06ea2 100644 --- a/arch/x86/kernel/time_32.c +++ b/arch/x86/kernel/time_32.c | |||
@@ -47,10 +47,9 @@ unsigned long profile_pc(struct pt_regs *regs) | |||
47 | unsigned long pc = instruction_pointer(regs); | 47 | unsigned long pc = instruction_pointer(regs); |
48 | 48 | ||
49 | #ifdef CONFIG_SMP | 49 | #ifdef CONFIG_SMP |
50 | if (!v8086_mode(regs) && SEGMENT_IS_KERNEL_CODE(regs->cs) && | 50 | if (!user_mode_vm(regs) && in_lock_functions(pc)) { |
51 | in_lock_functions(pc)) { | ||
52 | #ifdef CONFIG_FRAME_POINTER | 51 | #ifdef CONFIG_FRAME_POINTER |
53 | return *(unsigned long *)(regs->bp + 4); | 52 | return *(unsigned long *)(regs->bp + sizeof(long)); |
54 | #else | 53 | #else |
55 | unsigned long *sp = (unsigned long *)®s->sp; | 54 | unsigned long *sp = (unsigned long *)®s->sp; |
56 | 55 | ||
@@ -95,6 +94,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) | |||
95 | 94 | ||
96 | do_timer_interrupt_hook(); | 95 | do_timer_interrupt_hook(); |
97 | 96 | ||
97 | #ifdef CONFIG_MCA | ||
98 | if (MCA_bus) { | 98 | if (MCA_bus) { |
99 | /* The PS/2 uses level-triggered interrupts. You can't | 99 | /* The PS/2 uses level-triggered interrupts. You can't |
100 | turn them off, nor would you want to (any attempt to | 100 | turn them off, nor would you want to (any attempt to |
@@ -108,6 +108,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) | |||
108 | u8 irq_v = inb_p( 0x61 ); /* read the current state */ | 108 | u8 irq_v = inb_p( 0x61 ); /* read the current state */ |
109 | outb_p( irq_v|0x80, 0x61 ); /* reset the IRQ */ | 109 | outb_p( irq_v|0x80, 0x61 ); /* reset the IRQ */ |
110 | } | 110 | } |
111 | #endif | ||
111 | 112 | ||
112 | return IRQ_HANDLED; | 113 | return IRQ_HANDLED; |
113 | } | 114 | } |
diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c index e3d49c553af2..cb19d650c216 100644 --- a/arch/x86/kernel/time_64.c +++ b/arch/x86/kernel/time_64.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/time.h> | 18 | #include <linux/time.h> |
19 | #include <linux/mca.h> | ||
19 | 20 | ||
20 | #include <asm/i8253.h> | 21 | #include <asm/i8253.h> |
21 | #include <asm/hpet.h> | 22 | #include <asm/hpet.h> |
@@ -33,23 +34,34 @@ unsigned long profile_pc(struct pt_regs *regs) | |||
33 | /* Assume the lock function has either no stack frame or a copy | 34 | /* Assume the lock function has either no stack frame or a copy |
34 | of flags from PUSHF | 35 | of flags from PUSHF |
35 | Eflags always has bits 22 and up cleared unlike kernel addresses. */ | 36 | Eflags always has bits 22 and up cleared unlike kernel addresses. */ |
36 | if (!user_mode(regs) && in_lock_functions(pc)) { | 37 | if (!user_mode_vm(regs) && in_lock_functions(pc)) { |
38 | #ifdef CONFIG_FRAME_POINTER | ||
39 | return *(unsigned long *)(regs->bp + sizeof(long)); | ||
40 | #else | ||
37 | unsigned long *sp = (unsigned long *)regs->sp; | 41 | unsigned long *sp = (unsigned long *)regs->sp; |
38 | if (sp[0] >> 22) | 42 | if (sp[0] >> 22) |
39 | return sp[0]; | 43 | return sp[0]; |
40 | if (sp[1] >> 22) | 44 | if (sp[1] >> 22) |
41 | return sp[1]; | 45 | return sp[1]; |
46 | #endif | ||
42 | } | 47 | } |
43 | return pc; | 48 | return pc; |
44 | } | 49 | } |
45 | EXPORT_SYMBOL(profile_pc); | 50 | EXPORT_SYMBOL(profile_pc); |
46 | 51 | ||
47 | static irqreturn_t timer_event_interrupt(int irq, void *dev_id) | 52 | irqreturn_t timer_interrupt(int irq, void *dev_id) |
48 | { | 53 | { |
49 | add_pda(irq0_irqs, 1); | 54 | add_pda(irq0_irqs, 1); |
50 | 55 | ||
51 | global_clock_event->event_handler(global_clock_event); | 56 | global_clock_event->event_handler(global_clock_event); |
52 | 57 | ||
58 | #ifdef CONFIG_MCA | ||
59 | if (MCA_bus) { | ||
60 | u8 irq_v = inb_p(0x61); /* read the current state */ | ||
61 | outb_p(irq_v|0x80, 0x61); /* reset the IRQ */ | ||
62 | } | ||
63 | #endif | ||
64 | |||
53 | return IRQ_HANDLED; | 65 | return IRQ_HANDLED; |
54 | } | 66 | } |
55 | 67 | ||
@@ -100,7 +112,7 @@ unsigned long __init calibrate_cpu(void) | |||
100 | } | 112 | } |
101 | 113 | ||
102 | static struct irqaction irq0 = { | 114 | static struct irqaction irq0 = { |
103 | .handler = timer_event_interrupt, | 115 | .handler = timer_interrupt, |
104 | .flags = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING, | 116 | .flags = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING, |
105 | .mask = CPU_MASK_NONE, | 117 | .mask = CPU_MASK_NONE, |
106 | .name = "timer" | 118 | .name = "timer" |
@@ -111,16 +123,13 @@ void __init hpet_time_init(void) | |||
111 | if (!hpet_enable()) | 123 | if (!hpet_enable()) |
112 | setup_pit_timer(); | 124 | setup_pit_timer(); |
113 | 125 | ||
126 | irq0.mask = cpumask_of_cpu(0); | ||
114 | setup_irq(0, &irq0); | 127 | setup_irq(0, &irq0); |
115 | } | 128 | } |
116 | 129 | ||
117 | void __init time_init(void) | 130 | void __init time_init(void) |
118 | { | 131 | { |
119 | tsc_init(); | 132 | tsc_init(); |
120 | if (cpu_has(&boot_cpu_data, X86_FEATURE_RDTSCP)) | ||
121 | vgetcpu_mode = VGETCPU_RDTSCP; | ||
122 | else | ||
123 | vgetcpu_mode = VGETCPU_LSL; | ||
124 | 133 | ||
125 | late_time_init = choose_time_init(); | 134 | late_time_init = choose_time_init(); |
126 | } | 135 | } |
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps.c index 0429c5de5ea9..e062974cce34 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps.c | |||
@@ -7,13 +7,11 @@ | |||
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* | 9 | /* |
10 | * 'Traps.c' handles hardware traps and faults after we have saved some | 10 | * Handle hardware traps and faults. |
11 | * state in 'asm.s'. | ||
12 | */ | 11 | */ |
13 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
14 | #include <linux/kallsyms.h> | 13 | #include <linux/kallsyms.h> |
15 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
16 | #include <linux/highmem.h> | ||
17 | #include <linux/kprobes.h> | 15 | #include <linux/kprobes.h> |
18 | #include <linux/uaccess.h> | 16 | #include <linux/uaccess.h> |
19 | #include <linux/utsname.h> | 17 | #include <linux/utsname.h> |
@@ -32,6 +30,8 @@ | |||
32 | #include <linux/bug.h> | 30 | #include <linux/bug.h> |
33 | #include <linux/nmi.h> | 31 | #include <linux/nmi.h> |
34 | #include <linux/mm.h> | 32 | #include <linux/mm.h> |
33 | #include <linux/smp.h> | ||
34 | #include <linux/io.h> | ||
35 | 35 | ||
36 | #ifdef CONFIG_EISA | 36 | #ifdef CONFIG_EISA |
37 | #include <linux/ioport.h> | 37 | #include <linux/ioport.h> |
@@ -46,21 +46,31 @@ | |||
46 | #include <linux/edac.h> | 46 | #include <linux/edac.h> |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #include <asm/arch_hooks.h> | ||
50 | #include <asm/stacktrace.h> | 49 | #include <asm/stacktrace.h> |
51 | #include <asm/processor.h> | 50 | #include <asm/processor.h> |
52 | #include <asm/debugreg.h> | 51 | #include <asm/debugreg.h> |
53 | #include <asm/atomic.h> | 52 | #include <asm/atomic.h> |
54 | #include <asm/system.h> | 53 | #include <asm/system.h> |
55 | #include <asm/unwind.h> | 54 | #include <asm/unwind.h> |
55 | #include <asm/traps.h> | ||
56 | #include <asm/desc.h> | 56 | #include <asm/desc.h> |
57 | #include <asm/i387.h> | 57 | #include <asm/i387.h> |
58 | |||
59 | #include <mach_traps.h> | ||
60 | |||
61 | #ifdef CONFIG_X86_64 | ||
62 | #include <asm/pgalloc.h> | ||
63 | #include <asm/proto.h> | ||
64 | #include <asm/pda.h> | ||
65 | #else | ||
66 | #include <asm/processor-flags.h> | ||
67 | #include <asm/arch_hooks.h> | ||
58 | #include <asm/nmi.h> | 68 | #include <asm/nmi.h> |
59 | #include <asm/smp.h> | 69 | #include <asm/smp.h> |
60 | #include <asm/io.h> | 70 | #include <asm/io.h> |
61 | #include <asm/traps.h> | 71 | #include <asm/traps.h> |
62 | 72 | ||
63 | #include "mach_traps.h" | 73 | #include "cpu/mcheck/mce.h" |
64 | 74 | ||
65 | DECLARE_BITMAP(used_vectors, NR_VECTORS); | 75 | DECLARE_BITMAP(used_vectors, NR_VECTORS); |
66 | EXPORT_SYMBOL_GPL(used_vectors); | 76 | EXPORT_SYMBOL_GPL(used_vectors); |
@@ -77,418 +87,104 @@ char ignore_fpu_irq; | |||
77 | */ | 87 | */ |
78 | gate_desc idt_table[256] | 88 | gate_desc idt_table[256] |
79 | __attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, }; | 89 | __attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, }; |
80 | |||
81 | int panic_on_unrecovered_nmi; | ||
82 | int kstack_depth_to_print = 24; | ||
83 | static unsigned int code_bytes = 64; | ||
84 | static int ignore_nmis; | ||
85 | static int die_counter; | ||
86 | |||
87 | void printk_address(unsigned long address, int reliable) | ||
88 | { | ||
89 | #ifdef CONFIG_KALLSYMS | ||
90 | unsigned long offset = 0; | ||
91 | unsigned long symsize; | ||
92 | const char *symname; | ||
93 | char *modname; | ||
94 | char *delim = ":"; | ||
95 | char namebuf[KSYM_NAME_LEN]; | ||
96 | char reliab[4] = ""; | ||
97 | |||
98 | symname = kallsyms_lookup(address, &symsize, &offset, | ||
99 | &modname, namebuf); | ||
100 | if (!symname) { | ||
101 | printk(" [<%08lx>]\n", address); | ||
102 | return; | ||
103 | } | ||
104 | if (!reliable) | ||
105 | strcpy(reliab, "? "); | ||
106 | |||
107 | if (!modname) | ||
108 | modname = delim = ""; | ||
109 | printk(" [<%08lx>] %s%s%s%s%s+0x%lx/0x%lx\n", | ||
110 | address, reliab, delim, modname, delim, symname, offset, symsize); | ||
111 | #else | ||
112 | printk(" [<%08lx>]\n", address); | ||
113 | #endif | 90 | #endif |
114 | } | ||
115 | |||
116 | static inline int valid_stack_ptr(struct thread_info *tinfo, | ||
117 | void *p, unsigned int size) | ||
118 | { | ||
119 | void *t = tinfo; | ||
120 | return p > t && p <= t + THREAD_SIZE - size; | ||
121 | } | ||
122 | |||
123 | /* The form of the top of the frame on the stack */ | ||
124 | struct stack_frame { | ||
125 | struct stack_frame *next_frame; | ||
126 | unsigned long return_address; | ||
127 | }; | ||
128 | |||
129 | static inline unsigned long | ||
130 | print_context_stack(struct thread_info *tinfo, | ||
131 | unsigned long *stack, unsigned long bp, | ||
132 | const struct stacktrace_ops *ops, void *data) | ||
133 | { | ||
134 | struct stack_frame *frame = (struct stack_frame *)bp; | ||
135 | |||
136 | while (valid_stack_ptr(tinfo, stack, sizeof(*stack))) { | ||
137 | unsigned long addr; | ||
138 | |||
139 | addr = *stack; | ||
140 | if (__kernel_text_address(addr)) { | ||
141 | if ((unsigned long) stack == bp + 4) { | ||
142 | ops->address(data, addr, 1); | ||
143 | frame = frame->next_frame; | ||
144 | bp = (unsigned long) frame; | ||
145 | } else { | ||
146 | ops->address(data, addr, bp == 0); | ||
147 | } | ||
148 | } | ||
149 | stack++; | ||
150 | } | ||
151 | return bp; | ||
152 | } | ||
153 | |||
154 | void dump_trace(struct task_struct *task, struct pt_regs *regs, | ||
155 | unsigned long *stack, unsigned long bp, | ||
156 | const struct stacktrace_ops *ops, void *data) | ||
157 | { | ||
158 | if (!task) | ||
159 | task = current; | ||
160 | |||
161 | if (!stack) { | ||
162 | unsigned long dummy; | ||
163 | stack = &dummy; | ||
164 | if (task != current) | ||
165 | stack = (unsigned long *)task->thread.sp; | ||
166 | } | ||
167 | |||
168 | #ifdef CONFIG_FRAME_POINTER | ||
169 | if (!bp) { | ||
170 | if (task == current) { | ||
171 | /* Grab bp right from our regs */ | ||
172 | asm("movl %%ebp, %0" : "=r" (bp) :); | ||
173 | } else { | ||
174 | /* bp is the last reg pushed by switch_to */ | ||
175 | bp = *(unsigned long *) task->thread.sp; | ||
176 | } | ||
177 | } | ||
178 | #endif | ||
179 | |||
180 | for (;;) { | ||
181 | struct thread_info *context; | ||
182 | |||
183 | context = (struct thread_info *) | ||
184 | ((unsigned long)stack & (~(THREAD_SIZE - 1))); | ||
185 | bp = print_context_stack(context, stack, bp, ops, data); | ||
186 | /* | ||
187 | * Should be after the line below, but somewhere | ||
188 | * in early boot context comes out corrupted and we | ||
189 | * can't reference it: | ||
190 | */ | ||
191 | if (ops->stack(data, "IRQ") < 0) | ||
192 | break; | ||
193 | stack = (unsigned long *)context->previous_esp; | ||
194 | if (!stack) | ||
195 | break; | ||
196 | touch_nmi_watchdog(); | ||
197 | } | ||
198 | } | ||
199 | EXPORT_SYMBOL(dump_trace); | ||
200 | |||
201 | static void | ||
202 | print_trace_warning_symbol(void *data, char *msg, unsigned long symbol) | ||
203 | { | ||
204 | printk(data); | ||
205 | print_symbol(msg, symbol); | ||
206 | printk("\n"); | ||
207 | } | ||
208 | |||
209 | static void print_trace_warning(void *data, char *msg) | ||
210 | { | ||
211 | printk("%s%s\n", (char *)data, msg); | ||
212 | } | ||
213 | 91 | ||
214 | static int print_trace_stack(void *data, char *name) | 92 | static int ignore_nmis; |
215 | { | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * Print one address/symbol entries per line. | ||
221 | */ | ||
222 | static void print_trace_address(void *data, unsigned long addr, int reliable) | ||
223 | { | ||
224 | printk("%s [<%08lx>] ", (char *)data, addr); | ||
225 | if (!reliable) | ||
226 | printk("? "); | ||
227 | print_symbol("%s\n", addr); | ||
228 | touch_nmi_watchdog(); | ||
229 | } | ||
230 | |||
231 | static const struct stacktrace_ops print_trace_ops = { | ||
232 | .warning = print_trace_warning, | ||
233 | .warning_symbol = print_trace_warning_symbol, | ||
234 | .stack = print_trace_stack, | ||
235 | .address = print_trace_address, | ||
236 | }; | ||
237 | 93 | ||
238 | static void | 94 | static inline void conditional_sti(struct pt_regs *regs) |
239 | show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, | ||
240 | unsigned long *stack, unsigned long bp, char *log_lvl) | ||
241 | { | 95 | { |
242 | dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl); | 96 | if (regs->flags & X86_EFLAGS_IF) |
243 | printk("%s =======================\n", log_lvl); | 97 | local_irq_enable(); |
244 | } | 98 | } |
245 | 99 | ||
246 | void show_trace(struct task_struct *task, struct pt_regs *regs, | 100 | static inline void preempt_conditional_sti(struct pt_regs *regs) |
247 | unsigned long *stack, unsigned long bp) | ||
248 | { | 101 | { |
249 | show_trace_log_lvl(task, regs, stack, bp, ""); | 102 | inc_preempt_count(); |
103 | if (regs->flags & X86_EFLAGS_IF) | ||
104 | local_irq_enable(); | ||
250 | } | 105 | } |
251 | 106 | ||
252 | static void | 107 | static inline void preempt_conditional_cli(struct pt_regs *regs) |
253 | show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, | ||
254 | unsigned long *sp, unsigned long bp, char *log_lvl) | ||
255 | { | 108 | { |
256 | unsigned long *stack; | 109 | if (regs->flags & X86_EFLAGS_IF) |
257 | int i; | 110 | local_irq_disable(); |
258 | 111 | dec_preempt_count(); | |
259 | if (sp == NULL) { | ||
260 | if (task) | ||
261 | sp = (unsigned long *)task->thread.sp; | ||
262 | else | ||
263 | sp = (unsigned long *)&sp; | ||
264 | } | ||
265 | |||
266 | stack = sp; | ||
267 | for (i = 0; i < kstack_depth_to_print; i++) { | ||
268 | if (kstack_end(stack)) | ||
269 | break; | ||
270 | if (i && ((i % 8) == 0)) | ||
271 | printk("\n%s ", log_lvl); | ||
272 | printk("%08lx ", *stack++); | ||
273 | } | ||
274 | printk("\n%sCall Trace:\n", log_lvl); | ||
275 | |||
276 | show_trace_log_lvl(task, regs, sp, bp, log_lvl); | ||
277 | } | 112 | } |
278 | 113 | ||
279 | void show_stack(struct task_struct *task, unsigned long *sp) | 114 | #ifdef CONFIG_X86_32 |
115 | static inline void | ||
116 | die_if_kernel(const char *str, struct pt_regs *regs, long err) | ||
280 | { | 117 | { |
281 | printk(" "); | 118 | if (!user_mode_vm(regs)) |
282 | show_stack_log_lvl(task, NULL, sp, 0, ""); | 119 | die(str, regs, err); |
283 | } | 120 | } |
284 | 121 | ||
285 | /* | 122 | /* |
286 | * The architecture-independent dump_stack generator | 123 | * Perform the lazy TSS's I/O bitmap copy. If the TSS has an |
124 | * invalid offset set (the LAZY one) and the faulting thread has | ||
125 | * a valid I/O bitmap pointer, we copy the I/O bitmap in the TSS, | ||
126 | * we set the offset field correctly and return 1. | ||
287 | */ | 127 | */ |
288 | void dump_stack(void) | 128 | static int lazy_iobitmap_copy(void) |
289 | { | 129 | { |
290 | unsigned long bp = 0; | 130 | struct thread_struct *thread; |
291 | unsigned long stack; | 131 | struct tss_struct *tss; |
292 | 132 | int cpu; | |
293 | #ifdef CONFIG_FRAME_POINTER | ||
294 | if (!bp) | ||
295 | asm("movl %%ebp, %0" : "=r" (bp):); | ||
296 | #endif | ||
297 | |||
298 | printk("Pid: %d, comm: %.20s %s %s %.*s\n", | ||
299 | current->pid, current->comm, print_tainted(), | ||
300 | init_utsname()->release, | ||
301 | (int)strcspn(init_utsname()->version, " "), | ||
302 | init_utsname()->version); | ||
303 | |||
304 | show_trace(current, NULL, &stack, bp); | ||
305 | } | ||
306 | |||
307 | EXPORT_SYMBOL(dump_stack); | ||
308 | |||
309 | void show_registers(struct pt_regs *regs) | ||
310 | { | ||
311 | int i; | ||
312 | 133 | ||
313 | print_modules(); | 134 | cpu = get_cpu(); |
314 | __show_registers(regs, 0); | 135 | tss = &per_cpu(init_tss, cpu); |
136 | thread = ¤t->thread; | ||
315 | 137 | ||
316 | printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)", | 138 | if (tss->x86_tss.io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY && |
317 | TASK_COMM_LEN, current->comm, task_pid_nr(current), | 139 | thread->io_bitmap_ptr) { |
318 | current_thread_info(), current, task_thread_info(current)); | 140 | memcpy(tss->io_bitmap, thread->io_bitmap_ptr, |
319 | /* | 141 | thread->io_bitmap_max); |
320 | * When in-kernel, we also print out the stack and code at the | 142 | /* |
321 | * time of the fault.. | 143 | * If the previously set map was extending to higher ports |
322 | */ | 144 | * than the current one, pad extra space with 0xff (no access). |
323 | if (!user_mode_vm(regs)) { | 145 | */ |
324 | unsigned int code_prologue = code_bytes * 43 / 64; | 146 | if (thread->io_bitmap_max < tss->io_bitmap_max) { |
325 | unsigned int code_len = code_bytes; | 147 | memset((char *) tss->io_bitmap + |
326 | unsigned char c; | 148 | thread->io_bitmap_max, 0xff, |
327 | u8 *ip; | 149 | tss->io_bitmap_max - thread->io_bitmap_max); |
328 | |||
329 | printk("\n" KERN_EMERG "Stack: "); | ||
330 | show_stack_log_lvl(NULL, regs, ®s->sp, 0, KERN_EMERG); | ||
331 | |||
332 | printk(KERN_EMERG "Code: "); | ||
333 | |||
334 | ip = (u8 *)regs->ip - code_prologue; | ||
335 | if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { | ||
336 | /* try starting at EIP */ | ||
337 | ip = (u8 *)regs->ip; | ||
338 | code_len = code_len - code_prologue + 1; | ||
339 | } | ||
340 | for (i = 0; i < code_len; i++, ip++) { | ||
341 | if (ip < (u8 *)PAGE_OFFSET || | ||
342 | probe_kernel_address(ip, c)) { | ||
343 | printk(" Bad EIP value."); | ||
344 | break; | ||
345 | } | ||
346 | if (ip == (u8 *)regs->ip) | ||
347 | printk("<%02x> ", c); | ||
348 | else | ||
349 | printk("%02x ", c); | ||
350 | } | 150 | } |
351 | } | 151 | tss->io_bitmap_max = thread->io_bitmap_max; |
352 | printk("\n"); | 152 | tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET; |
353 | } | 153 | tss->io_bitmap_owner = thread; |
354 | 154 | put_cpu(); | |
355 | int is_valid_bugaddr(unsigned long ip) | ||
356 | { | ||
357 | unsigned short ud2; | ||
358 | |||
359 | if (ip < PAGE_OFFSET) | ||
360 | return 0; | ||
361 | if (probe_kernel_address((unsigned short *)ip, ud2)) | ||
362 | return 0; | ||
363 | |||
364 | return ud2 == 0x0b0f; | ||
365 | } | ||
366 | |||
367 | static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED; | ||
368 | static int die_owner = -1; | ||
369 | static unsigned int die_nest_count; | ||
370 | |||
371 | unsigned __kprobes long oops_begin(void) | ||
372 | { | ||
373 | unsigned long flags; | ||
374 | |||
375 | oops_enter(); | ||
376 | |||
377 | if (die_owner != raw_smp_processor_id()) { | ||
378 | console_verbose(); | ||
379 | raw_local_irq_save(flags); | ||
380 | __raw_spin_lock(&die_lock); | ||
381 | die_owner = smp_processor_id(); | ||
382 | die_nest_count = 0; | ||
383 | bust_spinlocks(1); | ||
384 | } else { | ||
385 | raw_local_irq_save(flags); | ||
386 | } | ||
387 | die_nest_count++; | ||
388 | return flags; | ||
389 | } | ||
390 | |||
391 | void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr) | ||
392 | { | ||
393 | bust_spinlocks(0); | ||
394 | die_owner = -1; | ||
395 | add_taint(TAINT_DIE); | ||
396 | __raw_spin_unlock(&die_lock); | ||
397 | raw_local_irq_restore(flags); | ||
398 | |||
399 | if (!regs) | ||
400 | return; | ||
401 | |||
402 | if (kexec_should_crash(current)) | ||
403 | crash_kexec(regs); | ||
404 | |||
405 | if (in_interrupt()) | ||
406 | panic("Fatal exception in interrupt"); | ||
407 | |||
408 | if (panic_on_oops) | ||
409 | panic("Fatal exception"); | ||
410 | |||
411 | oops_exit(); | ||
412 | do_exit(signr); | ||
413 | } | ||
414 | |||
415 | int __kprobes __die(const char *str, struct pt_regs *regs, long err) | ||
416 | { | ||
417 | unsigned short ss; | ||
418 | unsigned long sp; | ||
419 | 155 | ||
420 | printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter); | ||
421 | #ifdef CONFIG_PREEMPT | ||
422 | printk("PREEMPT "); | ||
423 | #endif | ||
424 | #ifdef CONFIG_SMP | ||
425 | printk("SMP "); | ||
426 | #endif | ||
427 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
428 | printk("DEBUG_PAGEALLOC"); | ||
429 | #endif | ||
430 | printk("\n"); | ||
431 | if (notify_die(DIE_OOPS, str, regs, err, | ||
432 | current->thread.trap_no, SIGSEGV) == NOTIFY_STOP) | ||
433 | return 1; | 156 | return 1; |
434 | |||
435 | show_registers(regs); | ||
436 | /* Executive summary in case the oops scrolled away */ | ||
437 | sp = (unsigned long) (®s->sp); | ||
438 | savesegment(ss, ss); | ||
439 | if (user_mode(regs)) { | ||
440 | sp = regs->sp; | ||
441 | ss = regs->ss & 0xffff; | ||
442 | } | 157 | } |
443 | printk(KERN_EMERG "EIP: [<%08lx>] ", regs->ip); | 158 | put_cpu(); |
444 | print_symbol("%s", regs->ip); | ||
445 | printk(" SS:ESP %04x:%08lx\n", ss, sp); | ||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | /* | ||
450 | * This is gone through when something in the kernel has done something bad | ||
451 | * and is about to be terminated: | ||
452 | */ | ||
453 | void die(const char *str, struct pt_regs *regs, long err) | ||
454 | { | ||
455 | unsigned long flags = oops_begin(); | ||
456 | |||
457 | if (die_nest_count < 3) { | ||
458 | report_bug(regs->ip, regs); | ||
459 | |||
460 | if (__die(str, regs, err)) | ||
461 | regs = NULL; | ||
462 | } else { | ||
463 | printk(KERN_EMERG "Recursive die() failure, output suppressed\n"); | ||
464 | } | ||
465 | |||
466 | oops_end(flags, regs, SIGSEGV); | ||
467 | } | ||
468 | 159 | ||
469 | static inline void | 160 | return 0; |
470 | die_if_kernel(const char *str, struct pt_regs *regs, long err) | ||
471 | { | ||
472 | if (!user_mode_vm(regs)) | ||
473 | die(str, regs, err); | ||
474 | } | 161 | } |
162 | #endif | ||
475 | 163 | ||
476 | static void __kprobes | 164 | static void __kprobes |
477 | do_trap(int trapnr, int signr, char *str, int vm86, struct pt_regs *regs, | 165 | do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, |
478 | long error_code, siginfo_t *info) | 166 | long error_code, siginfo_t *info) |
479 | { | 167 | { |
480 | struct task_struct *tsk = current; | 168 | struct task_struct *tsk = current; |
481 | 169 | ||
170 | #ifdef CONFIG_X86_32 | ||
482 | if (regs->flags & X86_VM_MASK) { | 171 | if (regs->flags & X86_VM_MASK) { |
483 | if (vm86) | 172 | /* |
173 | * traps 0, 1, 3, 4, and 5 should be forwarded to vm86. | ||
174 | * On nmi (interrupt 2), do_trap should not be called. | ||
175 | */ | ||
176 | if (trapnr < 6) | ||
484 | goto vm86_trap; | 177 | goto vm86_trap; |
485 | goto trap_signal; | 178 | goto trap_signal; |
486 | } | 179 | } |
180 | #endif | ||
487 | 181 | ||
488 | if (!user_mode(regs)) | 182 | if (!user_mode(regs)) |
489 | goto kernel_trap; | 183 | goto kernel_trap; |
490 | 184 | ||
185 | #ifdef CONFIG_X86_32 | ||
491 | trap_signal: | 186 | trap_signal: |
187 | #endif | ||
492 | /* | 188 | /* |
493 | * We want error_code and trap_no set for userspace faults and | 189 | * We want error_code and trap_no set for userspace faults and |
494 | * kernelspace faults which result in die(), but not | 190 | * kernelspace faults which result in die(), but not |
@@ -501,6 +197,18 @@ trap_signal: | |||
501 | tsk->thread.error_code = error_code; | 197 | tsk->thread.error_code = error_code; |
502 | tsk->thread.trap_no = trapnr; | 198 | tsk->thread.trap_no = trapnr; |
503 | 199 | ||
200 | #ifdef CONFIG_X86_64 | ||
201 | if (show_unhandled_signals && unhandled_signal(tsk, signr) && | ||
202 | printk_ratelimit()) { | ||
203 | printk(KERN_INFO | ||
204 | "%s[%d] trap %s ip:%lx sp:%lx error:%lx", | ||
205 | tsk->comm, tsk->pid, str, | ||
206 | regs->ip, regs->sp, error_code); | ||
207 | print_vma_addr(" in ", regs->ip); | ||
208 | printk("\n"); | ||
209 | } | ||
210 | #endif | ||
211 | |||
504 | if (info) | 212 | if (info) |
505 | force_sig_info(signr, info, tsk); | 213 | force_sig_info(signr, info, tsk); |
506 | else | 214 | else |
@@ -515,29 +223,29 @@ kernel_trap: | |||
515 | } | 223 | } |
516 | return; | 224 | return; |
517 | 225 | ||
226 | #ifdef CONFIG_X86_32 | ||
518 | vm86_trap: | 227 | vm86_trap: |
519 | if (handle_vm86_trap((struct kernel_vm86_regs *) regs, | 228 | if (handle_vm86_trap((struct kernel_vm86_regs *) regs, |
520 | error_code, trapnr)) | 229 | error_code, trapnr)) |
521 | goto trap_signal; | 230 | goto trap_signal; |
522 | return; | 231 | return; |
232 | #endif | ||
523 | } | 233 | } |
524 | 234 | ||
525 | #define DO_ERROR(trapnr, signr, str, name) \ | 235 | #define DO_ERROR(trapnr, signr, str, name) \ |
526 | void do_##name(struct pt_regs *regs, long error_code) \ | 236 | dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ |
527 | { \ | 237 | { \ |
528 | trace_hardirqs_fixup(); \ | ||
529 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | 238 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ |
530 | == NOTIFY_STOP) \ | 239 | == NOTIFY_STOP) \ |
531 | return; \ | 240 | return; \ |
532 | do_trap(trapnr, signr, str, 0, regs, error_code, NULL); \ | 241 | conditional_sti(regs); \ |
242 | do_trap(trapnr, signr, str, regs, error_code, NULL); \ | ||
533 | } | 243 | } |
534 | 244 | ||
535 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr, irq) \ | 245 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ |
536 | void do_##name(struct pt_regs *regs, long error_code) \ | 246 | dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ |
537 | { \ | 247 | { \ |
538 | siginfo_t info; \ | 248 | siginfo_t info; \ |
539 | if (irq) \ | ||
540 | local_irq_enable(); \ | ||
541 | info.si_signo = signr; \ | 249 | info.si_signo = signr; \ |
542 | info.si_errno = 0; \ | 250 | info.si_errno = 0; \ |
543 | info.si_code = sicode; \ | 251 | info.si_code = sicode; \ |
@@ -545,90 +253,68 @@ void do_##name(struct pt_regs *regs, long error_code) \ | |||
545 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | 253 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ |
546 | == NOTIFY_STOP) \ | 254 | == NOTIFY_STOP) \ |
547 | return; \ | 255 | return; \ |
548 | do_trap(trapnr, signr, str, 0, regs, error_code, &info); \ | 256 | conditional_sti(regs); \ |
257 | do_trap(trapnr, signr, str, regs, error_code, &info); \ | ||
549 | } | 258 | } |
550 | 259 | ||
551 | #define DO_VM86_ERROR(trapnr, signr, str, name) \ | 260 | DO_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip) |
552 | void do_##name(struct pt_regs *regs, long error_code) \ | 261 | DO_ERROR(4, SIGSEGV, "overflow", overflow) |
553 | { \ | 262 | DO_ERROR(5, SIGSEGV, "bounds", bounds) |
554 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | 263 | DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip) |
555 | == NOTIFY_STOP) \ | ||
556 | return; \ | ||
557 | do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \ | ||
558 | } | ||
559 | |||
560 | #define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ | ||
561 | void do_##name(struct pt_regs *regs, long error_code) \ | ||
562 | { \ | ||
563 | siginfo_t info; \ | ||
564 | info.si_signo = signr; \ | ||
565 | info.si_errno = 0; \ | ||
566 | info.si_code = sicode; \ | ||
567 | info.si_addr = (void __user *)siaddr; \ | ||
568 | trace_hardirqs_fixup(); \ | ||
569 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | ||
570 | == NOTIFY_STOP) \ | ||
571 | return; \ | ||
572 | do_trap(trapnr, signr, str, 1, regs, error_code, &info); \ | ||
573 | } | ||
574 | |||
575 | DO_VM86_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip) | ||
576 | #ifndef CONFIG_KPROBES | ||
577 | DO_VM86_ERROR(3, SIGTRAP, "int3", int3) | ||
578 | #endif | ||
579 | DO_VM86_ERROR(4, SIGSEGV, "overflow", overflow) | ||
580 | DO_VM86_ERROR(5, SIGSEGV, "bounds", bounds) | ||
581 | DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip, 0) | ||
582 | DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) | 264 | DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) |
583 | DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) | 265 | DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) |
584 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) | 266 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) |
267 | #ifdef CONFIG_X86_32 | ||
585 | DO_ERROR(12, SIGBUS, "stack segment", stack_segment) | 268 | DO_ERROR(12, SIGBUS, "stack segment", stack_segment) |
586 | DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0, 0) | 269 | #endif |
587 | DO_ERROR_INFO(32, SIGILL, "iret exception", iret_error, ILL_BADSTK, 0, 1) | 270 | DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) |
271 | |||
272 | #ifdef CONFIG_X86_64 | ||
273 | /* Runs on IST stack */ | ||
274 | dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code) | ||
275 | { | ||
276 | if (notify_die(DIE_TRAP, "stack segment", regs, error_code, | ||
277 | 12, SIGBUS) == NOTIFY_STOP) | ||
278 | return; | ||
279 | preempt_conditional_sti(regs); | ||
280 | do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL); | ||
281 | preempt_conditional_cli(regs); | ||
282 | } | ||
283 | |||
284 | dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) | ||
285 | { | ||
286 | static const char str[] = "double fault"; | ||
287 | struct task_struct *tsk = current; | ||
288 | |||
289 | /* Return not checked because double check cannot be ignored */ | ||
290 | notify_die(DIE_TRAP, str, regs, error_code, 8, SIGSEGV); | ||
588 | 291 | ||
589 | void __kprobes | 292 | tsk->thread.error_code = error_code; |
293 | tsk->thread.trap_no = 8; | ||
294 | |||
295 | /* This is always a kernel trap and never fixable (and thus must | ||
296 | never return). */ | ||
297 | for (;;) | ||
298 | die(str, regs, error_code); | ||
299 | } | ||
300 | #endif | ||
301 | |||
302 | dotraplinkage void __kprobes | ||
590 | do_general_protection(struct pt_regs *regs, long error_code) | 303 | do_general_protection(struct pt_regs *regs, long error_code) |
591 | { | 304 | { |
592 | struct task_struct *tsk; | 305 | struct task_struct *tsk; |
593 | struct thread_struct *thread; | ||
594 | struct tss_struct *tss; | ||
595 | int cpu; | ||
596 | 306 | ||
597 | cpu = get_cpu(); | 307 | conditional_sti(regs); |
598 | tss = &per_cpu(init_tss, cpu); | ||
599 | thread = ¤t->thread; | ||
600 | |||
601 | /* | ||
602 | * Perform the lazy TSS's I/O bitmap copy. If the TSS has an | ||
603 | * invalid offset set (the LAZY one) and the faulting thread has | ||
604 | * a valid I/O bitmap pointer, we copy the I/O bitmap in the TSS | ||
605 | * and we set the offset field correctly. Then we let the CPU to | ||
606 | * restart the faulting instruction. | ||
607 | */ | ||
608 | if (tss->x86_tss.io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY && | ||
609 | thread->io_bitmap_ptr) { | ||
610 | memcpy(tss->io_bitmap, thread->io_bitmap_ptr, | ||
611 | thread->io_bitmap_max); | ||
612 | /* | ||
613 | * If the previously set map was extending to higher ports | ||
614 | * than the current one, pad extra space with 0xff (no access). | ||
615 | */ | ||
616 | if (thread->io_bitmap_max < tss->io_bitmap_max) { | ||
617 | memset((char *) tss->io_bitmap + | ||
618 | thread->io_bitmap_max, 0xff, | ||
619 | tss->io_bitmap_max - thread->io_bitmap_max); | ||
620 | } | ||
621 | tss->io_bitmap_max = thread->io_bitmap_max; | ||
622 | tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET; | ||
623 | tss->io_bitmap_owner = thread; | ||
624 | put_cpu(); | ||
625 | 308 | ||
309 | #ifdef CONFIG_X86_32 | ||
310 | if (lazy_iobitmap_copy()) { | ||
311 | /* restart the faulting instruction */ | ||
626 | return; | 312 | return; |
627 | } | 313 | } |
628 | put_cpu(); | ||
629 | 314 | ||
630 | if (regs->flags & X86_VM_MASK) | 315 | if (regs->flags & X86_VM_MASK) |
631 | goto gp_in_vm86; | 316 | goto gp_in_vm86; |
317 | #endif | ||
632 | 318 | ||
633 | tsk = current; | 319 | tsk = current; |
634 | if (!user_mode(regs)) | 320 | if (!user_mode(regs)) |
@@ -650,10 +336,12 @@ do_general_protection(struct pt_regs *regs, long error_code) | |||
650 | force_sig(SIGSEGV, tsk); | 336 | force_sig(SIGSEGV, tsk); |
651 | return; | 337 | return; |
652 | 338 | ||
339 | #ifdef CONFIG_X86_32 | ||
653 | gp_in_vm86: | 340 | gp_in_vm86: |
654 | local_irq_enable(); | 341 | local_irq_enable(); |
655 | handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); | 342 | handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); |
656 | return; | 343 | return; |
344 | #endif | ||
657 | 345 | ||
658 | gp_in_kernel: | 346 | gp_in_kernel: |
659 | if (fixup_exception(regs)) | 347 | if (fixup_exception(regs)) |
@@ -690,7 +378,8 @@ mem_parity_error(unsigned char reason, struct pt_regs *regs) | |||
690 | printk(KERN_EMERG "Dazed and confused, but trying to continue\n"); | 378 | printk(KERN_EMERG "Dazed and confused, but trying to continue\n"); |
691 | 379 | ||
692 | /* Clear and disable the memory parity error line. */ | 380 | /* Clear and disable the memory parity error line. */ |
693 | clear_mem_error(reason); | 381 | reason = (reason & 0xf) | 4; |
382 | outb(reason, 0x61); | ||
694 | } | 383 | } |
695 | 384 | ||
696 | static notrace __kprobes void | 385 | static notrace __kprobes void |
@@ -716,7 +405,8 @@ io_check_error(unsigned char reason, struct pt_regs *regs) | |||
716 | static notrace __kprobes void | 405 | static notrace __kprobes void |
717 | unknown_nmi_error(unsigned char reason, struct pt_regs *regs) | 406 | unknown_nmi_error(unsigned char reason, struct pt_regs *regs) |
718 | { | 407 | { |
719 | if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP) | 408 | if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == |
409 | NOTIFY_STOP) | ||
720 | return; | 410 | return; |
721 | #ifdef CONFIG_MCA | 411 | #ifdef CONFIG_MCA |
722 | /* | 412 | /* |
@@ -739,41 +429,6 @@ unknown_nmi_error(unsigned char reason, struct pt_regs *regs) | |||
739 | printk(KERN_EMERG "Dazed and confused, but trying to continue\n"); | 429 | printk(KERN_EMERG "Dazed and confused, but trying to continue\n"); |
740 | } | 430 | } |
741 | 431 | ||
742 | static DEFINE_SPINLOCK(nmi_print_lock); | ||
743 | |||
744 | void notrace __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic) | ||
745 | { | ||
746 | if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP) | ||
747 | return; | ||
748 | |||
749 | spin_lock(&nmi_print_lock); | ||
750 | /* | ||
751 | * We are in trouble anyway, lets at least try | ||
752 | * to get a message out: | ||
753 | */ | ||
754 | bust_spinlocks(1); | ||
755 | printk(KERN_EMERG "%s", str); | ||
756 | printk(" on CPU%d, ip %08lx, registers:\n", | ||
757 | smp_processor_id(), regs->ip); | ||
758 | show_registers(regs); | ||
759 | if (do_panic) | ||
760 | panic("Non maskable interrupt"); | ||
761 | console_silent(); | ||
762 | spin_unlock(&nmi_print_lock); | ||
763 | bust_spinlocks(0); | ||
764 | |||
765 | /* | ||
766 | * If we are in kernel we are probably nested up pretty bad | ||
767 | * and might aswell get out now while we still can: | ||
768 | */ | ||
769 | if (!user_mode_vm(regs)) { | ||
770 | current->thread.trap_no = 2; | ||
771 | crash_kexec(regs); | ||
772 | } | ||
773 | |||
774 | do_exit(SIGSEGV); | ||
775 | } | ||
776 | |||
777 | static notrace __kprobes void default_do_nmi(struct pt_regs *regs) | 432 | static notrace __kprobes void default_do_nmi(struct pt_regs *regs) |
778 | { | 433 | { |
779 | unsigned char reason = 0; | 434 | unsigned char reason = 0; |
@@ -812,22 +467,25 @@ static notrace __kprobes void default_do_nmi(struct pt_regs *regs) | |||
812 | mem_parity_error(reason, regs); | 467 | mem_parity_error(reason, regs); |
813 | if (reason & 0x40) | 468 | if (reason & 0x40) |
814 | io_check_error(reason, regs); | 469 | io_check_error(reason, regs); |
470 | #ifdef CONFIG_X86_32 | ||
815 | /* | 471 | /* |
816 | * Reassert NMI in case it became active meanwhile | 472 | * Reassert NMI in case it became active meanwhile |
817 | * as it's edge-triggered: | 473 | * as it's edge-triggered: |
818 | */ | 474 | */ |
819 | reassert_nmi(); | 475 | reassert_nmi(); |
476 | #endif | ||
820 | } | 477 | } |
821 | 478 | ||
822 | notrace __kprobes void do_nmi(struct pt_regs *regs, long error_code) | 479 | dotraplinkage notrace __kprobes void |
480 | do_nmi(struct pt_regs *regs, long error_code) | ||
823 | { | 481 | { |
824 | int cpu; | ||
825 | |||
826 | nmi_enter(); | 482 | nmi_enter(); |
827 | 483 | ||
828 | cpu = smp_processor_id(); | 484 | #ifdef CONFIG_X86_32 |
829 | 485 | { int cpu; cpu = smp_processor_id(); ++nmi_count(cpu); } | |
830 | ++nmi_count(cpu); | 486 | #else |
487 | add_pda(__nmi_count, 1); | ||
488 | #endif | ||
831 | 489 | ||
832 | if (!ignore_nmis) | 490 | if (!ignore_nmis) |
833 | default_do_nmi(regs); | 491 | default_do_nmi(regs); |
@@ -847,21 +505,44 @@ void restart_nmi(void) | |||
847 | acpi_nmi_enable(); | 505 | acpi_nmi_enable(); |
848 | } | 506 | } |
849 | 507 | ||
850 | #ifdef CONFIG_KPROBES | 508 | /* May run on IST stack. */ |
851 | void __kprobes do_int3(struct pt_regs *regs, long error_code) | 509 | dotraplinkage void __kprobes do_int3(struct pt_regs *regs, long error_code) |
852 | { | 510 | { |
853 | trace_hardirqs_fixup(); | 511 | #ifdef CONFIG_KPROBES |
854 | |||
855 | if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) | 512 | if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) |
856 | == NOTIFY_STOP) | 513 | == NOTIFY_STOP) |
857 | return; | 514 | return; |
858 | /* | 515 | #else |
859 | * This is an interrupt gate, because kprobes wants interrupts | 516 | if (notify_die(DIE_TRAP, "int3", regs, error_code, 3, SIGTRAP) |
860 | * disabled. Normal trap handlers don't. | 517 | == NOTIFY_STOP) |
861 | */ | 518 | return; |
862 | restore_interrupts(regs); | 519 | #endif |
520 | |||
521 | preempt_conditional_sti(regs); | ||
522 | do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); | ||
523 | preempt_conditional_cli(regs); | ||
524 | } | ||
863 | 525 | ||
864 | do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL); | 526 | #ifdef CONFIG_X86_64 |
527 | /* Help handler running on IST stack to switch back to user stack | ||
528 | for scheduling or signal handling. The actual stack switch is done in | ||
529 | entry.S */ | ||
530 | asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) | ||
531 | { | ||
532 | struct pt_regs *regs = eregs; | ||
533 | /* Did already sync */ | ||
534 | if (eregs == (struct pt_regs *)eregs->sp) | ||
535 | ; | ||
536 | /* Exception from user space */ | ||
537 | else if (user_mode(eregs)) | ||
538 | regs = task_pt_regs(current); | ||
539 | /* Exception from kernel and interrupts are enabled. Move to | ||
540 | kernel process stack. */ | ||
541 | else if (eregs->flags & X86_EFLAGS_IF) | ||
542 | regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs)); | ||
543 | if (eregs != regs) | ||
544 | *regs = *eregs; | ||
545 | return regs; | ||
865 | } | 546 | } |
866 | #endif | 547 | #endif |
867 | 548 | ||
@@ -886,15 +567,15 @@ void __kprobes do_int3(struct pt_regs *regs, long error_code) | |||
886 | * about restoring all the debug state, and ptrace doesn't have to | 567 | * about restoring all the debug state, and ptrace doesn't have to |
887 | * find every occurrence of the TF bit that could be saved away even | 568 | * find every occurrence of the TF bit that could be saved away even |
888 | * by user code) | 569 | * by user code) |
570 | * | ||
571 | * May run on IST stack. | ||
889 | */ | 572 | */ |
890 | void __kprobes do_debug(struct pt_regs *regs, long error_code) | 573 | dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) |
891 | { | 574 | { |
892 | struct task_struct *tsk = current; | 575 | struct task_struct *tsk = current; |
893 | unsigned int condition; | 576 | unsigned long condition; |
894 | int si_code; | 577 | int si_code; |
895 | 578 | ||
896 | trace_hardirqs_fixup(); | ||
897 | |||
898 | get_debugreg(condition, 6); | 579 | get_debugreg(condition, 6); |
899 | 580 | ||
900 | /* | 581 | /* |
@@ -906,9 +587,9 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
906 | if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, | 587 | if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, |
907 | SIGTRAP) == NOTIFY_STOP) | 588 | SIGTRAP) == NOTIFY_STOP) |
908 | return; | 589 | return; |
590 | |||
909 | /* It's safe to allow irq's after DR6 has been saved */ | 591 | /* It's safe to allow irq's after DR6 has been saved */ |
910 | if (regs->flags & X86_EFLAGS_IF) | 592 | preempt_conditional_sti(regs); |
911 | local_irq_enable(); | ||
912 | 593 | ||
913 | /* Mask out spurious debug traps due to lazy DR7 setting */ | 594 | /* Mask out spurious debug traps due to lazy DR7 setting */ |
914 | if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { | 595 | if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { |
@@ -916,8 +597,10 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
916 | goto clear_dr7; | 597 | goto clear_dr7; |
917 | } | 598 | } |
918 | 599 | ||
600 | #ifdef CONFIG_X86_32 | ||
919 | if (regs->flags & X86_VM_MASK) | 601 | if (regs->flags & X86_VM_MASK) |
920 | goto debug_vm86; | 602 | goto debug_vm86; |
603 | #endif | ||
921 | 604 | ||
922 | /* Save debug status register where ptrace can see it */ | 605 | /* Save debug status register where ptrace can see it */ |
923 | tsk->thread.debugreg6 = condition; | 606 | tsk->thread.debugreg6 = condition; |
@@ -927,16 +610,11 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
927 | * kernel space (but re-enable TF when returning to user mode). | 610 | * kernel space (but re-enable TF when returning to user mode). |
928 | */ | 611 | */ |
929 | if (condition & DR_STEP) { | 612 | if (condition & DR_STEP) { |
930 | /* | ||
931 | * We already checked v86 mode above, so we can | ||
932 | * check for kernel mode by just checking the CPL | ||
933 | * of CS. | ||
934 | */ | ||
935 | if (!user_mode(regs)) | 613 | if (!user_mode(regs)) |
936 | goto clear_TF_reenable; | 614 | goto clear_TF_reenable; |
937 | } | 615 | } |
938 | 616 | ||
939 | si_code = get_si_code((unsigned long)condition); | 617 | si_code = get_si_code(condition); |
940 | /* Ok, finally something we can handle */ | 618 | /* Ok, finally something we can handle */ |
941 | send_sigtrap(tsk, regs, error_code, si_code); | 619 | send_sigtrap(tsk, regs, error_code, si_code); |
942 | 620 | ||
@@ -946,18 +624,37 @@ void __kprobes do_debug(struct pt_regs *regs, long error_code) | |||
946 | */ | 624 | */ |
947 | clear_dr7: | 625 | clear_dr7: |
948 | set_debugreg(0, 7); | 626 | set_debugreg(0, 7); |
627 | preempt_conditional_cli(regs); | ||
949 | return; | 628 | return; |
950 | 629 | ||
630 | #ifdef CONFIG_X86_32 | ||
951 | debug_vm86: | 631 | debug_vm86: |
952 | handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1); | 632 | handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1); |
633 | preempt_conditional_cli(regs); | ||
953 | return; | 634 | return; |
635 | #endif | ||
954 | 636 | ||
955 | clear_TF_reenable: | 637 | clear_TF_reenable: |
956 | set_tsk_thread_flag(tsk, TIF_SINGLESTEP); | 638 | set_tsk_thread_flag(tsk, TIF_SINGLESTEP); |
957 | regs->flags &= ~X86_EFLAGS_TF; | 639 | regs->flags &= ~X86_EFLAGS_TF; |
640 | preempt_conditional_cli(regs); | ||
958 | return; | 641 | return; |
959 | } | 642 | } |
960 | 643 | ||
644 | #ifdef CONFIG_X86_64 | ||
645 | static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr) | ||
646 | { | ||
647 | if (fixup_exception(regs)) | ||
648 | return 1; | ||
649 | |||
650 | notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE); | ||
651 | /* Illegal floating point operation in the kernel */ | ||
652 | current->thread.trap_no = trapnr; | ||
653 | die(str, regs, 0); | ||
654 | return 0; | ||
655 | } | ||
656 | #endif | ||
657 | |||
961 | /* | 658 | /* |
962 | * Note that we play around with the 'TS' bit in an attempt to get | 659 | * Note that we play around with the 'TS' bit in an attempt to get |
963 | * the correct behaviour even in the presence of the asynchronous | 660 | * the correct behaviour even in the presence of the asynchronous |
@@ -994,7 +691,9 @@ void math_error(void __user *ip) | |||
994 | swd = get_fpu_swd(task); | 691 | swd = get_fpu_swd(task); |
995 | switch (swd & ~cwd & 0x3f) { | 692 | switch (swd & ~cwd & 0x3f) { |
996 | case 0x000: /* No unmasked exception */ | 693 | case 0x000: /* No unmasked exception */ |
694 | #ifdef CONFIG_X86_32 | ||
997 | return; | 695 | return; |
696 | #endif | ||
998 | default: /* Multiple exceptions */ | 697 | default: /* Multiple exceptions */ |
999 | break; | 698 | break; |
1000 | case 0x001: /* Invalid Op */ | 699 | case 0x001: /* Invalid Op */ |
@@ -1022,9 +721,18 @@ void math_error(void __user *ip) | |||
1022 | force_sig_info(SIGFPE, &info, task); | 721 | force_sig_info(SIGFPE, &info, task); |
1023 | } | 722 | } |
1024 | 723 | ||
1025 | void do_coprocessor_error(struct pt_regs *regs, long error_code) | 724 | dotraplinkage void do_coprocessor_error(struct pt_regs *regs, long error_code) |
1026 | { | 725 | { |
726 | conditional_sti(regs); | ||
727 | |||
728 | #ifdef CONFIG_X86_32 | ||
1027 | ignore_fpu_irq = 1; | 729 | ignore_fpu_irq = 1; |
730 | #else | ||
731 | if (!user_mode(regs) && | ||
732 | kernel_math_error(regs, "kernel x87 math error", 16)) | ||
733 | return; | ||
734 | #endif | ||
735 | |||
1028 | math_error((void __user *)regs->ip); | 736 | math_error((void __user *)regs->ip); |
1029 | } | 737 | } |
1030 | 738 | ||
@@ -1076,8 +784,12 @@ static void simd_math_error(void __user *ip) | |||
1076 | force_sig_info(SIGFPE, &info, task); | 784 | force_sig_info(SIGFPE, &info, task); |
1077 | } | 785 | } |
1078 | 786 | ||
1079 | void do_simd_coprocessor_error(struct pt_regs *regs, long error_code) | 787 | dotraplinkage void |
788 | do_simd_coprocessor_error(struct pt_regs *regs, long error_code) | ||
1080 | { | 789 | { |
790 | conditional_sti(regs); | ||
791 | |||
792 | #ifdef CONFIG_X86_32 | ||
1081 | if (cpu_has_xmm) { | 793 | if (cpu_has_xmm) { |
1082 | /* Handle SIMD FPU exceptions on PIII+ processors. */ | 794 | /* Handle SIMD FPU exceptions on PIII+ processors. */ |
1083 | ignore_fpu_irq = 1; | 795 | ignore_fpu_irq = 1; |
@@ -1096,16 +808,25 @@ void do_simd_coprocessor_error(struct pt_regs *regs, long error_code) | |||
1096 | current->thread.error_code = error_code; | 808 | current->thread.error_code = error_code; |
1097 | die_if_kernel("cache flush denied", regs, error_code); | 809 | die_if_kernel("cache flush denied", regs, error_code); |
1098 | force_sig(SIGSEGV, current); | 810 | force_sig(SIGSEGV, current); |
811 | #else | ||
812 | if (!user_mode(regs) && | ||
813 | kernel_math_error(regs, "kernel simd math error", 19)) | ||
814 | return; | ||
815 | simd_math_error((void __user *)regs->ip); | ||
816 | #endif | ||
1099 | } | 817 | } |
1100 | 818 | ||
1101 | void do_spurious_interrupt_bug(struct pt_regs *regs, long error_code) | 819 | dotraplinkage void |
820 | do_spurious_interrupt_bug(struct pt_regs *regs, long error_code) | ||
1102 | { | 821 | { |
822 | conditional_sti(regs); | ||
1103 | #if 0 | 823 | #if 0 |
1104 | /* No need to warn about this any longer. */ | 824 | /* No need to warn about this any longer. */ |
1105 | printk(KERN_INFO "Ignoring P6 Local APIC Spurious Interrupt Bug...\n"); | 825 | printk(KERN_INFO "Ignoring P6 Local APIC Spurious Interrupt Bug...\n"); |
1106 | #endif | 826 | #endif |
1107 | } | 827 | } |
1108 | 828 | ||
829 | #ifdef CONFIG_X86_32 | ||
1109 | unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp) | 830 | unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp) |
1110 | { | 831 | { |
1111 | struct desc_struct *gdt = get_cpu_gdt_table(smp_processor_id()); | 832 | struct desc_struct *gdt = get_cpu_gdt_table(smp_processor_id()); |
@@ -1124,6 +845,15 @@ unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp) | |||
1124 | 845 | ||
1125 | return new_kesp; | 846 | return new_kesp; |
1126 | } | 847 | } |
848 | #else | ||
849 | asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void) | ||
850 | { | ||
851 | } | ||
852 | |||
853 | asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void) | ||
854 | { | ||
855 | } | ||
856 | #endif | ||
1127 | 857 | ||
1128 | /* | 858 | /* |
1129 | * 'math_state_restore()' saves the current math information in the | 859 | * 'math_state_restore()' saves the current math information in the |
@@ -1156,14 +886,24 @@ asmlinkage void math_state_restore(void) | |||
1156 | } | 886 | } |
1157 | 887 | ||
1158 | clts(); /* Allow maths ops (or we recurse) */ | 888 | clts(); /* Allow maths ops (or we recurse) */ |
889 | #ifdef CONFIG_X86_32 | ||
1159 | restore_fpu(tsk); | 890 | restore_fpu(tsk); |
891 | #else | ||
892 | /* | ||
893 | * Paranoid restore. send a SIGSEGV if we fail to restore the state. | ||
894 | */ | ||
895 | if (unlikely(restore_fpu_checking(tsk))) { | ||
896 | stts(); | ||
897 | force_sig(SIGSEGV, tsk); | ||
898 | return; | ||
899 | } | ||
900 | #endif | ||
1160 | thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ | 901 | thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ |
1161 | tsk->fpu_counter++; | 902 | tsk->fpu_counter++; |
1162 | } | 903 | } |
1163 | EXPORT_SYMBOL_GPL(math_state_restore); | 904 | EXPORT_SYMBOL_GPL(math_state_restore); |
1164 | 905 | ||
1165 | #ifndef CONFIG_MATH_EMULATION | 906 | #ifndef CONFIG_MATH_EMULATION |
1166 | |||
1167 | asmlinkage void math_emulate(long arg) | 907 | asmlinkage void math_emulate(long arg) |
1168 | { | 908 | { |
1169 | printk(KERN_EMERG | 909 | printk(KERN_EMERG |
@@ -1172,12 +912,54 @@ asmlinkage void math_emulate(long arg) | |||
1172 | force_sig(SIGFPE, current); | 912 | force_sig(SIGFPE, current); |
1173 | schedule(); | 913 | schedule(); |
1174 | } | 914 | } |
1175 | |||
1176 | #endif /* CONFIG_MATH_EMULATION */ | 915 | #endif /* CONFIG_MATH_EMULATION */ |
1177 | 916 | ||
917 | dotraplinkage void __kprobes | ||
918 | do_device_not_available(struct pt_regs *regs, long error) | ||
919 | { | ||
920 | #ifdef CONFIG_X86_32 | ||
921 | if (read_cr0() & X86_CR0_EM) { | ||
922 | conditional_sti(regs); | ||
923 | math_emulate(0); | ||
924 | } else { | ||
925 | math_state_restore(); /* interrupts still off */ | ||
926 | conditional_sti(regs); | ||
927 | } | ||
928 | #else | ||
929 | math_state_restore(); | ||
930 | #endif | ||
931 | } | ||
932 | |||
933 | #ifdef CONFIG_X86_32 | ||
934 | #ifdef CONFIG_X86_MCE | ||
935 | dotraplinkage void __kprobes do_machine_check(struct pt_regs *regs, long error) | ||
936 | { | ||
937 | conditional_sti(regs); | ||
938 | machine_check_vector(regs, error); | ||
939 | } | ||
940 | #endif | ||
941 | |||
942 | dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code) | ||
943 | { | ||
944 | siginfo_t info; | ||
945 | local_irq_enable(); | ||
946 | |||
947 | info.si_signo = SIGILL; | ||
948 | info.si_errno = 0; | ||
949 | info.si_code = ILL_BADSTK; | ||
950 | info.si_addr = 0; | ||
951 | if (notify_die(DIE_TRAP, "iret exception", | ||
952 | regs, error_code, 32, SIGILL) == NOTIFY_STOP) | ||
953 | return; | ||
954 | do_trap(32, SIGILL, "iret exception", regs, error_code, &info); | ||
955 | } | ||
956 | #endif | ||
957 | |||
1178 | void __init trap_init(void) | 958 | void __init trap_init(void) |
1179 | { | 959 | { |
960 | #ifdef CONFIG_X86_32 | ||
1180 | int i; | 961 | int i; |
962 | #endif | ||
1181 | 963 | ||
1182 | #ifdef CONFIG_EISA | 964 | #ifdef CONFIG_EISA |
1183 | void __iomem *p = early_ioremap(0x0FFFD9, 4); | 965 | void __iomem *p = early_ioremap(0x0FFFD9, 4); |
@@ -1187,29 +969,40 @@ void __init trap_init(void) | |||
1187 | early_iounmap(p, 4); | 969 | early_iounmap(p, 4); |
1188 | #endif | 970 | #endif |
1189 | 971 | ||
1190 | set_trap_gate(0, ÷_error); | 972 | set_intr_gate(0, ÷_error); |
1191 | set_intr_gate(1, &debug); | 973 | set_intr_gate_ist(1, &debug, DEBUG_STACK); |
1192 | set_intr_gate(2, &nmi); | 974 | set_intr_gate_ist(2, &nmi, NMI_STACK); |
1193 | set_system_intr_gate(3, &int3); /* int3 can be called from all */ | 975 | /* int3 can be called from all */ |
1194 | set_system_gate(4, &overflow); /* int4 can be called from all */ | 976 | set_system_intr_gate_ist(3, &int3, DEBUG_STACK); |
1195 | set_trap_gate(5, &bounds); | 977 | /* int4 can be called from all */ |
1196 | set_trap_gate(6, &invalid_op); | 978 | set_system_intr_gate(4, &overflow); |
1197 | set_trap_gate(7, &device_not_available); | 979 | set_intr_gate(5, &bounds); |
980 | set_intr_gate(6, &invalid_op); | ||
981 | set_intr_gate(7, &device_not_available); | ||
982 | #ifdef CONFIG_X86_32 | ||
1198 | set_task_gate(8, GDT_ENTRY_DOUBLEFAULT_TSS); | 983 | set_task_gate(8, GDT_ENTRY_DOUBLEFAULT_TSS); |
1199 | set_trap_gate(9, &coprocessor_segment_overrun); | 984 | #else |
1200 | set_trap_gate(10, &invalid_TSS); | 985 | set_intr_gate_ist(8, &double_fault, DOUBLEFAULT_STACK); |
1201 | set_trap_gate(11, &segment_not_present); | 986 | #endif |
1202 | set_trap_gate(12, &stack_segment); | 987 | set_intr_gate(9, &coprocessor_segment_overrun); |
1203 | set_trap_gate(13, &general_protection); | 988 | set_intr_gate(10, &invalid_TSS); |
989 | set_intr_gate(11, &segment_not_present); | ||
990 | set_intr_gate_ist(12, &stack_segment, STACKFAULT_STACK); | ||
991 | set_intr_gate(13, &general_protection); | ||
1204 | set_intr_gate(14, &page_fault); | 992 | set_intr_gate(14, &page_fault); |
1205 | set_trap_gate(15, &spurious_interrupt_bug); | 993 | set_intr_gate(15, &spurious_interrupt_bug); |
1206 | set_trap_gate(16, &coprocessor_error); | 994 | set_intr_gate(16, &coprocessor_error); |
1207 | set_trap_gate(17, &alignment_check); | 995 | set_intr_gate(17, &alignment_check); |
1208 | #ifdef CONFIG_X86_MCE | 996 | #ifdef CONFIG_X86_MCE |
1209 | set_trap_gate(18, &machine_check); | 997 | set_intr_gate_ist(18, &machine_check, MCE_STACK); |
1210 | #endif | 998 | #endif |
1211 | set_trap_gate(19, &simd_coprocessor_error); | 999 | set_intr_gate(19, &simd_coprocessor_error); |
1212 | 1000 | ||
1001 | #ifdef CONFIG_IA32_EMULATION | ||
1002 | set_system_intr_gate(IA32_SYSCALL_VECTOR, ia32_syscall); | ||
1003 | #endif | ||
1004 | |||
1005 | #ifdef CONFIG_X86_32 | ||
1213 | if (cpu_has_fxsr) { | 1006 | if (cpu_has_fxsr) { |
1214 | printk(KERN_INFO "Enabling fast FPU save and restore... "); | 1007 | printk(KERN_INFO "Enabling fast FPU save and restore... "); |
1215 | set_in_cr4(X86_CR4_OSFXSR); | 1008 | set_in_cr4(X86_CR4_OSFXSR); |
@@ -1222,36 +1015,20 @@ void __init trap_init(void) | |||
1222 | printk("done.\n"); | 1015 | printk("done.\n"); |
1223 | } | 1016 | } |
1224 | 1017 | ||
1225 | set_system_gate(SYSCALL_VECTOR, &system_call); | 1018 | set_system_trap_gate(SYSCALL_VECTOR, &system_call); |
1226 | 1019 | ||
1227 | /* Reserve all the builtin and the syscall vector: */ | 1020 | /* Reserve all the builtin and the syscall vector: */ |
1228 | for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) | 1021 | for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) |
1229 | set_bit(i, used_vectors); | 1022 | set_bit(i, used_vectors); |
1230 | 1023 | ||
1231 | set_bit(SYSCALL_VECTOR, used_vectors); | 1024 | set_bit(SYSCALL_VECTOR, used_vectors); |
1232 | 1025 | #endif | |
1233 | /* | 1026 | /* |
1234 | * Should be a barrier for any external CPU state: | 1027 | * Should be a barrier for any external CPU state: |
1235 | */ | 1028 | */ |
1236 | cpu_init(); | 1029 | cpu_init(); |
1237 | 1030 | ||
1031 | #ifdef CONFIG_X86_32 | ||
1238 | trap_init_hook(); | 1032 | trap_init_hook(); |
1033 | #endif | ||
1239 | } | 1034 | } |
1240 | |||
1241 | static int __init kstack_setup(char *s) | ||
1242 | { | ||
1243 | kstack_depth_to_print = simple_strtoul(s, NULL, 0); | ||
1244 | |||
1245 | return 1; | ||
1246 | } | ||
1247 | __setup("kstack=", kstack_setup); | ||
1248 | |||
1249 | static int __init code_bytes_setup(char *s) | ||
1250 | { | ||
1251 | code_bytes = simple_strtoul(s, NULL, 0); | ||
1252 | if (code_bytes > 8192) | ||
1253 | code_bytes = 8192; | ||
1254 | |||
1255 | return 1; | ||
1256 | } | ||
1257 | __setup("code_bytes=", code_bytes_setup); | ||
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c deleted file mode 100644 index 9c0ac0cab013..000000000000 --- a/arch/x86/kernel/traps_64.c +++ /dev/null | |||
@@ -1,1214 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
3 | * Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs | ||
4 | * | ||
5 | * Pentium III FXSR, SSE support | ||
6 | * Gareth Hughes <gareth@valinux.com>, May 2000 | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * 'Traps.c' handles hardware traps and faults after we have saved some | ||
11 | * state in 'entry.S'. | ||
12 | */ | ||
13 | #include <linux/moduleparam.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/kallsyms.h> | ||
16 | #include <linux/spinlock.h> | ||
17 | #include <linux/kprobes.h> | ||
18 | #include <linux/uaccess.h> | ||
19 | #include <linux/utsname.h> | ||
20 | #include <linux/kdebug.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/ptrace.h> | ||
24 | #include <linux/string.h> | ||
25 | #include <linux/unwind.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/kexec.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/timer.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/bug.h> | ||
33 | #include <linux/nmi.h> | ||
34 | #include <linux/mm.h> | ||
35 | #include <linux/smp.h> | ||
36 | #include <linux/io.h> | ||
37 | |||
38 | #if defined(CONFIG_EDAC) | ||
39 | #include <linux/edac.h> | ||
40 | #endif | ||
41 | |||
42 | #include <asm/stacktrace.h> | ||
43 | #include <asm/processor.h> | ||
44 | #include <asm/debugreg.h> | ||
45 | #include <asm/atomic.h> | ||
46 | #include <asm/system.h> | ||
47 | #include <asm/unwind.h> | ||
48 | #include <asm/desc.h> | ||
49 | #include <asm/i387.h> | ||
50 | #include <asm/pgalloc.h> | ||
51 | #include <asm/proto.h> | ||
52 | #include <asm/pda.h> | ||
53 | #include <asm/traps.h> | ||
54 | |||
55 | #include <mach_traps.h> | ||
56 | |||
57 | int panic_on_unrecovered_nmi; | ||
58 | int kstack_depth_to_print = 12; | ||
59 | static unsigned int code_bytes = 64; | ||
60 | static int ignore_nmis; | ||
61 | static int die_counter; | ||
62 | |||
63 | static inline void conditional_sti(struct pt_regs *regs) | ||
64 | { | ||
65 | if (regs->flags & X86_EFLAGS_IF) | ||
66 | local_irq_enable(); | ||
67 | } | ||
68 | |||
69 | static inline void preempt_conditional_sti(struct pt_regs *regs) | ||
70 | { | ||
71 | inc_preempt_count(); | ||
72 | if (regs->flags & X86_EFLAGS_IF) | ||
73 | local_irq_enable(); | ||
74 | } | ||
75 | |||
76 | static inline void preempt_conditional_cli(struct pt_regs *regs) | ||
77 | { | ||
78 | if (regs->flags & X86_EFLAGS_IF) | ||
79 | local_irq_disable(); | ||
80 | /* Make sure to not schedule here because we could be running | ||
81 | on an exception stack. */ | ||
82 | dec_preempt_count(); | ||
83 | } | ||
84 | |||
85 | void printk_address(unsigned long address, int reliable) | ||
86 | { | ||
87 | printk(" [<%016lx>] %s%pS\n", | ||
88 | address, reliable ? "" : "? ", (void *) address); | ||
89 | } | ||
90 | |||
91 | static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, | ||
92 | unsigned *usedp, char **idp) | ||
93 | { | ||
94 | static char ids[][8] = { | ||
95 | [DEBUG_STACK - 1] = "#DB", | ||
96 | [NMI_STACK - 1] = "NMI", | ||
97 | [DOUBLEFAULT_STACK - 1] = "#DF", | ||
98 | [STACKFAULT_STACK - 1] = "#SS", | ||
99 | [MCE_STACK - 1] = "#MC", | ||
100 | #if DEBUG_STKSZ > EXCEPTION_STKSZ | ||
101 | [N_EXCEPTION_STACKS ... | ||
102 | N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]" | ||
103 | #endif | ||
104 | }; | ||
105 | unsigned k; | ||
106 | |||
107 | /* | ||
108 | * Iterate over all exception stacks, and figure out whether | ||
109 | * 'stack' is in one of them: | ||
110 | */ | ||
111 | for (k = 0; k < N_EXCEPTION_STACKS; k++) { | ||
112 | unsigned long end = per_cpu(orig_ist, cpu).ist[k]; | ||
113 | /* | ||
114 | * Is 'stack' above this exception frame's end? | ||
115 | * If yes then skip to the next frame. | ||
116 | */ | ||
117 | if (stack >= end) | ||
118 | continue; | ||
119 | /* | ||
120 | * Is 'stack' above this exception frame's start address? | ||
121 | * If yes then we found the right frame. | ||
122 | */ | ||
123 | if (stack >= end - EXCEPTION_STKSZ) { | ||
124 | /* | ||
125 | * Make sure we only iterate through an exception | ||
126 | * stack once. If it comes up for the second time | ||
127 | * then there's something wrong going on - just | ||
128 | * break out and return NULL: | ||
129 | */ | ||
130 | if (*usedp & (1U << k)) | ||
131 | break; | ||
132 | *usedp |= 1U << k; | ||
133 | *idp = ids[k]; | ||
134 | return (unsigned long *)end; | ||
135 | } | ||
136 | /* | ||
137 | * If this is a debug stack, and if it has a larger size than | ||
138 | * the usual exception stacks, then 'stack' might still | ||
139 | * be within the lower portion of the debug stack: | ||
140 | */ | ||
141 | #if DEBUG_STKSZ > EXCEPTION_STKSZ | ||
142 | if (k == DEBUG_STACK - 1 && stack >= end - DEBUG_STKSZ) { | ||
143 | unsigned j = N_EXCEPTION_STACKS - 1; | ||
144 | |||
145 | /* | ||
146 | * Black magic. A large debug stack is composed of | ||
147 | * multiple exception stack entries, which we | ||
148 | * iterate through now. Dont look: | ||
149 | */ | ||
150 | do { | ||
151 | ++j; | ||
152 | end -= EXCEPTION_STKSZ; | ||
153 | ids[j][4] = '1' + (j - N_EXCEPTION_STACKS); | ||
154 | } while (stack < end - EXCEPTION_STKSZ); | ||
155 | if (*usedp & (1U << j)) | ||
156 | break; | ||
157 | *usedp |= 1U << j; | ||
158 | *idp = ids[j]; | ||
159 | return (unsigned long *)end; | ||
160 | } | ||
161 | #endif | ||
162 | } | ||
163 | return NULL; | ||
164 | } | ||
165 | |||
166 | /* | ||
167 | * x86-64 can have up to three kernel stacks: | ||
168 | * process stack | ||
169 | * interrupt stack | ||
170 | * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack | ||
171 | */ | ||
172 | |||
173 | static inline int valid_stack_ptr(struct thread_info *tinfo, | ||
174 | void *p, unsigned int size, void *end) | ||
175 | { | ||
176 | void *t = tinfo; | ||
177 | if (end) { | ||
178 | if (p < end && p >= (end-THREAD_SIZE)) | ||
179 | return 1; | ||
180 | else | ||
181 | return 0; | ||
182 | } | ||
183 | return p > t && p < t + THREAD_SIZE - size; | ||
184 | } | ||
185 | |||
186 | /* The form of the top of the frame on the stack */ | ||
187 | struct stack_frame { | ||
188 | struct stack_frame *next_frame; | ||
189 | unsigned long return_address; | ||
190 | }; | ||
191 | |||
192 | static inline unsigned long | ||
193 | print_context_stack(struct thread_info *tinfo, | ||
194 | unsigned long *stack, unsigned long bp, | ||
195 | const struct stacktrace_ops *ops, void *data, | ||
196 | unsigned long *end) | ||
197 | { | ||
198 | struct stack_frame *frame = (struct stack_frame *)bp; | ||
199 | |||
200 | while (valid_stack_ptr(tinfo, stack, sizeof(*stack), end)) { | ||
201 | unsigned long addr; | ||
202 | |||
203 | addr = *stack; | ||
204 | if (__kernel_text_address(addr)) { | ||
205 | if ((unsigned long) stack == bp + 8) { | ||
206 | ops->address(data, addr, 1); | ||
207 | frame = frame->next_frame; | ||
208 | bp = (unsigned long) frame; | ||
209 | } else { | ||
210 | ops->address(data, addr, bp == 0); | ||
211 | } | ||
212 | } | ||
213 | stack++; | ||
214 | } | ||
215 | return bp; | ||
216 | } | ||
217 | |||
218 | void dump_trace(struct task_struct *task, struct pt_regs *regs, | ||
219 | unsigned long *stack, unsigned long bp, | ||
220 | const struct stacktrace_ops *ops, void *data) | ||
221 | { | ||
222 | const unsigned cpu = get_cpu(); | ||
223 | unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr; | ||
224 | unsigned used = 0; | ||
225 | struct thread_info *tinfo; | ||
226 | |||
227 | if (!task) | ||
228 | task = current; | ||
229 | |||
230 | if (!stack) { | ||
231 | unsigned long dummy; | ||
232 | stack = &dummy; | ||
233 | if (task && task != current) | ||
234 | stack = (unsigned long *)task->thread.sp; | ||
235 | } | ||
236 | |||
237 | #ifdef CONFIG_FRAME_POINTER | ||
238 | if (!bp) { | ||
239 | if (task == current) { | ||
240 | /* Grab bp right from our regs */ | ||
241 | asm("movq %%rbp, %0" : "=r" (bp) : ); | ||
242 | } else { | ||
243 | /* bp is the last reg pushed by switch_to */ | ||
244 | bp = *(unsigned long *) task->thread.sp; | ||
245 | } | ||
246 | } | ||
247 | #endif | ||
248 | |||
249 | /* | ||
250 | * Print function call entries in all stacks, starting at the | ||
251 | * current stack address. If the stacks consist of nested | ||
252 | * exceptions | ||
253 | */ | ||
254 | tinfo = task_thread_info(task); | ||
255 | for (;;) { | ||
256 | char *id; | ||
257 | unsigned long *estack_end; | ||
258 | estack_end = in_exception_stack(cpu, (unsigned long)stack, | ||
259 | &used, &id); | ||
260 | |||
261 | if (estack_end) { | ||
262 | if (ops->stack(data, id) < 0) | ||
263 | break; | ||
264 | |||
265 | bp = print_context_stack(tinfo, stack, bp, ops, | ||
266 | data, estack_end); | ||
267 | ops->stack(data, "<EOE>"); | ||
268 | /* | ||
269 | * We link to the next stack via the | ||
270 | * second-to-last pointer (index -2 to end) in the | ||
271 | * exception stack: | ||
272 | */ | ||
273 | stack = (unsigned long *) estack_end[-2]; | ||
274 | continue; | ||
275 | } | ||
276 | if (irqstack_end) { | ||
277 | unsigned long *irqstack; | ||
278 | irqstack = irqstack_end - | ||
279 | (IRQSTACKSIZE - 64) / sizeof(*irqstack); | ||
280 | |||
281 | if (stack >= irqstack && stack < irqstack_end) { | ||
282 | if (ops->stack(data, "IRQ") < 0) | ||
283 | break; | ||
284 | bp = print_context_stack(tinfo, stack, bp, | ||
285 | ops, data, irqstack_end); | ||
286 | /* | ||
287 | * We link to the next stack (which would be | ||
288 | * the process stack normally) the last | ||
289 | * pointer (index -1 to end) in the IRQ stack: | ||
290 | */ | ||
291 | stack = (unsigned long *) (irqstack_end[-1]); | ||
292 | irqstack_end = NULL; | ||
293 | ops->stack(data, "EOI"); | ||
294 | continue; | ||
295 | } | ||
296 | } | ||
297 | break; | ||
298 | } | ||
299 | |||
300 | /* | ||
301 | * This handles the process stack: | ||
302 | */ | ||
303 | bp = print_context_stack(tinfo, stack, bp, ops, data, NULL); | ||
304 | put_cpu(); | ||
305 | } | ||
306 | EXPORT_SYMBOL(dump_trace); | ||
307 | |||
308 | static void | ||
309 | print_trace_warning_symbol(void *data, char *msg, unsigned long symbol) | ||
310 | { | ||
311 | print_symbol(msg, symbol); | ||
312 | printk("\n"); | ||
313 | } | ||
314 | |||
315 | static void print_trace_warning(void *data, char *msg) | ||
316 | { | ||
317 | printk("%s\n", msg); | ||
318 | } | ||
319 | |||
320 | static int print_trace_stack(void *data, char *name) | ||
321 | { | ||
322 | printk(" <%s> ", name); | ||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | static void print_trace_address(void *data, unsigned long addr, int reliable) | ||
327 | { | ||
328 | touch_nmi_watchdog(); | ||
329 | printk_address(addr, reliable); | ||
330 | } | ||
331 | |||
332 | static const struct stacktrace_ops print_trace_ops = { | ||
333 | .warning = print_trace_warning, | ||
334 | .warning_symbol = print_trace_warning_symbol, | ||
335 | .stack = print_trace_stack, | ||
336 | .address = print_trace_address, | ||
337 | }; | ||
338 | |||
339 | static void | ||
340 | show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, | ||
341 | unsigned long *stack, unsigned long bp, char *log_lvl) | ||
342 | { | ||
343 | printk("Call Trace:\n"); | ||
344 | dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl); | ||
345 | } | ||
346 | |||
347 | void show_trace(struct task_struct *task, struct pt_regs *regs, | ||
348 | unsigned long *stack, unsigned long bp) | ||
349 | { | ||
350 | show_trace_log_lvl(task, regs, stack, bp, ""); | ||
351 | } | ||
352 | |||
353 | static void | ||
354 | show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, | ||
355 | unsigned long *sp, unsigned long bp, char *log_lvl) | ||
356 | { | ||
357 | unsigned long *stack; | ||
358 | int i; | ||
359 | const int cpu = smp_processor_id(); | ||
360 | unsigned long *irqstack_end = | ||
361 | (unsigned long *) (cpu_pda(cpu)->irqstackptr); | ||
362 | unsigned long *irqstack = | ||
363 | (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE); | ||
364 | |||
365 | /* | ||
366 | * debugging aid: "show_stack(NULL, NULL);" prints the | ||
367 | * back trace for this cpu. | ||
368 | */ | ||
369 | |||
370 | if (sp == NULL) { | ||
371 | if (task) | ||
372 | sp = (unsigned long *)task->thread.sp; | ||
373 | else | ||
374 | sp = (unsigned long *)&sp; | ||
375 | } | ||
376 | |||
377 | stack = sp; | ||
378 | for (i = 0; i < kstack_depth_to_print; i++) { | ||
379 | if (stack >= irqstack && stack <= irqstack_end) { | ||
380 | if (stack == irqstack_end) { | ||
381 | stack = (unsigned long *) (irqstack_end[-1]); | ||
382 | printk(" <EOI> "); | ||
383 | } | ||
384 | } else { | ||
385 | if (((long) stack & (THREAD_SIZE-1)) == 0) | ||
386 | break; | ||
387 | } | ||
388 | if (i && ((i % 4) == 0)) | ||
389 | printk("\n"); | ||
390 | printk(" %016lx", *stack++); | ||
391 | touch_nmi_watchdog(); | ||
392 | } | ||
393 | printk("\n"); | ||
394 | show_trace_log_lvl(task, regs, sp, bp, log_lvl); | ||
395 | } | ||
396 | |||
397 | void show_stack(struct task_struct *task, unsigned long *sp) | ||
398 | { | ||
399 | show_stack_log_lvl(task, NULL, sp, 0, ""); | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * The architecture-independent dump_stack generator | ||
404 | */ | ||
405 | void dump_stack(void) | ||
406 | { | ||
407 | unsigned long bp = 0; | ||
408 | unsigned long stack; | ||
409 | |||
410 | #ifdef CONFIG_FRAME_POINTER | ||
411 | if (!bp) | ||
412 | asm("movq %%rbp, %0" : "=r" (bp) : ); | ||
413 | #endif | ||
414 | |||
415 | printk("Pid: %d, comm: %.20s %s %s %.*s\n", | ||
416 | current->pid, current->comm, print_tainted(), | ||
417 | init_utsname()->release, | ||
418 | (int)strcspn(init_utsname()->version, " "), | ||
419 | init_utsname()->version); | ||
420 | show_trace(NULL, NULL, &stack, bp); | ||
421 | } | ||
422 | EXPORT_SYMBOL(dump_stack); | ||
423 | |||
424 | void show_registers(struct pt_regs *regs) | ||
425 | { | ||
426 | int i; | ||
427 | unsigned long sp; | ||
428 | const int cpu = smp_processor_id(); | ||
429 | struct task_struct *cur = cpu_pda(cpu)->pcurrent; | ||
430 | |||
431 | sp = regs->sp; | ||
432 | printk("CPU %d ", cpu); | ||
433 | __show_regs(regs); | ||
434 | printk("Process %s (pid: %d, threadinfo %p, task %p)\n", | ||
435 | cur->comm, cur->pid, task_thread_info(cur), cur); | ||
436 | |||
437 | /* | ||
438 | * When in-kernel, we also print out the stack and code at the | ||
439 | * time of the fault.. | ||
440 | */ | ||
441 | if (!user_mode(regs)) { | ||
442 | unsigned int code_prologue = code_bytes * 43 / 64; | ||
443 | unsigned int code_len = code_bytes; | ||
444 | unsigned char c; | ||
445 | u8 *ip; | ||
446 | |||
447 | printk("Stack: "); | ||
448 | show_stack_log_lvl(NULL, regs, (unsigned long *)sp, | ||
449 | regs->bp, ""); | ||
450 | |||
451 | printk(KERN_EMERG "Code: "); | ||
452 | |||
453 | ip = (u8 *)regs->ip - code_prologue; | ||
454 | if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { | ||
455 | /* try starting at RIP */ | ||
456 | ip = (u8 *)regs->ip; | ||
457 | code_len = code_len - code_prologue + 1; | ||
458 | } | ||
459 | for (i = 0; i < code_len; i++, ip++) { | ||
460 | if (ip < (u8 *)PAGE_OFFSET || | ||
461 | probe_kernel_address(ip, c)) { | ||
462 | printk(" Bad RIP value."); | ||
463 | break; | ||
464 | } | ||
465 | if (ip == (u8 *)regs->ip) | ||
466 | printk("<%02x> ", c); | ||
467 | else | ||
468 | printk("%02x ", c); | ||
469 | } | ||
470 | } | ||
471 | printk("\n"); | ||
472 | } | ||
473 | |||
474 | int is_valid_bugaddr(unsigned long ip) | ||
475 | { | ||
476 | unsigned short ud2; | ||
477 | |||
478 | if (__copy_from_user(&ud2, (const void __user *) ip, sizeof(ud2))) | ||
479 | return 0; | ||
480 | |||
481 | return ud2 == 0x0b0f; | ||
482 | } | ||
483 | |||
484 | static raw_spinlock_t die_lock = __RAW_SPIN_LOCK_UNLOCKED; | ||
485 | static int die_owner = -1; | ||
486 | static unsigned int die_nest_count; | ||
487 | |||
488 | unsigned __kprobes long oops_begin(void) | ||
489 | { | ||
490 | int cpu; | ||
491 | unsigned long flags; | ||
492 | |||
493 | oops_enter(); | ||
494 | |||
495 | /* racy, but better than risking deadlock. */ | ||
496 | raw_local_irq_save(flags); | ||
497 | cpu = smp_processor_id(); | ||
498 | if (!__raw_spin_trylock(&die_lock)) { | ||
499 | if (cpu == die_owner) | ||
500 | /* nested oops. should stop eventually */; | ||
501 | else | ||
502 | __raw_spin_lock(&die_lock); | ||
503 | } | ||
504 | die_nest_count++; | ||
505 | die_owner = cpu; | ||
506 | console_verbose(); | ||
507 | bust_spinlocks(1); | ||
508 | return flags; | ||
509 | } | ||
510 | |||
511 | void __kprobes oops_end(unsigned long flags, struct pt_regs *regs, int signr) | ||
512 | { | ||
513 | die_owner = -1; | ||
514 | bust_spinlocks(0); | ||
515 | die_nest_count--; | ||
516 | if (!die_nest_count) | ||
517 | /* Nest count reaches zero, release the lock. */ | ||
518 | __raw_spin_unlock(&die_lock); | ||
519 | raw_local_irq_restore(flags); | ||
520 | if (!regs) { | ||
521 | oops_exit(); | ||
522 | return; | ||
523 | } | ||
524 | if (panic_on_oops) | ||
525 | panic("Fatal exception"); | ||
526 | oops_exit(); | ||
527 | do_exit(signr); | ||
528 | } | ||
529 | |||
530 | int __kprobes __die(const char *str, struct pt_regs *regs, long err) | ||
531 | { | ||
532 | printk(KERN_EMERG "%s: %04lx [%u] ", str, err & 0xffff, ++die_counter); | ||
533 | #ifdef CONFIG_PREEMPT | ||
534 | printk("PREEMPT "); | ||
535 | #endif | ||
536 | #ifdef CONFIG_SMP | ||
537 | printk("SMP "); | ||
538 | #endif | ||
539 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
540 | printk("DEBUG_PAGEALLOC"); | ||
541 | #endif | ||
542 | printk("\n"); | ||
543 | if (notify_die(DIE_OOPS, str, regs, err, | ||
544 | current->thread.trap_no, SIGSEGV) == NOTIFY_STOP) | ||
545 | return 1; | ||
546 | |||
547 | show_registers(regs); | ||
548 | add_taint(TAINT_DIE); | ||
549 | /* Executive summary in case the oops scrolled away */ | ||
550 | printk(KERN_ALERT "RIP "); | ||
551 | printk_address(regs->ip, 1); | ||
552 | printk(" RSP <%016lx>\n", regs->sp); | ||
553 | if (kexec_should_crash(current)) | ||
554 | crash_kexec(regs); | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | void die(const char *str, struct pt_regs *regs, long err) | ||
559 | { | ||
560 | unsigned long flags = oops_begin(); | ||
561 | |||
562 | if (!user_mode(regs)) | ||
563 | report_bug(regs->ip, regs); | ||
564 | |||
565 | if (__die(str, regs, err)) | ||
566 | regs = NULL; | ||
567 | oops_end(flags, regs, SIGSEGV); | ||
568 | } | ||
569 | |||
570 | notrace __kprobes void | ||
571 | die_nmi(char *str, struct pt_regs *regs, int do_panic) | ||
572 | { | ||
573 | unsigned long flags; | ||
574 | |||
575 | if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP) | ||
576 | return; | ||
577 | |||
578 | flags = oops_begin(); | ||
579 | /* | ||
580 | * We are in trouble anyway, lets at least try | ||
581 | * to get a message out. | ||
582 | */ | ||
583 | printk(KERN_EMERG "%s", str); | ||
584 | printk(" on CPU%d, ip %08lx, registers:\n", | ||
585 | smp_processor_id(), regs->ip); | ||
586 | show_registers(regs); | ||
587 | if (kexec_should_crash(current)) | ||
588 | crash_kexec(regs); | ||
589 | if (do_panic || panic_on_oops) | ||
590 | panic("Non maskable interrupt"); | ||
591 | oops_end(flags, NULL, SIGBUS); | ||
592 | nmi_exit(); | ||
593 | local_irq_enable(); | ||
594 | do_exit(SIGBUS); | ||
595 | } | ||
596 | |||
597 | static void __kprobes | ||
598 | do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, | ||
599 | long error_code, siginfo_t *info) | ||
600 | { | ||
601 | struct task_struct *tsk = current; | ||
602 | |||
603 | if (!user_mode(regs)) | ||
604 | goto kernel_trap; | ||
605 | |||
606 | /* | ||
607 | * We want error_code and trap_no set for userspace faults and | ||
608 | * kernelspace faults which result in die(), but not | ||
609 | * kernelspace faults which are fixed up. die() gives the | ||
610 | * process no chance to handle the signal and notice the | ||
611 | * kernel fault information, so that won't result in polluting | ||
612 | * the information about previously queued, but not yet | ||
613 | * delivered, faults. See also do_general_protection below. | ||
614 | */ | ||
615 | tsk->thread.error_code = error_code; | ||
616 | tsk->thread.trap_no = trapnr; | ||
617 | |||
618 | if (show_unhandled_signals && unhandled_signal(tsk, signr) && | ||
619 | printk_ratelimit()) { | ||
620 | printk(KERN_INFO | ||
621 | "%s[%d] trap %s ip:%lx sp:%lx error:%lx", | ||
622 | tsk->comm, tsk->pid, str, | ||
623 | regs->ip, regs->sp, error_code); | ||
624 | print_vma_addr(" in ", regs->ip); | ||
625 | printk("\n"); | ||
626 | } | ||
627 | |||
628 | if (info) | ||
629 | force_sig_info(signr, info, tsk); | ||
630 | else | ||
631 | force_sig(signr, tsk); | ||
632 | return; | ||
633 | |||
634 | kernel_trap: | ||
635 | if (!fixup_exception(regs)) { | ||
636 | tsk->thread.error_code = error_code; | ||
637 | tsk->thread.trap_no = trapnr; | ||
638 | die(str, regs, error_code); | ||
639 | } | ||
640 | return; | ||
641 | } | ||
642 | |||
643 | #define DO_ERROR(trapnr, signr, str, name) \ | ||
644 | asmlinkage void do_##name(struct pt_regs *regs, long error_code) \ | ||
645 | { \ | ||
646 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | ||
647 | == NOTIFY_STOP) \ | ||
648 | return; \ | ||
649 | conditional_sti(regs); \ | ||
650 | do_trap(trapnr, signr, str, regs, error_code, NULL); \ | ||
651 | } | ||
652 | |||
653 | #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \ | ||
654 | asmlinkage void do_##name(struct pt_regs *regs, long error_code) \ | ||
655 | { \ | ||
656 | siginfo_t info; \ | ||
657 | info.si_signo = signr; \ | ||
658 | info.si_errno = 0; \ | ||
659 | info.si_code = sicode; \ | ||
660 | info.si_addr = (void __user *)siaddr; \ | ||
661 | trace_hardirqs_fixup(); \ | ||
662 | if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) \ | ||
663 | == NOTIFY_STOP) \ | ||
664 | return; \ | ||
665 | conditional_sti(regs); \ | ||
666 | do_trap(trapnr, signr, str, regs, error_code, &info); \ | ||
667 | } | ||
668 | |||
669 | DO_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip) | ||
670 | DO_ERROR(4, SIGSEGV, "overflow", overflow) | ||
671 | DO_ERROR(5, SIGSEGV, "bounds", bounds) | ||
672 | DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip) | ||
673 | DO_ERROR(9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) | ||
674 | DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) | ||
675 | DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) | ||
676 | DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0) | ||
677 | |||
678 | /* Runs on IST stack */ | ||
679 | asmlinkage void do_stack_segment(struct pt_regs *regs, long error_code) | ||
680 | { | ||
681 | if (notify_die(DIE_TRAP, "stack segment", regs, error_code, | ||
682 | 12, SIGBUS) == NOTIFY_STOP) | ||
683 | return; | ||
684 | preempt_conditional_sti(regs); | ||
685 | do_trap(12, SIGBUS, "stack segment", regs, error_code, NULL); | ||
686 | preempt_conditional_cli(regs); | ||
687 | } | ||
688 | |||
689 | asmlinkage void do_double_fault(struct pt_regs *regs, long error_code) | ||
690 | { | ||
691 | static const char str[] = "double fault"; | ||
692 | struct task_struct *tsk = current; | ||
693 | |||
694 | /* Return not checked because double check cannot be ignored */ | ||
695 | notify_die(DIE_TRAP, str, regs, error_code, 8, SIGSEGV); | ||
696 | |||
697 | tsk->thread.error_code = error_code; | ||
698 | tsk->thread.trap_no = 8; | ||
699 | |||
700 | /* This is always a kernel trap and never fixable (and thus must | ||
701 | never return). */ | ||
702 | for (;;) | ||
703 | die(str, regs, error_code); | ||
704 | } | ||
705 | |||
706 | asmlinkage void __kprobes | ||
707 | do_general_protection(struct pt_regs *regs, long error_code) | ||
708 | { | ||
709 | struct task_struct *tsk; | ||
710 | |||
711 | conditional_sti(regs); | ||
712 | |||
713 | tsk = current; | ||
714 | if (!user_mode(regs)) | ||
715 | goto gp_in_kernel; | ||
716 | |||
717 | tsk->thread.error_code = error_code; | ||
718 | tsk->thread.trap_no = 13; | ||
719 | |||
720 | if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && | ||
721 | printk_ratelimit()) { | ||
722 | printk(KERN_INFO | ||
723 | "%s[%d] general protection ip:%lx sp:%lx error:%lx", | ||
724 | tsk->comm, tsk->pid, | ||
725 | regs->ip, regs->sp, error_code); | ||
726 | print_vma_addr(" in ", regs->ip); | ||
727 | printk("\n"); | ||
728 | } | ||
729 | |||
730 | force_sig(SIGSEGV, tsk); | ||
731 | return; | ||
732 | |||
733 | gp_in_kernel: | ||
734 | if (fixup_exception(regs)) | ||
735 | return; | ||
736 | |||
737 | tsk->thread.error_code = error_code; | ||
738 | tsk->thread.trap_no = 13; | ||
739 | if (notify_die(DIE_GPF, "general protection fault", regs, | ||
740 | error_code, 13, SIGSEGV) == NOTIFY_STOP) | ||
741 | return; | ||
742 | die("general protection fault", regs, error_code); | ||
743 | } | ||
744 | |||
745 | static notrace __kprobes void | ||
746 | mem_parity_error(unsigned char reason, struct pt_regs *regs) | ||
747 | { | ||
748 | printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n", | ||
749 | reason); | ||
750 | printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n"); | ||
751 | |||
752 | #if defined(CONFIG_EDAC) | ||
753 | if (edac_handler_set()) { | ||
754 | edac_atomic_assert_error(); | ||
755 | return; | ||
756 | } | ||
757 | #endif | ||
758 | |||
759 | if (panic_on_unrecovered_nmi) | ||
760 | panic("NMI: Not continuing"); | ||
761 | |||
762 | printk(KERN_EMERG "Dazed and confused, but trying to continue\n"); | ||
763 | |||
764 | /* Clear and disable the memory parity error line. */ | ||
765 | reason = (reason & 0xf) | 4; | ||
766 | outb(reason, 0x61); | ||
767 | } | ||
768 | |||
769 | static notrace __kprobes void | ||
770 | io_check_error(unsigned char reason, struct pt_regs *regs) | ||
771 | { | ||
772 | printk("NMI: IOCK error (debug interrupt?)\n"); | ||
773 | show_registers(regs); | ||
774 | |||
775 | /* Re-enable the IOCK line, wait for a few seconds */ | ||
776 | reason = (reason & 0xf) | 8; | ||
777 | outb(reason, 0x61); | ||
778 | mdelay(2000); | ||
779 | reason &= ~8; | ||
780 | outb(reason, 0x61); | ||
781 | } | ||
782 | |||
783 | static notrace __kprobes void | ||
784 | unknown_nmi_error(unsigned char reason, struct pt_regs *regs) | ||
785 | { | ||
786 | if (notify_die(DIE_NMIUNKNOWN, "nmi", regs, reason, 2, SIGINT) == | ||
787 | NOTIFY_STOP) | ||
788 | return; | ||
789 | printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n", | ||
790 | reason); | ||
791 | printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n"); | ||
792 | |||
793 | if (panic_on_unrecovered_nmi) | ||
794 | panic("NMI: Not continuing"); | ||
795 | |||
796 | printk(KERN_EMERG "Dazed and confused, but trying to continue\n"); | ||
797 | } | ||
798 | |||
799 | /* Runs on IST stack. This code must keep interrupts off all the time. | ||
800 | Nested NMIs are prevented by the CPU. */ | ||
801 | asmlinkage notrace __kprobes void default_do_nmi(struct pt_regs *regs) | ||
802 | { | ||
803 | unsigned char reason = 0; | ||
804 | int cpu; | ||
805 | |||
806 | cpu = smp_processor_id(); | ||
807 | |||
808 | /* Only the BSP gets external NMIs from the system. */ | ||
809 | if (!cpu) | ||
810 | reason = get_nmi_reason(); | ||
811 | |||
812 | if (!(reason & 0xc0)) { | ||
813 | if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT) | ||
814 | == NOTIFY_STOP) | ||
815 | return; | ||
816 | /* | ||
817 | * Ok, so this is none of the documented NMI sources, | ||
818 | * so it must be the NMI watchdog. | ||
819 | */ | ||
820 | if (nmi_watchdog_tick(regs, reason)) | ||
821 | return; | ||
822 | if (!do_nmi_callback(regs, cpu)) | ||
823 | unknown_nmi_error(reason, regs); | ||
824 | |||
825 | return; | ||
826 | } | ||
827 | if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP) | ||
828 | return; | ||
829 | |||
830 | /* AK: following checks seem to be broken on modern chipsets. FIXME */ | ||
831 | if (reason & 0x80) | ||
832 | mem_parity_error(reason, regs); | ||
833 | if (reason & 0x40) | ||
834 | io_check_error(reason, regs); | ||
835 | } | ||
836 | |||
837 | asmlinkage notrace __kprobes void | ||
838 | do_nmi(struct pt_regs *regs, long error_code) | ||
839 | { | ||
840 | nmi_enter(); | ||
841 | |||
842 | add_pda(__nmi_count, 1); | ||
843 | |||
844 | if (!ignore_nmis) | ||
845 | default_do_nmi(regs); | ||
846 | |||
847 | nmi_exit(); | ||
848 | } | ||
849 | |||
850 | void stop_nmi(void) | ||
851 | { | ||
852 | acpi_nmi_disable(); | ||
853 | ignore_nmis++; | ||
854 | } | ||
855 | |||
856 | void restart_nmi(void) | ||
857 | { | ||
858 | ignore_nmis--; | ||
859 | acpi_nmi_enable(); | ||
860 | } | ||
861 | |||
862 | /* runs on IST stack. */ | ||
863 | asmlinkage void __kprobes do_int3(struct pt_regs *regs, long error_code) | ||
864 | { | ||
865 | trace_hardirqs_fixup(); | ||
866 | |||
867 | if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) | ||
868 | == NOTIFY_STOP) | ||
869 | return; | ||
870 | |||
871 | preempt_conditional_sti(regs); | ||
872 | do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); | ||
873 | preempt_conditional_cli(regs); | ||
874 | } | ||
875 | |||
876 | /* Help handler running on IST stack to switch back to user stack | ||
877 | for scheduling or signal handling. The actual stack switch is done in | ||
878 | entry.S */ | ||
879 | asmlinkage __kprobes struct pt_regs *sync_regs(struct pt_regs *eregs) | ||
880 | { | ||
881 | struct pt_regs *regs = eregs; | ||
882 | /* Did already sync */ | ||
883 | if (eregs == (struct pt_regs *)eregs->sp) | ||
884 | ; | ||
885 | /* Exception from user space */ | ||
886 | else if (user_mode(eregs)) | ||
887 | regs = task_pt_regs(current); | ||
888 | /* Exception from kernel and interrupts are enabled. Move to | ||
889 | kernel process stack. */ | ||
890 | else if (eregs->flags & X86_EFLAGS_IF) | ||
891 | regs = (struct pt_regs *)(eregs->sp -= sizeof(struct pt_regs)); | ||
892 | if (eregs != regs) | ||
893 | *regs = *eregs; | ||
894 | return regs; | ||
895 | } | ||
896 | |||
897 | /* runs on IST stack. */ | ||
898 | asmlinkage void __kprobes do_debug(struct pt_regs *regs, | ||
899 | unsigned long error_code) | ||
900 | { | ||
901 | struct task_struct *tsk = current; | ||
902 | unsigned long condition; | ||
903 | siginfo_t info; | ||
904 | |||
905 | trace_hardirqs_fixup(); | ||
906 | |||
907 | get_debugreg(condition, 6); | ||
908 | |||
909 | /* | ||
910 | * The processor cleared BTF, so don't mark that we need it set. | ||
911 | */ | ||
912 | clear_tsk_thread_flag(tsk, TIF_DEBUGCTLMSR); | ||
913 | tsk->thread.debugctlmsr = 0; | ||
914 | |||
915 | if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code, | ||
916 | SIGTRAP) == NOTIFY_STOP) | ||
917 | return; | ||
918 | |||
919 | preempt_conditional_sti(regs); | ||
920 | |||
921 | /* Mask out spurious debug traps due to lazy DR7 setting */ | ||
922 | if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { | ||
923 | if (!tsk->thread.debugreg7) | ||
924 | goto clear_dr7; | ||
925 | } | ||
926 | |||
927 | tsk->thread.debugreg6 = condition; | ||
928 | |||
929 | /* | ||
930 | * Single-stepping through TF: make sure we ignore any events in | ||
931 | * kernel space (but re-enable TF when returning to user mode). | ||
932 | */ | ||
933 | if (condition & DR_STEP) { | ||
934 | if (!user_mode(regs)) | ||
935 | goto clear_TF_reenable; | ||
936 | } | ||
937 | |||
938 | /* Ok, finally something we can handle */ | ||
939 | tsk->thread.trap_no = 1; | ||
940 | tsk->thread.error_code = error_code; | ||
941 | info.si_signo = SIGTRAP; | ||
942 | info.si_errno = 0; | ||
943 | info.si_code = get_si_code(condition); | ||
944 | info.si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL; | ||
945 | force_sig_info(SIGTRAP, &info, tsk); | ||
946 | |||
947 | clear_dr7: | ||
948 | set_debugreg(0, 7); | ||
949 | preempt_conditional_cli(regs); | ||
950 | return; | ||
951 | |||
952 | clear_TF_reenable: | ||
953 | set_tsk_thread_flag(tsk, TIF_SINGLESTEP); | ||
954 | regs->flags &= ~X86_EFLAGS_TF; | ||
955 | preempt_conditional_cli(regs); | ||
956 | return; | ||
957 | } | ||
958 | |||
959 | static int kernel_math_error(struct pt_regs *regs, const char *str, int trapnr) | ||
960 | { | ||
961 | if (fixup_exception(regs)) | ||
962 | return 1; | ||
963 | |||
964 | notify_die(DIE_GPF, str, regs, 0, trapnr, SIGFPE); | ||
965 | /* Illegal floating point operation in the kernel */ | ||
966 | current->thread.trap_no = trapnr; | ||
967 | die(str, regs, 0); | ||
968 | return 0; | ||
969 | } | ||
970 | |||
971 | /* | ||
972 | * Note that we play around with the 'TS' bit in an attempt to get | ||
973 | * the correct behaviour even in the presence of the asynchronous | ||
974 | * IRQ13 behaviour | ||
975 | */ | ||
976 | asmlinkage void do_coprocessor_error(struct pt_regs *regs) | ||
977 | { | ||
978 | void __user *ip = (void __user *)(regs->ip); | ||
979 | struct task_struct *task; | ||
980 | siginfo_t info; | ||
981 | unsigned short cwd, swd; | ||
982 | |||
983 | conditional_sti(regs); | ||
984 | if (!user_mode(regs) && | ||
985 | kernel_math_error(regs, "kernel x87 math error", 16)) | ||
986 | return; | ||
987 | |||
988 | /* | ||
989 | * Save the info for the exception handler and clear the error. | ||
990 | */ | ||
991 | task = current; | ||
992 | save_init_fpu(task); | ||
993 | task->thread.trap_no = 16; | ||
994 | task->thread.error_code = 0; | ||
995 | info.si_signo = SIGFPE; | ||
996 | info.si_errno = 0; | ||
997 | info.si_code = __SI_FAULT; | ||
998 | info.si_addr = ip; | ||
999 | /* | ||
1000 | * (~cwd & swd) will mask out exceptions that are not set to unmasked | ||
1001 | * status. 0x3f is the exception bits in these regs, 0x200 is the | ||
1002 | * C1 reg you need in case of a stack fault, 0x040 is the stack | ||
1003 | * fault bit. We should only be taking one exception at a time, | ||
1004 | * so if this combination doesn't produce any single exception, | ||
1005 | * then we have a bad program that isn't synchronizing its FPU usage | ||
1006 | * and it will suffer the consequences since we won't be able to | ||
1007 | * fully reproduce the context of the exception | ||
1008 | */ | ||
1009 | cwd = get_fpu_cwd(task); | ||
1010 | swd = get_fpu_swd(task); | ||
1011 | switch (swd & ~cwd & 0x3f) { | ||
1012 | case 0x000: /* No unmasked exception */ | ||
1013 | default: /* Multiple exceptions */ | ||
1014 | break; | ||
1015 | case 0x001: /* Invalid Op */ | ||
1016 | /* | ||
1017 | * swd & 0x240 == 0x040: Stack Underflow | ||
1018 | * swd & 0x240 == 0x240: Stack Overflow | ||
1019 | * User must clear the SF bit (0x40) if set | ||
1020 | */ | ||
1021 | info.si_code = FPE_FLTINV; | ||
1022 | break; | ||
1023 | case 0x002: /* Denormalize */ | ||
1024 | case 0x010: /* Underflow */ | ||
1025 | info.si_code = FPE_FLTUND; | ||
1026 | break; | ||
1027 | case 0x004: /* Zero Divide */ | ||
1028 | info.si_code = FPE_FLTDIV; | ||
1029 | break; | ||
1030 | case 0x008: /* Overflow */ | ||
1031 | info.si_code = FPE_FLTOVF; | ||
1032 | break; | ||
1033 | case 0x020: /* Precision */ | ||
1034 | info.si_code = FPE_FLTRES; | ||
1035 | break; | ||
1036 | } | ||
1037 | force_sig_info(SIGFPE, &info, task); | ||
1038 | } | ||
1039 | |||
1040 | asmlinkage void bad_intr(void) | ||
1041 | { | ||
1042 | printk("bad interrupt"); | ||
1043 | } | ||
1044 | |||
1045 | asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs) | ||
1046 | { | ||
1047 | void __user *ip = (void __user *)(regs->ip); | ||
1048 | struct task_struct *task; | ||
1049 | siginfo_t info; | ||
1050 | unsigned short mxcsr; | ||
1051 | |||
1052 | conditional_sti(regs); | ||
1053 | if (!user_mode(regs) && | ||
1054 | kernel_math_error(regs, "kernel simd math error", 19)) | ||
1055 | return; | ||
1056 | |||
1057 | /* | ||
1058 | * Save the info for the exception handler and clear the error. | ||
1059 | */ | ||
1060 | task = current; | ||
1061 | save_init_fpu(task); | ||
1062 | task->thread.trap_no = 19; | ||
1063 | task->thread.error_code = 0; | ||
1064 | info.si_signo = SIGFPE; | ||
1065 | info.si_errno = 0; | ||
1066 | info.si_code = __SI_FAULT; | ||
1067 | info.si_addr = ip; | ||
1068 | /* | ||
1069 | * The SIMD FPU exceptions are handled a little differently, as there | ||
1070 | * is only a single status/control register. Thus, to determine which | ||
1071 | * unmasked exception was caught we must mask the exception mask bits | ||
1072 | * at 0x1f80, and then use these to mask the exception bits at 0x3f. | ||
1073 | */ | ||
1074 | mxcsr = get_fpu_mxcsr(task); | ||
1075 | switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) { | ||
1076 | case 0x000: | ||
1077 | default: | ||
1078 | break; | ||
1079 | case 0x001: /* Invalid Op */ | ||
1080 | info.si_code = FPE_FLTINV; | ||
1081 | break; | ||
1082 | case 0x002: /* Denormalize */ | ||
1083 | case 0x010: /* Underflow */ | ||
1084 | info.si_code = FPE_FLTUND; | ||
1085 | break; | ||
1086 | case 0x004: /* Zero Divide */ | ||
1087 | info.si_code = FPE_FLTDIV; | ||
1088 | break; | ||
1089 | case 0x008: /* Overflow */ | ||
1090 | info.si_code = FPE_FLTOVF; | ||
1091 | break; | ||
1092 | case 0x020: /* Precision */ | ||
1093 | info.si_code = FPE_FLTRES; | ||
1094 | break; | ||
1095 | } | ||
1096 | force_sig_info(SIGFPE, &info, task); | ||
1097 | } | ||
1098 | |||
1099 | asmlinkage void do_spurious_interrupt_bug(struct pt_regs *regs) | ||
1100 | { | ||
1101 | } | ||
1102 | |||
1103 | asmlinkage void __attribute__((weak)) smp_thermal_interrupt(void) | ||
1104 | { | ||
1105 | } | ||
1106 | |||
1107 | asmlinkage void __attribute__((weak)) mce_threshold_interrupt(void) | ||
1108 | { | ||
1109 | } | ||
1110 | |||
1111 | /* | ||
1112 | * 'math_state_restore()' saves the current math information in the | ||
1113 | * old math state array, and gets the new ones from the current task | ||
1114 | * | ||
1115 | * Careful.. There are problems with IBM-designed IRQ13 behaviour. | ||
1116 | * Don't touch unless you *really* know how it works. | ||
1117 | */ | ||
1118 | asmlinkage void math_state_restore(void) | ||
1119 | { | ||
1120 | struct task_struct *me = current; | ||
1121 | |||
1122 | if (!used_math()) { | ||
1123 | local_irq_enable(); | ||
1124 | /* | ||
1125 | * does a slab alloc which can sleep | ||
1126 | */ | ||
1127 | if (init_fpu(me)) { | ||
1128 | /* | ||
1129 | * ran out of memory! | ||
1130 | */ | ||
1131 | do_group_exit(SIGKILL); | ||
1132 | return; | ||
1133 | } | ||
1134 | local_irq_disable(); | ||
1135 | } | ||
1136 | |||
1137 | clts(); /* Allow maths ops (or we recurse) */ | ||
1138 | /* | ||
1139 | * Paranoid restore. send a SIGSEGV if we fail to restore the state. | ||
1140 | */ | ||
1141 | if (unlikely(restore_fpu_checking(me))) { | ||
1142 | stts(); | ||
1143 | force_sig(SIGSEGV, me); | ||
1144 | return; | ||
1145 | } | ||
1146 | task_thread_info(me)->status |= TS_USEDFPU; | ||
1147 | me->fpu_counter++; | ||
1148 | } | ||
1149 | EXPORT_SYMBOL_GPL(math_state_restore); | ||
1150 | |||
1151 | void __init trap_init(void) | ||
1152 | { | ||
1153 | set_intr_gate(0, ÷_error); | ||
1154 | set_intr_gate_ist(1, &debug, DEBUG_STACK); | ||
1155 | set_intr_gate_ist(2, &nmi, NMI_STACK); | ||
1156 | /* int3 can be called from all */ | ||
1157 | set_system_gate_ist(3, &int3, DEBUG_STACK); | ||
1158 | /* int4 can be called from all */ | ||
1159 | set_system_gate(4, &overflow); | ||
1160 | set_intr_gate(5, &bounds); | ||
1161 | set_intr_gate(6, &invalid_op); | ||
1162 | set_intr_gate(7, &device_not_available); | ||
1163 | set_intr_gate_ist(8, &double_fault, DOUBLEFAULT_STACK); | ||
1164 | set_intr_gate(9, &coprocessor_segment_overrun); | ||
1165 | set_intr_gate(10, &invalid_TSS); | ||
1166 | set_intr_gate(11, &segment_not_present); | ||
1167 | set_intr_gate_ist(12, &stack_segment, STACKFAULT_STACK); | ||
1168 | set_intr_gate(13, &general_protection); | ||
1169 | set_intr_gate(14, &page_fault); | ||
1170 | set_intr_gate(15, &spurious_interrupt_bug); | ||
1171 | set_intr_gate(16, &coprocessor_error); | ||
1172 | set_intr_gate(17, &alignment_check); | ||
1173 | #ifdef CONFIG_X86_MCE | ||
1174 | set_intr_gate_ist(18, &machine_check, MCE_STACK); | ||
1175 | #endif | ||
1176 | set_intr_gate(19, &simd_coprocessor_error); | ||
1177 | |||
1178 | #ifdef CONFIG_IA32_EMULATION | ||
1179 | set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall); | ||
1180 | #endif | ||
1181 | /* | ||
1182 | * Should be a barrier for any external CPU state: | ||
1183 | */ | ||
1184 | cpu_init(); | ||
1185 | } | ||
1186 | |||
1187 | static int __init oops_setup(char *s) | ||
1188 | { | ||
1189 | if (!s) | ||
1190 | return -EINVAL; | ||
1191 | if (!strcmp(s, "panic")) | ||
1192 | panic_on_oops = 1; | ||
1193 | return 0; | ||
1194 | } | ||
1195 | early_param("oops", oops_setup); | ||
1196 | |||
1197 | static int __init kstack_setup(char *s) | ||
1198 | { | ||
1199 | if (!s) | ||
1200 | return -EINVAL; | ||
1201 | kstack_depth_to_print = simple_strtoul(s, NULL, 0); | ||
1202 | return 0; | ||
1203 | } | ||
1204 | early_param("kstack", kstack_setup); | ||
1205 | |||
1206 | static int __init code_bytes_setup(char *s) | ||
1207 | { | ||
1208 | code_bytes = simple_strtoul(s, NULL, 0); | ||
1209 | if (code_bytes > 8192) | ||
1210 | code_bytes = 8192; | ||
1211 | |||
1212 | return 1; | ||
1213 | } | ||
1214 | __setup("code_bytes=", code_bytes_setup); | ||
diff --git a/arch/x86/mach-generic/es7000.c b/arch/x86/mach-generic/es7000.c index 520cca0ee04e..6513d41ea21e 100644 --- a/arch/x86/mach-generic/es7000.c +++ b/arch/x86/mach-generic/es7000.c | |||
@@ -47,16 +47,26 @@ static __init int mps_oem_check(struct mp_config_table *mpc, char *oem, | |||
47 | /* Hook from generic ACPI tables.c */ | 47 | /* Hook from generic ACPI tables.c */ |
48 | static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 48 | static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) |
49 | { | 49 | { |
50 | unsigned long oem_addr; | 50 | unsigned long oem_addr = 0; |
51 | int check_dsdt; | ||
52 | int ret = 0; | ||
53 | |||
54 | /* check dsdt at first to avoid clear fix_map for oem_addr */ | ||
55 | check_dsdt = es7000_check_dsdt(); | ||
56 | |||
51 | if (!find_unisys_acpi_oem_table(&oem_addr)) { | 57 | if (!find_unisys_acpi_oem_table(&oem_addr)) { |
52 | if (es7000_check_dsdt()) | 58 | if (check_dsdt) |
53 | return parse_unisys_oem((char *)oem_addr); | 59 | ret = parse_unisys_oem((char *)oem_addr); |
54 | else { | 60 | else { |
55 | setup_unisys(); | 61 | setup_unisys(); |
56 | return 1; | 62 | ret = 1; |
57 | } | 63 | } |
64 | /* | ||
65 | * we need to unmap it | ||
66 | */ | ||
67 | unmap_unisys_acpi_oem_table(oem_addr); | ||
58 | } | 68 | } |
59 | return 0; | 69 | return ret; |
60 | } | 70 | } |
61 | #else | 71 | #else |
62 | static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) | 72 | static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) |
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile index dfb932dcf136..59f89b434b45 100644 --- a/arch/x86/mm/Makefile +++ b/arch/x86/mm/Makefile | |||
@@ -13,12 +13,8 @@ obj-$(CONFIG_MMIOTRACE) += mmiotrace.o | |||
13 | mmiotrace-y := pf_in.o mmio-mod.o | 13 | mmiotrace-y := pf_in.o mmio-mod.o |
14 | obj-$(CONFIG_MMIOTRACE_TEST) += testmmiotrace.o | 14 | obj-$(CONFIG_MMIOTRACE_TEST) += testmmiotrace.o |
15 | 15 | ||
16 | ifeq ($(CONFIG_X86_32),y) | 16 | obj-$(CONFIG_NUMA) += numa_$(BITS).o |
17 | obj-$(CONFIG_NUMA) += discontig_32.o | ||
18 | else | ||
19 | obj-$(CONFIG_NUMA) += numa_64.o | ||
20 | obj-$(CONFIG_K8_NUMA) += k8topology_64.o | 17 | obj-$(CONFIG_K8_NUMA) += k8topology_64.o |
21 | endif | ||
22 | obj-$(CONFIG_ACPI_NUMA) += srat_$(BITS).o | 18 | obj-$(CONFIG_ACPI_NUMA) += srat_$(BITS).o |
23 | 19 | ||
24 | obj-$(CONFIG_MEMTEST) += memtest.o | 20 | obj-$(CONFIG_MEMTEST) += memtest.o |
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index a742d753d5b0..3f2b8962cbd0 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -592,11 +592,6 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
592 | unsigned long flags; | 592 | unsigned long flags; |
593 | #endif | 593 | #endif |
594 | 594 | ||
595 | /* | ||
596 | * We can fault from pretty much anywhere, with unknown IRQ state. | ||
597 | */ | ||
598 | trace_hardirqs_fixup(); | ||
599 | |||
600 | tsk = current; | 595 | tsk = current; |
601 | mm = tsk->mm; | 596 | mm = tsk->mm; |
602 | prefetchw(&mm->mmap_sem); | 597 | prefetchw(&mm->mmap_sem); |
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c index 007bb06c7504..4ba373c5b8c8 100644 --- a/arch/x86/mm/gup.c +++ b/arch/x86/mm/gup.c | |||
@@ -82,7 +82,7 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr, | |||
82 | pte_t pte = gup_get_pte(ptep); | 82 | pte_t pte = gup_get_pte(ptep); |
83 | struct page *page; | 83 | struct page *page; |
84 | 84 | ||
85 | if ((pte_val(pte) & (mask | _PAGE_SPECIAL)) != mask) { | 85 | if ((pte_flags(pte) & (mask | _PAGE_SPECIAL)) != mask) { |
86 | pte_unmap(ptep); | 86 | pte_unmap(ptep); |
87 | return 0; | 87 | return 0; |
88 | } | 88 | } |
@@ -116,10 +116,10 @@ static noinline int gup_huge_pmd(pmd_t pmd, unsigned long addr, | |||
116 | mask = _PAGE_PRESENT|_PAGE_USER; | 116 | mask = _PAGE_PRESENT|_PAGE_USER; |
117 | if (write) | 117 | if (write) |
118 | mask |= _PAGE_RW; | 118 | mask |= _PAGE_RW; |
119 | if ((pte_val(pte) & mask) != mask) | 119 | if ((pte_flags(pte) & mask) != mask) |
120 | return 0; | 120 | return 0; |
121 | /* hugepages are never "special" */ | 121 | /* hugepages are never "special" */ |
122 | VM_BUG_ON(pte_val(pte) & _PAGE_SPECIAL); | 122 | VM_BUG_ON(pte_flags(pte) & _PAGE_SPECIAL); |
123 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); | 123 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); |
124 | 124 | ||
125 | refs = 0; | 125 | refs = 0; |
@@ -173,10 +173,10 @@ static noinline int gup_huge_pud(pud_t pud, unsigned long addr, | |||
173 | mask = _PAGE_PRESENT|_PAGE_USER; | 173 | mask = _PAGE_PRESENT|_PAGE_USER; |
174 | if (write) | 174 | if (write) |
175 | mask |= _PAGE_RW; | 175 | mask |= _PAGE_RW; |
176 | if ((pte_val(pte) & mask) != mask) | 176 | if ((pte_flags(pte) & mask) != mask) |
177 | return 0; | 177 | return 0; |
178 | /* hugepages are never "special" */ | 178 | /* hugepages are never "special" */ |
179 | VM_BUG_ON(pte_val(pte) & _PAGE_SPECIAL); | 179 | VM_BUG_ON(pte_flags(pte) & _PAGE_SPECIAL); |
180 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); | 180 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); |
181 | 181 | ||
182 | refs = 0; | 182 | refs = 0; |
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index bbe044dbe014..8396868e82c5 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c | |||
@@ -558,7 +558,7 @@ void zap_low_mappings(void) | |||
558 | 558 | ||
559 | int nx_enabled; | 559 | int nx_enabled; |
560 | 560 | ||
561 | pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL); | 561 | pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL | _PAGE_IOMAP); |
562 | EXPORT_SYMBOL_GPL(__supported_pte_mask); | 562 | EXPORT_SYMBOL_GPL(__supported_pte_mask); |
563 | 563 | ||
564 | #ifdef CONFIG_X86_PAE | 564 | #ifdef CONFIG_X86_PAE |
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 3e10054c5731..b8e461d49412 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
@@ -89,7 +89,7 @@ early_param("gbpages", parse_direct_gbpages_on); | |||
89 | 89 | ||
90 | int after_bootmem; | 90 | int after_bootmem; |
91 | 91 | ||
92 | unsigned long __supported_pte_mask __read_mostly = ~0UL; | 92 | pteval_t __supported_pte_mask __read_mostly = ~_PAGE_IOMAP; |
93 | EXPORT_SYMBOL_GPL(__supported_pte_mask); | 93 | EXPORT_SYMBOL_GPL(__supported_pte_mask); |
94 | 94 | ||
95 | static int do_not_nx __cpuinitdata; | 95 | static int do_not_nx __cpuinitdata; |
@@ -196,9 +196,6 @@ set_pte_vaddr_pud(pud_t *pud_page, unsigned long vaddr, pte_t new_pte) | |||
196 | } | 196 | } |
197 | 197 | ||
198 | pte = pte_offset_kernel(pmd, vaddr); | 198 | pte = pte_offset_kernel(pmd, vaddr); |
199 | if (!pte_none(*pte) && pte_val(new_pte) && | ||
200 | pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask)) | ||
201 | pte_ERROR(*pte); | ||
202 | set_pte(pte, new_pte); | 199 | set_pte(pte, new_pte); |
203 | 200 | ||
204 | /* | 201 | /* |
@@ -313,7 +310,7 @@ static __ref void *alloc_low_page(unsigned long *phys) | |||
313 | if (pfn >= table_top) | 310 | if (pfn >= table_top) |
314 | panic("alloc_low_page: ran out of memory"); | 311 | panic("alloc_low_page: ran out of memory"); |
315 | 312 | ||
316 | adr = early_ioremap(pfn * PAGE_SIZE, PAGE_SIZE); | 313 | adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE); |
317 | memset(adr, 0, PAGE_SIZE); | 314 | memset(adr, 0, PAGE_SIZE); |
318 | *phys = pfn * PAGE_SIZE; | 315 | *phys = pfn * PAGE_SIZE; |
319 | return adr; | 316 | return adr; |
@@ -749,7 +746,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, | |||
749 | old_start = mr[i].start; | 746 | old_start = mr[i].start; |
750 | memmove(&mr[i], &mr[i+1], | 747 | memmove(&mr[i], &mr[i+1], |
751 | (nr_range - 1 - i) * sizeof (struct map_range)); | 748 | (nr_range - 1 - i) * sizeof (struct map_range)); |
752 | mr[i].start = old_start; | 749 | mr[i--].start = old_start; |
753 | nr_range--; | 750 | nr_range--; |
754 | } | 751 | } |
755 | 752 | ||
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 8cbeda15cd29..e4c43ec71b29 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c | |||
@@ -45,6 +45,27 @@ unsigned long __phys_addr(unsigned long x) | |||
45 | } | 45 | } |
46 | EXPORT_SYMBOL(__phys_addr); | 46 | EXPORT_SYMBOL(__phys_addr); |
47 | 47 | ||
48 | bool __virt_addr_valid(unsigned long x) | ||
49 | { | ||
50 | if (x >= __START_KERNEL_map) { | ||
51 | x -= __START_KERNEL_map; | ||
52 | if (x >= KERNEL_IMAGE_SIZE) | ||
53 | return false; | ||
54 | x += phys_base; | ||
55 | } else { | ||
56 | if (x < PAGE_OFFSET) | ||
57 | return false; | ||
58 | x -= PAGE_OFFSET; | ||
59 | if (system_state == SYSTEM_BOOTING ? | ||
60 | x > MAXMEM : !phys_addr_valid(x)) { | ||
61 | return false; | ||
62 | } | ||
63 | } | ||
64 | |||
65 | return pfn_valid(x >> PAGE_SHIFT); | ||
66 | } | ||
67 | EXPORT_SYMBOL(__virt_addr_valid); | ||
68 | |||
48 | #else | 69 | #else |
49 | 70 | ||
50 | static inline int phys_addr_valid(unsigned long addr) | 71 | static inline int phys_addr_valid(unsigned long addr) |
@@ -56,13 +77,24 @@ static inline int phys_addr_valid(unsigned long addr) | |||
56 | unsigned long __phys_addr(unsigned long x) | 77 | unsigned long __phys_addr(unsigned long x) |
57 | { | 78 | { |
58 | /* VMALLOC_* aren't constants; not available at the boot time */ | 79 | /* VMALLOC_* aren't constants; not available at the boot time */ |
59 | VIRTUAL_BUG_ON(x < PAGE_OFFSET || (system_state != SYSTEM_BOOTING && | 80 | VIRTUAL_BUG_ON(x < PAGE_OFFSET); |
60 | is_vmalloc_addr((void *)x))); | 81 | VIRTUAL_BUG_ON(system_state != SYSTEM_BOOTING && |
82 | is_vmalloc_addr((void *) x)); | ||
61 | return x - PAGE_OFFSET; | 83 | return x - PAGE_OFFSET; |
62 | } | 84 | } |
63 | EXPORT_SYMBOL(__phys_addr); | 85 | EXPORT_SYMBOL(__phys_addr); |
64 | #endif | 86 | #endif |
65 | 87 | ||
88 | bool __virt_addr_valid(unsigned long x) | ||
89 | { | ||
90 | if (x < PAGE_OFFSET) | ||
91 | return false; | ||
92 | if (system_state != SYSTEM_BOOTING && is_vmalloc_addr((void *) x)) | ||
93 | return false; | ||
94 | return pfn_valid((x - PAGE_OFFSET) >> PAGE_SHIFT); | ||
95 | } | ||
96 | EXPORT_SYMBOL(__virt_addr_valid); | ||
97 | |||
66 | #endif | 98 | #endif |
67 | 99 | ||
68 | int page_is_ram(unsigned long pagenr) | 100 | int page_is_ram(unsigned long pagenr) |
@@ -242,16 +274,16 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr, | |||
242 | switch (prot_val) { | 274 | switch (prot_val) { |
243 | case _PAGE_CACHE_UC: | 275 | case _PAGE_CACHE_UC: |
244 | default: | 276 | default: |
245 | prot = PAGE_KERNEL_NOCACHE; | 277 | prot = PAGE_KERNEL_IO_NOCACHE; |
246 | break; | 278 | break; |
247 | case _PAGE_CACHE_UC_MINUS: | 279 | case _PAGE_CACHE_UC_MINUS: |
248 | prot = PAGE_KERNEL_UC_MINUS; | 280 | prot = PAGE_KERNEL_IO_UC_MINUS; |
249 | break; | 281 | break; |
250 | case _PAGE_CACHE_WC: | 282 | case _PAGE_CACHE_WC: |
251 | prot = PAGE_KERNEL_WC; | 283 | prot = PAGE_KERNEL_IO_WC; |
252 | break; | 284 | break; |
253 | case _PAGE_CACHE_WB: | 285 | case _PAGE_CACHE_WB: |
254 | prot = PAGE_KERNEL; | 286 | prot = PAGE_KERNEL_IO; |
255 | break; | 287 | break; |
256 | } | 288 | } |
257 | 289 | ||
@@ -568,12 +600,12 @@ static void __init __early_set_fixmap(enum fixed_addresses idx, | |||
568 | } | 600 | } |
569 | 601 | ||
570 | static inline void __init early_set_fixmap(enum fixed_addresses idx, | 602 | static inline void __init early_set_fixmap(enum fixed_addresses idx, |
571 | unsigned long phys) | 603 | unsigned long phys, pgprot_t prot) |
572 | { | 604 | { |
573 | if (after_paging_init) | 605 | if (after_paging_init) |
574 | set_fixmap(idx, phys); | 606 | __set_fixmap(idx, phys, prot); |
575 | else | 607 | else |
576 | __early_set_fixmap(idx, phys, PAGE_KERNEL); | 608 | __early_set_fixmap(idx, phys, prot); |
577 | } | 609 | } |
578 | 610 | ||
579 | static inline void __init early_clear_fixmap(enum fixed_addresses idx) | 611 | static inline void __init early_clear_fixmap(enum fixed_addresses idx) |
@@ -584,16 +616,22 @@ static inline void __init early_clear_fixmap(enum fixed_addresses idx) | |||
584 | __early_set_fixmap(idx, 0, __pgprot(0)); | 616 | __early_set_fixmap(idx, 0, __pgprot(0)); |
585 | } | 617 | } |
586 | 618 | ||
587 | 619 | static void *prev_map[FIX_BTMAPS_SLOTS] __initdata; | |
588 | static int __initdata early_ioremap_nested; | 620 | static unsigned long prev_size[FIX_BTMAPS_SLOTS] __initdata; |
589 | |||
590 | static int __init check_early_ioremap_leak(void) | 621 | static int __init check_early_ioremap_leak(void) |
591 | { | 622 | { |
592 | if (!early_ioremap_nested) | 623 | int count = 0; |
624 | int i; | ||
625 | |||
626 | for (i = 0; i < FIX_BTMAPS_SLOTS; i++) | ||
627 | if (prev_map[i]) | ||
628 | count++; | ||
629 | |||
630 | if (!count) | ||
593 | return 0; | 631 | return 0; |
594 | WARN(1, KERN_WARNING | 632 | WARN(1, KERN_WARNING |
595 | "Debug warning: early ioremap leak of %d areas detected.\n", | 633 | "Debug warning: early ioremap leak of %d areas detected.\n", |
596 | early_ioremap_nested); | 634 | count); |
597 | printk(KERN_WARNING | 635 | printk(KERN_WARNING |
598 | "please boot with early_ioremap_debug and report the dmesg.\n"); | 636 | "please boot with early_ioremap_debug and report the dmesg.\n"); |
599 | 637 | ||
@@ -601,18 +639,33 @@ static int __init check_early_ioremap_leak(void) | |||
601 | } | 639 | } |
602 | late_initcall(check_early_ioremap_leak); | 640 | late_initcall(check_early_ioremap_leak); |
603 | 641 | ||
604 | void __init *early_ioremap(unsigned long phys_addr, unsigned long size) | 642 | static void __init *__early_ioremap(unsigned long phys_addr, unsigned long size, pgprot_t prot) |
605 | { | 643 | { |
606 | unsigned long offset, last_addr; | 644 | unsigned long offset, last_addr; |
607 | unsigned int nrpages, nesting; | 645 | unsigned int nrpages; |
608 | enum fixed_addresses idx0, idx; | 646 | enum fixed_addresses idx0, idx; |
647 | int i, slot; | ||
609 | 648 | ||
610 | WARN_ON(system_state != SYSTEM_BOOTING); | 649 | WARN_ON(system_state != SYSTEM_BOOTING); |
611 | 650 | ||
612 | nesting = early_ioremap_nested; | 651 | slot = -1; |
652 | for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { | ||
653 | if (!prev_map[i]) { | ||
654 | slot = i; | ||
655 | break; | ||
656 | } | ||
657 | } | ||
658 | |||
659 | if (slot < 0) { | ||
660 | printk(KERN_INFO "early_iomap(%08lx, %08lx) not found slot\n", | ||
661 | phys_addr, size); | ||
662 | WARN_ON(1); | ||
663 | return NULL; | ||
664 | } | ||
665 | |||
613 | if (early_ioremap_debug) { | 666 | if (early_ioremap_debug) { |
614 | printk(KERN_INFO "early_ioremap(%08lx, %08lx) [%d] => ", | 667 | printk(KERN_INFO "early_ioremap(%08lx, %08lx) [%d] => ", |
615 | phys_addr, size, nesting); | 668 | phys_addr, size, slot); |
616 | dump_stack(); | 669 | dump_stack(); |
617 | } | 670 | } |
618 | 671 | ||
@@ -623,11 +676,7 @@ void __init *early_ioremap(unsigned long phys_addr, unsigned long size) | |||
623 | return NULL; | 676 | return NULL; |
624 | } | 677 | } |
625 | 678 | ||
626 | if (nesting >= FIX_BTMAPS_NESTING) { | 679 | prev_size[slot] = size; |
627 | WARN_ON(1); | ||
628 | return NULL; | ||
629 | } | ||
630 | early_ioremap_nested++; | ||
631 | /* | 680 | /* |
632 | * Mappings have to be page-aligned | 681 | * Mappings have to be page-aligned |
633 | */ | 682 | */ |
@@ -647,10 +696,10 @@ void __init *early_ioremap(unsigned long phys_addr, unsigned long size) | |||
647 | /* | 696 | /* |
648 | * Ok, go for it.. | 697 | * Ok, go for it.. |
649 | */ | 698 | */ |
650 | idx0 = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*nesting; | 699 | idx0 = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot; |
651 | idx = idx0; | 700 | idx = idx0; |
652 | while (nrpages > 0) { | 701 | while (nrpages > 0) { |
653 | early_set_fixmap(idx, phys_addr); | 702 | early_set_fixmap(idx, phys_addr, prot); |
654 | phys_addr += PAGE_SIZE; | 703 | phys_addr += PAGE_SIZE; |
655 | --idx; | 704 | --idx; |
656 | --nrpages; | 705 | --nrpages; |
@@ -658,7 +707,20 @@ void __init *early_ioremap(unsigned long phys_addr, unsigned long size) | |||
658 | if (early_ioremap_debug) | 707 | if (early_ioremap_debug) |
659 | printk(KERN_CONT "%08lx + %08lx\n", offset, fix_to_virt(idx0)); | 708 | printk(KERN_CONT "%08lx + %08lx\n", offset, fix_to_virt(idx0)); |
660 | 709 | ||
661 | return (void *) (offset + fix_to_virt(idx0)); | 710 | prev_map[slot] = (void *) (offset + fix_to_virt(idx0)); |
711 | return prev_map[slot]; | ||
712 | } | ||
713 | |||
714 | /* Remap an IO device */ | ||
715 | void __init *early_ioremap(unsigned long phys_addr, unsigned long size) | ||
716 | { | ||
717 | return __early_ioremap(phys_addr, size, PAGE_KERNEL_IO); | ||
718 | } | ||
719 | |||
720 | /* Remap memory */ | ||
721 | void __init *early_memremap(unsigned long phys_addr, unsigned long size) | ||
722 | { | ||
723 | return __early_ioremap(phys_addr, size, PAGE_KERNEL); | ||
662 | } | 724 | } |
663 | 725 | ||
664 | void __init early_iounmap(void *addr, unsigned long size) | 726 | void __init early_iounmap(void *addr, unsigned long size) |
@@ -667,15 +729,33 @@ void __init early_iounmap(void *addr, unsigned long size) | |||
667 | unsigned long offset; | 729 | unsigned long offset; |
668 | unsigned int nrpages; | 730 | unsigned int nrpages; |
669 | enum fixed_addresses idx; | 731 | enum fixed_addresses idx; |
670 | int nesting; | 732 | int i, slot; |
733 | |||
734 | slot = -1; | ||
735 | for (i = 0; i < FIX_BTMAPS_SLOTS; i++) { | ||
736 | if (prev_map[i] == addr) { | ||
737 | slot = i; | ||
738 | break; | ||
739 | } | ||
740 | } | ||
671 | 741 | ||
672 | nesting = --early_ioremap_nested; | 742 | if (slot < 0) { |
673 | if (WARN_ON(nesting < 0)) | 743 | printk(KERN_INFO "early_iounmap(%p, %08lx) not found slot\n", |
744 | addr, size); | ||
745 | WARN_ON(1); | ||
746 | return; | ||
747 | } | ||
748 | |||
749 | if (prev_size[slot] != size) { | ||
750 | printk(KERN_INFO "early_iounmap(%p, %08lx) [%d] size not consistent %08lx\n", | ||
751 | addr, size, slot, prev_size[slot]); | ||
752 | WARN_ON(1); | ||
674 | return; | 753 | return; |
754 | } | ||
675 | 755 | ||
676 | if (early_ioremap_debug) { | 756 | if (early_ioremap_debug) { |
677 | printk(KERN_INFO "early_iounmap(%p, %08lx) [%d]\n", addr, | 757 | printk(KERN_INFO "early_iounmap(%p, %08lx) [%d]\n", addr, |
678 | size, nesting); | 758 | size, slot); |
679 | dump_stack(); | 759 | dump_stack(); |
680 | } | 760 | } |
681 | 761 | ||
@@ -687,12 +767,13 @@ void __init early_iounmap(void *addr, unsigned long size) | |||
687 | offset = virt_addr & ~PAGE_MASK; | 767 | offset = virt_addr & ~PAGE_MASK; |
688 | nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT; | 768 | nrpages = PAGE_ALIGN(offset + size - 1) >> PAGE_SHIFT; |
689 | 769 | ||
690 | idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*nesting; | 770 | idx = FIX_BTMAP_BEGIN - NR_FIX_BTMAPS*slot; |
691 | while (nrpages > 0) { | 771 | while (nrpages > 0) { |
692 | early_clear_fixmap(idx); | 772 | early_clear_fixmap(idx); |
693 | --idx; | 773 | --idx; |
694 | --nrpages; | 774 | --nrpages; |
695 | } | 775 | } |
776 | prev_map[slot] = 0; | ||
696 | } | 777 | } |
697 | 778 | ||
698 | void __this_fixmap_does_not_exist(void) | 779 | void __this_fixmap_does_not_exist(void) |
diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/numa_32.c index 847c164725f4..847c164725f4 100644 --- a/arch/x86/mm/discontig_32.c +++ b/arch/x86/mm/numa_32.c | |||
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c index 1b4763e26ea9..51c0a2fc14fe 100644 --- a/arch/x86/mm/srat_64.c +++ b/arch/x86/mm/srat_64.c | |||
@@ -138,7 +138,7 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) | |||
138 | return; | 138 | return; |
139 | } | 139 | } |
140 | 140 | ||
141 | if (is_uv_system()) | 141 | if (get_uv_system_type() >= UV_X2APIC) |
142 | apic_id = (pa->apic_id << 8) | pa->local_sapic_eid; | 142 | apic_id = (pa->apic_id << 8) | pa->local_sapic_eid; |
143 | else | 143 | else |
144 | apic_id = pa->apic_id; | 144 | apic_id = pa->apic_id; |
diff --git a/arch/x86/oprofile/Makefile b/arch/x86/oprofile/Makefile index 30f3eb366667..446902b2a6b6 100644 --- a/arch/x86/oprofile/Makefile +++ b/arch/x86/oprofile/Makefile | |||
@@ -7,6 +7,6 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ | |||
7 | timer_int.o ) | 7 | timer_int.o ) |
8 | 8 | ||
9 | oprofile-y := $(DRIVER_OBJS) init.o backtrace.o | 9 | oprofile-y := $(DRIVER_OBJS) init.o backtrace.o |
10 | oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o \ | 10 | oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_amd.o \ |
11 | op_model_ppro.o op_model_p4.o | 11 | op_model_ppro.o op_model_p4.o |
12 | oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o | 12 | oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o |
diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 8a5f1614a3d5..57f6c9088081 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c | |||
@@ -1,10 +1,11 @@ | |||
1 | /** | 1 | /** |
2 | * @file nmi_int.c | 2 | * @file nmi_int.c |
3 | * | 3 | * |
4 | * @remark Copyright 2002 OProfile authors | 4 | * @remark Copyright 2002-2008 OProfile authors |
5 | * @remark Read the file COPYING | 5 | * @remark Read the file COPYING |
6 | * | 6 | * |
7 | * @author John Levon <levon@movementarian.org> | 7 | * @author John Levon <levon@movementarian.org> |
8 | * @author Robert Richter <robert.richter@amd.com> | ||
8 | */ | 9 | */ |
9 | 10 | ||
10 | #include <linux/init.h> | 11 | #include <linux/init.h> |
@@ -439,6 +440,7 @@ int __init op_nmi_init(struct oprofile_operations *ops) | |||
439 | __u8 vendor = boot_cpu_data.x86_vendor; | 440 | __u8 vendor = boot_cpu_data.x86_vendor; |
440 | __u8 family = boot_cpu_data.x86; | 441 | __u8 family = boot_cpu_data.x86; |
441 | char *cpu_type; | 442 | char *cpu_type; |
443 | int ret = 0; | ||
442 | 444 | ||
443 | if (!cpu_has_apic) | 445 | if (!cpu_has_apic) |
444 | return -ENODEV; | 446 | return -ENODEV; |
@@ -451,19 +453,23 @@ int __init op_nmi_init(struct oprofile_operations *ops) | |||
451 | default: | 453 | default: |
452 | return -ENODEV; | 454 | return -ENODEV; |
453 | case 6: | 455 | case 6: |
454 | model = &op_athlon_spec; | 456 | model = &op_amd_spec; |
455 | cpu_type = "i386/athlon"; | 457 | cpu_type = "i386/athlon"; |
456 | break; | 458 | break; |
457 | case 0xf: | 459 | case 0xf: |
458 | model = &op_athlon_spec; | 460 | model = &op_amd_spec; |
459 | /* Actually it could be i386/hammer too, but give | 461 | /* Actually it could be i386/hammer too, but give |
460 | user space an consistent name. */ | 462 | user space an consistent name. */ |
461 | cpu_type = "x86-64/hammer"; | 463 | cpu_type = "x86-64/hammer"; |
462 | break; | 464 | break; |
463 | case 0x10: | 465 | case 0x10: |
464 | model = &op_athlon_spec; | 466 | model = &op_amd_spec; |
465 | cpu_type = "x86-64/family10"; | 467 | cpu_type = "x86-64/family10"; |
466 | break; | 468 | break; |
469 | case 0x11: | ||
470 | model = &op_amd_spec; | ||
471 | cpu_type = "x86-64/family11h"; | ||
472 | break; | ||
467 | } | 473 | } |
468 | break; | 474 | break; |
469 | 475 | ||
@@ -490,17 +496,24 @@ int __init op_nmi_init(struct oprofile_operations *ops) | |||
490 | return -ENODEV; | 496 | return -ENODEV; |
491 | } | 497 | } |
492 | 498 | ||
493 | init_sysfs(); | ||
494 | #ifdef CONFIG_SMP | 499 | #ifdef CONFIG_SMP |
495 | register_cpu_notifier(&oprofile_cpu_nb); | 500 | register_cpu_notifier(&oprofile_cpu_nb); |
496 | #endif | 501 | #endif |
497 | using_nmi = 1; | 502 | /* default values, can be overwritten by model */ |
498 | ops->create_files = nmi_create_files; | 503 | ops->create_files = nmi_create_files; |
499 | ops->setup = nmi_setup; | 504 | ops->setup = nmi_setup; |
500 | ops->shutdown = nmi_shutdown; | 505 | ops->shutdown = nmi_shutdown; |
501 | ops->start = nmi_start; | 506 | ops->start = nmi_start; |
502 | ops->stop = nmi_stop; | 507 | ops->stop = nmi_stop; |
503 | ops->cpu_type = cpu_type; | 508 | ops->cpu_type = cpu_type; |
509 | |||
510 | if (model->init) | ||
511 | ret = model->init(ops); | ||
512 | if (ret) | ||
513 | return ret; | ||
514 | |||
515 | init_sysfs(); | ||
516 | using_nmi = 1; | ||
504 | printk(KERN_INFO "oprofile: using NMI interrupt.\n"); | 517 | printk(KERN_INFO "oprofile: using NMI interrupt.\n"); |
505 | return 0; | 518 | return 0; |
506 | } | 519 | } |
@@ -513,4 +526,6 @@ void op_nmi_exit(void) | |||
513 | unregister_cpu_notifier(&oprofile_cpu_nb); | 526 | unregister_cpu_notifier(&oprofile_cpu_nb); |
514 | #endif | 527 | #endif |
515 | } | 528 | } |
529 | if (model->exit) | ||
530 | model->exit(); | ||
516 | } | 531 | } |
diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c new file mode 100644 index 000000000000..d9faf607b3a6 --- /dev/null +++ b/arch/x86/oprofile/op_model_amd.c | |||
@@ -0,0 +1,543 @@ | |||
1 | /* | ||
2 | * @file op_model_amd.c | ||
3 | * athlon / K7 / K8 / Family 10h model-specific MSR operations | ||
4 | * | ||
5 | * @remark Copyright 2002-2008 OProfile authors | ||
6 | * @remark Read the file COPYING | ||
7 | * | ||
8 | * @author John Levon | ||
9 | * @author Philippe Elie | ||
10 | * @author Graydon Hoare | ||
11 | * @author Robert Richter <robert.richter@amd.com> | ||
12 | * @author Barry Kasindorf | ||
13 | */ | ||
14 | |||
15 | #include <linux/oprofile.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/pci.h> | ||
18 | |||
19 | #include <asm/ptrace.h> | ||
20 | #include <asm/msr.h> | ||
21 | #include <asm/nmi.h> | ||
22 | |||
23 | #include "op_x86_model.h" | ||
24 | #include "op_counter.h" | ||
25 | |||
26 | #define NUM_COUNTERS 4 | ||
27 | #define NUM_CONTROLS 4 | ||
28 | |||
29 | #define CTR_IS_RESERVED(msrs, c) (msrs->counters[(c)].addr ? 1 : 0) | ||
30 | #define CTR_READ(l, h, msrs, c) do {rdmsr(msrs->counters[(c)].addr, (l), (h)); } while (0) | ||
31 | #define CTR_WRITE(l, msrs, c) do {wrmsr(msrs->counters[(c)].addr, -(unsigned int)(l), -1); } while (0) | ||
32 | #define CTR_OVERFLOWED(n) (!((n) & (1U<<31))) | ||
33 | |||
34 | #define CTRL_IS_RESERVED(msrs, c) (msrs->controls[(c)].addr ? 1 : 0) | ||
35 | #define CTRL_READ(l, h, msrs, c) do {rdmsr(msrs->controls[(c)].addr, (l), (h)); } while (0) | ||
36 | #define CTRL_WRITE(l, h, msrs, c) do {wrmsr(msrs->controls[(c)].addr, (l), (h)); } while (0) | ||
37 | #define CTRL_SET_ACTIVE(n) (n |= (1<<22)) | ||
38 | #define CTRL_SET_INACTIVE(n) (n &= ~(1<<22)) | ||
39 | #define CTRL_CLEAR_LO(x) (x &= (1<<21)) | ||
40 | #define CTRL_CLEAR_HI(x) (x &= 0xfffffcf0) | ||
41 | #define CTRL_SET_ENABLE(val) (val |= 1<<20) | ||
42 | #define CTRL_SET_USR(val, u) (val |= ((u & 1) << 16)) | ||
43 | #define CTRL_SET_KERN(val, k) (val |= ((k & 1) << 17)) | ||
44 | #define CTRL_SET_UM(val, m) (val |= (m << 8)) | ||
45 | #define CTRL_SET_EVENT_LOW(val, e) (val |= (e & 0xff)) | ||
46 | #define CTRL_SET_EVENT_HIGH(val, e) (val |= ((e >> 8) & 0xf)) | ||
47 | #define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9)) | ||
48 | #define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8)) | ||
49 | |||
50 | static unsigned long reset_value[NUM_COUNTERS]; | ||
51 | |||
52 | #ifdef CONFIG_OPROFILE_IBS | ||
53 | |||
54 | /* IbsFetchCtl bits/masks */ | ||
55 | #define IBS_FETCH_HIGH_VALID_BIT (1UL << 17) /* bit 49 */ | ||
56 | #define IBS_FETCH_HIGH_ENABLE (1UL << 16) /* bit 48 */ | ||
57 | #define IBS_FETCH_LOW_MAX_CNT_MASK 0x0000FFFFUL /* MaxCnt mask */ | ||
58 | |||
59 | /*IbsOpCtl bits */ | ||
60 | #define IBS_OP_LOW_VALID_BIT (1ULL<<18) /* bit 18 */ | ||
61 | #define IBS_OP_LOW_ENABLE (1ULL<<17) /* bit 17 */ | ||
62 | |||
63 | /* Codes used in cpu_buffer.c */ | ||
64 | /* This produces duplicate code, need to be fixed */ | ||
65 | #define IBS_FETCH_BEGIN 3 | ||
66 | #define IBS_OP_BEGIN 4 | ||
67 | |||
68 | /* The function interface needs to be fixed, something like add | ||
69 | data. Should then be added to linux/oprofile.h. */ | ||
70 | extern void oprofile_add_ibs_sample(struct pt_regs *const regs, | ||
71 | unsigned int * const ibs_sample, u8 code); | ||
72 | |||
73 | struct ibs_fetch_sample { | ||
74 | /* MSRC001_1031 IBS Fetch Linear Address Register */ | ||
75 | unsigned int ibs_fetch_lin_addr_low; | ||
76 | unsigned int ibs_fetch_lin_addr_high; | ||
77 | /* MSRC001_1030 IBS Fetch Control Register */ | ||
78 | unsigned int ibs_fetch_ctl_low; | ||
79 | unsigned int ibs_fetch_ctl_high; | ||
80 | /* MSRC001_1032 IBS Fetch Physical Address Register */ | ||
81 | unsigned int ibs_fetch_phys_addr_low; | ||
82 | unsigned int ibs_fetch_phys_addr_high; | ||
83 | }; | ||
84 | |||
85 | struct ibs_op_sample { | ||
86 | /* MSRC001_1034 IBS Op Logical Address Register (IbsRIP) */ | ||
87 | unsigned int ibs_op_rip_low; | ||
88 | unsigned int ibs_op_rip_high; | ||
89 | /* MSRC001_1035 IBS Op Data Register */ | ||
90 | unsigned int ibs_op_data1_low; | ||
91 | unsigned int ibs_op_data1_high; | ||
92 | /* MSRC001_1036 IBS Op Data 2 Register */ | ||
93 | unsigned int ibs_op_data2_low; | ||
94 | unsigned int ibs_op_data2_high; | ||
95 | /* MSRC001_1037 IBS Op Data 3 Register */ | ||
96 | unsigned int ibs_op_data3_low; | ||
97 | unsigned int ibs_op_data3_high; | ||
98 | /* MSRC001_1038 IBS DC Linear Address Register (IbsDcLinAd) */ | ||
99 | unsigned int ibs_dc_linear_low; | ||
100 | unsigned int ibs_dc_linear_high; | ||
101 | /* MSRC001_1039 IBS DC Physical Address Register (IbsDcPhysAd) */ | ||
102 | unsigned int ibs_dc_phys_low; | ||
103 | unsigned int ibs_dc_phys_high; | ||
104 | }; | ||
105 | |||
106 | /* | ||
107 | * unitialize the APIC for the IBS interrupts if needed on AMD Family10h+ | ||
108 | */ | ||
109 | static void clear_ibs_nmi(void); | ||
110 | |||
111 | static int ibs_allowed; /* AMD Family10h and later */ | ||
112 | |||
113 | struct op_ibs_config { | ||
114 | unsigned long op_enabled; | ||
115 | unsigned long fetch_enabled; | ||
116 | unsigned long max_cnt_fetch; | ||
117 | unsigned long max_cnt_op; | ||
118 | unsigned long rand_en; | ||
119 | unsigned long dispatched_ops; | ||
120 | }; | ||
121 | |||
122 | static struct op_ibs_config ibs_config; | ||
123 | |||
124 | #endif | ||
125 | |||
126 | /* functions for op_amd_spec */ | ||
127 | |||
128 | static void op_amd_fill_in_addresses(struct op_msrs * const msrs) | ||
129 | { | ||
130 | int i; | ||
131 | |||
132 | for (i = 0; i < NUM_COUNTERS; i++) { | ||
133 | if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i)) | ||
134 | msrs->counters[i].addr = MSR_K7_PERFCTR0 + i; | ||
135 | else | ||
136 | msrs->counters[i].addr = 0; | ||
137 | } | ||
138 | |||
139 | for (i = 0; i < NUM_CONTROLS; i++) { | ||
140 | if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) | ||
141 | msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i; | ||
142 | else | ||
143 | msrs->controls[i].addr = 0; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | |||
148 | static void op_amd_setup_ctrs(struct op_msrs const * const msrs) | ||
149 | { | ||
150 | unsigned int low, high; | ||
151 | int i; | ||
152 | |||
153 | /* clear all counters */ | ||
154 | for (i = 0 ; i < NUM_CONTROLS; ++i) { | ||
155 | if (unlikely(!CTRL_IS_RESERVED(msrs, i))) | ||
156 | continue; | ||
157 | CTRL_READ(low, high, msrs, i); | ||
158 | CTRL_CLEAR_LO(low); | ||
159 | CTRL_CLEAR_HI(high); | ||
160 | CTRL_WRITE(low, high, msrs, i); | ||
161 | } | ||
162 | |||
163 | /* avoid a false detection of ctr overflows in NMI handler */ | ||
164 | for (i = 0; i < NUM_COUNTERS; ++i) { | ||
165 | if (unlikely(!CTR_IS_RESERVED(msrs, i))) | ||
166 | continue; | ||
167 | CTR_WRITE(1, msrs, i); | ||
168 | } | ||
169 | |||
170 | /* enable active counters */ | ||
171 | for (i = 0; i < NUM_COUNTERS; ++i) { | ||
172 | if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs, i))) { | ||
173 | reset_value[i] = counter_config[i].count; | ||
174 | |||
175 | CTR_WRITE(counter_config[i].count, msrs, i); | ||
176 | |||
177 | CTRL_READ(low, high, msrs, i); | ||
178 | CTRL_CLEAR_LO(low); | ||
179 | CTRL_CLEAR_HI(high); | ||
180 | CTRL_SET_ENABLE(low); | ||
181 | CTRL_SET_USR(low, counter_config[i].user); | ||
182 | CTRL_SET_KERN(low, counter_config[i].kernel); | ||
183 | CTRL_SET_UM(low, counter_config[i].unit_mask); | ||
184 | CTRL_SET_EVENT_LOW(low, counter_config[i].event); | ||
185 | CTRL_SET_EVENT_HIGH(high, counter_config[i].event); | ||
186 | CTRL_SET_HOST_ONLY(high, 0); | ||
187 | CTRL_SET_GUEST_ONLY(high, 0); | ||
188 | |||
189 | CTRL_WRITE(low, high, msrs, i); | ||
190 | } else { | ||
191 | reset_value[i] = 0; | ||
192 | } | ||
193 | } | ||
194 | } | ||
195 | |||
196 | #ifdef CONFIG_OPROFILE_IBS | ||
197 | |||
198 | static inline int | ||
199 | op_amd_handle_ibs(struct pt_regs * const regs, | ||
200 | struct op_msrs const * const msrs) | ||
201 | { | ||
202 | unsigned int low, high; | ||
203 | struct ibs_fetch_sample ibs_fetch; | ||
204 | struct ibs_op_sample ibs_op; | ||
205 | |||
206 | if (!ibs_allowed) | ||
207 | return 1; | ||
208 | |||
209 | if (ibs_config.fetch_enabled) { | ||
210 | rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); | ||
211 | if (high & IBS_FETCH_HIGH_VALID_BIT) { | ||
212 | ibs_fetch.ibs_fetch_ctl_high = high; | ||
213 | ibs_fetch.ibs_fetch_ctl_low = low; | ||
214 | rdmsr(MSR_AMD64_IBSFETCHLINAD, low, high); | ||
215 | ibs_fetch.ibs_fetch_lin_addr_high = high; | ||
216 | ibs_fetch.ibs_fetch_lin_addr_low = low; | ||
217 | rdmsr(MSR_AMD64_IBSFETCHPHYSAD, low, high); | ||
218 | ibs_fetch.ibs_fetch_phys_addr_high = high; | ||
219 | ibs_fetch.ibs_fetch_phys_addr_low = low; | ||
220 | |||
221 | oprofile_add_ibs_sample(regs, | ||
222 | (unsigned int *)&ibs_fetch, | ||
223 | IBS_FETCH_BEGIN); | ||
224 | |||
225 | /*reenable the IRQ */ | ||
226 | rdmsr(MSR_AMD64_IBSFETCHCTL, low, high); | ||
227 | high &= ~IBS_FETCH_HIGH_VALID_BIT; | ||
228 | high |= IBS_FETCH_HIGH_ENABLE; | ||
229 | low &= IBS_FETCH_LOW_MAX_CNT_MASK; | ||
230 | wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | if (ibs_config.op_enabled) { | ||
235 | rdmsr(MSR_AMD64_IBSOPCTL, low, high); | ||
236 | if (low & IBS_OP_LOW_VALID_BIT) { | ||
237 | rdmsr(MSR_AMD64_IBSOPRIP, low, high); | ||
238 | ibs_op.ibs_op_rip_low = low; | ||
239 | ibs_op.ibs_op_rip_high = high; | ||
240 | rdmsr(MSR_AMD64_IBSOPDATA, low, high); | ||
241 | ibs_op.ibs_op_data1_low = low; | ||
242 | ibs_op.ibs_op_data1_high = high; | ||
243 | rdmsr(MSR_AMD64_IBSOPDATA2, low, high); | ||
244 | ibs_op.ibs_op_data2_low = low; | ||
245 | ibs_op.ibs_op_data2_high = high; | ||
246 | rdmsr(MSR_AMD64_IBSOPDATA3, low, high); | ||
247 | ibs_op.ibs_op_data3_low = low; | ||
248 | ibs_op.ibs_op_data3_high = high; | ||
249 | rdmsr(MSR_AMD64_IBSDCLINAD, low, high); | ||
250 | ibs_op.ibs_dc_linear_low = low; | ||
251 | ibs_op.ibs_dc_linear_high = high; | ||
252 | rdmsr(MSR_AMD64_IBSDCPHYSAD, low, high); | ||
253 | ibs_op.ibs_dc_phys_low = low; | ||
254 | ibs_op.ibs_dc_phys_high = high; | ||
255 | |||
256 | /* reenable the IRQ */ | ||
257 | oprofile_add_ibs_sample(regs, | ||
258 | (unsigned int *)&ibs_op, | ||
259 | IBS_OP_BEGIN); | ||
260 | rdmsr(MSR_AMD64_IBSOPCTL, low, high); | ||
261 | high = 0; | ||
262 | low &= ~IBS_OP_LOW_VALID_BIT; | ||
263 | low |= IBS_OP_LOW_ENABLE; | ||
264 | wrmsr(MSR_AMD64_IBSOPCTL, low, high); | ||
265 | } | ||
266 | } | ||
267 | |||
268 | return 1; | ||
269 | } | ||
270 | |||
271 | #endif | ||
272 | |||
273 | static int op_amd_check_ctrs(struct pt_regs * const regs, | ||
274 | struct op_msrs const * const msrs) | ||
275 | { | ||
276 | unsigned int low, high; | ||
277 | int i; | ||
278 | |||
279 | for (i = 0 ; i < NUM_COUNTERS; ++i) { | ||
280 | if (!reset_value[i]) | ||
281 | continue; | ||
282 | CTR_READ(low, high, msrs, i); | ||
283 | if (CTR_OVERFLOWED(low)) { | ||
284 | oprofile_add_sample(regs, i); | ||
285 | CTR_WRITE(reset_value[i], msrs, i); | ||
286 | } | ||
287 | } | ||
288 | |||
289 | #ifdef CONFIG_OPROFILE_IBS | ||
290 | op_amd_handle_ibs(regs, msrs); | ||
291 | #endif | ||
292 | |||
293 | /* See op_model_ppro.c */ | ||
294 | return 1; | ||
295 | } | ||
296 | |||
297 | static void op_amd_start(struct op_msrs const * const msrs) | ||
298 | { | ||
299 | unsigned int low, high; | ||
300 | int i; | ||
301 | for (i = 0 ; i < NUM_COUNTERS ; ++i) { | ||
302 | if (reset_value[i]) { | ||
303 | CTRL_READ(low, high, msrs, i); | ||
304 | CTRL_SET_ACTIVE(low); | ||
305 | CTRL_WRITE(low, high, msrs, i); | ||
306 | } | ||
307 | } | ||
308 | |||
309 | #ifdef CONFIG_OPROFILE_IBS | ||
310 | if (ibs_allowed && ibs_config.fetch_enabled) { | ||
311 | low = (ibs_config.max_cnt_fetch >> 4) & 0xFFFF; | ||
312 | high = IBS_FETCH_HIGH_ENABLE; | ||
313 | wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); | ||
314 | } | ||
315 | |||
316 | if (ibs_allowed && ibs_config.op_enabled) { | ||
317 | low = ((ibs_config.max_cnt_op >> 4) & 0xFFFF) + IBS_OP_LOW_ENABLE; | ||
318 | high = 0; | ||
319 | wrmsr(MSR_AMD64_IBSOPCTL, low, high); | ||
320 | } | ||
321 | #endif | ||
322 | } | ||
323 | |||
324 | |||
325 | static void op_amd_stop(struct op_msrs const * const msrs) | ||
326 | { | ||
327 | unsigned int low, high; | ||
328 | int i; | ||
329 | |||
330 | /* Subtle: stop on all counters to avoid race with | ||
331 | * setting our pm callback */ | ||
332 | for (i = 0 ; i < NUM_COUNTERS ; ++i) { | ||
333 | if (!reset_value[i]) | ||
334 | continue; | ||
335 | CTRL_READ(low, high, msrs, i); | ||
336 | CTRL_SET_INACTIVE(low); | ||
337 | CTRL_WRITE(low, high, msrs, i); | ||
338 | } | ||
339 | |||
340 | #ifdef CONFIG_OPROFILE_IBS | ||
341 | if (ibs_allowed && ibs_config.fetch_enabled) { | ||
342 | low = 0; /* clear max count and enable */ | ||
343 | high = 0; | ||
344 | wrmsr(MSR_AMD64_IBSFETCHCTL, low, high); | ||
345 | } | ||
346 | |||
347 | if (ibs_allowed && ibs_config.op_enabled) { | ||
348 | low = 0; /* clear max count and enable */ | ||
349 | high = 0; | ||
350 | wrmsr(MSR_AMD64_IBSOPCTL, low, high); | ||
351 | } | ||
352 | #endif | ||
353 | } | ||
354 | |||
355 | static void op_amd_shutdown(struct op_msrs const * const msrs) | ||
356 | { | ||
357 | int i; | ||
358 | |||
359 | for (i = 0 ; i < NUM_COUNTERS ; ++i) { | ||
360 | if (CTR_IS_RESERVED(msrs, i)) | ||
361 | release_perfctr_nmi(MSR_K7_PERFCTR0 + i); | ||
362 | } | ||
363 | for (i = 0 ; i < NUM_CONTROLS ; ++i) { | ||
364 | if (CTRL_IS_RESERVED(msrs, i)) | ||
365 | release_evntsel_nmi(MSR_K7_EVNTSEL0 + i); | ||
366 | } | ||
367 | } | ||
368 | |||
369 | #ifndef CONFIG_OPROFILE_IBS | ||
370 | |||
371 | /* no IBS support */ | ||
372 | |||
373 | static int op_amd_init(struct oprofile_operations *ops) | ||
374 | { | ||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | static void op_amd_exit(void) {} | ||
379 | |||
380 | #else | ||
381 | |||
382 | static u8 ibs_eilvt_off; | ||
383 | |||
384 | static inline void apic_init_ibs_nmi_per_cpu(void *arg) | ||
385 | { | ||
386 | ibs_eilvt_off = setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_NMI, 0); | ||
387 | } | ||
388 | |||
389 | static inline void apic_clear_ibs_nmi_per_cpu(void *arg) | ||
390 | { | ||
391 | setup_APIC_eilvt_ibs(0, APIC_EILVT_MSG_FIX, 1); | ||
392 | } | ||
393 | |||
394 | static int pfm_amd64_setup_eilvt(void) | ||
395 | { | ||
396 | #define IBSCTL_LVTOFFSETVAL (1 << 8) | ||
397 | #define IBSCTL 0x1cc | ||
398 | struct pci_dev *cpu_cfg; | ||
399 | int nodes; | ||
400 | u32 value = 0; | ||
401 | |||
402 | /* per CPU setup */ | ||
403 | on_each_cpu(apic_init_ibs_nmi_per_cpu, NULL, 1); | ||
404 | |||
405 | nodes = 0; | ||
406 | cpu_cfg = NULL; | ||
407 | do { | ||
408 | cpu_cfg = pci_get_device(PCI_VENDOR_ID_AMD, | ||
409 | PCI_DEVICE_ID_AMD_10H_NB_MISC, | ||
410 | cpu_cfg); | ||
411 | if (!cpu_cfg) | ||
412 | break; | ||
413 | ++nodes; | ||
414 | pci_write_config_dword(cpu_cfg, IBSCTL, ibs_eilvt_off | ||
415 | | IBSCTL_LVTOFFSETVAL); | ||
416 | pci_read_config_dword(cpu_cfg, IBSCTL, &value); | ||
417 | if (value != (ibs_eilvt_off | IBSCTL_LVTOFFSETVAL)) { | ||
418 | printk(KERN_DEBUG "Failed to setup IBS LVT offset, " | ||
419 | "IBSCTL = 0x%08x", value); | ||
420 | return 1; | ||
421 | } | ||
422 | } while (1); | ||
423 | |||
424 | if (!nodes) { | ||
425 | printk(KERN_DEBUG "No CPU node configured for IBS"); | ||
426 | return 1; | ||
427 | } | ||
428 | |||
429 | #ifdef CONFIG_NUMA | ||
430 | /* Sanity check */ | ||
431 | /* Works only for 64bit with proper numa implementation. */ | ||
432 | if (nodes != num_possible_nodes()) { | ||
433 | printk(KERN_DEBUG "Failed to setup CPU node(s) for IBS, " | ||
434 | "found: %d, expected %d", | ||
435 | nodes, num_possible_nodes()); | ||
436 | return 1; | ||
437 | } | ||
438 | #endif | ||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | /* | ||
443 | * initialize the APIC for the IBS interrupts | ||
444 | * if available (AMD Family10h rev B0 and later) | ||
445 | */ | ||
446 | static void setup_ibs(void) | ||
447 | { | ||
448 | ibs_allowed = boot_cpu_has(X86_FEATURE_IBS); | ||
449 | |||
450 | if (!ibs_allowed) | ||
451 | return; | ||
452 | |||
453 | if (pfm_amd64_setup_eilvt()) { | ||
454 | ibs_allowed = 0; | ||
455 | return; | ||
456 | } | ||
457 | |||
458 | printk(KERN_INFO "oprofile: AMD IBS detected\n"); | ||
459 | } | ||
460 | |||
461 | |||
462 | /* | ||
463 | * unitialize the APIC for the IBS interrupts if needed on AMD Family10h | ||
464 | * rev B0 and later */ | ||
465 | static void clear_ibs_nmi(void) | ||
466 | { | ||
467 | if (ibs_allowed) | ||
468 | on_each_cpu(apic_clear_ibs_nmi_per_cpu, NULL, 1); | ||
469 | } | ||
470 | |||
471 | static int (*create_arch_files)(struct super_block * sb, struct dentry * root); | ||
472 | |||
473 | static int setup_ibs_files(struct super_block * sb, struct dentry * root) | ||
474 | { | ||
475 | char buf[12]; | ||
476 | struct dentry *dir; | ||
477 | int ret = 0; | ||
478 | |||
479 | /* architecture specific files */ | ||
480 | if (create_arch_files) | ||
481 | ret = create_arch_files(sb, root); | ||
482 | |||
483 | if (ret) | ||
484 | return ret; | ||
485 | |||
486 | if (!ibs_allowed) | ||
487 | return ret; | ||
488 | |||
489 | /* model specific files */ | ||
490 | |||
491 | /* setup some reasonable defaults */ | ||
492 | ibs_config.max_cnt_fetch = 250000; | ||
493 | ibs_config.fetch_enabled = 0; | ||
494 | ibs_config.max_cnt_op = 250000; | ||
495 | ibs_config.op_enabled = 0; | ||
496 | ibs_config.dispatched_ops = 1; | ||
497 | snprintf(buf, sizeof(buf), "ibs_fetch"); | ||
498 | dir = oprofilefs_mkdir(sb, root, buf); | ||
499 | oprofilefs_create_ulong(sb, dir, "rand_enable", | ||
500 | &ibs_config.rand_en); | ||
501 | oprofilefs_create_ulong(sb, dir, "enable", | ||
502 | &ibs_config.fetch_enabled); | ||
503 | oprofilefs_create_ulong(sb, dir, "max_count", | ||
504 | &ibs_config.max_cnt_fetch); | ||
505 | snprintf(buf, sizeof(buf), "ibs_uops"); | ||
506 | dir = oprofilefs_mkdir(sb, root, buf); | ||
507 | oprofilefs_create_ulong(sb, dir, "enable", | ||
508 | &ibs_config.op_enabled); | ||
509 | oprofilefs_create_ulong(sb, dir, "max_count", | ||
510 | &ibs_config.max_cnt_op); | ||
511 | oprofilefs_create_ulong(sb, dir, "dispatched_ops", | ||
512 | &ibs_config.dispatched_ops); | ||
513 | |||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | static int op_amd_init(struct oprofile_operations *ops) | ||
518 | { | ||
519 | setup_ibs(); | ||
520 | create_arch_files = ops->create_files; | ||
521 | ops->create_files = setup_ibs_files; | ||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static void op_amd_exit(void) | ||
526 | { | ||
527 | clear_ibs_nmi(); | ||
528 | } | ||
529 | |||
530 | #endif | ||
531 | |||
532 | struct op_x86_model_spec const op_amd_spec = { | ||
533 | .init = op_amd_init, | ||
534 | .exit = op_amd_exit, | ||
535 | .num_counters = NUM_COUNTERS, | ||
536 | .num_controls = NUM_CONTROLS, | ||
537 | .fill_in_addresses = &op_amd_fill_in_addresses, | ||
538 | .setup_ctrs = &op_amd_setup_ctrs, | ||
539 | .check_ctrs = &op_amd_check_ctrs, | ||
540 | .start = &op_amd_start, | ||
541 | .stop = &op_amd_stop, | ||
542 | .shutdown = &op_amd_shutdown | ||
543 | }; | ||
diff --git a/arch/x86/oprofile/op_model_athlon.c b/arch/x86/oprofile/op_model_athlon.c deleted file mode 100644 index 3d534879a9dc..000000000000 --- a/arch/x86/oprofile/op_model_athlon.c +++ /dev/null | |||
@@ -1,190 +0,0 @@ | |||
1 | /* | ||
2 | * @file op_model_athlon.h | ||
3 | * athlon / K7 / K8 / Family 10h model-specific MSR operations | ||
4 | * | ||
5 | * @remark Copyright 2002 OProfile authors | ||
6 | * @remark Read the file COPYING | ||
7 | * | ||
8 | * @author John Levon | ||
9 | * @author Philippe Elie | ||
10 | * @author Graydon Hoare | ||
11 | */ | ||
12 | |||
13 | #include <linux/oprofile.h> | ||
14 | #include <asm/ptrace.h> | ||
15 | #include <asm/msr.h> | ||
16 | #include <asm/nmi.h> | ||
17 | |||
18 | #include "op_x86_model.h" | ||
19 | #include "op_counter.h" | ||
20 | |||
21 | #define NUM_COUNTERS 4 | ||
22 | #define NUM_CONTROLS 4 | ||
23 | |||
24 | #define CTR_IS_RESERVED(msrs, c) (msrs->counters[(c)].addr ? 1 : 0) | ||
25 | #define CTR_READ(l, h, msrs, c) do {rdmsr(msrs->counters[(c)].addr, (l), (h)); } while (0) | ||
26 | #define CTR_WRITE(l, msrs, c) do {wrmsr(msrs->counters[(c)].addr, -(unsigned int)(l), -1); } while (0) | ||
27 | #define CTR_OVERFLOWED(n) (!((n) & (1U<<31))) | ||
28 | |||
29 | #define CTRL_IS_RESERVED(msrs, c) (msrs->controls[(c)].addr ? 1 : 0) | ||
30 | #define CTRL_READ(l, h, msrs, c) do {rdmsr(msrs->controls[(c)].addr, (l), (h)); } while (0) | ||
31 | #define CTRL_WRITE(l, h, msrs, c) do {wrmsr(msrs->controls[(c)].addr, (l), (h)); } while (0) | ||
32 | #define CTRL_SET_ACTIVE(n) (n |= (1<<22)) | ||
33 | #define CTRL_SET_INACTIVE(n) (n &= ~(1<<22)) | ||
34 | #define CTRL_CLEAR_LO(x) (x &= (1<<21)) | ||
35 | #define CTRL_CLEAR_HI(x) (x &= 0xfffffcf0) | ||
36 | #define CTRL_SET_ENABLE(val) (val |= 1<<20) | ||
37 | #define CTRL_SET_USR(val, u) (val |= ((u & 1) << 16)) | ||
38 | #define CTRL_SET_KERN(val, k) (val |= ((k & 1) << 17)) | ||
39 | #define CTRL_SET_UM(val, m) (val |= (m << 8)) | ||
40 | #define CTRL_SET_EVENT_LOW(val, e) (val |= (e & 0xff)) | ||
41 | #define CTRL_SET_EVENT_HIGH(val, e) (val |= ((e >> 8) & 0xf)) | ||
42 | #define CTRL_SET_HOST_ONLY(val, h) (val |= ((h & 1) << 9)) | ||
43 | #define CTRL_SET_GUEST_ONLY(val, h) (val |= ((h & 1) << 8)) | ||
44 | |||
45 | static unsigned long reset_value[NUM_COUNTERS]; | ||
46 | |||
47 | static void athlon_fill_in_addresses(struct op_msrs * const msrs) | ||
48 | { | ||
49 | int i; | ||
50 | |||
51 | for (i = 0; i < NUM_COUNTERS; i++) { | ||
52 | if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i)) | ||
53 | msrs->counters[i].addr = MSR_K7_PERFCTR0 + i; | ||
54 | else | ||
55 | msrs->counters[i].addr = 0; | ||
56 | } | ||
57 | |||
58 | for (i = 0; i < NUM_CONTROLS; i++) { | ||
59 | if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i)) | ||
60 | msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i; | ||
61 | else | ||
62 | msrs->controls[i].addr = 0; | ||
63 | } | ||
64 | } | ||
65 | |||
66 | |||
67 | static void athlon_setup_ctrs(struct op_msrs const * const msrs) | ||
68 | { | ||
69 | unsigned int low, high; | ||
70 | int i; | ||
71 | |||
72 | /* clear all counters */ | ||
73 | for (i = 0 ; i < NUM_CONTROLS; ++i) { | ||
74 | if (unlikely(!CTRL_IS_RESERVED(msrs, i))) | ||
75 | continue; | ||
76 | CTRL_READ(low, high, msrs, i); | ||
77 | CTRL_CLEAR_LO(low); | ||
78 | CTRL_CLEAR_HI(high); | ||
79 | CTRL_WRITE(low, high, msrs, i); | ||
80 | } | ||
81 | |||
82 | /* avoid a false detection of ctr overflows in NMI handler */ | ||
83 | for (i = 0; i < NUM_COUNTERS; ++i) { | ||
84 | if (unlikely(!CTR_IS_RESERVED(msrs, i))) | ||
85 | continue; | ||
86 | CTR_WRITE(1, msrs, i); | ||
87 | } | ||
88 | |||
89 | /* enable active counters */ | ||
90 | for (i = 0; i < NUM_COUNTERS; ++i) { | ||
91 | if ((counter_config[i].enabled) && (CTR_IS_RESERVED(msrs, i))) { | ||
92 | reset_value[i] = counter_config[i].count; | ||
93 | |||
94 | CTR_WRITE(counter_config[i].count, msrs, i); | ||
95 | |||
96 | CTRL_READ(low, high, msrs, i); | ||
97 | CTRL_CLEAR_LO(low); | ||
98 | CTRL_CLEAR_HI(high); | ||
99 | CTRL_SET_ENABLE(low); | ||
100 | CTRL_SET_USR(low, counter_config[i].user); | ||
101 | CTRL_SET_KERN(low, counter_config[i].kernel); | ||
102 | CTRL_SET_UM(low, counter_config[i].unit_mask); | ||
103 | CTRL_SET_EVENT_LOW(low, counter_config[i].event); | ||
104 | CTRL_SET_EVENT_HIGH(high, counter_config[i].event); | ||
105 | CTRL_SET_HOST_ONLY(high, 0); | ||
106 | CTRL_SET_GUEST_ONLY(high, 0); | ||
107 | |||
108 | CTRL_WRITE(low, high, msrs, i); | ||
109 | } else { | ||
110 | reset_value[i] = 0; | ||
111 | } | ||
112 | } | ||
113 | } | ||
114 | |||
115 | |||
116 | static int athlon_check_ctrs(struct pt_regs * const regs, | ||
117 | struct op_msrs const * const msrs) | ||
118 | { | ||
119 | unsigned int low, high; | ||
120 | int i; | ||
121 | |||
122 | for (i = 0 ; i < NUM_COUNTERS; ++i) { | ||
123 | if (!reset_value[i]) | ||
124 | continue; | ||
125 | CTR_READ(low, high, msrs, i); | ||
126 | if (CTR_OVERFLOWED(low)) { | ||
127 | oprofile_add_sample(regs, i); | ||
128 | CTR_WRITE(reset_value[i], msrs, i); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | /* See op_model_ppro.c */ | ||
133 | return 1; | ||
134 | } | ||
135 | |||
136 | |||
137 | static void athlon_start(struct op_msrs const * const msrs) | ||
138 | { | ||
139 | unsigned int low, high; | ||
140 | int i; | ||
141 | for (i = 0 ; i < NUM_COUNTERS ; ++i) { | ||
142 | if (reset_value[i]) { | ||
143 | CTRL_READ(low, high, msrs, i); | ||
144 | CTRL_SET_ACTIVE(low); | ||
145 | CTRL_WRITE(low, high, msrs, i); | ||
146 | } | ||
147 | } | ||
148 | } | ||
149 | |||
150 | |||
151 | static void athlon_stop(struct op_msrs const * const msrs) | ||
152 | { | ||
153 | unsigned int low, high; | ||
154 | int i; | ||
155 | |||
156 | /* Subtle: stop on all counters to avoid race with | ||
157 | * setting our pm callback */ | ||
158 | for (i = 0 ; i < NUM_COUNTERS ; ++i) { | ||
159 | if (!reset_value[i]) | ||
160 | continue; | ||
161 | CTRL_READ(low, high, msrs, i); | ||
162 | CTRL_SET_INACTIVE(low); | ||
163 | CTRL_WRITE(low, high, msrs, i); | ||
164 | } | ||
165 | } | ||
166 | |||
167 | static void athlon_shutdown(struct op_msrs const * const msrs) | ||
168 | { | ||
169 | int i; | ||
170 | |||
171 | for (i = 0 ; i < NUM_COUNTERS ; ++i) { | ||
172 | if (CTR_IS_RESERVED(msrs, i)) | ||
173 | release_perfctr_nmi(MSR_K7_PERFCTR0 + i); | ||
174 | } | ||
175 | for (i = 0 ; i < NUM_CONTROLS ; ++i) { | ||
176 | if (CTRL_IS_RESERVED(msrs, i)) | ||
177 | release_evntsel_nmi(MSR_K7_EVNTSEL0 + i); | ||
178 | } | ||
179 | } | ||
180 | |||
181 | struct op_x86_model_spec const op_athlon_spec = { | ||
182 | .num_counters = NUM_COUNTERS, | ||
183 | .num_controls = NUM_CONTROLS, | ||
184 | .fill_in_addresses = &athlon_fill_in_addresses, | ||
185 | .setup_ctrs = &athlon_setup_ctrs, | ||
186 | .check_ctrs = &athlon_check_ctrs, | ||
187 | .start = &athlon_start, | ||
188 | .stop = &athlon_stop, | ||
189 | .shutdown = &athlon_shutdown | ||
190 | }; | ||
diff --git a/arch/x86/oprofile/op_x86_model.h b/arch/x86/oprofile/op_x86_model.h index 45b605fa71d0..05a0261ba0c3 100644 --- a/arch/x86/oprofile/op_x86_model.h +++ b/arch/x86/oprofile/op_x86_model.h | |||
@@ -32,6 +32,8 @@ struct pt_regs; | |||
32 | * various x86 CPU models' perfctr support. | 32 | * various x86 CPU models' perfctr support. |
33 | */ | 33 | */ |
34 | struct op_x86_model_spec { | 34 | struct op_x86_model_spec { |
35 | int (*init)(struct oprofile_operations *ops); | ||
36 | void (*exit)(void); | ||
35 | unsigned int const num_counters; | 37 | unsigned int const num_counters; |
36 | unsigned int const num_controls; | 38 | unsigned int const num_controls; |
37 | void (*fill_in_addresses)(struct op_msrs * const msrs); | 39 | void (*fill_in_addresses)(struct op_msrs * const msrs); |
@@ -46,6 +48,6 @@ struct op_x86_model_spec { | |||
46 | extern struct op_x86_model_spec const op_ppro_spec; | 48 | extern struct op_x86_model_spec const op_ppro_spec; |
47 | extern struct op_x86_model_spec const op_p4_spec; | 49 | extern struct op_x86_model_spec const op_p4_spec; |
48 | extern struct op_x86_model_spec const op_p4_ht2_spec; | 50 | extern struct op_x86_model_spec const op_p4_ht2_spec; |
49 | extern struct op_x86_model_spec const op_athlon_spec; | 51 | extern struct op_x86_model_spec const op_amd_spec; |
50 | 52 | ||
51 | #endif /* OP_X86_MODEL_H */ | 53 | #endif /* OP_X86_MODEL_H */ |
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index 4bdaa590375d..3c27a809393b 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c | |||
@@ -511,3 +511,31 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1201, fam10h_pci_cfg_space_size); | |||
511 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1202, fam10h_pci_cfg_space_size); | 511 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1202, fam10h_pci_cfg_space_size); |
512 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1203, fam10h_pci_cfg_space_size); | 512 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1203, fam10h_pci_cfg_space_size); |
513 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1204, fam10h_pci_cfg_space_size); | 513 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1204, fam10h_pci_cfg_space_size); |
514 | |||
515 | /* | ||
516 | * SB600: Disable BAR1 on device 14.0 to avoid HPET resources from | ||
517 | * confusing the PCI engine: | ||
518 | */ | ||
519 | static void sb600_disable_hpet_bar(struct pci_dev *dev) | ||
520 | { | ||
521 | u8 val; | ||
522 | |||
523 | /* | ||
524 | * The SB600 and SB700 both share the same device | ||
525 | * ID, but the PM register 0x55 does something different | ||
526 | * for the SB700, so make sure we are dealing with the | ||
527 | * SB600 before touching the bit: | ||
528 | */ | ||
529 | |||
530 | pci_read_config_byte(dev, 0x08, &val); | ||
531 | |||
532 | if (val < 0x2F) { | ||
533 | outb(0x55, 0xCD6); | ||
534 | val = inb(0xCD7); | ||
535 | |||
536 | /* Set bit 7 in PM register 0x55 */ | ||
537 | outb(0x55, 0xCD6); | ||
538 | outb(val | 0x80, 0xCD7); | ||
539 | } | ||
540 | } | ||
541 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4385, sb600_disable_hpet_bar); | ||
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 8dfcf77cb717..4426bb552bd9 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c | |||
@@ -484,7 +484,7 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file, | |||
484 | return -EUNATCH; | 484 | return -EUNATCH; |
485 | 485 | ||
486 | default: | 486 | default: |
487 | err = n_tty_ioctl(tty, file, cmd, arg); | 487 | err = n_tty_ioctl_helper(tty, file, cmd, arg); |
488 | break; | 488 | break; |
489 | }; | 489 | }; |
490 | 490 | ||
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index caff85149b9d..700ff9679457 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -350,7 +350,7 @@ config STALDRV | |||
350 | 350 | ||
351 | config STALLION | 351 | config STALLION |
352 | tristate "Stallion EasyIO or EC8/32 support" | 352 | tristate "Stallion EasyIO or EC8/32 support" |
353 | depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI) | 353 | depends on STALDRV && (ISA || EISA || PCI) |
354 | help | 354 | help |
355 | If you have an EasyIO or EasyConnection 8/32 multiport Stallion | 355 | If you have an EasyIO or EasyConnection 8/32 multiport Stallion |
356 | card, then this is for you; say Y. Make sure to read | 356 | card, then this is for you; say Y. Make sure to read |
@@ -361,7 +361,7 @@ config STALLION | |||
361 | 361 | ||
362 | config ISTALLION | 362 | config ISTALLION |
363 | tristate "Stallion EC8/64, ONboard, Brumby support" | 363 | tristate "Stallion EC8/64, ONboard, Brumby support" |
364 | depends on STALDRV && BROKEN_ON_SMP && (ISA || EISA || PCI) | 364 | depends on STALDRV && (ISA || EISA || PCI) |
365 | help | 365 | help |
366 | If you have an EasyConnection 8/64, ONboard, Brumby or Stallion | 366 | If you have an EasyConnection 8/64, ONboard, Brumby or Stallion |
367 | serial multiport card, say Y here. Make sure to read | 367 | serial multiport card, say Y here. Make sure to read |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 6850f6da7576..1a4247dccac4 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -7,7 +7,7 @@ | |||
7 | # | 7 | # |
8 | FONTMAPFILE = cp437.uni | 8 | FONTMAPFILE = cp437.uni |
9 | 9 | ||
10 | obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o | 10 | obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o |
11 | 11 | ||
12 | obj-$(CONFIG_LEGACY_PTYS) += pty.o | 12 | obj-$(CONFIG_LEGACY_PTYS) += pty.o |
13 | obj-$(CONFIG_UNIX98_PTYS) += pty.o | 13 | obj-$(CONFIG_UNIX98_PTYS) += pty.o |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 6e763e3f5a81..98821f97583c 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -837,9 +837,6 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch) | |||
837 | struct async_struct *info; | 837 | struct async_struct *info; |
838 | unsigned long flags; | 838 | unsigned long flags; |
839 | 839 | ||
840 | if (!tty) | ||
841 | return 0; | ||
842 | |||
843 | info = tty->driver_data; | 840 | info = tty->driver_data; |
844 | 841 | ||
845 | if (serial_paranoia_check(info, tty->name, "rs_put_char")) | 842 | if (serial_paranoia_check(info, tty->name, "rs_put_char")) |
@@ -892,9 +889,6 @@ static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count | |||
892 | struct async_struct *info; | 889 | struct async_struct *info; |
893 | unsigned long flags; | 890 | unsigned long flags; |
894 | 891 | ||
895 | if (!tty) | ||
896 | return 0; | ||
897 | |||
898 | info = tty->driver_data; | 892 | info = tty->driver_data; |
899 | 893 | ||
900 | if (serial_paranoia_check(info, tty->name, "rs_write")) | 894 | if (serial_paranoia_check(info, tty->name, "rs_write")) |
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c index 31d08b641f5b..b899d9182c7d 100644 --- a/drivers/char/applicom.c +++ b/drivers/char/applicom.c | |||
@@ -712,8 +712,7 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un | |||
712 | 712 | ||
713 | IndexCard = adgl->num_card-1; | 713 | IndexCard = adgl->num_card-1; |
714 | 714 | ||
715 | if(cmd != 0 && cmd != 6 && | 715 | if(cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) { |
716 | ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) { | ||
717 | static int warncount = 10; | 716 | static int warncount = 10; |
718 | if (warncount) { | 717 | if (warncount) { |
719 | printk( KERN_WARNING "APPLICOM driver IOCTL, bad board number %d\n",(int)IndexCard+1); | 718 | printk( KERN_WARNING "APPLICOM driver IOCTL, bad board number %d\n",(int)IndexCard+1); |
@@ -832,8 +831,7 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un | |||
832 | } | 831 | } |
833 | break; | 832 | break; |
834 | default: | 833 | default: |
835 | printk(KERN_INFO "APPLICOM driver ioctl, unknown function code %d\n",cmd) ; | 834 | ret = -ENOTTY; |
836 | ret = -EINVAL; | ||
837 | break; | 835 | break; |
838 | } | 836 | } |
839 | Dummy = readb(apbs[IndexCard].RamIO + VERS); | 837 | Dummy = readb(apbs[IndexCard].RamIO + VERS); |
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index fe6d774fe2e4..5e5b1dc1a0a7 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -4993,12 +4993,14 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
4993 | device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { | 4993 | device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { |
4994 | card_name = "Cyclom-Y"; | 4994 | card_name = "Cyclom-Y"; |
4995 | 4995 | ||
4996 | addr0 = pci_iomap(pdev, 0, CyPCI_Yctl); | 4996 | addr0 = ioremap_nocache(pci_resource_start(pdev, 0), |
4997 | CyPCI_Yctl); | ||
4997 | if (addr0 == NULL) { | 4998 | if (addr0 == NULL) { |
4998 | dev_err(&pdev->dev, "can't remap ctl region\n"); | 4999 | dev_err(&pdev->dev, "can't remap ctl region\n"); |
4999 | goto err_reg; | 5000 | goto err_reg; |
5000 | } | 5001 | } |
5001 | addr2 = pci_iomap(pdev, 2, CyPCI_Ywin); | 5002 | addr2 = ioremap_nocache(pci_resource_start(pdev, 2), |
5003 | CyPCI_Ywin); | ||
5002 | if (addr2 == NULL) { | 5004 | if (addr2 == NULL) { |
5003 | dev_err(&pdev->dev, "can't remap base region\n"); | 5005 | dev_err(&pdev->dev, "can't remap base region\n"); |
5004 | goto err_unmap; | 5006 | goto err_unmap; |
@@ -5013,7 +5015,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
5013 | } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { | 5015 | } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { |
5014 | struct RUNTIME_9060 __iomem *ctl_addr; | 5016 | struct RUNTIME_9060 __iomem *ctl_addr; |
5015 | 5017 | ||
5016 | ctl_addr = addr0 = pci_iomap(pdev, 0, CyPCI_Zctl); | 5018 | ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0), |
5019 | CyPCI_Zctl); | ||
5017 | if (addr0 == NULL) { | 5020 | if (addr0 == NULL) { |
5018 | dev_err(&pdev->dev, "can't remap ctl region\n"); | 5021 | dev_err(&pdev->dev, "can't remap ctl region\n"); |
5019 | goto err_reg; | 5022 | goto err_reg; |
@@ -5026,8 +5029,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
5026 | 5029 | ||
5027 | mailbox = (u32)readl(&ctl_addr->mail_box_0); | 5030 | mailbox = (u32)readl(&ctl_addr->mail_box_0); |
5028 | 5031 | ||
5029 | addr2 = pci_iomap(pdev, 2, mailbox == ZE_V1 ? | 5032 | addr2 = ioremap_nocache(pci_resource_start(pdev, 2), |
5030 | CyPCI_Ze_win : CyPCI_Zwin); | 5033 | mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin); |
5031 | if (addr2 == NULL) { | 5034 | if (addr2 == NULL) { |
5032 | dev_err(&pdev->dev, "can't remap base region\n"); | 5035 | dev_err(&pdev->dev, "can't remap base region\n"); |
5033 | goto err_unmap; | 5036 | goto err_unmap; |
@@ -5159,9 +5162,9 @@ err_null: | |||
5159 | cy_card[card_no].base_addr = NULL; | 5162 | cy_card[card_no].base_addr = NULL; |
5160 | free_irq(irq, &cy_card[card_no]); | 5163 | free_irq(irq, &cy_card[card_no]); |
5161 | err_unmap: | 5164 | err_unmap: |
5162 | pci_iounmap(pdev, addr0); | 5165 | iounmap(addr0); |
5163 | if (addr2) | 5166 | if (addr2) |
5164 | pci_iounmap(pdev, addr2); | 5167 | iounmap(addr2); |
5165 | err_reg: | 5168 | err_reg: |
5166 | pci_release_regions(pdev); | 5169 | pci_release_regions(pdev); |
5167 | err_dis: | 5170 | err_dis: |
@@ -5186,9 +5189,9 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev) | |||
5186 | cy_writew(cinfo->ctl_addr + 0x68, | 5189 | cy_writew(cinfo->ctl_addr + 0x68, |
5187 | readw(cinfo->ctl_addr + 0x68) & ~0x0900); | 5190 | readw(cinfo->ctl_addr + 0x68) & ~0x0900); |
5188 | 5191 | ||
5189 | pci_iounmap(pdev, cinfo->base_addr); | 5192 | iounmap(cinfo->base_addr); |
5190 | if (cinfo->ctl_addr) | 5193 | if (cinfo->ctl_addr) |
5191 | pci_iounmap(pdev, cinfo->ctl_addr); | 5194 | iounmap(cinfo->ctl_addr); |
5192 | if (cinfo->irq | 5195 | if (cinfo->irq |
5193 | #ifndef CONFIG_CYZ_INTR | 5196 | #ifndef CONFIG_CYZ_INTR |
5194 | && !IS_CYC_Z(*cinfo) | 5197 | && !IS_CYC_Z(*cinfo) |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 456e4ede049f..4998b2761e8f 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -1376,6 +1376,7 @@ static void post_fep_init(unsigned int crd) | |||
1376 | unsigned long flags; | 1376 | unsigned long flags; |
1377 | u16 tseg, rseg; | 1377 | u16 tseg, rseg; |
1378 | 1378 | ||
1379 | tty_port_init(&ch->port); | ||
1379 | ch->brdchan = bc; | 1380 | ch->brdchan = bc; |
1380 | ch->mailbox = gd; | 1381 | ch->mailbox = gd; |
1381 | INIT_WORK(&ch->tqueue, do_softint); | 1382 | INIT_WORK(&ch->tqueue, do_softint); |
@@ -1510,10 +1511,6 @@ static void post_fep_init(unsigned int crd) | |||
1510 | ch->fepstopca = 0; | 1511 | ch->fepstopca = 0; |
1511 | 1512 | ||
1512 | ch->close_delay = 50; | 1513 | ch->close_delay = 50; |
1513 | ch->port.count = 0; | ||
1514 | ch->port.blocked_open = 0; | ||
1515 | init_waitqueue_head(&ch->port.open_wait); | ||
1516 | init_waitqueue_head(&ch->port.close_wait); | ||
1517 | 1514 | ||
1518 | spin_unlock_irqrestore(&epca_lock, flags); | 1515 | spin_unlock_irqrestore(&epca_lock, flags); |
1519 | } | 1516 | } |
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 19d3afb0e50c..c6090f84a2e4 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c | |||
@@ -54,8 +54,6 @@ int gs_put_char(struct tty_struct * tty, unsigned char ch) | |||
54 | 54 | ||
55 | func_enter (); | 55 | func_enter (); |
56 | 56 | ||
57 | if (!tty) return 0; | ||
58 | |||
59 | port = tty->driver_data; | 57 | port = tty->driver_data; |
60 | 58 | ||
61 | if (!port) return 0; | 59 | if (!port) return 0; |
@@ -97,8 +95,6 @@ int gs_write(struct tty_struct * tty, | |||
97 | 95 | ||
98 | func_enter (); | 96 | func_enter (); |
99 | 97 | ||
100 | if (!tty) return 0; | ||
101 | |||
102 | port = tty->driver_data; | 98 | port = tty->driver_data; |
103 | 99 | ||
104 | if (!port) return 0; | 100 | if (!port) return 0; |
@@ -185,7 +181,6 @@ static int gs_real_chars_in_buffer(struct tty_struct *tty) | |||
185 | struct gs_port *port; | 181 | struct gs_port *port; |
186 | func_enter (); | 182 | func_enter (); |
187 | 183 | ||
188 | if (!tty) return 0; | ||
189 | port = tty->driver_data; | 184 | port = tty->driver_data; |
190 | 185 | ||
191 | if (!port->rd) return 0; | 186 | if (!port->rd) return 0; |
@@ -274,8 +269,6 @@ void gs_flush_buffer(struct tty_struct *tty) | |||
274 | 269 | ||
275 | func_enter (); | 270 | func_enter (); |
276 | 271 | ||
277 | if (!tty) return; | ||
278 | |||
279 | port = tty->driver_data; | 272 | port = tty->driver_data; |
280 | 273 | ||
281 | if (!port) return; | 274 | if (!port) return; |
@@ -296,8 +289,6 @@ void gs_flush_chars(struct tty_struct * tty) | |||
296 | 289 | ||
297 | func_enter (); | 290 | func_enter (); |
298 | 291 | ||
299 | if (!tty) return; | ||
300 | |||
301 | port = tty->driver_data; | 292 | port = tty->driver_data; |
302 | 293 | ||
303 | if (!port) return; | 294 | if (!port) return; |
@@ -321,8 +312,6 @@ void gs_stop(struct tty_struct * tty) | |||
321 | 312 | ||
322 | func_enter (); | 313 | func_enter (); |
323 | 314 | ||
324 | if (!tty) return; | ||
325 | |||
326 | port = tty->driver_data; | 315 | port = tty->driver_data; |
327 | 316 | ||
328 | if (!port) return; | 317 | if (!port) return; |
@@ -341,8 +330,6 @@ void gs_start(struct tty_struct * tty) | |||
341 | { | 330 | { |
342 | struct gs_port *port; | 331 | struct gs_port *port; |
343 | 332 | ||
344 | if (!tty) return; | ||
345 | |||
346 | port = tty->driver_data; | 333 | port = tty->driver_data; |
347 | 334 | ||
348 | if (!port) return; | 335 | if (!port) return; |
@@ -393,8 +380,6 @@ void gs_hangup(struct tty_struct *tty) | |||
393 | 380 | ||
394 | func_enter (); | 381 | func_enter (); |
395 | 382 | ||
396 | if (!tty) return; | ||
397 | |||
398 | port = tty->driver_data; | 383 | port = tty->driver_data; |
399 | tty = port->port.tty; | 384 | tty = port->port.tty; |
400 | if (!tty) | 385 | if (!tty) |
@@ -426,8 +411,6 @@ int gs_block_til_ready(void *port_, struct file * filp) | |||
426 | 411 | ||
427 | tty = port->port.tty; | 412 | tty = port->port.tty; |
428 | 413 | ||
429 | if (!tty) return 0; | ||
430 | |||
431 | gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); | 414 | gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); |
432 | /* | 415 | /* |
433 | * If the device is in the middle of being closed, then block | 416 | * If the device is in the middle of being closed, then block |
@@ -523,8 +506,6 @@ void gs_close(struct tty_struct * tty, struct file * filp) | |||
523 | 506 | ||
524 | func_enter (); | 507 | func_enter (); |
525 | 508 | ||
526 | if (!tty) return; | ||
527 | |||
528 | port = (struct gs_port *) tty->driver_data; | 509 | port = (struct gs_port *) tty->driver_data; |
529 | 510 | ||
530 | if (!port) return; | 511 | if (!port) return; |
@@ -621,8 +602,6 @@ void gs_set_termios (struct tty_struct * tty, | |||
621 | 602 | ||
622 | func_enter(); | 603 | func_enter(); |
623 | 604 | ||
624 | if (!tty) return; | ||
625 | |||
626 | port = tty->driver_data; | 605 | port = tty->driver_data; |
627 | 606 | ||
628 | if (!port) return; | 607 | if (!port) return; |
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index b3f5dbc6d880..f3cfb4c76125 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
@@ -53,6 +53,11 @@ | |||
53 | 53 | ||
54 | #define HPET_RANGE_SIZE 1024 /* from HPET spec */ | 54 | #define HPET_RANGE_SIZE 1024 /* from HPET spec */ |
55 | 55 | ||
56 | |||
57 | /* WARNING -- don't get confused. These macros are never used | ||
58 | * to write the (single) counter, and rarely to read it. | ||
59 | * They're badly named; to fix, someday. | ||
60 | */ | ||
56 | #if BITS_PER_LONG == 64 | 61 | #if BITS_PER_LONG == 64 |
57 | #define write_counter(V, MC) writeq(V, MC) | 62 | #define write_counter(V, MC) writeq(V, MC) |
58 | #define read_counter(MC) readq(MC) | 63 | #define read_counter(MC) readq(MC) |
@@ -77,7 +82,7 @@ static struct clocksource clocksource_hpet = { | |||
77 | .rating = 250, | 82 | .rating = 250, |
78 | .read = read_hpet, | 83 | .read = read_hpet, |
79 | .mask = CLOCKSOURCE_MASK(64), | 84 | .mask = CLOCKSOURCE_MASK(64), |
80 | .mult = 0, /*to be caluclated*/ | 85 | .mult = 0, /* to be calculated */ |
81 | .shift = 10, | 86 | .shift = 10, |
82 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 87 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
83 | }; | 88 | }; |
@@ -86,8 +91,6 @@ static struct clocksource *hpet_clocksource; | |||
86 | 91 | ||
87 | /* A lock for concurrent access by app and isr hpet activity. */ | 92 | /* A lock for concurrent access by app and isr hpet activity. */ |
88 | static DEFINE_SPINLOCK(hpet_lock); | 93 | static DEFINE_SPINLOCK(hpet_lock); |
89 | /* A lock for concurrent intermodule access to hpet and isr hpet activity. */ | ||
90 | static DEFINE_SPINLOCK(hpet_task_lock); | ||
91 | 94 | ||
92 | #define HPET_DEV_NAME (7) | 95 | #define HPET_DEV_NAME (7) |
93 | 96 | ||
@@ -99,7 +102,6 @@ struct hpet_dev { | |||
99 | unsigned long hd_irqdata; | 102 | unsigned long hd_irqdata; |
100 | wait_queue_head_t hd_waitqueue; | 103 | wait_queue_head_t hd_waitqueue; |
101 | struct fasync_struct *hd_async_queue; | 104 | struct fasync_struct *hd_async_queue; |
102 | struct hpet_task *hd_task; | ||
103 | unsigned int hd_flags; | 105 | unsigned int hd_flags; |
104 | unsigned int hd_irq; | 106 | unsigned int hd_irq; |
105 | unsigned int hd_hdwirq; | 107 | unsigned int hd_hdwirq; |
@@ -173,11 +175,6 @@ static irqreturn_t hpet_interrupt(int irq, void *data) | |||
173 | writel(isr, &devp->hd_hpet->hpet_isr); | 175 | writel(isr, &devp->hd_hpet->hpet_isr); |
174 | spin_unlock(&hpet_lock); | 176 | spin_unlock(&hpet_lock); |
175 | 177 | ||
176 | spin_lock(&hpet_task_lock); | ||
177 | if (devp->hd_task) | ||
178 | devp->hd_task->ht_func(devp->hd_task->ht_data); | ||
179 | spin_unlock(&hpet_task_lock); | ||
180 | |||
181 | wake_up_interruptible(&devp->hd_waitqueue); | 178 | wake_up_interruptible(&devp->hd_waitqueue); |
182 | 179 | ||
183 | kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN); | 180 | kill_fasync(&devp->hd_async_queue, SIGIO, POLL_IN); |
@@ -185,6 +182,67 @@ static irqreturn_t hpet_interrupt(int irq, void *data) | |||
185 | return IRQ_HANDLED; | 182 | return IRQ_HANDLED; |
186 | } | 183 | } |
187 | 184 | ||
185 | static void hpet_timer_set_irq(struct hpet_dev *devp) | ||
186 | { | ||
187 | unsigned long v; | ||
188 | int irq, gsi; | ||
189 | struct hpet_timer __iomem *timer; | ||
190 | |||
191 | spin_lock_irq(&hpet_lock); | ||
192 | if (devp->hd_hdwirq) { | ||
193 | spin_unlock_irq(&hpet_lock); | ||
194 | return; | ||
195 | } | ||
196 | |||
197 | timer = devp->hd_timer; | ||
198 | |||
199 | /* we prefer level triggered mode */ | ||
200 | v = readl(&timer->hpet_config); | ||
201 | if (!(v & Tn_INT_TYPE_CNF_MASK)) { | ||
202 | v |= Tn_INT_TYPE_CNF_MASK; | ||
203 | writel(v, &timer->hpet_config); | ||
204 | } | ||
205 | spin_unlock_irq(&hpet_lock); | ||
206 | |||
207 | v = (readq(&timer->hpet_config) & Tn_INT_ROUTE_CAP_MASK) >> | ||
208 | Tn_INT_ROUTE_CAP_SHIFT; | ||
209 | |||
210 | /* | ||
211 | * In PIC mode, skip IRQ0-4, IRQ6-9, IRQ12-15 which is always used by | ||
212 | * legacy device. In IO APIC mode, we skip all the legacy IRQS. | ||
213 | */ | ||
214 | if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) | ||
215 | v &= ~0xf3df; | ||
216 | else | ||
217 | v &= ~0xffff; | ||
218 | |||
219 | for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ; | ||
220 | irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) { | ||
221 | |||
222 | if (irq >= NR_IRQS) { | ||
223 | irq = HPET_MAX_IRQ; | ||
224 | break; | ||
225 | } | ||
226 | |||
227 | gsi = acpi_register_gsi(irq, ACPI_LEVEL_SENSITIVE, | ||
228 | ACPI_ACTIVE_LOW); | ||
229 | if (gsi > 0) | ||
230 | break; | ||
231 | |||
232 | /* FIXME: Setup interrupt source table */ | ||
233 | } | ||
234 | |||
235 | if (irq < HPET_MAX_IRQ) { | ||
236 | spin_lock_irq(&hpet_lock); | ||
237 | v = readl(&timer->hpet_config); | ||
238 | v |= irq << Tn_INT_ROUTE_CNF_SHIFT; | ||
239 | writel(v, &timer->hpet_config); | ||
240 | devp->hd_hdwirq = gsi; | ||
241 | spin_unlock_irq(&hpet_lock); | ||
242 | } | ||
243 | return; | ||
244 | } | ||
245 | |||
188 | static int hpet_open(struct inode *inode, struct file *file) | 246 | static int hpet_open(struct inode *inode, struct file *file) |
189 | { | 247 | { |
190 | struct hpet_dev *devp; | 248 | struct hpet_dev *devp; |
@@ -199,8 +257,7 @@ static int hpet_open(struct inode *inode, struct file *file) | |||
199 | 257 | ||
200 | for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) | 258 | for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next) |
201 | for (i = 0; i < hpetp->hp_ntimer; i++) | 259 | for (i = 0; i < hpetp->hp_ntimer; i++) |
202 | if (hpetp->hp_dev[i].hd_flags & HPET_OPEN | 260 | if (hpetp->hp_dev[i].hd_flags & HPET_OPEN) |
203 | || hpetp->hp_dev[i].hd_task) | ||
204 | continue; | 261 | continue; |
205 | else { | 262 | else { |
206 | devp = &hpetp->hp_dev[i]; | 263 | devp = &hpetp->hp_dev[i]; |
@@ -219,6 +276,8 @@ static int hpet_open(struct inode *inode, struct file *file) | |||
219 | spin_unlock_irq(&hpet_lock); | 276 | spin_unlock_irq(&hpet_lock); |
220 | unlock_kernel(); | 277 | unlock_kernel(); |
221 | 278 | ||
279 | hpet_timer_set_irq(devp); | ||
280 | |||
222 | return 0; | 281 | return 0; |
223 | } | 282 | } |
224 | 283 | ||
@@ -441,7 +500,11 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) | |||
441 | devp->hd_irq = irq; | 500 | devp->hd_irq = irq; |
442 | t = devp->hd_ireqfreq; | 501 | t = devp->hd_ireqfreq; |
443 | v = readq(&timer->hpet_config); | 502 | v = readq(&timer->hpet_config); |
444 | g = v | Tn_INT_ENB_CNF_MASK; | 503 | |
504 | /* 64-bit comparators are not yet supported through the ioctls, | ||
505 | * so force this into 32-bit mode if it supports both modes | ||
506 | */ | ||
507 | g = v | Tn_32MODE_CNF_MASK | Tn_INT_ENB_CNF_MASK; | ||
445 | 508 | ||
446 | if (devp->hd_flags & HPET_PERIODIC) { | 509 | if (devp->hd_flags & HPET_PERIODIC) { |
447 | write_counter(t, &timer->hpet_compare); | 510 | write_counter(t, &timer->hpet_compare); |
@@ -451,6 +514,12 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) | |||
451 | v |= Tn_VAL_SET_CNF_MASK; | 514 | v |= Tn_VAL_SET_CNF_MASK; |
452 | writeq(v, &timer->hpet_config); | 515 | writeq(v, &timer->hpet_config); |
453 | local_irq_save(flags); | 516 | local_irq_save(flags); |
517 | |||
518 | /* NOTE: what we modify here is a hidden accumulator | ||
519 | * register supported by periodic-capable comparators. | ||
520 | * We never want to modify the (single) counter; that | ||
521 | * would affect all the comparators. | ||
522 | */ | ||
454 | m = read_counter(&hpet->hpet_mc); | 523 | m = read_counter(&hpet->hpet_mc); |
455 | write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); | 524 | write_counter(t + m + hpetp->hp_delta, &timer->hpet_compare); |
456 | } else { | 525 | } else { |
@@ -604,57 +673,6 @@ static int hpet_is_known(struct hpet_data *hdp) | |||
604 | return 0; | 673 | return 0; |
605 | } | 674 | } |
606 | 675 | ||
607 | static inline int hpet_tpcheck(struct hpet_task *tp) | ||
608 | { | ||
609 | struct hpet_dev *devp; | ||
610 | struct hpets *hpetp; | ||
611 | |||
612 | devp = tp->ht_opaque; | ||
613 | |||
614 | if (!devp) | ||
615 | return -ENXIO; | ||
616 | |||
617 | for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) | ||
618 | if (devp >= hpetp->hp_dev | ||
619 | && devp < (hpetp->hp_dev + hpetp->hp_ntimer) | ||
620 | && devp->hd_hpet == hpetp->hp_hpet) | ||
621 | return 0; | ||
622 | |||
623 | return -ENXIO; | ||
624 | } | ||
625 | |||
626 | #if 0 | ||
627 | int hpet_unregister(struct hpet_task *tp) | ||
628 | { | ||
629 | struct hpet_dev *devp; | ||
630 | struct hpet_timer __iomem *timer; | ||
631 | int err; | ||
632 | |||
633 | if ((err = hpet_tpcheck(tp))) | ||
634 | return err; | ||
635 | |||
636 | spin_lock_irq(&hpet_task_lock); | ||
637 | spin_lock(&hpet_lock); | ||
638 | |||
639 | devp = tp->ht_opaque; | ||
640 | if (devp->hd_task != tp) { | ||
641 | spin_unlock(&hpet_lock); | ||
642 | spin_unlock_irq(&hpet_task_lock); | ||
643 | return -ENXIO; | ||
644 | } | ||
645 | |||
646 | timer = devp->hd_timer; | ||
647 | writeq((readq(&timer->hpet_config) & ~Tn_INT_ENB_CNF_MASK), | ||
648 | &timer->hpet_config); | ||
649 | devp->hd_flags &= ~(HPET_IE | HPET_PERIODIC); | ||
650 | devp->hd_task = NULL; | ||
651 | spin_unlock(&hpet_lock); | ||
652 | spin_unlock_irq(&hpet_task_lock); | ||
653 | |||
654 | return 0; | ||
655 | } | ||
656 | #endif /* 0 */ | ||
657 | |||
658 | static ctl_table hpet_table[] = { | 676 | static ctl_table hpet_table[] = { |
659 | { | 677 | { |
660 | .ctl_name = CTL_UNNUMBERED, | 678 | .ctl_name = CTL_UNNUMBERED, |
@@ -746,6 +764,7 @@ int hpet_alloc(struct hpet_data *hdp) | |||
746 | static struct hpets *last = NULL; | 764 | static struct hpets *last = NULL; |
747 | unsigned long period; | 765 | unsigned long period; |
748 | unsigned long long temp; | 766 | unsigned long long temp; |
767 | u32 remainder; | ||
749 | 768 | ||
750 | /* | 769 | /* |
751 | * hpet_alloc can be called by platform dependent code. | 770 | * hpet_alloc can be called by platform dependent code. |
@@ -809,9 +828,13 @@ int hpet_alloc(struct hpet_data *hdp) | |||
809 | printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); | 828 | printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); |
810 | printk("\n"); | 829 | printk("\n"); |
811 | 830 | ||
812 | printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n", | 831 | temp = hpetp->hp_tick_freq; |
813 | hpetp->hp_which, hpetp->hp_ntimer, | 832 | remainder = do_div(temp, 1000000); |
814 | cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, hpetp->hp_tick_freq); | 833 | printk(KERN_INFO |
834 | "hpet%u: %u comparators, %d-bit %u.%06u MHz counter\n", | ||
835 | hpetp->hp_which, hpetp->hp_ntimer, | ||
836 | cap & HPET_COUNTER_SIZE_MASK ? 64 : 32, | ||
837 | (unsigned) temp, remainder); | ||
815 | 838 | ||
816 | mcfg = readq(&hpet->hpet_config); | 839 | mcfg = readq(&hpet->hpet_config); |
817 | if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) { | 840 | if ((mcfg & HPET_ENABLE_CNF_MASK) == 0) { |
@@ -874,8 +897,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) | |||
874 | hdp->hd_address = ioremap(addr.minimum, addr.address_length); | 897 | hdp->hd_address = ioremap(addr.minimum, addr.address_length); |
875 | 898 | ||
876 | if (hpet_is_known(hdp)) { | 899 | if (hpet_is_known(hdp)) { |
877 | printk(KERN_DEBUG "%s: 0x%lx is busy\n", | ||
878 | __func__, hdp->hd_phys_address); | ||
879 | iounmap(hdp->hd_address); | 900 | iounmap(hdp->hd_address); |
880 | return AE_ALREADY_EXISTS; | 901 | return AE_ALREADY_EXISTS; |
881 | } | 902 | } |
@@ -891,8 +912,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) | |||
891 | HPET_RANGE_SIZE); | 912 | HPET_RANGE_SIZE); |
892 | 913 | ||
893 | if (hpet_is_known(hdp)) { | 914 | if (hpet_is_known(hdp)) { |
894 | printk(KERN_DEBUG "%s: 0x%lx is busy\n", | ||
895 | __func__, hdp->hd_phys_address); | ||
896 | iounmap(hdp->hd_address); | 915 | iounmap(hdp->hd_address); |
897 | return AE_ALREADY_EXISTS; | 916 | return AE_ALREADY_EXISTS; |
898 | } | 917 | } |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index fd64137b1ab9..ec7aded0a2df 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -819,11 +819,11 @@ static int hvc_init(void) | |||
819 | hvc_driver = drv; | 819 | hvc_driver = drv; |
820 | return 0; | 820 | return 0; |
821 | 821 | ||
822 | put_tty: | ||
823 | put_tty_driver(hvc_driver); | ||
824 | stop_thread: | 822 | stop_thread: |
825 | kthread_stop(hvc_task); | 823 | kthread_stop(hvc_task); |
826 | hvc_task = NULL; | 824 | hvc_task = NULL; |
825 | put_tty: | ||
826 | put_tty_driver(drv); | ||
827 | out: | 827 | out: |
828 | return err; | 828 | return err; |
829 | } | 829 | } |
diff --git a/drivers/char/ip2/Makefile b/drivers/char/ip2/Makefile index 939618f62fe1..bc397d92b499 100644 --- a/drivers/char/ip2/Makefile +++ b/drivers/char/ip2/Makefile | |||
@@ -4,5 +4,5 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_COMPUTONE) += ip2.o | 5 | obj-$(CONFIG_COMPUTONE) += ip2.o |
6 | 6 | ||
7 | ip2-objs := ip2base.o ip2main.o | 7 | ip2-objs := ip2main.o |
8 | 8 | ||
diff --git a/drivers/char/ip2/i2ellis.c b/drivers/char/ip2/i2ellis.c index 3601017f58cf..29db44de399f 100644 --- a/drivers/char/ip2/i2ellis.c +++ b/drivers/char/ip2/i2ellis.c | |||
@@ -69,38 +69,6 @@ static DEFINE_RWLOCK(Dl_spinlock); | |||
69 | //======================================================= | 69 | //======================================================= |
70 | 70 | ||
71 | //****************************************************************************** | 71 | //****************************************************************************** |
72 | // Function: iiEllisInit() | ||
73 | // Parameters: None | ||
74 | // | ||
75 | // Returns: Nothing | ||
76 | // | ||
77 | // Description: | ||
78 | // | ||
79 | // This routine performs any required initialization of the iiEllis subsystem. | ||
80 | // | ||
81 | //****************************************************************************** | ||
82 | static void | ||
83 | iiEllisInit(void) | ||
84 | { | ||
85 | } | ||
86 | |||
87 | //****************************************************************************** | ||
88 | // Function: iiEllisCleanup() | ||
89 | // Parameters: None | ||
90 | // | ||
91 | // Returns: Nothing | ||
92 | // | ||
93 | // Description: | ||
94 | // | ||
95 | // This routine performs any required cleanup of the iiEllis subsystem. | ||
96 | // | ||
97 | //****************************************************************************** | ||
98 | static void | ||
99 | iiEllisCleanup(void) | ||
100 | { | ||
101 | } | ||
102 | |||
103 | //****************************************************************************** | ||
104 | // Function: iiSetAddress(pB, address, delay) | 72 | // Function: iiSetAddress(pB, address, delay) |
105 | // Parameters: pB - pointer to the board structure | 73 | // Parameters: pB - pointer to the board structure |
106 | // address - the purported I/O address of the board | 74 | // address - the purported I/O address of the board |
diff --git a/drivers/char/ip2/i2ellis.h b/drivers/char/ip2/i2ellis.h index c88a64e527aa..fb6df2456018 100644 --- a/drivers/char/ip2/i2ellis.h +++ b/drivers/char/ip2/i2ellis.h | |||
@@ -511,7 +511,6 @@ typedef void (*delayFunc_t)(unsigned int); | |||
511 | // | 511 | // |
512 | // Initialization of a board & structure is in four (five!) parts: | 512 | // Initialization of a board & structure is in four (five!) parts: |
513 | // | 513 | // |
514 | // 0) iiEllisInit() - Initialize iiEllis subsystem. | ||
515 | // 1) iiSetAddress() - Define the board address & delay function for a board. | 514 | // 1) iiSetAddress() - Define the board address & delay function for a board. |
516 | // 2) iiReset() - Reset the board (provided it exists) | 515 | // 2) iiReset() - Reset the board (provided it exists) |
517 | // -- Note you may do this to several boards -- | 516 | // -- Note you may do this to several boards -- |
@@ -523,7 +522,6 @@ typedef void (*delayFunc_t)(unsigned int); | |||
523 | // loadware. To change loadware, you must begin again with step 2, resetting | 522 | // loadware. To change loadware, you must begin again with step 2, resetting |
524 | // the board again (step 1 not needed). | 523 | // the board again (step 1 not needed). |
525 | 524 | ||
526 | static void iiEllisInit(void); | ||
527 | static int iiSetAddress(i2eBordStrPtr, int, delayFunc_t ); | 525 | static int iiSetAddress(i2eBordStrPtr, int, delayFunc_t ); |
528 | static int iiReset(i2eBordStrPtr); | 526 | static int iiReset(i2eBordStrPtr); |
529 | static int iiResetDelay(i2eBordStrPtr); | 527 | static int iiResetDelay(i2eBordStrPtr); |
diff --git a/drivers/char/ip2/ip2base.c b/drivers/char/ip2/ip2base.c deleted file mode 100644 index 8155e247c04b..000000000000 --- a/drivers/char/ip2/ip2base.c +++ /dev/null | |||
@@ -1,108 +0,0 @@ | |||
1 | // ip2.c | ||
2 | // This is a dummy module to make the firmware available when needed | ||
3 | // and allows it to be unloaded when not. Rumor is the __initdata | ||
4 | // macro doesn't always works on all platforms so we use this kludge. | ||
5 | // If not compiled as a module it just makes fip_firm avaliable then | ||
6 | // __initdata should work as advertized | ||
7 | // | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/wait.h> | ||
12 | |||
13 | #ifndef __init | ||
14 | #define __init | ||
15 | #endif | ||
16 | #ifndef __initfunc | ||
17 | #define __initfunc(a) a | ||
18 | #endif | ||
19 | #ifndef __initdata | ||
20 | #define __initdata | ||
21 | #endif | ||
22 | |||
23 | #include "ip2types.h" | ||
24 | |||
25 | int | ||
26 | ip2_loadmain(int *, int *); // ref into ip2main.c | ||
27 | |||
28 | /* Note: Add compiled in defaults to these arrays, not to the structure | ||
29 | in ip2.h any longer. That structure WILL get overridden | ||
30 | by these values, or command line values, or insmod values!!! =mhw= | ||
31 | */ | ||
32 | static int io[IP2_MAX_BOARDS]= { 0, 0, 0, 0 }; | ||
33 | static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 }; | ||
34 | |||
35 | static int poll_only = 0; | ||
36 | |||
37 | MODULE_AUTHOR("Doug McNash"); | ||
38 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); | ||
39 | module_param_array(irq, int, NULL, 0); | ||
40 | MODULE_PARM_DESC(irq,"Interrupts for IntelliPort Cards"); | ||
41 | module_param_array(io, int, NULL, 0); | ||
42 | MODULE_PARM_DESC(io,"I/O ports for IntelliPort Cards"); | ||
43 | module_param(poll_only, bool, 0); | ||
44 | MODULE_PARM_DESC(poll_only,"Do not use card interrupts"); | ||
45 | |||
46 | |||
47 | static int __init ip2_init(void) | ||
48 | { | ||
49 | if( poll_only ) { | ||
50 | /* Hard lock the interrupts to zero */ | ||
51 | irq[0] = irq[1] = irq[2] = irq[3] = 0; | ||
52 | } | ||
53 | |||
54 | return ip2_loadmain(io, irq); | ||
55 | } | ||
56 | module_init(ip2_init); | ||
57 | |||
58 | MODULE_LICENSE("GPL"); | ||
59 | |||
60 | #ifndef MODULE | ||
61 | /****************************************************************************** | ||
62 | * ip2_setup: | ||
63 | * str: kernel command line string | ||
64 | * | ||
65 | * Can't autoprobe the boards so user must specify configuration on | ||
66 | * kernel command line. Sane people build it modular but the others | ||
67 | * come here. | ||
68 | * | ||
69 | * Alternating pairs of io,irq for up to 4 boards. | ||
70 | * ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3 | ||
71 | * | ||
72 | * io=0 => No board | ||
73 | * io=1 => PCI | ||
74 | * io=2 => EISA | ||
75 | * else => ISA I/O address | ||
76 | * | ||
77 | * irq=0 or invalid for ISA will revert to polling mode | ||
78 | * | ||
79 | * Any value = -1, do not overwrite compiled in value. | ||
80 | * | ||
81 | ******************************************************************************/ | ||
82 | static int __init ip2_setup(char *str) | ||
83 | { | ||
84 | int ints[10]; /* 4 boards, 2 parameters + 2 */ | ||
85 | int i, j; | ||
86 | |||
87 | str = get_options (str, ARRAY_SIZE(ints), ints); | ||
88 | |||
89 | for( i = 0, j = 1; i < 4; i++ ) { | ||
90 | if( j > ints[0] ) { | ||
91 | break; | ||
92 | } | ||
93 | if( ints[j] >= 0 ) { | ||
94 | io[i] = ints[j]; | ||
95 | } | ||
96 | j++; | ||
97 | if( j > ints[0] ) { | ||
98 | break; | ||
99 | } | ||
100 | if( ints[j] >= 0 ) { | ||
101 | irq[i] = ints[j]; | ||
102 | } | ||
103 | j++; | ||
104 | } | ||
105 | return 1; | ||
106 | } | ||
107 | __setup("ip2=", ip2_setup); | ||
108 | #endif /* !MODULE */ | ||
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 689f9dcd3b86..6774572d3759 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -150,15 +150,12 @@ static int ip2_read_proc(char *, char **, off_t, int, int *, void * ); | |||
150 | /*************/ | 150 | /*************/ |
151 | 151 | ||
152 | /* String constants to identify ourselves */ | 152 | /* String constants to identify ourselves */ |
153 | static char *pcName = "Computone IntelliPort Plus multiport driver"; | 153 | static const char pcName[] = "Computone IntelliPort Plus multiport driver"; |
154 | static char *pcVersion = "1.2.14"; | 154 | static const char pcVersion[] = "1.2.14"; |
155 | 155 | ||
156 | /* String constants for port names */ | 156 | /* String constants for port names */ |
157 | static char *pcDriver_name = "ip2"; | 157 | static const char pcDriver_name[] = "ip2"; |
158 | static char *pcIpl = "ip2ipl"; | 158 | static const char pcIpl[] = "ip2ipl"; |
159 | |||
160 | // cheezy kludge or genius - you decide? | ||
161 | int ip2_loadmain(int *, int *); | ||
162 | 159 | ||
163 | /***********************/ | 160 | /***********************/ |
164 | /* Function Prototypes */ | 161 | /* Function Prototypes */ |
@@ -240,8 +237,8 @@ static const struct file_operations ip2_ipl = { | |||
240 | .open = ip2_ipl_open, | 237 | .open = ip2_ipl_open, |
241 | }; | 238 | }; |
242 | 239 | ||
243 | static unsigned long irq_counter = 0; | 240 | static unsigned long irq_counter; |
244 | static unsigned long bh_counter = 0; | 241 | static unsigned long bh_counter; |
245 | 242 | ||
246 | // Use immediate queue to service interrupts | 243 | // Use immediate queue to service interrupts |
247 | #define USE_IQI | 244 | #define USE_IQI |
@@ -252,7 +249,6 @@ static unsigned long bh_counter = 0; | |||
252 | */ | 249 | */ |
253 | #define POLL_TIMEOUT (jiffies + 1) | 250 | #define POLL_TIMEOUT (jiffies + 1) |
254 | static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0); | 251 | static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0); |
255 | static char TimerOn; | ||
256 | 252 | ||
257 | #ifdef IP2DEBUG_TRACE | 253 | #ifdef IP2DEBUG_TRACE |
258 | /* Trace (debug) buffer data */ | 254 | /* Trace (debug) buffer data */ |
@@ -268,8 +264,8 @@ static int tracewrap; | |||
268 | /**********/ | 264 | /**********/ |
269 | 265 | ||
270 | #if defined(MODULE) && defined(IP2DEBUG_OPEN) | 266 | #if defined(MODULE) && defined(IP2DEBUG_OPEN) |
271 | #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] refc=%d, ttyc=%d, modc=%x -> %s\n", \ | 267 | #define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \ |
272 | tty->name,(pCh->flags),ip2_tty_driver->refcount, \ | 268 | tty->name,(pCh->flags), \ |
273 | tty->count,/*GET_USE_COUNT(module)*/0,s) | 269 | tty->count,/*GET_USE_COUNT(module)*/0,s) |
274 | #else | 270 | #else |
275 | #define DBG_CNT(s) | 271 | #define DBG_CNT(s) |
@@ -287,8 +283,9 @@ static int tracewrap; | |||
287 | 283 | ||
288 | MODULE_AUTHOR("Doug McNash"); | 284 | MODULE_AUTHOR("Doug McNash"); |
289 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); | 285 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); |
286 | MODULE_LICENSE("GPL"); | ||
290 | 287 | ||
291 | static int poll_only = 0; | 288 | static int poll_only; |
292 | 289 | ||
293 | static int Eisa_irq; | 290 | static int Eisa_irq; |
294 | static int Eisa_slot; | 291 | static int Eisa_slot; |
@@ -297,34 +294,46 @@ static int iindx; | |||
297 | static char rirqs[IP2_MAX_BOARDS]; | 294 | static char rirqs[IP2_MAX_BOARDS]; |
298 | static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0}; | 295 | static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0}; |
299 | 296 | ||
297 | /* Note: Add compiled in defaults to these arrays, not to the structure | ||
298 | in ip2.h any longer. That structure WILL get overridden | ||
299 | by these values, or command line values, or insmod values!!! =mhw= | ||
300 | */ | ||
301 | static int io[IP2_MAX_BOARDS]; | ||
302 | static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 }; | ||
303 | |||
304 | MODULE_AUTHOR("Doug McNash"); | ||
305 | MODULE_DESCRIPTION("Computone IntelliPort Plus Driver"); | ||
306 | module_param_array(irq, int, NULL, 0); | ||
307 | MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards"); | ||
308 | module_param_array(io, int, NULL, 0); | ||
309 | MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards"); | ||
310 | module_param(poll_only, bool, 0); | ||
311 | MODULE_PARM_DESC(poll_only, "Do not use card interrupts"); | ||
312 | |||
300 | /* for sysfs class support */ | 313 | /* for sysfs class support */ |
301 | static struct class *ip2_class; | 314 | static struct class *ip2_class; |
302 | 315 | ||
303 | // Some functions to keep track of what irq's we have | 316 | /* Some functions to keep track of what irqs we have */ |
304 | 317 | ||
305 | static int | 318 | static int __init is_valid_irq(int irq) |
306 | is_valid_irq(int irq) | ||
307 | { | 319 | { |
308 | int *i = Valid_Irqs; | 320 | int *i = Valid_Irqs; |
309 | 321 | ||
310 | while ((*i != 0) && (*i != irq)) { | 322 | while (*i != 0 && *i != irq) |
311 | i++; | 323 | i++; |
312 | } | 324 | |
313 | return (*i); | 325 | return *i; |
314 | } | 326 | } |
315 | 327 | ||
316 | static void | 328 | static void __init mark_requested_irq(char irq) |
317 | mark_requested_irq( char irq ) | ||
318 | { | 329 | { |
319 | rirqs[iindx++] = irq; | 330 | rirqs[iindx++] = irq; |
320 | } | 331 | } |
321 | 332 | ||
322 | #ifdef MODULE | 333 | static int __exit clear_requested_irq(char irq) |
323 | static int | ||
324 | clear_requested_irq( char irq ) | ||
325 | { | 334 | { |
326 | int i; | 335 | int i; |
327 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 336 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
328 | if (rirqs[i] == irq) { | 337 | if (rirqs[i] == irq) { |
329 | rirqs[i] = 0; | 338 | rirqs[i] = 0; |
330 | return 1; | 339 | return 1; |
@@ -332,17 +341,15 @@ clear_requested_irq( char irq ) | |||
332 | } | 341 | } |
333 | return 0; | 342 | return 0; |
334 | } | 343 | } |
335 | #endif | ||
336 | 344 | ||
337 | static int | 345 | static int have_requested_irq(char irq) |
338 | have_requested_irq( char irq ) | ||
339 | { | 346 | { |
340 | // array init to zeros so 0 irq will not be requested as a side effect | 347 | /* array init to zeros so 0 irq will not be requested as a side |
348 | * effect */ | ||
341 | int i; | 349 | int i; |
342 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 350 | for (i = 0; i < IP2_MAX_BOARDS; ++i) |
343 | if (rirqs[i] == irq) | 351 | if (rirqs[i] == irq) |
344 | return 1; | 352 | return 1; |
345 | } | ||
346 | return 0; | 353 | return 0; |
347 | } | 354 | } |
348 | 355 | ||
@@ -361,53 +368,45 @@ have_requested_irq( char irq ) | |||
361 | /* handle subsequent installations of the driver. All memory allocated by the */ | 368 | /* handle subsequent installations of the driver. All memory allocated by the */ |
362 | /* driver should be returned since it may be unloaded from memory. */ | 369 | /* driver should be returned since it may be unloaded from memory. */ |
363 | /******************************************************************************/ | 370 | /******************************************************************************/ |
364 | #ifdef MODULE | 371 | static void __exit ip2_cleanup_module(void) |
365 | void __exit | ||
366 | ip2_cleanup_module(void) | ||
367 | { | 372 | { |
368 | int err; | 373 | int err; |
369 | int i; | 374 | int i; |
370 | 375 | ||
371 | #ifdef IP2DEBUG_INIT | 376 | del_timer_sync(&PollTimer); |
372 | printk (KERN_DEBUG "Unloading %s: version %s\n", pcName, pcVersion ); | ||
373 | #endif | ||
374 | /* Stop poll timer if we had one. */ | ||
375 | if ( TimerOn ) { | ||
376 | del_timer ( &PollTimer ); | ||
377 | TimerOn = 0; | ||
378 | } | ||
379 | 377 | ||
380 | /* Reset the boards we have. */ | 378 | /* Reset the boards we have. */ |
381 | for( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 379 | for (i = 0; i < IP2_MAX_BOARDS; i++) |
382 | if ( i2BoardPtrTable[i] ) { | 380 | if (i2BoardPtrTable[i]) |
383 | iiReset( i2BoardPtrTable[i] ); | 381 | iiReset(i2BoardPtrTable[i]); |
384 | } | ||
385 | } | ||
386 | 382 | ||
387 | /* The following is done at most once, if any boards were installed. */ | 383 | /* The following is done at most once, if any boards were installed. */ |
388 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 384 | for (i = 0; i < IP2_MAX_BOARDS; i++) { |
389 | if ( i2BoardPtrTable[i] ) { | 385 | if (i2BoardPtrTable[i]) { |
390 | iiResetDelay( i2BoardPtrTable[i] ); | 386 | iiResetDelay(i2BoardPtrTable[i]); |
391 | /* free io addresses and Tibet */ | 387 | /* free io addresses and Tibet */ |
392 | release_region( ip2config.addr[i], 8 ); | 388 | release_region(ip2config.addr[i], 8); |
393 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); | 389 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i)); |
394 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1)); | 390 | device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, |
391 | 4 * i + 1)); | ||
395 | } | 392 | } |
396 | /* Disable and remove interrupt handler. */ | 393 | /* Disable and remove interrupt handler. */ |
397 | if ( (ip2config.irq[i] > 0) && have_requested_irq(ip2config.irq[i]) ) { | 394 | if (ip2config.irq[i] > 0 && |
398 | free_irq ( ip2config.irq[i], (void *)&pcName); | 395 | have_requested_irq(ip2config.irq[i])) { |
399 | clear_requested_irq( ip2config.irq[i]); | 396 | free_irq(ip2config.irq[i], (void *)&pcName); |
397 | clear_requested_irq(ip2config.irq[i]); | ||
400 | } | 398 | } |
401 | } | 399 | } |
402 | class_destroy(ip2_class); | 400 | class_destroy(ip2_class); |
403 | if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) { | 401 | err = tty_unregister_driver(ip2_tty_driver); |
404 | printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err); | 402 | if (err) |
405 | } | 403 | printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", |
404 | err); | ||
406 | put_tty_driver(ip2_tty_driver); | 405 | put_tty_driver(ip2_tty_driver); |
407 | unregister_chrdev(IP2_IPL_MAJOR, pcIpl); | 406 | unregister_chrdev(IP2_IPL_MAJOR, pcIpl); |
408 | remove_proc_entry("ip2mem", NULL); | 407 | remove_proc_entry("ip2mem", NULL); |
409 | 408 | ||
410 | // free memory | 409 | /* free memory */ |
411 | for (i = 0; i < IP2_MAX_BOARDS; i++) { | 410 | for (i = 0; i < IP2_MAX_BOARDS; i++) { |
412 | void *pB; | 411 | void *pB; |
413 | #ifdef CONFIG_PCI | 412 | #ifdef CONFIG_PCI |
@@ -417,24 +416,18 @@ ip2_cleanup_module(void) | |||
417 | ip2config.pci_dev[i] = NULL; | 416 | ip2config.pci_dev[i] = NULL; |
418 | } | 417 | } |
419 | #endif | 418 | #endif |
420 | if ((pB = i2BoardPtrTable[i]) != 0 ) { | 419 | pB = i2BoardPtrTable[i]; |
421 | kfree ( pB ); | 420 | if (pB != NULL) { |
421 | kfree(pB); | ||
422 | i2BoardPtrTable[i] = NULL; | 422 | i2BoardPtrTable[i] = NULL; |
423 | } | 423 | } |
424 | if ((DevTableMem[i]) != NULL ) { | 424 | if (DevTableMem[i] != NULL) { |
425 | kfree ( DevTableMem[i] ); | 425 | kfree(DevTableMem[i]); |
426 | DevTableMem[i] = NULL; | 426 | DevTableMem[i] = NULL; |
427 | } | 427 | } |
428 | } | 428 | } |
429 | |||
430 | /* Cleanup the iiEllis subsystem. */ | ||
431 | iiEllisCleanup(); | ||
432 | #ifdef IP2DEBUG_INIT | ||
433 | printk (KERN_DEBUG "IP2 Unloaded\n" ); | ||
434 | #endif | ||
435 | } | 429 | } |
436 | module_exit(ip2_cleanup_module); | 430 | module_exit(ip2_cleanup_module); |
437 | #endif /* MODULE */ | ||
438 | 431 | ||
439 | static const struct tty_operations ip2_ops = { | 432 | static const struct tty_operations ip2_ops = { |
440 | .open = ip2_open, | 433 | .open = ip2_open, |
@@ -494,139 +487,168 @@ static const struct firmware *ip2_request_firmware(void) | |||
494 | return fw; | 487 | return fw; |
495 | } | 488 | } |
496 | 489 | ||
497 | int | 490 | #ifndef MODULE |
498 | ip2_loadmain(int *iop, int *irqp) | 491 | /****************************************************************************** |
492 | * ip2_setup: | ||
493 | * str: kernel command line string | ||
494 | * | ||
495 | * Can't autoprobe the boards so user must specify configuration on | ||
496 | * kernel command line. Sane people build it modular but the others | ||
497 | * come here. | ||
498 | * | ||
499 | * Alternating pairs of io,irq for up to 4 boards. | ||
500 | * ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3 | ||
501 | * | ||
502 | * io=0 => No board | ||
503 | * io=1 => PCI | ||
504 | * io=2 => EISA | ||
505 | * else => ISA I/O address | ||
506 | * | ||
507 | * irq=0 or invalid for ISA will revert to polling mode | ||
508 | * | ||
509 | * Any value = -1, do not overwrite compiled in value. | ||
510 | * | ||
511 | ******************************************************************************/ | ||
512 | static int __init ip2_setup(char *str) | ||
513 | { | ||
514 | int j, ints[10]; /* 4 boards, 2 parameters + 2 */ | ||
515 | unsigned int i; | ||
516 | |||
517 | str = get_options(str, ARRAY_SIZE(ints), ints); | ||
518 | |||
519 | for (i = 0, j = 1; i < 4; i++) { | ||
520 | if (j > ints[0]) | ||
521 | break; | ||
522 | if (ints[j] >= 0) | ||
523 | io[i] = ints[j]; | ||
524 | j++; | ||
525 | if (j > ints[0]) | ||
526 | break; | ||
527 | if (ints[j] >= 0) | ||
528 | irq[i] = ints[j]; | ||
529 | j++; | ||
530 | } | ||
531 | return 1; | ||
532 | } | ||
533 | __setup("ip2=", ip2_setup); | ||
534 | #endif /* !MODULE */ | ||
535 | |||
536 | static int __init ip2_loadmain(void) | ||
499 | { | 537 | { |
500 | int i, j, box; | 538 | int i, j, box; |
501 | int err = 0; | 539 | int err = 0; |
502 | static int loaded; | ||
503 | i2eBordStrPtr pB = NULL; | 540 | i2eBordStrPtr pB = NULL; |
504 | int rc = -1; | 541 | int rc = -1; |
505 | static struct pci_dev *pci_dev_i = NULL; | 542 | struct pci_dev *pdev = NULL; |
506 | const struct firmware *fw = NULL; | 543 | const struct firmware *fw = NULL; |
507 | 544 | ||
508 | ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0 ); | 545 | if (poll_only) { |
546 | /* Hard lock the interrupts to zero */ | ||
547 | irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0; | ||
548 | } | ||
549 | |||
550 | ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0); | ||
509 | 551 | ||
510 | /* process command line arguments to modprobe or | 552 | /* process command line arguments to modprobe or |
511 | insmod i.e. iop & irqp */ | 553 | insmod i.e. iop & irqp */ |
512 | /* irqp and iop should ALWAYS be specified now... But we check | 554 | /* irqp and iop should ALWAYS be specified now... But we check |
513 | them individually just to be sure, anyways... */ | 555 | them individually just to be sure, anyways... */ |
514 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 556 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
515 | if (iop) { | 557 | ip2config.addr[i] = io[i]; |
516 | ip2config.addr[i] = iop[i]; | 558 | if (irq[i] >= 0) |
517 | if (irqp) { | 559 | ip2config.irq[i] = irq[i]; |
518 | if( irqp[i] >= 0 ) { | 560 | else |
519 | ip2config.irq[i] = irqp[i]; | 561 | ip2config.irq[i] = 0; |
520 | } else { | 562 | /* This is a little bit of a hack. If poll_only=1 on command |
521 | ip2config.irq[i] = 0; | 563 | line back in ip2.c OR all IRQs on all specified boards are |
522 | } | 564 | explicitly set to 0, then drop to poll only mode and override |
523 | // This is a little bit of a hack. If poll_only=1 on command | 565 | PCI or EISA interrupts. This superceeds the old hack of |
524 | // line back in ip2.c OR all IRQs on all specified boards are | 566 | triggering if all interrupts were zero (like da default). |
525 | // explicitly set to 0, then drop to poll only mode and override | 567 | Still a hack but less prone to random acts of terrorism. |
526 | // PCI or EISA interrupts. This superceeds the old hack of | 568 | |
527 | // triggering if all interrupts were zero (like da default). | 569 | What we really should do, now that the IRQ default is set |
528 | // Still a hack but less prone to random acts of terrorism. | 570 | to -1, is to use 0 as a hard coded, do not probe. |
529 | // | 571 | |
530 | // What we really should do, now that the IRQ default is set | 572 | /\/\|=mhw=|\/\/ |
531 | // to -1, is to use 0 as a hard coded, do not probe. | 573 | */ |
532 | // | 574 | poll_only |= irq[i]; |
533 | // /\/\|=mhw=|\/\/ | ||
534 | poll_only |= irqp[i]; | ||
535 | } | ||
536 | } | ||
537 | } | 575 | } |
538 | poll_only = !poll_only; | 576 | poll_only = !poll_only; |
539 | 577 | ||
540 | /* Announce our presence */ | 578 | /* Announce our presence */ |
541 | printk( KERN_INFO "%s version %s\n", pcName, pcVersion ); | 579 | printk(KERN_INFO "%s version %s\n", pcName, pcVersion); |
542 | |||
543 | // ip2 can be unloaded and reloaded for no good reason | ||
544 | // we can't let that happen here or bad things happen | ||
545 | // second load hoses board but not system - fixme later | ||
546 | if (loaded) { | ||
547 | printk( KERN_INFO "Still loaded\n" ); | ||
548 | return 0; | ||
549 | } | ||
550 | loaded++; | ||
551 | 580 | ||
552 | ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS); | 581 | ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS); |
553 | if (!ip2_tty_driver) | 582 | if (!ip2_tty_driver) |
554 | return -ENOMEM; | 583 | return -ENOMEM; |
555 | 584 | ||
556 | /* Initialise the iiEllis subsystem. */ | ||
557 | iiEllisInit(); | ||
558 | |||
559 | /* Initialize arrays. */ | ||
560 | memset( i2BoardPtrTable, 0, sizeof i2BoardPtrTable ); | ||
561 | memset( DevTable, 0, sizeof DevTable ); | ||
562 | |||
563 | /* Initialise all the boards we can find (up to the maximum). */ | 585 | /* Initialise all the boards we can find (up to the maximum). */ |
564 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 586 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
565 | switch ( ip2config.addr[i] ) { | 587 | switch (ip2config.addr[i]) { |
566 | case 0: /* skip this slot even if card is present */ | 588 | case 0: /* skip this slot even if card is present */ |
567 | break; | 589 | break; |
568 | default: /* ISA */ | 590 | default: /* ISA */ |
569 | /* ISA address must be specified */ | 591 | /* ISA address must be specified */ |
570 | if ( (ip2config.addr[i] < 0x100) || (ip2config.addr[i] > 0x3f8) ) { | 592 | if (ip2config.addr[i] < 0x100 || |
571 | printk ( KERN_ERR "IP2: Bad ISA board %d address %x\n", | 593 | ip2config.addr[i] > 0x3f8) { |
572 | i, ip2config.addr[i] ); | 594 | printk(KERN_ERR "IP2: Bad ISA board %d " |
595 | "address %x\n", i, | ||
596 | ip2config.addr[i]); | ||
573 | ip2config.addr[i] = 0; | 597 | ip2config.addr[i] = 0; |
574 | } else { | 598 | break; |
575 | ip2config.type[i] = ISA; | 599 | } |
576 | 600 | ip2config.type[i] = ISA; | |
577 | /* Check for valid irq argument, set for polling if invalid */ | 601 | |
578 | if (ip2config.irq[i] && !is_valid_irq(ip2config.irq[i])) { | 602 | /* Check for valid irq argument, set for polling if |
579 | printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",ip2config.irq[i]); | 603 | * invalid */ |
580 | ip2config.irq[i] = 0;// 0 is polling and is valid in that sense | 604 | if (ip2config.irq[i] && |
581 | } | 605 | !is_valid_irq(ip2config.irq[i])) { |
606 | printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n", | ||
607 | ip2config.irq[i]); | ||
608 | /* 0 is polling and is valid in that sense */ | ||
609 | ip2config.irq[i] = 0; | ||
582 | } | 610 | } |
583 | break; | 611 | break; |
584 | case PCI: | 612 | case PCI: |
585 | #ifdef CONFIG_PCI | 613 | #ifdef CONFIG_PCI |
586 | { | 614 | { |
587 | int status; | 615 | u32 addr; |
616 | int status; | ||
588 | 617 | ||
589 | pci_dev_i = pci_get_device(PCI_VENDOR_ID_COMPUTONE, | 618 | pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE, |
590 | PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i); | 619 | PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev); |
591 | if (pci_dev_i != NULL) { | 620 | if (pdev == NULL) { |
592 | unsigned int addr; | 621 | ip2config.addr[i] = 0; |
593 | 622 | printk(KERN_ERR "IP2: PCI board %d not " | |
594 | if (pci_enable_device(pci_dev_i)) { | 623 | "found\n", i); |
595 | printk( KERN_ERR "IP2: can't enable PCI device at %s\n", | 624 | break; |
596 | pci_name(pci_dev_i)); | 625 | } |
597 | break; | ||
598 | } | ||
599 | ip2config.type[i] = PCI; | ||
600 | ip2config.pci_dev[i] = pci_dev_get(pci_dev_i); | ||
601 | status = | ||
602 | pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr); | ||
603 | if ( addr & 1 ) { | ||
604 | ip2config.addr[i]=(USHORT)(addr&0xfffe); | ||
605 | } else { | ||
606 | printk( KERN_ERR "IP2: PCI I/O address error\n"); | ||
607 | } | ||
608 | 626 | ||
609 | // If the PCI BIOS assigned it, lets try and use it. If we | 627 | if (pci_enable_device(pdev)) { |
610 | // can't acquire it or it screws up, deal with it then. | 628 | dev_err(&pdev->dev, "can't enable device\n"); |
611 | 629 | break; | |
612 | // if (!is_valid_irq(pci_irq)) { | ||
613 | // printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq); | ||
614 | // pci_irq = 0; | ||
615 | // } | ||
616 | ip2config.irq[i] = pci_dev_i->irq; | ||
617 | } else { // ann error | ||
618 | ip2config.addr[i] = 0; | ||
619 | printk(KERN_ERR "IP2: PCI board %d not found\n", i); | ||
620 | } | ||
621 | } | 630 | } |
631 | ip2config.type[i] = PCI; | ||
632 | ip2config.pci_dev[i] = pci_dev_get(pdev); | ||
633 | status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1, | ||
634 | &addr); | ||
635 | if (addr & 1) | ||
636 | ip2config.addr[i] = (USHORT)(addr & 0xfffe); | ||
637 | else | ||
638 | dev_err(&pdev->dev, "I/O address error\n"); | ||
639 | |||
640 | ip2config.irq[i] = pdev->irq; | ||
641 | } | ||
622 | #else | 642 | #else |
623 | printk( KERN_ERR "IP2: PCI card specified but PCI support not\n"); | 643 | printk(KERN_ERR "IP2: PCI card specified but PCI " |
624 | printk( KERN_ERR "IP2: configured in this kernel.\n"); | 644 | "support not enabled.\n"); |
625 | printk( KERN_ERR "IP2: Recompile kernel with CONFIG_PCI defined!\n"); | 645 | printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI " |
646 | "defined!\n"); | ||
626 | #endif /* CONFIG_PCI */ | 647 | #endif /* CONFIG_PCI */ |
627 | break; | 648 | break; |
628 | case EISA: | 649 | case EISA: |
629 | if ( (ip2config.addr[i] = find_eisa_board( Eisa_slot + 1 )) != 0) { | 650 | ip2config.addr[i] = find_eisa_board(Eisa_slot + 1); |
651 | if (ip2config.addr[i] != 0) { | ||
630 | /* Eisa_irq set as side effect, boo */ | 652 | /* Eisa_irq set as side effect, boo */ |
631 | ip2config.type[i] = EISA; | 653 | ip2config.type[i] = EISA; |
632 | } | 654 | } |
@@ -634,31 +656,32 @@ ip2_loadmain(int *iop, int *irqp) | |||
634 | break; | 656 | break; |
635 | } /* switch */ | 657 | } /* switch */ |
636 | } /* for */ | 658 | } /* for */ |
637 | if (pci_dev_i) | 659 | pci_dev_put(pdev); |
638 | pci_dev_put(pci_dev_i); | ||
639 | 660 | ||
640 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 661 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
641 | if ( ip2config.addr[i] ) { | 662 | if (ip2config.addr[i]) { |
642 | pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL); | 663 | pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL); |
643 | if (pB) { | 664 | if (pB) { |
644 | i2BoardPtrTable[i] = pB; | 665 | i2BoardPtrTable[i] = pB; |
645 | iiSetAddress( pB, ip2config.addr[i], ii2DelayTimer ); | 666 | iiSetAddress(pB, ip2config.addr[i], |
646 | iiReset( pB ); | 667 | ii2DelayTimer); |
647 | } else { | 668 | iiReset(pB); |
648 | printk(KERN_ERR "IP2: board memory allocation error\n"); | 669 | } else |
649 | } | 670 | printk(KERN_ERR "IP2: board memory allocation " |
671 | "error\n"); | ||
650 | } | 672 | } |
651 | } | 673 | } |
652 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 674 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
653 | if ( ( pB = i2BoardPtrTable[i] ) != NULL ) { | 675 | pB = i2BoardPtrTable[i]; |
654 | iiResetDelay( pB ); | 676 | if (pB != NULL) { |
677 | iiResetDelay(pB); | ||
655 | break; | 678 | break; |
656 | } | 679 | } |
657 | } | 680 | } |
658 | for ( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 681 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
659 | /* We don't want to request the firmware unless we have at | 682 | /* We don't want to request the firmware unless we have at |
660 | least one board */ | 683 | least one board */ |
661 | if ( i2BoardPtrTable[i] != NULL ) { | 684 | if (i2BoardPtrTable[i] != NULL) { |
662 | if (!fw) | 685 | if (!fw) |
663 | fw = ip2_request_firmware(); | 686 | fw = ip2_request_firmware(); |
664 | if (!fw) | 687 | if (!fw) |
@@ -669,7 +692,7 @@ ip2_loadmain(int *iop, int *irqp) | |||
669 | if (fw) | 692 | if (fw) |
670 | release_firmware(fw); | 693 | release_firmware(fw); |
671 | 694 | ||
672 | ip2trace (ITRC_NO_PORT, ITRC_INIT, 2, 0 ); | 695 | ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0); |
673 | 696 | ||
674 | ip2_tty_driver->owner = THIS_MODULE; | 697 | ip2_tty_driver->owner = THIS_MODULE; |
675 | ip2_tty_driver->name = "ttyF"; | 698 | ip2_tty_driver->name = "ttyF"; |
@@ -680,20 +703,23 @@ ip2_loadmain(int *iop, int *irqp) | |||
680 | ip2_tty_driver->subtype = SERIAL_TYPE_NORMAL; | 703 | ip2_tty_driver->subtype = SERIAL_TYPE_NORMAL; |
681 | ip2_tty_driver->init_termios = tty_std_termios; | 704 | ip2_tty_driver->init_termios = tty_std_termios; |
682 | ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; | 705 | ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; |
683 | ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | 706 | ip2_tty_driver->flags = TTY_DRIVER_REAL_RAW | |
707 | TTY_DRIVER_DYNAMIC_DEV; | ||
684 | tty_set_operations(ip2_tty_driver, &ip2_ops); | 708 | tty_set_operations(ip2_tty_driver, &ip2_ops); |
685 | 709 | ||
686 | ip2trace (ITRC_NO_PORT, ITRC_INIT, 3, 0 ); | 710 | ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0); |
687 | 711 | ||
688 | /* Register the tty devices. */ | 712 | err = tty_register_driver(ip2_tty_driver); |
689 | if ( ( err = tty_register_driver ( ip2_tty_driver ) ) ) { | 713 | if (err) { |
690 | printk(KERN_ERR "IP2: failed to register tty driver (%d)\n", err); | 714 | printk(KERN_ERR "IP2: failed to register tty driver\n"); |
691 | put_tty_driver(ip2_tty_driver); | 715 | put_tty_driver(ip2_tty_driver); |
692 | return -EINVAL; | 716 | return err; /* leaking resources */ |
693 | } else | 717 | } |
694 | /* Register the IPL driver. */ | 718 | |
695 | if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) { | 719 | err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl); |
696 | printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err ); | 720 | if (err) { |
721 | printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", | ||
722 | err); | ||
697 | } else { | 723 | } else { |
698 | /* create the sysfs class */ | 724 | /* create the sysfs class */ |
699 | ip2_class = class_create(THIS_MODULE, "ip2"); | 725 | ip2_class = class_create(THIS_MODULE, "ip2"); |
@@ -705,84 +731,86 @@ ip2_loadmain(int *iop, int *irqp) | |||
705 | /* Register the read_procmem thing */ | 731 | /* Register the read_procmem thing */ |
706 | if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) { | 732 | if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) { |
707 | printk(KERN_ERR "IP2: failed to register read_procmem\n"); | 733 | printk(KERN_ERR "IP2: failed to register read_procmem\n"); |
708 | } else { | 734 | return -EIO; /* leaking resources */ |
735 | } | ||
709 | 736 | ||
710 | ip2trace (ITRC_NO_PORT, ITRC_INIT, 4, 0 ); | 737 | ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0); |
711 | /* Register the interrupt handler or poll handler, depending upon the | 738 | /* Register the interrupt handler or poll handler, depending upon the |
712 | * specified interrupt. | 739 | * specified interrupt. |
713 | */ | 740 | */ |
714 | 741 | ||
715 | for( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 742 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
716 | if ( 0 == ip2config.addr[i] ) { | 743 | if (ip2config.addr[i] == 0) |
717 | continue; | 744 | continue; |
718 | } | ||
719 | 745 | ||
720 | if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { | 746 | pB = i2BoardPtrTable[i]; |
721 | device_create_drvdata(ip2_class, NULL, | 747 | if (pB != NULL) { |
722 | MKDEV(IP2_IPL_MAJOR, 4 * i), | 748 | device_create_drvdata(ip2_class, NULL, |
723 | NULL, "ipl%d", i); | 749 | MKDEV(IP2_IPL_MAJOR, 4 * i), |
724 | device_create_drvdata(ip2_class, NULL, | 750 | NULL, "ipl%d", i); |
725 | MKDEV(IP2_IPL_MAJOR, 4 * i + 1), | 751 | device_create_drvdata(ip2_class, NULL, |
726 | NULL, "stat%d", i); | 752 | MKDEV(IP2_IPL_MAJOR, 4 * i + 1), |
727 | 753 | NULL, "stat%d", i); | |
728 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) | 754 | |
729 | { | 755 | for (box = 0; box < ABS_MAX_BOXES; box++) |
730 | for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) | 756 | for (j = 0; j < ABS_BIGGEST_BOX; j++) |
731 | { | 757 | if (pB->i2eChannelMap[box] & (1 << j)) |
732 | if ( pB->i2eChannelMap[box] & (1 << j) ) | 758 | tty_register_device( |
733 | { | 759 | ip2_tty_driver, |
734 | tty_register_device(ip2_tty_driver, | 760 | j + ABS_BIGGEST_BOX * |
735 | j + ABS_BIGGEST_BOX * | 761 | (box+i*ABS_MAX_BOXES), |
736 | (box+i*ABS_MAX_BOXES), NULL); | 762 | NULL); |
737 | } | 763 | } |
738 | } | ||
739 | } | ||
740 | } | ||
741 | 764 | ||
742 | if (poll_only) { | 765 | if (poll_only) { |
743 | // Poll only forces driver to only use polling and | 766 | /* Poll only forces driver to only use polling and |
744 | // to ignore the probed PCI or EISA interrupts. | 767 | to ignore the probed PCI or EISA interrupts. */ |
745 | ip2config.irq[i] = CIR_POLL; | 768 | ip2config.irq[i] = CIR_POLL; |
746 | } | 769 | } |
747 | if ( ip2config.irq[i] == CIR_POLL ) { | 770 | if (ip2config.irq[i] == CIR_POLL) { |
748 | retry: | 771 | retry: |
749 | if (!TimerOn) { | 772 | if (!timer_pending(&PollTimer)) { |
750 | PollTimer.expires = POLL_TIMEOUT; | 773 | mod_timer(&PollTimer, POLL_TIMEOUT); |
751 | add_timer ( &PollTimer ); | 774 | printk(KERN_INFO "IP2: polling\n"); |
752 | TimerOn = 1; | ||
753 | printk( KERN_INFO "IP2: polling\n"); | ||
754 | } | ||
755 | } else { | ||
756 | if (have_requested_irq(ip2config.irq[i])) | ||
757 | continue; | ||
758 | rc = request_irq( ip2config.irq[i], ip2_interrupt, | ||
759 | IP2_SA_FLAGS | (ip2config.type[i] == PCI ? IRQF_SHARED : 0), | ||
760 | pcName, i2BoardPtrTable[i]); | ||
761 | if (rc) { | ||
762 | printk(KERN_ERR "IP2: an request_irq failed: error %d\n",rc); | ||
763 | ip2config.irq[i] = CIR_POLL; | ||
764 | printk( KERN_INFO "IP2: Polling %ld/sec.\n", | ||
765 | (POLL_TIMEOUT - jiffies)); | ||
766 | goto retry; | ||
767 | } | ||
768 | mark_requested_irq(ip2config.irq[i]); | ||
769 | /* Initialise the interrupt handler bottom half (aka slih). */ | ||
770 | } | 775 | } |
771 | } | 776 | } else { |
772 | for( i = 0; i < IP2_MAX_BOARDS; ++i ) { | 777 | if (have_requested_irq(ip2config.irq[i])) |
773 | if ( i2BoardPtrTable[i] ) { | 778 | continue; |
774 | set_irq( i, ip2config.irq[i] ); /* set and enable board interrupt */ | 779 | rc = request_irq(ip2config.irq[i], ip2_interrupt, |
780 | IP2_SA_FLAGS | | ||
781 | (ip2config.type[i] == PCI ? IRQF_SHARED : 0), | ||
782 | pcName, i2BoardPtrTable[i]); | ||
783 | if (rc) { | ||
784 | printk(KERN_ERR "IP2: request_irq failed: " | ||
785 | "error %d\n", rc); | ||
786 | ip2config.irq[i] = CIR_POLL; | ||
787 | printk(KERN_INFO "IP2: Polling %ld/sec.\n", | ||
788 | (POLL_TIMEOUT - jiffies)); | ||
789 | goto retry; | ||
775 | } | 790 | } |
791 | mark_requested_irq(ip2config.irq[i]); | ||
792 | /* Initialise the interrupt handler bottom half | ||
793 | * (aka slih). */ | ||
776 | } | 794 | } |
777 | } | 795 | } |
778 | ip2trace (ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0 ); | 796 | |
779 | goto out; | 797 | for (i = 0; i < IP2_MAX_BOARDS; ++i) { |
798 | if (i2BoardPtrTable[i]) { | ||
799 | /* set and enable board interrupt */ | ||
800 | set_irq(i, ip2config.irq[i]); | ||
801 | } | ||
802 | } | ||
803 | |||
804 | ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0); | ||
805 | |||
806 | return 0; | ||
780 | 807 | ||
781 | out_chrdev: | 808 | out_chrdev: |
782 | unregister_chrdev(IP2_IPL_MAJOR, "ip2"); | 809 | unregister_chrdev(IP2_IPL_MAJOR, "ip2"); |
783 | out: | 810 | /* unregister and put tty here */ |
784 | return err; | 811 | return err; |
785 | } | 812 | } |
813 | module_init(ip2_loadmain); | ||
786 | 814 | ||
787 | /******************************************************************************/ | 815 | /******************************************************************************/ |
788 | /* Function: ip2_init_board() */ | 816 | /* Function: ip2_init_board() */ |
@@ -1199,9 +1227,8 @@ ip2_polled_interrupt(void) | |||
1199 | { | 1227 | { |
1200 | int i; | 1228 | int i; |
1201 | i2eBordStrPtr pB; | 1229 | i2eBordStrPtr pB; |
1202 | const int irq = 0; | ||
1203 | 1230 | ||
1204 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, irq ); | 1231 | ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0); |
1205 | 1232 | ||
1206 | /* Service just the boards on the list using this irq */ | 1233 | /* Service just the boards on the list using this irq */ |
1207 | for( i = 0; i < i2nBoards; ++i ) { | 1234 | for( i = 0; i < i2nBoards; ++i ) { |
@@ -1210,9 +1237,8 @@ ip2_polled_interrupt(void) | |||
1210 | // Only process those boards which match our IRQ. | 1237 | // Only process those boards which match our IRQ. |
1211 | // IRQ = 0 for polled boards, we won't poll "IRQ" boards | 1238 | // IRQ = 0 for polled boards, we won't poll "IRQ" boards |
1212 | 1239 | ||
1213 | if ( pB && (pB->i2eUsingIrq == irq) ) { | 1240 | if (pB && pB->i2eUsingIrq == 0) |
1214 | ip2_irq_work(pB); | 1241 | ip2_irq_work(pB); |
1215 | } | ||
1216 | } | 1242 | } |
1217 | 1243 | ||
1218 | ++irq_counter; | 1244 | ++irq_counter; |
@@ -1250,16 +1276,12 @@ ip2_poll(unsigned long arg) | |||
1250 | { | 1276 | { |
1251 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 ); | 1277 | ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 ); |
1252 | 1278 | ||
1253 | TimerOn = 0; // it's the truth but not checked in service | ||
1254 | |||
1255 | // Just polled boards, IRQ = 0 will hit all non-interrupt boards. | 1279 | // Just polled boards, IRQ = 0 will hit all non-interrupt boards. |
1256 | // It will NOT poll boards handled by hard interrupts. | 1280 | // It will NOT poll boards handled by hard interrupts. |
1257 | // The issue of queued BH interrupts is handled in ip2_interrupt(). | 1281 | // The issue of queued BH interrupts is handled in ip2_interrupt(). |
1258 | ip2_polled_interrupt(); | 1282 | ip2_polled_interrupt(); |
1259 | 1283 | ||
1260 | PollTimer.expires = POLL_TIMEOUT; | 1284 | mod_timer(&PollTimer, POLL_TIMEOUT); |
1261 | add_timer( &PollTimer ); | ||
1262 | TimerOn = 1; | ||
1263 | 1285 | ||
1264 | ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); | 1286 | ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 ); |
1265 | } | 1287 | } |
@@ -2871,7 +2893,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg ) | |||
2871 | case 13: | 2893 | case 13: |
2872 | switch ( cmd ) { | 2894 | switch ( cmd ) { |
2873 | case 64: /* Driver - ip2stat */ | 2895 | case 64: /* Driver - ip2stat */ |
2874 | rc = put_user(ip2_tty_driver->refcount, pIndex++ ); | 2896 | rc = put_user(-1, pIndex++ ); |
2875 | rc = put_user(irq_counter, pIndex++ ); | 2897 | rc = put_user(irq_counter, pIndex++ ); |
2876 | rc = put_user(bh_counter, pIndex++ ); | 2898 | rc = put_user(bh_counter, pIndex++ ); |
2877 | break; | 2899 | break; |
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 8f7cc190b62d..7d30ee1d3fca 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -421,17 +421,16 @@ static void isicom_tx(unsigned long _data) | |||
421 | if (retries >= 100) | 421 | if (retries >= 100) |
422 | goto unlock; | 422 | goto unlock; |
423 | 423 | ||
424 | tty = tty_port_tty_get(&port->port); | ||
425 | if (tty == NULL) | ||
426 | goto put_unlock; | ||
427 | |||
424 | for (; count > 0; count--, port++) { | 428 | for (; count > 0; count--, port++) { |
425 | /* port not active or tx disabled to force flow control */ | 429 | /* port not active or tx disabled to force flow control */ |
426 | if (!(port->port.flags & ASYNC_INITIALIZED) || | 430 | if (!(port->port.flags & ASYNC_INITIALIZED) || |
427 | !(port->status & ISI_TXOK)) | 431 | !(port->status & ISI_TXOK)) |
428 | continue; | 432 | continue; |
429 | 433 | ||
430 | tty = port->port.tty; | ||
431 | |||
432 | if (tty == NULL) | ||
433 | continue; | ||
434 | |||
435 | txcount = min_t(short, TX_SIZE, port->xmit_cnt); | 434 | txcount = min_t(short, TX_SIZE, port->xmit_cnt); |
436 | if (txcount <= 0 || tty->stopped || tty->hw_stopped) | 435 | if (txcount <= 0 || tty->stopped || tty->hw_stopped) |
437 | continue; | 436 | continue; |
@@ -489,6 +488,8 @@ static void isicom_tx(unsigned long _data) | |||
489 | tty_wakeup(tty); | 488 | tty_wakeup(tty); |
490 | } | 489 | } |
491 | 490 | ||
491 | put_unlock: | ||
492 | tty_kref_put(tty); | ||
492 | unlock: | 493 | unlock: |
493 | spin_unlock_irqrestore(&isi_card[card].card_lock, flags); | 494 | spin_unlock_irqrestore(&isi_card[card].card_lock, flags); |
494 | /* schedule another tx for hopefully in about 10ms */ | 495 | /* schedule another tx for hopefully in about 10ms */ |
@@ -547,7 +548,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
547 | return IRQ_HANDLED; | 548 | return IRQ_HANDLED; |
548 | } | 549 | } |
549 | 550 | ||
550 | tty = port->port.tty; | 551 | tty = tty_port_tty_get(&port->port); |
551 | if (tty == NULL) { | 552 | if (tty == NULL) { |
552 | word_count = byte_count >> 1; | 553 | word_count = byte_count >> 1; |
553 | while (byte_count > 1) { | 554 | while (byte_count > 1) { |
@@ -588,7 +589,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
588 | } | 589 | } |
589 | 590 | ||
590 | if (port->port.flags & ASYNC_CTS_FLOW) { | 591 | if (port->port.flags & ASYNC_CTS_FLOW) { |
591 | if (port->port.tty->hw_stopped) { | 592 | if (tty->hw_stopped) { |
592 | if (header & ISI_CTS) { | 593 | if (header & ISI_CTS) { |
593 | port->port.tty->hw_stopped = 0; | 594 | port->port.tty->hw_stopped = 0; |
594 | /* start tx ing */ | 595 | /* start tx ing */ |
@@ -597,7 +598,7 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
597 | tty_wakeup(tty); | 598 | tty_wakeup(tty); |
598 | } | 599 | } |
599 | } else if (!(header & ISI_CTS)) { | 600 | } else if (!(header & ISI_CTS)) { |
600 | port->port.tty->hw_stopped = 1; | 601 | tty->hw_stopped = 1; |
601 | /* stop tx ing */ | 602 | /* stop tx ing */ |
602 | port->status &= ~(ISI_TXOK | ISI_CTS); | 603 | port->status &= ~(ISI_TXOK | ISI_CTS); |
603 | } | 604 | } |
@@ -660,24 +661,21 @@ static irqreturn_t isicom_interrupt(int irq, void *dev_id) | |||
660 | } | 661 | } |
661 | outw(0x0000, base+0x04); /* enable interrupts */ | 662 | outw(0x0000, base+0x04); /* enable interrupts */ |
662 | spin_unlock(&card->card_lock); | 663 | spin_unlock(&card->card_lock); |
664 | tty_kref_put(tty); | ||
663 | 665 | ||
664 | return IRQ_HANDLED; | 666 | return IRQ_HANDLED; |
665 | } | 667 | } |
666 | 668 | ||
667 | static void isicom_config_port(struct isi_port *port) | 669 | static void isicom_config_port(struct tty_struct *tty) |
668 | { | 670 | { |
671 | struct isi_port *port = tty->driver_data; | ||
669 | struct isi_board *card = port->card; | 672 | struct isi_board *card = port->card; |
670 | struct tty_struct *tty; | ||
671 | unsigned long baud; | 673 | unsigned long baud; |
672 | unsigned long base = card->base; | 674 | unsigned long base = card->base; |
673 | u16 channel_setup, channel = port->channel, | 675 | u16 channel_setup, channel = port->channel, |
674 | shift_count = card->shift_count; | 676 | shift_count = card->shift_count; |
675 | unsigned char flow_ctrl; | 677 | unsigned char flow_ctrl; |
676 | 678 | ||
677 | tty = port->port.tty; | ||
678 | |||
679 | if (tty == NULL) | ||
680 | return; | ||
681 | /* FIXME: Switch to new tty baud API */ | 679 | /* FIXME: Switch to new tty baud API */ |
682 | baud = C_BAUD(tty); | 680 | baud = C_BAUD(tty); |
683 | if (baud & CBAUDEX) { | 681 | if (baud & CBAUDEX) { |
@@ -690,7 +688,7 @@ static void isicom_config_port(struct isi_port *port) | |||
690 | 688 | ||
691 | /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */ | 689 | /* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */ |
692 | if (baud < 1 || baud > 4) | 690 | if (baud < 1 || baud > 4) |
693 | port->port.tty->termios->c_cflag &= ~CBAUDEX; | 691 | tty->termios->c_cflag &= ~CBAUDEX; |
694 | else | 692 | else |
695 | baud += 15; | 693 | baud += 15; |
696 | } | 694 | } |
@@ -797,8 +795,9 @@ static inline void isicom_setup_board(struct isi_board *bp) | |||
797 | spin_unlock_irqrestore(&bp->card_lock, flags); | 795 | spin_unlock_irqrestore(&bp->card_lock, flags); |
798 | } | 796 | } |
799 | 797 | ||
800 | static int isicom_setup_port(struct isi_port *port) | 798 | static int isicom_setup_port(struct tty_struct *tty) |
801 | { | 799 | { |
800 | struct isi_port *port = tty->driver_data; | ||
802 | struct isi_board *card = port->card; | 801 | struct isi_board *card = port->card; |
803 | unsigned long flags; | 802 | unsigned long flags; |
804 | 803 | ||
@@ -808,8 +807,7 @@ static int isicom_setup_port(struct isi_port *port) | |||
808 | return -ENOMEM; | 807 | return -ENOMEM; |
809 | 808 | ||
810 | spin_lock_irqsave(&card->card_lock, flags); | 809 | spin_lock_irqsave(&card->card_lock, flags); |
811 | if (port->port.tty) | 810 | clear_bit(TTY_IO_ERROR, &tty->flags); |
812 | clear_bit(TTY_IO_ERROR, &port->port.tty->flags); | ||
813 | if (port->port.count == 1) | 811 | if (port->port.count == 1) |
814 | card->count++; | 812 | card->count++; |
815 | 813 | ||
@@ -823,7 +821,7 @@ static int isicom_setup_port(struct isi_port *port) | |||
823 | InterruptTheCard(card->base); | 821 | InterruptTheCard(card->base); |
824 | } | 822 | } |
825 | 823 | ||
826 | isicom_config_port(port); | 824 | isicom_config_port(tty); |
827 | port->port.flags |= ASYNC_INITIALIZED; | 825 | port->port.flags |= ASYNC_INITIALIZED; |
828 | spin_unlock_irqrestore(&card->card_lock, flags); | 826 | spin_unlock_irqrestore(&card->card_lock, flags); |
829 | 827 | ||
@@ -934,8 +932,8 @@ static int isicom_open(struct tty_struct *tty, struct file *filp) | |||
934 | 932 | ||
935 | port->port.count++; | 933 | port->port.count++; |
936 | tty->driver_data = port; | 934 | tty->driver_data = port; |
937 | port->port.tty = tty; | 935 | tty_port_tty_set(&port->port, tty); |
938 | error = isicom_setup_port(port); | 936 | error = isicom_setup_port(tty); |
939 | if (error == 0) | 937 | if (error == 0) |
940 | error = block_til_ready(tty, filp, port); | 938 | error = block_til_ready(tty, filp, port); |
941 | return error; | 939 | return error; |
@@ -955,15 +953,17 @@ static void isicom_shutdown_port(struct isi_port *port) | |||
955 | struct isi_board *card = port->card; | 953 | struct isi_board *card = port->card; |
956 | struct tty_struct *tty; | 954 | struct tty_struct *tty; |
957 | 955 | ||
958 | tty = port->port.tty; | 956 | tty = tty_port_tty_get(&port->port); |
959 | 957 | ||
960 | if (!(port->port.flags & ASYNC_INITIALIZED)) | 958 | if (!(port->port.flags & ASYNC_INITIALIZED)) { |
959 | tty_kref_put(tty); | ||
961 | return; | 960 | return; |
961 | } | ||
962 | 962 | ||
963 | tty_port_free_xmit_buf(&port->port); | 963 | tty_port_free_xmit_buf(&port->port); |
964 | port->port.flags &= ~ASYNC_INITIALIZED; | 964 | port->port.flags &= ~ASYNC_INITIALIZED; |
965 | /* 3rd October 2000 : Vinayak P Risbud */ | 965 | /* 3rd October 2000 : Vinayak P Risbud */ |
966 | port->port.tty = NULL; | 966 | tty_port_tty_set(&port->port, NULL); |
967 | 967 | ||
968 | /*Fix done by Anil .S on 30-04-2001 | 968 | /*Fix done by Anil .S on 30-04-2001 |
969 | remote login through isi port has dtr toggle problem | 969 | remote login through isi port has dtr toggle problem |
@@ -1243,9 +1243,10 @@ static int isicom_tiocmset(struct tty_struct *tty, struct file *file, | |||
1243 | return 0; | 1243 | return 0; |
1244 | } | 1244 | } |
1245 | 1245 | ||
1246 | static int isicom_set_serial_info(struct isi_port *port, | 1246 | static int isicom_set_serial_info(struct tty_struct *tty, |
1247 | struct serial_struct __user *info) | 1247 | struct serial_struct __user *info) |
1248 | { | 1248 | { |
1249 | struct isi_port *port = tty->driver_data; | ||
1249 | struct serial_struct newinfo; | 1250 | struct serial_struct newinfo; |
1250 | int reconfig_port; | 1251 | int reconfig_port; |
1251 | 1252 | ||
@@ -1276,7 +1277,7 @@ static int isicom_set_serial_info(struct isi_port *port, | |||
1276 | if (reconfig_port) { | 1277 | if (reconfig_port) { |
1277 | unsigned long flags; | 1278 | unsigned long flags; |
1278 | spin_lock_irqsave(&port->card->card_lock, flags); | 1279 | spin_lock_irqsave(&port->card->card_lock, flags); |
1279 | isicom_config_port(port); | 1280 | isicom_config_port(tty); |
1280 | spin_unlock_irqrestore(&port->card->card_lock, flags); | 1281 | spin_unlock_irqrestore(&port->card->card_lock, flags); |
1281 | } | 1282 | } |
1282 | unlock_kernel(); | 1283 | unlock_kernel(); |
@@ -1318,7 +1319,7 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp, | |||
1318 | return isicom_get_serial_info(port, argp); | 1319 | return isicom_get_serial_info(port, argp); |
1319 | 1320 | ||
1320 | case TIOCSSERIAL: | 1321 | case TIOCSSERIAL: |
1321 | return isicom_set_serial_info(port, argp); | 1322 | return isicom_set_serial_info(tty, argp); |
1322 | 1323 | ||
1323 | default: | 1324 | default: |
1324 | return -ENOIOCTLCMD; | 1325 | return -ENOIOCTLCMD; |
@@ -1341,7 +1342,7 @@ static void isicom_set_termios(struct tty_struct *tty, | |||
1341 | return; | 1342 | return; |
1342 | 1343 | ||
1343 | spin_lock_irqsave(&port->card->card_lock, flags); | 1344 | spin_lock_irqsave(&port->card->card_lock, flags); |
1344 | isicom_config_port(port); | 1345 | isicom_config_port(tty); |
1345 | spin_unlock_irqrestore(&port->card->card_lock, flags); | 1346 | spin_unlock_irqrestore(&port->card->card_lock, flags); |
1346 | 1347 | ||
1347 | if ((old_termios->c_cflag & CRTSCTS) && | 1348 | if ((old_termios->c_cflag & CRTSCTS) && |
@@ -1419,7 +1420,7 @@ static void isicom_hangup(struct tty_struct *tty) | |||
1419 | 1420 | ||
1420 | port->port.count = 0; | 1421 | port->port.count = 0; |
1421 | port->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 1422 | port->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
1422 | port->port.tty = NULL; | 1423 | tty_port_tty_set(&port->port, NULL); |
1423 | wake_up_interruptible(&port->port.open_wait); | 1424 | wake_up_interruptible(&port->port.open_wait); |
1424 | } | 1425 | } |
1425 | 1426 | ||
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 843a2afaf204..505d7a1f6b8c 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -623,24 +623,25 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un | |||
623 | static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp); | 623 | static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp); |
624 | static void stli_poll(unsigned long arg); | 624 | static void stli_poll(unsigned long arg); |
625 | static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); | 625 | static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp); |
626 | static int stli_initopen(struct stlibrd *brdp, struct stliport *portp); | 626 | static int stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp); |
627 | static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); | 627 | static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); |
628 | static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); | 628 | static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); |
629 | static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp); | 629 | static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp, |
630 | static int stli_setport(struct stliport *portp); | 630 | struct stliport *portp, struct file *filp); |
631 | static int stli_setport(struct tty_struct *tty); | ||
631 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); | 632 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); |
632 | static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); | 633 | static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); |
633 | static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); | 634 | static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); |
634 | static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp); | 635 | static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp); |
635 | static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp); | 636 | static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp, asyport_t *pp, struct ktermios *tiosp); |
636 | static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts); | 637 | static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts); |
637 | static long stli_mktiocm(unsigned long sigvalue); | 638 | static long stli_mktiocm(unsigned long sigvalue); |
638 | static void stli_read(struct stlibrd *brdp, struct stliport *portp); | 639 | static void stli_read(struct stlibrd *brdp, struct stliport *portp); |
639 | static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp); | 640 | static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp); |
640 | static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp); | 641 | static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp); |
641 | static int stli_getbrdstats(combrd_t __user *bp); | 642 | static int stli_getbrdstats(combrd_t __user *bp); |
642 | static int stli_getportstats(struct stliport *portp, comstats_t __user *cp); | 643 | static int stli_getportstats(struct tty_struct *tty, struct stliport *portp, comstats_t __user *cp); |
643 | static int stli_portcmdstats(struct stliport *portp); | 644 | static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp); |
644 | static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp); | 645 | static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp); |
645 | static int stli_getportstruct(struct stliport __user *arg); | 646 | static int stli_getportstruct(struct stliport __user *arg); |
646 | static int stli_getbrdstruct(struct stlibrd __user *arg); | 647 | static int stli_getbrdstruct(struct stlibrd __user *arg); |
@@ -731,12 +732,16 @@ static void stli_cleanup_ports(struct stlibrd *brdp) | |||
731 | { | 732 | { |
732 | struct stliport *portp; | 733 | struct stliport *portp; |
733 | unsigned int j; | 734 | unsigned int j; |
735 | struct tty_struct *tty; | ||
734 | 736 | ||
735 | for (j = 0; j < STL_MAXPORTS; j++) { | 737 | for (j = 0; j < STL_MAXPORTS; j++) { |
736 | portp = brdp->ports[j]; | 738 | portp = brdp->ports[j]; |
737 | if (portp != NULL) { | 739 | if (portp != NULL) { |
738 | if (portp->port.tty != NULL) | 740 | tty = tty_port_tty_get(&portp->port); |
739 | tty_hangup(portp->port.tty); | 741 | if (tty != NULL) { |
742 | tty_hangup(tty); | ||
743 | tty_kref_put(tty); | ||
744 | } | ||
740 | kfree(portp); | 745 | kfree(portp); |
741 | } | 746 | } |
742 | } | 747 | } |
@@ -824,7 +829,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
824 | * requires several commands to the board we will need to wait for any | 829 | * requires several commands to the board we will need to wait for any |
825 | * other open that is already initializing the port. | 830 | * other open that is already initializing the port. |
826 | */ | 831 | */ |
827 | portp->port.tty = tty; | 832 | tty_port_tty_set(&portp->port, tty); |
828 | tty->driver_data = portp; | 833 | tty->driver_data = portp; |
829 | portp->port.count++; | 834 | portp->port.count++; |
830 | 835 | ||
@@ -835,7 +840,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
835 | 840 | ||
836 | if ((portp->port.flags & ASYNC_INITIALIZED) == 0) { | 841 | if ((portp->port.flags & ASYNC_INITIALIZED) == 0) { |
837 | set_bit(ST_INITIALIZING, &portp->state); | 842 | set_bit(ST_INITIALIZING, &portp->state); |
838 | if ((rc = stli_initopen(brdp, portp)) >= 0) { | 843 | if ((rc = stli_initopen(tty, brdp, portp)) >= 0) { |
839 | portp->port.flags |= ASYNC_INITIALIZED; | 844 | portp->port.flags |= ASYNC_INITIALIZED; |
840 | clear_bit(TTY_IO_ERROR, &tty->flags); | 845 | clear_bit(TTY_IO_ERROR, &tty->flags); |
841 | } | 846 | } |
@@ -864,7 +869,7 @@ static int stli_open(struct tty_struct *tty, struct file *filp) | |||
864 | * then also we might have to wait for carrier. | 869 | * then also we might have to wait for carrier. |
865 | */ | 870 | */ |
866 | if (!(filp->f_flags & O_NONBLOCK)) { | 871 | if (!(filp->f_flags & O_NONBLOCK)) { |
867 | if ((rc = stli_waitcarrier(brdp, portp, filp)) != 0) | 872 | if ((rc = stli_waitcarrier(tty, brdp, portp, filp)) != 0) |
868 | return rc; | 873 | return rc; |
869 | } | 874 | } |
870 | portp->port.flags |= ASYNC_NORMAL_ACTIVE; | 875 | portp->port.flags |= ASYNC_NORMAL_ACTIVE; |
@@ -930,7 +935,7 @@ static void stli_close(struct tty_struct *tty, struct file *filp) | |||
930 | stli_flushbuffer(tty); | 935 | stli_flushbuffer(tty); |
931 | 936 | ||
932 | tty->closing = 0; | 937 | tty->closing = 0; |
933 | portp->port.tty = NULL; | 938 | tty_port_tty_set(&portp->port, NULL); |
934 | 939 | ||
935 | if (portp->openwaitcnt) { | 940 | if (portp->openwaitcnt) { |
936 | if (portp->close_delay) | 941 | if (portp->close_delay) |
@@ -952,9 +957,9 @@ static void stli_close(struct tty_struct *tty, struct file *filp) | |||
952 | * this still all happens pretty quickly. | 957 | * this still all happens pretty quickly. |
953 | */ | 958 | */ |
954 | 959 | ||
955 | static int stli_initopen(struct stlibrd *brdp, struct stliport *portp) | 960 | static int stli_initopen(struct tty_struct *tty, |
961 | struct stlibrd *brdp, struct stliport *portp) | ||
956 | { | 962 | { |
957 | struct tty_struct *tty; | ||
958 | asynotify_t nt; | 963 | asynotify_t nt; |
959 | asyport_t aport; | 964 | asyport_t aport; |
960 | int rc; | 965 | int rc; |
@@ -969,10 +974,7 @@ static int stli_initopen(struct stlibrd *brdp, struct stliport *portp) | |||
969 | sizeof(asynotify_t), 0)) < 0) | 974 | sizeof(asynotify_t), 0)) < 0) |
970 | return rc; | 975 | return rc; |
971 | 976 | ||
972 | tty = portp->port.tty; | 977 | stli_mkasyport(tty, portp, &aport, tty->termios); |
973 | if (tty == NULL) | ||
974 | return -ENODEV; | ||
975 | stli_mkasyport(portp, &aport, tty->termios); | ||
976 | if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport, | 978 | if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport, |
977 | sizeof(asyport_t), 0)) < 0) | 979 | sizeof(asyport_t), 0)) < 0) |
978 | return rc; | 980 | return rc; |
@@ -1161,22 +1163,21 @@ static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned l | |||
1161 | * waiting for the command to complete - so must have user context. | 1163 | * waiting for the command to complete - so must have user context. |
1162 | */ | 1164 | */ |
1163 | 1165 | ||
1164 | static int stli_setport(struct stliport *portp) | 1166 | static int stli_setport(struct tty_struct *tty) |
1165 | { | 1167 | { |
1168 | struct stliport *portp = tty->driver_data; | ||
1166 | struct stlibrd *brdp; | 1169 | struct stlibrd *brdp; |
1167 | asyport_t aport; | 1170 | asyport_t aport; |
1168 | 1171 | ||
1169 | if (portp == NULL) | 1172 | if (portp == NULL) |
1170 | return -ENODEV; | 1173 | return -ENODEV; |
1171 | if (portp->port.tty == NULL) | ||
1172 | return -ENODEV; | ||
1173 | if (portp->brdnr >= stli_nrbrds) | 1174 | if (portp->brdnr >= stli_nrbrds) |
1174 | return -ENODEV; | 1175 | return -ENODEV; |
1175 | brdp = stli_brds[portp->brdnr]; | 1176 | brdp = stli_brds[portp->brdnr]; |
1176 | if (brdp == NULL) | 1177 | if (brdp == NULL) |
1177 | return -ENODEV; | 1178 | return -ENODEV; |
1178 | 1179 | ||
1179 | stli_mkasyport(portp, &aport, portp->port.tty->termios); | 1180 | stli_mkasyport(tty, portp, &aport, tty->termios); |
1180 | return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0)); | 1181 | return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0)); |
1181 | } | 1182 | } |
1182 | 1183 | ||
@@ -1187,7 +1188,8 @@ static int stli_setport(struct stliport *portp) | |||
1187 | * maybe because if we are clocal then we don't need to wait... | 1188 | * maybe because if we are clocal then we don't need to wait... |
1188 | */ | 1189 | */ |
1189 | 1190 | ||
1190 | static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp) | 1191 | static int stli_waitcarrier(struct tty_struct *tty, struct stlibrd *brdp, |
1192 | struct stliport *portp, struct file *filp) | ||
1191 | { | 1193 | { |
1192 | unsigned long flags; | 1194 | unsigned long flags; |
1193 | int rc, doclocal; | 1195 | int rc, doclocal; |
@@ -1195,7 +1197,7 @@ static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct | |||
1195 | rc = 0; | 1197 | rc = 0; |
1196 | doclocal = 0; | 1198 | doclocal = 0; |
1197 | 1199 | ||
1198 | if (portp->port.tty->termios->c_cflag & CLOCAL) | 1200 | if (tty->termios->c_cflag & CLOCAL) |
1199 | doclocal++; | 1201 | doclocal++; |
1200 | 1202 | ||
1201 | spin_lock_irqsave(&stli_lock, flags); | 1203 | spin_lock_irqsave(&stli_lock, flags); |
@@ -1373,8 +1375,6 @@ static void stli_flushchars(struct tty_struct *tty) | |||
1373 | stli_txcookrealsize = 0; | 1375 | stli_txcookrealsize = 0; |
1374 | stli_txcooktty = NULL; | 1376 | stli_txcooktty = NULL; |
1375 | 1377 | ||
1376 | if (tty == NULL) | ||
1377 | return; | ||
1378 | if (cooktty == NULL) | 1378 | if (cooktty == NULL) |
1379 | return; | 1379 | return; |
1380 | if (tty != cooktty) | 1380 | if (tty != cooktty) |
@@ -1572,10 +1572,11 @@ static int stli_getserial(struct stliport *portp, struct serial_struct __user *s | |||
1572 | * just quietly ignore any requests to change irq, etc. | 1572 | * just quietly ignore any requests to change irq, etc. |
1573 | */ | 1573 | */ |
1574 | 1574 | ||
1575 | static int stli_setserial(struct stliport *portp, struct serial_struct __user *sp) | 1575 | static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp) |
1576 | { | 1576 | { |
1577 | struct serial_struct sio; | 1577 | struct serial_struct sio; |
1578 | int rc; | 1578 | int rc; |
1579 | struct stliport *portp = tty->driver_data; | ||
1579 | 1580 | ||
1580 | if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) | 1581 | if (copy_from_user(&sio, sp, sizeof(struct serial_struct))) |
1581 | return -EFAULT; | 1582 | return -EFAULT; |
@@ -1594,7 +1595,7 @@ static int stli_setserial(struct stliport *portp, struct serial_struct __user *s | |||
1594 | portp->closing_wait = sio.closing_wait; | 1595 | portp->closing_wait = sio.closing_wait; |
1595 | portp->custom_divisor = sio.custom_divisor; | 1596 | portp->custom_divisor = sio.custom_divisor; |
1596 | 1597 | ||
1597 | if ((rc = stli_setport(portp)) < 0) | 1598 | if ((rc = stli_setport(tty)) < 0) |
1598 | return rc; | 1599 | return rc; |
1599 | return 0; | 1600 | return 0; |
1600 | } | 1601 | } |
@@ -1685,17 +1686,17 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm | |||
1685 | rc = stli_getserial(portp, argp); | 1686 | rc = stli_getserial(portp, argp); |
1686 | break; | 1687 | break; |
1687 | case TIOCSSERIAL: | 1688 | case TIOCSSERIAL: |
1688 | rc = stli_setserial(portp, argp); | 1689 | rc = stli_setserial(tty, argp); |
1689 | break; | 1690 | break; |
1690 | case STL_GETPFLAG: | 1691 | case STL_GETPFLAG: |
1691 | rc = put_user(portp->pflag, (unsigned __user *)argp); | 1692 | rc = put_user(portp->pflag, (unsigned __user *)argp); |
1692 | break; | 1693 | break; |
1693 | case STL_SETPFLAG: | 1694 | case STL_SETPFLAG: |
1694 | if ((rc = get_user(portp->pflag, (unsigned __user *)argp)) == 0) | 1695 | if ((rc = get_user(portp->pflag, (unsigned __user *)argp)) == 0) |
1695 | stli_setport(portp); | 1696 | stli_setport(tty); |
1696 | break; | 1697 | break; |
1697 | case COM_GETPORTSTATS: | 1698 | case COM_GETPORTSTATS: |
1698 | rc = stli_getportstats(portp, argp); | 1699 | rc = stli_getportstats(tty, portp, argp); |
1699 | break; | 1700 | break; |
1700 | case COM_CLRPORTSTATS: | 1701 | case COM_CLRPORTSTATS: |
1701 | rc = stli_clrportstats(portp, argp); | 1702 | rc = stli_clrportstats(portp, argp); |
@@ -1729,8 +1730,6 @@ static void stli_settermios(struct tty_struct *tty, struct ktermios *old) | |||
1729 | struct ktermios *tiosp; | 1730 | struct ktermios *tiosp; |
1730 | asyport_t aport; | 1731 | asyport_t aport; |
1731 | 1732 | ||
1732 | if (tty == NULL) | ||
1733 | return; | ||
1734 | portp = tty->driver_data; | 1733 | portp = tty->driver_data; |
1735 | if (portp == NULL) | 1734 | if (portp == NULL) |
1736 | return; | 1735 | return; |
@@ -1742,7 +1741,7 @@ static void stli_settermios(struct tty_struct *tty, struct ktermios *old) | |||
1742 | 1741 | ||
1743 | tiosp = tty->termios; | 1742 | tiosp = tty->termios; |
1744 | 1743 | ||
1745 | stli_mkasyport(portp, &aport, tiosp); | 1744 | stli_mkasyport(tty, portp, &aport, tiosp); |
1746 | stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0); | 1745 | stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0); |
1747 | stli_mkasysigs(&portp->asig, ((tiosp->c_cflag & CBAUD) ? 1 : 0), -1); | 1746 | stli_mkasysigs(&portp->asig, ((tiosp->c_cflag & CBAUD) ? 1 : 0), -1); |
1748 | stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, | 1747 | stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, |
@@ -1854,7 +1853,7 @@ static void stli_hangup(struct tty_struct *tty) | |||
1854 | clear_bit(ST_TXBUSY, &portp->state); | 1853 | clear_bit(ST_TXBUSY, &portp->state); |
1855 | clear_bit(ST_RXSTOP, &portp->state); | 1854 | clear_bit(ST_RXSTOP, &portp->state); |
1856 | set_bit(TTY_IO_ERROR, &tty->flags); | 1855 | set_bit(TTY_IO_ERROR, &tty->flags); |
1857 | portp->port.tty = NULL; | 1856 | tty_port_tty_set(&portp->port, NULL); |
1858 | portp->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 1857 | portp->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
1859 | portp->port.count = 0; | 1858 | portp->port.count = 0; |
1860 | spin_unlock_irqrestore(&stli_lock, flags); | 1859 | spin_unlock_irqrestore(&stli_lock, flags); |
@@ -1935,8 +1934,6 @@ static void stli_waituntilsent(struct tty_struct *tty, int timeout) | |||
1935 | struct stliport *portp; | 1934 | struct stliport *portp; |
1936 | unsigned long tend; | 1935 | unsigned long tend; |
1937 | 1936 | ||
1938 | if (tty == NULL) | ||
1939 | return; | ||
1940 | portp = tty->driver_data; | 1937 | portp = tty->driver_data; |
1941 | if (portp == NULL) | 1938 | if (portp == NULL) |
1942 | return; | 1939 | return; |
@@ -1998,7 +1995,7 @@ static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portn | |||
1998 | char *sp, *uart; | 1995 | char *sp, *uart; |
1999 | int rc, cnt; | 1996 | int rc, cnt; |
2000 | 1997 | ||
2001 | rc = stli_portcmdstats(portp); | 1998 | rc = stli_portcmdstats(NULL, portp); |
2002 | 1999 | ||
2003 | uart = "UNKNOWN"; | 2000 | uart = "UNKNOWN"; |
2004 | if (brdp->state & BST_STARTED) { | 2001 | if (brdp->state & BST_STARTED) { |
@@ -2188,7 +2185,7 @@ static void stli_read(struct stlibrd *brdp, struct stliport *portp) | |||
2188 | 2185 | ||
2189 | if (test_bit(ST_RXSTOP, &portp->state)) | 2186 | if (test_bit(ST_RXSTOP, &portp->state)) |
2190 | return; | 2187 | return; |
2191 | tty = portp->port.tty; | 2188 | tty = tty_port_tty_get(&portp->port); |
2192 | if (tty == NULL) | 2189 | if (tty == NULL) |
2193 | return; | 2190 | return; |
2194 | 2191 | ||
@@ -2230,6 +2227,7 @@ static void stli_read(struct stlibrd *brdp, struct stliport *portp) | |||
2230 | set_bit(ST_RXING, &portp->state); | 2227 | set_bit(ST_RXING, &portp->state); |
2231 | 2228 | ||
2232 | tty_schedule_flip(tty); | 2229 | tty_schedule_flip(tty); |
2230 | tty_kref_put(tty); | ||
2233 | } | 2231 | } |
2234 | 2232 | ||
2235 | /*****************************************************************************/ | 2233 | /*****************************************************************************/ |
@@ -2362,7 +2360,7 @@ static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp) | |||
2362 | if (ap->notify) { | 2360 | if (ap->notify) { |
2363 | nt = ap->changed; | 2361 | nt = ap->changed; |
2364 | ap->notify = 0; | 2362 | ap->notify = 0; |
2365 | tty = portp->port.tty; | 2363 | tty = tty_port_tty_get(&portp->port); |
2366 | 2364 | ||
2367 | if (nt.signal & SG_DCD) { | 2365 | if (nt.signal & SG_DCD) { |
2368 | oldsigs = portp->sigs; | 2366 | oldsigs = portp->sigs; |
@@ -2399,6 +2397,7 @@ static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp) | |||
2399 | tty_schedule_flip(tty); | 2397 | tty_schedule_flip(tty); |
2400 | } | 2398 | } |
2401 | } | 2399 | } |
2400 | tty_kref_put(tty); | ||
2402 | 2401 | ||
2403 | if (nt.data & DT_RXBUSY) { | 2402 | if (nt.data & DT_RXBUSY) { |
2404 | donerx++; | 2403 | donerx++; |
@@ -2535,14 +2534,15 @@ static void stli_poll(unsigned long arg) | |||
2535 | * the slave. | 2534 | * the slave. |
2536 | */ | 2535 | */ |
2537 | 2536 | ||
2538 | static void stli_mkasyport(struct stliport *portp, asyport_t *pp, struct ktermios *tiosp) | 2537 | static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp, |
2538 | asyport_t *pp, struct ktermios *tiosp) | ||
2539 | { | 2539 | { |
2540 | memset(pp, 0, sizeof(asyport_t)); | 2540 | memset(pp, 0, sizeof(asyport_t)); |
2541 | 2541 | ||
2542 | /* | 2542 | /* |
2543 | * Start of by setting the baud, char size, parity and stop bit info. | 2543 | * Start of by setting the baud, char size, parity and stop bit info. |
2544 | */ | 2544 | */ |
2545 | pp->baudout = tty_get_baud_rate(portp->port.tty); | 2545 | pp->baudout = tty_get_baud_rate(tty); |
2546 | if ((tiosp->c_cflag & CBAUD) == B38400) { | 2546 | if ((tiosp->c_cflag & CBAUD) == B38400) { |
2547 | if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | 2547 | if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) |
2548 | pp->baudout = 57600; | 2548 | pp->baudout = 57600; |
@@ -2695,7 +2695,7 @@ static int stli_initports(struct stlibrd *brdp) | |||
2695 | printk("STALLION: failed to allocate port structure\n"); | 2695 | printk("STALLION: failed to allocate port structure\n"); |
2696 | continue; | 2696 | continue; |
2697 | } | 2697 | } |
2698 | 2698 | tty_port_init(&portp->port); | |
2699 | portp->magic = STLI_PORTMAGIC; | 2699 | portp->magic = STLI_PORTMAGIC; |
2700 | portp->portnr = i; | 2700 | portp->portnr = i; |
2701 | portp->brdnr = brdp->brdnr; | 2701 | portp->brdnr = brdp->brdnr; |
@@ -4220,7 +4220,7 @@ static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, | |||
4220 | * what port to get stats for (used through board control device). | 4220 | * what port to get stats for (used through board control device). |
4221 | */ | 4221 | */ |
4222 | 4222 | ||
4223 | static int stli_portcmdstats(struct stliport *portp) | 4223 | static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp) |
4224 | { | 4224 | { |
4225 | unsigned long flags; | 4225 | unsigned long flags; |
4226 | struct stlibrd *brdp; | 4226 | struct stlibrd *brdp; |
@@ -4249,15 +4249,15 @@ static int stli_portcmdstats(struct stliport *portp) | |||
4249 | stli_comstats.flags = portp->port.flags; | 4249 | stli_comstats.flags = portp->port.flags; |
4250 | 4250 | ||
4251 | spin_lock_irqsave(&brd_lock, flags); | 4251 | spin_lock_irqsave(&brd_lock, flags); |
4252 | if (portp->port.tty != NULL) { | 4252 | if (tty != NULL) { |
4253 | if (portp->port.tty->driver_data == portp) { | 4253 | if (portp->port.tty == tty) { |
4254 | stli_comstats.ttystate = portp->port.tty->flags; | 4254 | stli_comstats.ttystate = tty->flags; |
4255 | stli_comstats.rxbuffered = -1; | 4255 | stli_comstats.rxbuffered = -1; |
4256 | if (portp->port.tty->termios != NULL) { | 4256 | if (tty->termios != NULL) { |
4257 | stli_comstats.cflags = portp->port.tty->termios->c_cflag; | 4257 | stli_comstats.cflags = tty->termios->c_cflag; |
4258 | stli_comstats.iflags = portp->port.tty->termios->c_iflag; | 4258 | stli_comstats.iflags = tty->termios->c_iflag; |
4259 | stli_comstats.oflags = portp->port.tty->termios->c_oflag; | 4259 | stli_comstats.oflags = tty->termios->c_oflag; |
4260 | stli_comstats.lflags = portp->port.tty->termios->c_lflag; | 4260 | stli_comstats.lflags = tty->termios->c_lflag; |
4261 | } | 4261 | } |
4262 | } | 4262 | } |
4263 | } | 4263 | } |
@@ -4294,7 +4294,8 @@ static int stli_portcmdstats(struct stliport *portp) | |||
4294 | * what port to get stats for (used through board control device). | 4294 | * what port to get stats for (used through board control device). |
4295 | */ | 4295 | */ |
4296 | 4296 | ||
4297 | static int stli_getportstats(struct stliport *portp, comstats_t __user *cp) | 4297 | static int stli_getportstats(struct tty_struct *tty, struct stliport *portp, |
4298 | comstats_t __user *cp) | ||
4298 | { | 4299 | { |
4299 | struct stlibrd *brdp; | 4300 | struct stlibrd *brdp; |
4300 | int rc; | 4301 | int rc; |
@@ -4312,7 +4313,7 @@ static int stli_getportstats(struct stliport *portp, comstats_t __user *cp) | |||
4312 | if (!brdp) | 4313 | if (!brdp) |
4313 | return -ENODEV; | 4314 | return -ENODEV; |
4314 | 4315 | ||
4315 | if ((rc = stli_portcmdstats(portp)) < 0) | 4316 | if ((rc = stli_portcmdstats(tty, portp)) < 0) |
4316 | return rc; | 4317 | return rc; |
4317 | 4318 | ||
4318 | return copy_to_user(cp, &stli_comstats, sizeof(comstats_t)) ? | 4319 | return copy_to_user(cp, &stli_comstats, sizeof(comstats_t)) ? |
@@ -4427,7 +4428,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un | |||
4427 | 4428 | ||
4428 | switch (cmd) { | 4429 | switch (cmd) { |
4429 | case COM_GETPORTSTATS: | 4430 | case COM_GETPORTSTATS: |
4430 | rc = stli_getportstats(NULL, argp); | 4431 | rc = stli_getportstats(NULL, NULL, argp); |
4431 | done++; | 4432 | done++; |
4432 | break; | 4433 | break; |
4433 | case COM_CLRPORTSTATS: | 4434 | case COM_CLRPORTSTATS: |
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index d3d7864e0c1e..5df4003ad873 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -205,7 +205,7 @@ static int moxa_tiocmset(struct tty_struct *tty, struct file *file, | |||
205 | static void moxa_poll(unsigned long); | 205 | static void moxa_poll(unsigned long); |
206 | static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); | 206 | static void moxa_set_tty_param(struct tty_struct *, struct ktermios *); |
207 | static void moxa_setup_empty_event(struct tty_struct *); | 207 | static void moxa_setup_empty_event(struct tty_struct *); |
208 | static void moxa_shut_down(struct moxa_port *); | 208 | static void moxa_shut_down(struct tty_struct *); |
209 | /* | 209 | /* |
210 | * moxa board interface functions: | 210 | * moxa board interface functions: |
211 | */ | 211 | */ |
@@ -217,7 +217,7 @@ static void MoxaPortLineCtrl(struct moxa_port *, int, int); | |||
217 | static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int); | 217 | static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int); |
218 | static int MoxaPortLineStatus(struct moxa_port *); | 218 | static int MoxaPortLineStatus(struct moxa_port *); |
219 | static void MoxaPortFlushData(struct moxa_port *, int); | 219 | static void MoxaPortFlushData(struct moxa_port *, int); |
220 | static int MoxaPortWriteData(struct moxa_port *, const unsigned char *, int); | 220 | static int MoxaPortWriteData(struct tty_struct *, const unsigned char *, int); |
221 | static int MoxaPortReadData(struct moxa_port *); | 221 | static int MoxaPortReadData(struct moxa_port *); |
222 | static int MoxaPortTxQueue(struct moxa_port *); | 222 | static int MoxaPortTxQueue(struct moxa_port *); |
223 | static int MoxaPortRxQueue(struct moxa_port *); | 223 | static int MoxaPortRxQueue(struct moxa_port *); |
@@ -332,6 +332,7 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, | |||
332 | for (i = 0; i < MAX_BOARDS; i++) { | 332 | for (i = 0; i < MAX_BOARDS; i++) { |
333 | p = moxa_boards[i].ports; | 333 | p = moxa_boards[i].ports; |
334 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { | 334 | for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) { |
335 | struct tty_struct *ttyp; | ||
335 | memset(&tmp, 0, sizeof(tmp)); | 336 | memset(&tmp, 0, sizeof(tmp)); |
336 | if (!moxa_boards[i].ready) | 337 | if (!moxa_boards[i].ready) |
337 | goto copy; | 338 | goto copy; |
@@ -344,10 +345,12 @@ static int moxa_ioctl(struct tty_struct *tty, struct file *file, | |||
344 | if (status & 4) | 345 | if (status & 4) |
345 | tmp.dcd = 1; | 346 | tmp.dcd = 1; |
346 | 347 | ||
347 | if (!p->port.tty || !p->port.tty->termios) | 348 | ttyp = tty_port_tty_get(&p->port); |
349 | if (!ttyp || !ttyp->termios) | ||
348 | tmp.cflag = p->cflag; | 350 | tmp.cflag = p->cflag; |
349 | else | 351 | else |
350 | tmp.cflag = p->port.tty->termios->c_cflag; | 352 | tmp.cflag = ttyp->termios->c_cflag; |
353 | tty_kref_put(tty); | ||
351 | copy: | 354 | copy: |
352 | if (copy_to_user(argm, &tmp, sizeof(tmp))) { | 355 | if (copy_to_user(argm, &tmp, sizeof(tmp))) { |
353 | mutex_unlock(&moxa_openlock); | 356 | mutex_unlock(&moxa_openlock); |
@@ -880,8 +883,14 @@ static void moxa_board_deinit(struct moxa_board_conf *brd) | |||
880 | 883 | ||
881 | /* pci hot-un-plug support */ | 884 | /* pci hot-un-plug support */ |
882 | for (a = 0; a < brd->numPorts; a++) | 885 | for (a = 0; a < brd->numPorts; a++) |
883 | if (brd->ports[a].port.flags & ASYNC_INITIALIZED) | 886 | if (brd->ports[a].port.flags & ASYNC_INITIALIZED) { |
884 | tty_hangup(brd->ports[a].port.tty); | 887 | struct tty_struct *tty = tty_port_tty_get( |
888 | &brd->ports[a].port); | ||
889 | if (tty) { | ||
890 | tty_hangup(tty); | ||
891 | tty_kref_put(tty); | ||
892 | } | ||
893 | } | ||
885 | while (1) { | 894 | while (1) { |
886 | opened = 0; | 895 | opened = 0; |
887 | for (a = 0; a < brd->numPorts; a++) | 896 | for (a = 0; a < brd->numPorts; a++) |
@@ -1096,13 +1105,14 @@ static void __exit moxa_exit(void) | |||
1096 | module_init(moxa_init); | 1105 | module_init(moxa_init); |
1097 | module_exit(moxa_exit); | 1106 | module_exit(moxa_exit); |
1098 | 1107 | ||
1099 | static void moxa_close_port(struct moxa_port *ch) | 1108 | static void moxa_close_port(struct tty_struct *tty) |
1100 | { | 1109 | { |
1101 | moxa_shut_down(ch); | 1110 | struct moxa_port *ch = tty->driver_data; |
1111 | moxa_shut_down(tty); | ||
1102 | MoxaPortFlushData(ch, 2); | 1112 | MoxaPortFlushData(ch, 2); |
1103 | ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 1113 | ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
1104 | ch->port.tty->driver_data = NULL; | 1114 | tty->driver_data = NULL; |
1105 | ch->port.tty = NULL; | 1115 | tty_port_tty_set(&ch->port, NULL); |
1106 | } | 1116 | } |
1107 | 1117 | ||
1108 | static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, | 1118 | static int moxa_block_till_ready(struct tty_struct *tty, struct file *filp, |
@@ -1161,7 +1171,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
1161 | ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; | 1171 | ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; |
1162 | ch->port.count++; | 1172 | ch->port.count++; |
1163 | tty->driver_data = ch; | 1173 | tty->driver_data = ch; |
1164 | ch->port.tty = tty; | 1174 | tty_port_tty_set(&ch->port, tty); |
1165 | if (!(ch->port.flags & ASYNC_INITIALIZED)) { | 1175 | if (!(ch->port.flags & ASYNC_INITIALIZED)) { |
1166 | ch->statusflags = 0; | 1176 | ch->statusflags = 0; |
1167 | moxa_set_tty_param(tty, tty->termios); | 1177 | moxa_set_tty_param(tty, tty->termios); |
@@ -1179,7 +1189,7 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
1179 | if (retval) { | 1189 | if (retval) { |
1180 | if (ch->port.count) /* 0 means already hung up... */ | 1190 | if (ch->port.count) /* 0 means already hung up... */ |
1181 | if (--ch->port.count == 0) | 1191 | if (--ch->port.count == 0) |
1182 | moxa_close_port(ch); | 1192 | moxa_close_port(tty); |
1183 | } else | 1193 | } else |
1184 | ch->port.flags |= ASYNC_NORMAL_ACTIVE; | 1194 | ch->port.flags |= ASYNC_NORMAL_ACTIVE; |
1185 | mutex_unlock(&moxa_openlock); | 1195 | mutex_unlock(&moxa_openlock); |
@@ -1219,7 +1229,7 @@ static void moxa_close(struct tty_struct *tty, struct file *filp) | |||
1219 | tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ | 1229 | tty_wait_until_sent(tty, 30 * HZ); /* 30 seconds timeout */ |
1220 | } | 1230 | } |
1221 | 1231 | ||
1222 | moxa_close_port(ch); | 1232 | moxa_close_port(tty); |
1223 | unlock: | 1233 | unlock: |
1224 | mutex_unlock(&moxa_openlock); | 1234 | mutex_unlock(&moxa_openlock); |
1225 | } | 1235 | } |
@@ -1234,7 +1244,7 @@ static int moxa_write(struct tty_struct *tty, | |||
1234 | return 0; | 1244 | return 0; |
1235 | 1245 | ||
1236 | spin_lock_bh(&moxa_lock); | 1246 | spin_lock_bh(&moxa_lock); |
1237 | len = MoxaPortWriteData(ch, buf, count); | 1247 | len = MoxaPortWriteData(tty, buf, count); |
1238 | spin_unlock_bh(&moxa_lock); | 1248 | spin_unlock_bh(&moxa_lock); |
1239 | 1249 | ||
1240 | ch->statusflags |= LOWWAIT; | 1250 | ch->statusflags |= LOWWAIT; |
@@ -1409,7 +1419,7 @@ static void moxa_hangup(struct tty_struct *tty) | |||
1409 | return; | 1419 | return; |
1410 | } | 1420 | } |
1411 | ch->port.count = 0; | 1421 | ch->port.count = 0; |
1412 | moxa_close_port(ch); | 1422 | moxa_close_port(tty); |
1413 | mutex_unlock(&moxa_openlock); | 1423 | mutex_unlock(&moxa_openlock); |
1414 | 1424 | ||
1415 | wake_up_interruptible(&ch->port.open_wait); | 1425 | wake_up_interruptible(&ch->port.open_wait); |
@@ -1417,11 +1427,14 @@ static void moxa_hangup(struct tty_struct *tty) | |||
1417 | 1427 | ||
1418 | static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) | 1428 | static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) |
1419 | { | 1429 | { |
1430 | struct tty_struct *tty; | ||
1420 | dcd = !!dcd; | 1431 | dcd = !!dcd; |
1421 | 1432 | ||
1422 | if (dcd != p->DCDState && p->port.tty && C_CLOCAL(p->port.tty)) { | 1433 | if (dcd != p->DCDState) { |
1423 | if (!dcd) | 1434 | tty = tty_port_tty_get(&p->port); |
1424 | tty_hangup(p->port.tty); | 1435 | if (tty && C_CLOCAL(tty) && !dcd) |
1436 | tty_hangup(tty); | ||
1437 | tty_kref_put(tty); | ||
1425 | } | 1438 | } |
1426 | p->DCDState = dcd; | 1439 | p->DCDState = dcd; |
1427 | } | 1440 | } |
@@ -1429,7 +1442,7 @@ static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd) | |||
1429 | static int moxa_poll_port(struct moxa_port *p, unsigned int handle, | 1442 | static int moxa_poll_port(struct moxa_port *p, unsigned int handle, |
1430 | u16 __iomem *ip) | 1443 | u16 __iomem *ip) |
1431 | { | 1444 | { |
1432 | struct tty_struct *tty = p->port.tty; | 1445 | struct tty_struct *tty = tty_port_tty_get(&p->port); |
1433 | void __iomem *ofsAddr; | 1446 | void __iomem *ofsAddr; |
1434 | unsigned int inited = p->port.flags & ASYNC_INITIALIZED; | 1447 | unsigned int inited = p->port.flags & ASYNC_INITIALIZED; |
1435 | u16 intr; | 1448 | u16 intr; |
@@ -1476,6 +1489,7 @@ static int moxa_poll_port(struct moxa_port *p, unsigned int handle, | |||
1476 | tty_insert_flip_char(tty, 0, TTY_BREAK); | 1489 | tty_insert_flip_char(tty, 0, TTY_BREAK); |
1477 | tty_schedule_flip(tty); | 1490 | tty_schedule_flip(tty); |
1478 | } | 1491 | } |
1492 | tty_kref_put(tty); | ||
1479 | 1493 | ||
1480 | if (intr & IntrLine) | 1494 | if (intr & IntrLine) |
1481 | moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state); | 1495 | moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state); |
@@ -1560,9 +1574,9 @@ static void moxa_setup_empty_event(struct tty_struct *tty) | |||
1560 | spin_unlock_bh(&moxa_lock); | 1574 | spin_unlock_bh(&moxa_lock); |
1561 | } | 1575 | } |
1562 | 1576 | ||
1563 | static void moxa_shut_down(struct moxa_port *ch) | 1577 | static void moxa_shut_down(struct tty_struct *tty) |
1564 | { | 1578 | { |
1565 | struct tty_struct *tp = ch->port.tty; | 1579 | struct moxa_port *ch = tty->driver_data; |
1566 | 1580 | ||
1567 | if (!(ch->port.flags & ASYNC_INITIALIZED)) | 1581 | if (!(ch->port.flags & ASYNC_INITIALIZED)) |
1568 | return; | 1582 | return; |
@@ -1572,7 +1586,7 @@ static void moxa_shut_down(struct moxa_port *ch) | |||
1572 | /* | 1586 | /* |
1573 | * If we're a modem control device and HUPCL is on, drop RTS & DTR. | 1587 | * If we're a modem control device and HUPCL is on, drop RTS & DTR. |
1574 | */ | 1588 | */ |
1575 | if (C_HUPCL(tp)) | 1589 | if (C_HUPCL(tty)) |
1576 | MoxaPortLineCtrl(ch, 0, 0); | 1590 | MoxaPortLineCtrl(ch, 0, 0); |
1577 | 1591 | ||
1578 | spin_lock_bh(&moxa_lock); | 1592 | spin_lock_bh(&moxa_lock); |
@@ -1953,9 +1967,10 @@ static int MoxaPortLineStatus(struct moxa_port *port) | |||
1953 | return val; | 1967 | return val; |
1954 | } | 1968 | } |
1955 | 1969 | ||
1956 | static int MoxaPortWriteData(struct moxa_port *port, | 1970 | static int MoxaPortWriteData(struct tty_struct *tty, |
1957 | const unsigned char *buffer, int len) | 1971 | const unsigned char *buffer, int len) |
1958 | { | 1972 | { |
1973 | struct moxa_port *port = tty->driver_data; | ||
1959 | void __iomem *baseAddr, *ofsAddr, *ofs; | 1974 | void __iomem *baseAddr, *ofsAddr, *ofs; |
1960 | unsigned int c, total; | 1975 | unsigned int c, total; |
1961 | u16 head, tail, tx_mask, spage, epage; | 1976 | u16 head, tail, tx_mask, spage, epage; |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index b638403e8e9c..8beef50f95a0 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -610,15 +610,13 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, | |||
610 | return 0; | 610 | return 0; |
611 | } | 611 | } |
612 | 612 | ||
613 | static int mxser_set_baud(struct mxser_port *info, long newspd) | 613 | static int mxser_set_baud(struct tty_struct *tty, long newspd) |
614 | { | 614 | { |
615 | struct mxser_port *info = tty->driver_data; | ||
615 | int quot = 0, baud; | 616 | int quot = 0, baud; |
616 | unsigned char cval; | 617 | unsigned char cval; |
617 | 618 | ||
618 | if (!info->port.tty || !info->port.tty->termios) | 619 | if (!info->ioaddr) |
619 | return -1; | ||
620 | |||
621 | if (!(info->ioaddr)) | ||
622 | return -1; | 620 | return -1; |
623 | 621 | ||
624 | if (newspd > info->max_baud) | 622 | if (newspd > info->max_baud) |
@@ -626,13 +624,13 @@ static int mxser_set_baud(struct mxser_port *info, long newspd) | |||
626 | 624 | ||
627 | if (newspd == 134) { | 625 | if (newspd == 134) { |
628 | quot = 2 * info->baud_base / 269; | 626 | quot = 2 * info->baud_base / 269; |
629 | tty_encode_baud_rate(info->port.tty, 134, 134); | 627 | tty_encode_baud_rate(tty, 134, 134); |
630 | } else if (newspd) { | 628 | } else if (newspd) { |
631 | quot = info->baud_base / newspd; | 629 | quot = info->baud_base / newspd; |
632 | if (quot == 0) | 630 | if (quot == 0) |
633 | quot = 1; | 631 | quot = 1; |
634 | baud = info->baud_base/quot; | 632 | baud = info->baud_base/quot; |
635 | tty_encode_baud_rate(info->port.tty, baud, baud); | 633 | tty_encode_baud_rate(tty, baud, baud); |
636 | } else { | 634 | } else { |
637 | quot = 0; | 635 | quot = 0; |
638 | } | 636 | } |
@@ -658,7 +656,7 @@ static int mxser_set_baud(struct mxser_port *info, long newspd) | |||
658 | outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */ | 656 | outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */ |
659 | 657 | ||
660 | #ifdef BOTHER | 658 | #ifdef BOTHER |
661 | if (C_BAUD(info->port.tty) == BOTHER) { | 659 | if (C_BAUD(tty) == BOTHER) { |
662 | quot = info->baud_base % newspd; | 660 | quot = info->baud_base % newspd; |
663 | quot *= 8; | 661 | quot *= 8; |
664 | if (quot % newspd > newspd / 2) { | 662 | if (quot % newspd > newspd / 2) { |
@@ -679,21 +677,20 @@ static int mxser_set_baud(struct mxser_port *info, long newspd) | |||
679 | * This routine is called to set the UART divisor registers to match | 677 | * This routine is called to set the UART divisor registers to match |
680 | * the specified baud rate for a serial port. | 678 | * the specified baud rate for a serial port. |
681 | */ | 679 | */ |
682 | static int mxser_change_speed(struct mxser_port *info, | 680 | static int mxser_change_speed(struct tty_struct *tty, |
683 | struct ktermios *old_termios) | 681 | struct ktermios *old_termios) |
684 | { | 682 | { |
683 | struct mxser_port *info = tty->driver_data; | ||
685 | unsigned cflag, cval, fcr; | 684 | unsigned cflag, cval, fcr; |
686 | int ret = 0; | 685 | int ret = 0; |
687 | unsigned char status; | 686 | unsigned char status; |
688 | 687 | ||
689 | if (!info->port.tty || !info->port.tty->termios) | 688 | cflag = tty->termios->c_cflag; |
690 | return ret; | 689 | if (!info->ioaddr) |
691 | cflag = info->port.tty->termios->c_cflag; | ||
692 | if (!(info->ioaddr)) | ||
693 | return ret; | 690 | return ret; |
694 | 691 | ||
695 | if (mxser_set_baud_method[info->port.tty->index] == 0) | 692 | if (mxser_set_baud_method[tty->index] == 0) |
696 | mxser_set_baud(info, tty_get_baud_rate(info->port.tty)); | 693 | mxser_set_baud(tty, tty_get_baud_rate(tty)); |
697 | 694 | ||
698 | /* byte size and parity */ | 695 | /* byte size and parity */ |
699 | switch (cflag & CSIZE) { | 696 | switch (cflag & CSIZE) { |
@@ -762,9 +759,9 @@ static int mxser_change_speed(struct mxser_port *info, | |||
762 | info->MCR |= UART_MCR_AFE; | 759 | info->MCR |= UART_MCR_AFE; |
763 | } else { | 760 | } else { |
764 | status = inb(info->ioaddr + UART_MSR); | 761 | status = inb(info->ioaddr + UART_MSR); |
765 | if (info->port.tty->hw_stopped) { | 762 | if (tty->hw_stopped) { |
766 | if (status & UART_MSR_CTS) { | 763 | if (status & UART_MSR_CTS) { |
767 | info->port.tty->hw_stopped = 0; | 764 | tty->hw_stopped = 0; |
768 | if (info->type != PORT_16550A && | 765 | if (info->type != PORT_16550A && |
769 | !info->board->chip_flag) { | 766 | !info->board->chip_flag) { |
770 | outb(info->IER & ~UART_IER_THRI, | 767 | outb(info->IER & ~UART_IER_THRI, |
@@ -774,11 +771,11 @@ static int mxser_change_speed(struct mxser_port *info, | |||
774 | outb(info->IER, info->ioaddr + | 771 | outb(info->IER, info->ioaddr + |
775 | UART_IER); | 772 | UART_IER); |
776 | } | 773 | } |
777 | tty_wakeup(info->port.tty); | 774 | tty_wakeup(tty); |
778 | } | 775 | } |
779 | } else { | 776 | } else { |
780 | if (!(status & UART_MSR_CTS)) { | 777 | if (!(status & UART_MSR_CTS)) { |
781 | info->port.tty->hw_stopped = 1; | 778 | tty->hw_stopped = 1; |
782 | if ((info->type != PORT_16550A) && | 779 | if ((info->type != PORT_16550A) && |
783 | (!info->board->chip_flag)) { | 780 | (!info->board->chip_flag)) { |
784 | info->IER &= ~UART_IER_THRI; | 781 | info->IER &= ~UART_IER_THRI; |
@@ -804,21 +801,21 @@ static int mxser_change_speed(struct mxser_port *info, | |||
804 | * Set up parity check flag | 801 | * Set up parity check flag |
805 | */ | 802 | */ |
806 | info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; | 803 | info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; |
807 | if (I_INPCK(info->port.tty)) | 804 | if (I_INPCK(tty)) |
808 | info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; | 805 | info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; |
809 | if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) | 806 | if (I_BRKINT(tty) || I_PARMRK(tty)) |
810 | info->read_status_mask |= UART_LSR_BI; | 807 | info->read_status_mask |= UART_LSR_BI; |
811 | 808 | ||
812 | info->ignore_status_mask = 0; | 809 | info->ignore_status_mask = 0; |
813 | 810 | ||
814 | if (I_IGNBRK(info->port.tty)) { | 811 | if (I_IGNBRK(tty)) { |
815 | info->ignore_status_mask |= UART_LSR_BI; | 812 | info->ignore_status_mask |= UART_LSR_BI; |
816 | info->read_status_mask |= UART_LSR_BI; | 813 | info->read_status_mask |= UART_LSR_BI; |
817 | /* | 814 | /* |
818 | * If we're ignore parity and break indicators, ignore | 815 | * If we're ignore parity and break indicators, ignore |
819 | * overruns too. (For real raw support). | 816 | * overruns too. (For real raw support). |
820 | */ | 817 | */ |
821 | if (I_IGNPAR(info->port.tty)) { | 818 | if (I_IGNPAR(tty)) { |
822 | info->ignore_status_mask |= | 819 | info->ignore_status_mask |= |
823 | UART_LSR_OE | | 820 | UART_LSR_OE | |
824 | UART_LSR_PE | | 821 | UART_LSR_PE | |
@@ -830,16 +827,16 @@ static int mxser_change_speed(struct mxser_port *info, | |||
830 | } | 827 | } |
831 | } | 828 | } |
832 | if (info->board->chip_flag) { | 829 | if (info->board->chip_flag) { |
833 | mxser_set_must_xon1_value(info->ioaddr, START_CHAR(info->port.tty)); | 830 | mxser_set_must_xon1_value(info->ioaddr, START_CHAR(tty)); |
834 | mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(info->port.tty)); | 831 | mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(tty)); |
835 | if (I_IXON(info->port.tty)) { | 832 | if (I_IXON(tty)) { |
836 | mxser_enable_must_rx_software_flow_control( | 833 | mxser_enable_must_rx_software_flow_control( |
837 | info->ioaddr); | 834 | info->ioaddr); |
838 | } else { | 835 | } else { |
839 | mxser_disable_must_rx_software_flow_control( | 836 | mxser_disable_must_rx_software_flow_control( |
840 | info->ioaddr); | 837 | info->ioaddr); |
841 | } | 838 | } |
842 | if (I_IXOFF(info->port.tty)) { | 839 | if (I_IXOFF(tty)) { |
843 | mxser_enable_must_tx_software_flow_control( | 840 | mxser_enable_must_tx_software_flow_control( |
844 | info->ioaddr); | 841 | info->ioaddr); |
845 | } else { | 842 | } else { |
@@ -855,7 +852,8 @@ static int mxser_change_speed(struct mxser_port *info, | |||
855 | return ret; | 852 | return ret; |
856 | } | 853 | } |
857 | 854 | ||
858 | static void mxser_check_modem_status(struct mxser_port *port, int status) | 855 | static void mxser_check_modem_status(struct tty_struct *tty, |
856 | struct mxser_port *port, int status) | ||
859 | { | 857 | { |
860 | /* update input line counters */ | 858 | /* update input line counters */ |
861 | if (status & UART_MSR_TERI) | 859 | if (status & UART_MSR_TERI) |
@@ -874,10 +872,11 @@ static void mxser_check_modem_status(struct mxser_port *port, int status) | |||
874 | wake_up_interruptible(&port->port.open_wait); | 872 | wake_up_interruptible(&port->port.open_wait); |
875 | } | 873 | } |
876 | 874 | ||
875 | tty = tty_port_tty_get(&port->port); | ||
877 | if (port->port.flags & ASYNC_CTS_FLOW) { | 876 | if (port->port.flags & ASYNC_CTS_FLOW) { |
878 | if (port->port.tty->hw_stopped) { | 877 | if (tty->hw_stopped) { |
879 | if (status & UART_MSR_CTS) { | 878 | if (status & UART_MSR_CTS) { |
880 | port->port.tty->hw_stopped = 0; | 879 | tty->hw_stopped = 0; |
881 | 880 | ||
882 | if ((port->type != PORT_16550A) && | 881 | if ((port->type != PORT_16550A) && |
883 | (!port->board->chip_flag)) { | 882 | (!port->board->chip_flag)) { |
@@ -887,11 +886,11 @@ static void mxser_check_modem_status(struct mxser_port *port, int status) | |||
887 | outb(port->IER, port->ioaddr + | 886 | outb(port->IER, port->ioaddr + |
888 | UART_IER); | 887 | UART_IER); |
889 | } | 888 | } |
890 | tty_wakeup(port->port.tty); | 889 | tty_wakeup(tty); |
891 | } | 890 | } |
892 | } else { | 891 | } else { |
893 | if (!(status & UART_MSR_CTS)) { | 892 | if (!(status & UART_MSR_CTS)) { |
894 | port->port.tty->hw_stopped = 1; | 893 | tty->hw_stopped = 1; |
895 | if (port->type != PORT_16550A && | 894 | if (port->type != PORT_16550A && |
896 | !port->board->chip_flag) { | 895 | !port->board->chip_flag) { |
897 | port->IER &= ~UART_IER_THRI; | 896 | port->IER &= ~UART_IER_THRI; |
@@ -903,8 +902,9 @@ static void mxser_check_modem_status(struct mxser_port *port, int status) | |||
903 | } | 902 | } |
904 | } | 903 | } |
905 | 904 | ||
906 | static int mxser_startup(struct mxser_port *info) | 905 | static int mxser_startup(struct tty_struct *tty) |
907 | { | 906 | { |
907 | struct mxser_port *info = tty->driver_data; | ||
908 | unsigned long page; | 908 | unsigned long page; |
909 | unsigned long flags; | 909 | unsigned long flags; |
910 | 910 | ||
@@ -921,8 +921,7 @@ static int mxser_startup(struct mxser_port *info) | |||
921 | } | 921 | } |
922 | 922 | ||
923 | if (!info->ioaddr || !info->type) { | 923 | if (!info->ioaddr || !info->type) { |
924 | if (info->port.tty) | 924 | set_bit(TTY_IO_ERROR, &tty->flags); |
925 | set_bit(TTY_IO_ERROR, &info->port.tty->flags); | ||
926 | free_page(page); | 925 | free_page(page); |
927 | spin_unlock_irqrestore(&info->slock, flags); | 926 | spin_unlock_irqrestore(&info->slock, flags); |
928 | return 0; | 927 | return 0; |
@@ -952,8 +951,8 @@ static int mxser_startup(struct mxser_port *info) | |||
952 | if (inb(info->ioaddr + UART_LSR) == 0xff) { | 951 | if (inb(info->ioaddr + UART_LSR) == 0xff) { |
953 | spin_unlock_irqrestore(&info->slock, flags); | 952 | spin_unlock_irqrestore(&info->slock, flags); |
954 | if (capable(CAP_SYS_ADMIN)) { | 953 | if (capable(CAP_SYS_ADMIN)) { |
955 | if (info->port.tty) | 954 | if (tty) |
956 | set_bit(TTY_IO_ERROR, &info->port.tty->flags); | 955 | set_bit(TTY_IO_ERROR, &tty->flags); |
957 | return 0; | 956 | return 0; |
958 | } else | 957 | } else |
959 | return -ENODEV; | 958 | return -ENODEV; |
@@ -991,14 +990,13 @@ static int mxser_startup(struct mxser_port *info) | |||
991 | (void) inb(info->ioaddr + UART_IIR); | 990 | (void) inb(info->ioaddr + UART_IIR); |
992 | (void) inb(info->ioaddr + UART_MSR); | 991 | (void) inb(info->ioaddr + UART_MSR); |
993 | 992 | ||
994 | if (info->port.tty) | 993 | clear_bit(TTY_IO_ERROR, &tty->flags); |
995 | clear_bit(TTY_IO_ERROR, &info->port.tty->flags); | ||
996 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | 994 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; |
997 | 995 | ||
998 | /* | 996 | /* |
999 | * and set the speed of the serial port | 997 | * and set the speed of the serial port |
1000 | */ | 998 | */ |
1001 | mxser_change_speed(info, NULL); | 999 | mxser_change_speed(tty, NULL); |
1002 | info->port.flags |= ASYNC_INITIALIZED; | 1000 | info->port.flags |= ASYNC_INITIALIZED; |
1003 | spin_unlock_irqrestore(&info->slock, flags); | 1001 | spin_unlock_irqrestore(&info->slock, flags); |
1004 | 1002 | ||
@@ -1009,8 +1007,9 @@ static int mxser_startup(struct mxser_port *info) | |||
1009 | * This routine will shutdown a serial port; interrupts maybe disabled, and | 1007 | * This routine will shutdown a serial port; interrupts maybe disabled, and |
1010 | * DTR is dropped if the hangup on close termio flag is on. | 1008 | * DTR is dropped if the hangup on close termio flag is on. |
1011 | */ | 1009 | */ |
1012 | static void mxser_shutdown(struct mxser_port *info) | 1010 | static void mxser_shutdown(struct tty_struct *tty) |
1013 | { | 1011 | { |
1012 | struct mxser_port *info = tty->driver_data; | ||
1014 | unsigned long flags; | 1013 | unsigned long flags; |
1015 | 1014 | ||
1016 | if (!(info->port.flags & ASYNC_INITIALIZED)) | 1015 | if (!(info->port.flags & ASYNC_INITIALIZED)) |
@@ -1035,7 +1034,7 @@ static void mxser_shutdown(struct mxser_port *info) | |||
1035 | info->IER = 0; | 1034 | info->IER = 0; |
1036 | outb(0x00, info->ioaddr + UART_IER); | 1035 | outb(0x00, info->ioaddr + UART_IER); |
1037 | 1036 | ||
1038 | if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) | 1037 | if (tty->termios->c_cflag & HUPCL) |
1039 | info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS); | 1038 | info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS); |
1040 | outb(info->MCR, info->ioaddr + UART_MCR); | 1039 | outb(info->MCR, info->ioaddr + UART_MCR); |
1041 | 1040 | ||
@@ -1051,8 +1050,7 @@ static void mxser_shutdown(struct mxser_port *info) | |||
1051 | /* read data port to reset things */ | 1050 | /* read data port to reset things */ |
1052 | (void) inb(info->ioaddr + UART_RX); | 1051 | (void) inb(info->ioaddr + UART_RX); |
1053 | 1052 | ||
1054 | if (info->port.tty) | 1053 | set_bit(TTY_IO_ERROR, &tty->flags); |
1055 | set_bit(TTY_IO_ERROR, &info->port.tty->flags); | ||
1056 | 1054 | ||
1057 | info->port.flags &= ~ASYNC_INITIALIZED; | 1055 | info->port.flags &= ~ASYNC_INITIALIZED; |
1058 | 1056 | ||
@@ -1084,14 +1082,14 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
1084 | return -ENODEV; | 1082 | return -ENODEV; |
1085 | 1083 | ||
1086 | tty->driver_data = info; | 1084 | tty->driver_data = info; |
1087 | info->port.tty = tty; | 1085 | tty_port_tty_set(&info->port, tty); |
1088 | /* | 1086 | /* |
1089 | * Start up serial port | 1087 | * Start up serial port |
1090 | */ | 1088 | */ |
1091 | spin_lock_irqsave(&info->slock, flags); | 1089 | spin_lock_irqsave(&info->slock, flags); |
1092 | info->port.count++; | 1090 | info->port.count++; |
1093 | spin_unlock_irqrestore(&info->slock, flags); | 1091 | spin_unlock_irqrestore(&info->slock, flags); |
1094 | retval = mxser_startup(info); | 1092 | retval = mxser_startup(tty); |
1095 | if (retval) | 1093 | if (retval) |
1096 | return retval; | 1094 | return retval; |
1097 | 1095 | ||
@@ -1209,13 +1207,13 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
1209 | break; | 1207 | break; |
1210 | } | 1208 | } |
1211 | } | 1209 | } |
1212 | mxser_shutdown(info); | 1210 | mxser_shutdown(tty); |
1213 | 1211 | ||
1214 | mxser_flush_buffer(tty); | 1212 | mxser_flush_buffer(tty); |
1215 | tty_ldisc_flush(tty); | 1213 | tty_ldisc_flush(tty); |
1216 | 1214 | ||
1217 | tty->closing = 0; | 1215 | tty->closing = 0; |
1218 | info->port.tty = NULL; | 1216 | tty_port_tty_set(&info->port, NULL); |
1219 | if (info->port.blocked_open) { | 1217 | if (info->port.blocked_open) { |
1220 | if (info->port.close_delay) | 1218 | if (info->port.close_delay) |
1221 | schedule_timeout_interruptible(info->port.close_delay); | 1219 | schedule_timeout_interruptible(info->port.close_delay); |
@@ -1337,12 +1335,13 @@ static int mxser_chars_in_buffer(struct tty_struct *tty) | |||
1337 | * friends of mxser_ioctl() | 1335 | * friends of mxser_ioctl() |
1338 | * ------------------------------------------------------------ | 1336 | * ------------------------------------------------------------ |
1339 | */ | 1337 | */ |
1340 | static int mxser_get_serial_info(struct mxser_port *info, | 1338 | static int mxser_get_serial_info(struct tty_struct *tty, |
1341 | struct serial_struct __user *retinfo) | 1339 | struct serial_struct __user *retinfo) |
1342 | { | 1340 | { |
1341 | struct mxser_port *info = tty->driver_data; | ||
1343 | struct serial_struct tmp = { | 1342 | struct serial_struct tmp = { |
1344 | .type = info->type, | 1343 | .type = info->type, |
1345 | .line = info->port.tty->index, | 1344 | .line = tty->index, |
1346 | .port = info->ioaddr, | 1345 | .port = info->ioaddr, |
1347 | .irq = info->board->irq, | 1346 | .irq = info->board->irq, |
1348 | .flags = info->port.flags, | 1347 | .flags = info->port.flags, |
@@ -1357,9 +1356,10 @@ static int mxser_get_serial_info(struct mxser_port *info, | |||
1357 | return 0; | 1356 | return 0; |
1358 | } | 1357 | } |
1359 | 1358 | ||
1360 | static int mxser_set_serial_info(struct mxser_port *info, | 1359 | static int mxser_set_serial_info(struct tty_struct *tty, |
1361 | struct serial_struct __user *new_info) | 1360 | struct serial_struct __user *new_info) |
1362 | { | 1361 | { |
1362 | struct mxser_port *info = tty->driver_data; | ||
1363 | struct serial_struct new_serial; | 1363 | struct serial_struct new_serial; |
1364 | speed_t baud; | 1364 | speed_t baud; |
1365 | unsigned long sl_flags; | 1365 | unsigned long sl_flags; |
@@ -1393,14 +1393,14 @@ static int mxser_set_serial_info(struct mxser_port *info, | |||
1393 | (new_serial.flags & ASYNC_FLAGS)); | 1393 | (new_serial.flags & ASYNC_FLAGS)); |
1394 | info->port.close_delay = new_serial.close_delay * HZ / 100; | 1394 | info->port.close_delay = new_serial.close_delay * HZ / 100; |
1395 | info->port.closing_wait = new_serial.closing_wait * HZ / 100; | 1395 | info->port.closing_wait = new_serial.closing_wait * HZ / 100; |
1396 | info->port.tty->low_latency = | 1396 | tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) |
1397 | (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 1397 | ? 1 : 0; |
1398 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && | 1398 | if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && |
1399 | (new_serial.baud_base != info->baud_base || | 1399 | (new_serial.baud_base != info->baud_base || |
1400 | new_serial.custom_divisor != | 1400 | new_serial.custom_divisor != |
1401 | info->custom_divisor)) { | 1401 | info->custom_divisor)) { |
1402 | baud = new_serial.baud_base / new_serial.custom_divisor; | 1402 | baud = new_serial.baud_base / new_serial.custom_divisor; |
1403 | tty_encode_baud_rate(info->port.tty, baud, baud); | 1403 | tty_encode_baud_rate(tty, baud, baud); |
1404 | } | 1404 | } |
1405 | } | 1405 | } |
1406 | 1406 | ||
@@ -1411,11 +1411,11 @@ static int mxser_set_serial_info(struct mxser_port *info, | |||
1411 | if (info->port.flags & ASYNC_INITIALIZED) { | 1411 | if (info->port.flags & ASYNC_INITIALIZED) { |
1412 | if (flags != (info->port.flags & ASYNC_SPD_MASK)) { | 1412 | if (flags != (info->port.flags & ASYNC_SPD_MASK)) { |
1413 | spin_lock_irqsave(&info->slock, sl_flags); | 1413 | spin_lock_irqsave(&info->slock, sl_flags); |
1414 | mxser_change_speed(info, NULL); | 1414 | mxser_change_speed(tty, NULL); |
1415 | spin_unlock_irqrestore(&info->slock, sl_flags); | 1415 | spin_unlock_irqrestore(&info->slock, sl_flags); |
1416 | } | 1416 | } |
1417 | } else | 1417 | } else |
1418 | retval = mxser_startup(info); | 1418 | retval = mxser_startup(tty); |
1419 | 1419 | ||
1420 | return retval; | 1420 | return retval; |
1421 | } | 1421 | } |
@@ -1461,7 +1461,7 @@ static int mxser_tiocmget(struct tty_struct *tty, struct file *file) | |||
1461 | spin_lock_irqsave(&info->slock, flags); | 1461 | spin_lock_irqsave(&info->slock, flags); |
1462 | status = inb(info->ioaddr + UART_MSR); | 1462 | status = inb(info->ioaddr + UART_MSR); |
1463 | if (status & UART_MSR_ANY_DELTA) | 1463 | if (status & UART_MSR_ANY_DELTA) |
1464 | mxser_check_modem_status(info, status); | 1464 | mxser_check_modem_status(tty, info, status); |
1465 | spin_unlock_irqrestore(&info->slock, flags); | 1465 | spin_unlock_irqrestore(&info->slock, flags); |
1466 | return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | | 1466 | return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | |
1467 | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | | 1467 | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | |
@@ -1606,6 +1606,7 @@ static int __init mxser_read_register(int port, unsigned short *regs) | |||
1606 | static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | 1606 | static int mxser_ioctl_special(unsigned int cmd, void __user *argp) |
1607 | { | 1607 | { |
1608 | struct mxser_port *port; | 1608 | struct mxser_port *port; |
1609 | struct tty_struct *tty; | ||
1609 | int result, status; | 1610 | int result, status; |
1610 | unsigned int i, j; | 1611 | unsigned int i, j; |
1611 | int ret = 0; | 1612 | int ret = 0; |
@@ -1643,12 +1644,14 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1643 | 1644 | ||
1644 | if (!port->ioaddr) | 1645 | if (!port->ioaddr) |
1645 | goto copy; | 1646 | goto copy; |
1647 | |||
1648 | tty = tty_port_tty_get(&port->port); | ||
1646 | 1649 | ||
1647 | if (!port->port.tty || !port->port.tty->termios) | 1650 | if (!tty || !tty->termios) |
1648 | ms.cflag = port->normal_termios.c_cflag; | 1651 | ms.cflag = port->normal_termios.c_cflag; |
1649 | else | 1652 | else |
1650 | ms.cflag = port->port.tty->termios->c_cflag; | 1653 | ms.cflag = tty->termios->c_cflag; |
1651 | 1654 | tty_kref_put(tty); | |
1652 | status = inb(port->ioaddr + UART_MSR); | 1655 | status = inb(port->ioaddr + UART_MSR); |
1653 | if (status & UART_MSR_DCD) | 1656 | if (status & UART_MSR_DCD) |
1654 | ms.dcd = 1; | 1657 | ms.dcd = 1; |
@@ -1704,15 +1707,18 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1704 | me->up_txcnt[p] = port->mon_data.up_txcnt; | 1707 | me->up_txcnt[p] = port->mon_data.up_txcnt; |
1705 | me->modem_status[p] = | 1708 | me->modem_status[p] = |
1706 | port->mon_data.modem_status; | 1709 | port->mon_data.modem_status; |
1707 | me->baudrate[p] = tty_get_baud_rate(port->port.tty); | 1710 | tty = tty_port_tty_get(&port->port); |
1708 | 1711 | ||
1709 | if (!port->port.tty || !port->port.tty->termios) { | 1712 | if (!tty || !tty->termios) { |
1710 | cflag = port->normal_termios.c_cflag; | 1713 | cflag = port->normal_termios.c_cflag; |
1711 | iflag = port->normal_termios.c_iflag; | 1714 | iflag = port->normal_termios.c_iflag; |
1715 | me->baudrate[p] = tty_termios_baud_rate(&port->normal_termios); | ||
1712 | } else { | 1716 | } else { |
1713 | cflag = port->port.tty->termios->c_cflag; | 1717 | cflag = tty->termios->c_cflag; |
1714 | iflag = port->port.tty->termios->c_iflag; | 1718 | iflag = tty->termios->c_iflag; |
1719 | me->baudrate[p] = tty_get_baud_rate(tty); | ||
1715 | } | 1720 | } |
1721 | tty_kref_put(tty); | ||
1716 | 1722 | ||
1717 | me->databits[p] = cflag & CSIZE; | 1723 | me->databits[p] = cflag & CSIZE; |
1718 | me->stopbits[p] = cflag & CSTOPB; | 1724 | me->stopbits[p] = cflag & CSTOPB; |
@@ -1822,12 +1828,12 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1822 | switch (cmd) { | 1828 | switch (cmd) { |
1823 | case TIOCGSERIAL: | 1829 | case TIOCGSERIAL: |
1824 | lock_kernel(); | 1830 | lock_kernel(); |
1825 | retval = mxser_get_serial_info(info, argp); | 1831 | retval = mxser_get_serial_info(tty, argp); |
1826 | unlock_kernel(); | 1832 | unlock_kernel(); |
1827 | return retval; | 1833 | return retval; |
1828 | case TIOCSSERIAL: | 1834 | case TIOCSSERIAL: |
1829 | lock_kernel(); | 1835 | lock_kernel(); |
1830 | retval = mxser_set_serial_info(info, argp); | 1836 | retval = mxser_set_serial_info(tty, argp); |
1831 | unlock_kernel(); | 1837 | unlock_kernel(); |
1832 | return retval; | 1838 | return retval; |
1833 | case TIOCSERGETLSR: /* Get line status register */ | 1839 | case TIOCSERGETLSR: /* Get line status register */ |
@@ -1896,7 +1902,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1896 | 1902 | ||
1897 | lock_kernel(); | 1903 | lock_kernel(); |
1898 | status = mxser_get_msr(info->ioaddr, 1, tty->index); | 1904 | status = mxser_get_msr(info->ioaddr, 1, tty->index); |
1899 | mxser_check_modem_status(info, status); | 1905 | mxser_check_modem_status(tty, info, status); |
1900 | 1906 | ||
1901 | mcr = inb(info->ioaddr + UART_MCR); | 1907 | mcr = inb(info->ioaddr + UART_MCR); |
1902 | if (mcr & MOXA_MUST_MCR_XON_FLAG) | 1908 | if (mcr & MOXA_MUST_MCR_XON_FLAG) |
@@ -1909,7 +1915,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, | |||
1909 | else | 1915 | else |
1910 | info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT; | 1916 | info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT; |
1911 | 1917 | ||
1912 | if (info->port.tty->hw_stopped) | 1918 | if (tty->hw_stopped) |
1913 | info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; | 1919 | info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; |
1914 | else | 1920 | else |
1915 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; | 1921 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; |
@@ -1958,7 +1964,7 @@ static void mxser_stoprx(struct tty_struct *tty) | |||
1958 | } | 1964 | } |
1959 | } | 1965 | } |
1960 | 1966 | ||
1961 | if (info->port.tty->termios->c_cflag & CRTSCTS) { | 1967 | if (tty->termios->c_cflag & CRTSCTS) { |
1962 | info->MCR &= ~UART_MCR_RTS; | 1968 | info->MCR &= ~UART_MCR_RTS; |
1963 | outb(info->MCR, info->ioaddr + UART_MCR); | 1969 | outb(info->MCR, info->ioaddr + UART_MCR); |
1964 | } | 1970 | } |
@@ -1995,7 +2001,7 @@ static void mxser_unthrottle(struct tty_struct *tty) | |||
1995 | } | 2001 | } |
1996 | } | 2002 | } |
1997 | 2003 | ||
1998 | if (info->port.tty->termios->c_cflag & CRTSCTS) { | 2004 | if (tty->termios->c_cflag & CRTSCTS) { |
1999 | info->MCR |= UART_MCR_RTS; | 2005 | info->MCR |= UART_MCR_RTS; |
2000 | outb(info->MCR, info->ioaddr + UART_MCR); | 2006 | outb(info->MCR, info->ioaddr + UART_MCR); |
2001 | } | 2007 | } |
@@ -2040,7 +2046,7 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi | |||
2040 | unsigned long flags; | 2046 | unsigned long flags; |
2041 | 2047 | ||
2042 | spin_lock_irqsave(&info->slock, flags); | 2048 | spin_lock_irqsave(&info->slock, flags); |
2043 | mxser_change_speed(info, old_termios); | 2049 | mxser_change_speed(tty, old_termios); |
2044 | spin_unlock_irqrestore(&info->slock, flags); | 2050 | spin_unlock_irqrestore(&info->slock, flags); |
2045 | 2051 | ||
2046 | if ((old_termios->c_cflag & CRTSCTS) && | 2052 | if ((old_termios->c_cflag & CRTSCTS) && |
@@ -2138,10 +2144,10 @@ static void mxser_hangup(struct tty_struct *tty) | |||
2138 | struct mxser_port *info = tty->driver_data; | 2144 | struct mxser_port *info = tty->driver_data; |
2139 | 2145 | ||
2140 | mxser_flush_buffer(tty); | 2146 | mxser_flush_buffer(tty); |
2141 | mxser_shutdown(info); | 2147 | mxser_shutdown(tty); |
2142 | info->port.count = 0; | 2148 | info->port.count = 0; |
2143 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 2149 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
2144 | info->port.tty = NULL; | 2150 | tty_port_tty_set(&info->port, NULL); |
2145 | wake_up_interruptible(&info->port.open_wait); | 2151 | wake_up_interruptible(&info->port.open_wait); |
2146 | } | 2152 | } |
2147 | 2153 | ||
@@ -2164,9 +2170,9 @@ static int mxser_rs_break(struct tty_struct *tty, int break_state) | |||
2164 | return 0; | 2170 | return 0; |
2165 | } | 2171 | } |
2166 | 2172 | ||
2167 | static void mxser_receive_chars(struct mxser_port *port, int *status) | 2173 | static void mxser_receive_chars(struct tty_struct *tty, |
2174 | struct mxser_port *port, int *status) | ||
2168 | { | 2175 | { |
2169 | struct tty_struct *tty = port->port.tty; | ||
2170 | unsigned char ch, gdl; | 2176 | unsigned char ch, gdl; |
2171 | int ignored = 0; | 2177 | int ignored = 0; |
2172 | int cnt = 0; | 2178 | int cnt = 0; |
@@ -2174,9 +2180,8 @@ static void mxser_receive_chars(struct mxser_port *port, int *status) | |||
2174 | int max = 256; | 2180 | int max = 256; |
2175 | 2181 | ||
2176 | recv_room = tty->receive_room; | 2182 | recv_room = tty->receive_room; |
2177 | if ((recv_room == 0) && (!port->ldisc_stop_rx)) | 2183 | if (recv_room == 0 && !port->ldisc_stop_rx) |
2178 | mxser_stoprx(tty); | 2184 | mxser_stoprx(tty); |
2179 | |||
2180 | if (port->board->chip_flag != MOXA_OTHER_UART) { | 2185 | if (port->board->chip_flag != MOXA_OTHER_UART) { |
2181 | 2186 | ||
2182 | if (*status & UART_LSR_SPECIAL) | 2187 | if (*status & UART_LSR_SPECIAL) |
@@ -2253,7 +2258,7 @@ intr_old: | |||
2253 | } while (*status & UART_LSR_DR); | 2258 | } while (*status & UART_LSR_DR); |
2254 | 2259 | ||
2255 | end_intr: | 2260 | end_intr: |
2256 | mxvar_log.rxcnt[port->port.tty->index] += cnt; | 2261 | mxvar_log.rxcnt[tty->index] += cnt; |
2257 | port->mon_data.rxcnt += cnt; | 2262 | port->mon_data.rxcnt += cnt; |
2258 | port->mon_data.up_rxcnt += cnt; | 2263 | port->mon_data.up_rxcnt += cnt; |
2259 | 2264 | ||
@@ -2267,14 +2272,14 @@ end_intr: | |||
2267 | spin_lock(&port->slock); | 2272 | spin_lock(&port->slock); |
2268 | } | 2273 | } |
2269 | 2274 | ||
2270 | static void mxser_transmit_chars(struct mxser_port *port) | 2275 | static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port) |
2271 | { | 2276 | { |
2272 | int count, cnt; | 2277 | int count, cnt; |
2273 | 2278 | ||
2274 | if (port->x_char) { | 2279 | if (port->x_char) { |
2275 | outb(port->x_char, port->ioaddr + UART_TX); | 2280 | outb(port->x_char, port->ioaddr + UART_TX); |
2276 | port->x_char = 0; | 2281 | port->x_char = 0; |
2277 | mxvar_log.txcnt[port->port.tty->index]++; | 2282 | mxvar_log.txcnt[tty->index]++; |
2278 | port->mon_data.txcnt++; | 2283 | port->mon_data.txcnt++; |
2279 | port->mon_data.up_txcnt++; | 2284 | port->mon_data.up_txcnt++; |
2280 | port->icount.tx++; | 2285 | port->icount.tx++; |
@@ -2284,8 +2289,8 @@ static void mxser_transmit_chars(struct mxser_port *port) | |||
2284 | if (port->port.xmit_buf == NULL) | 2289 | if (port->port.xmit_buf == NULL) |
2285 | return; | 2290 | return; |
2286 | 2291 | ||
2287 | if ((port->xmit_cnt <= 0) || port->port.tty->stopped || | 2292 | if (port->xmit_cnt <= 0 || tty->stopped || |
2288 | (port->port.tty->hw_stopped && | 2293 | (tty->hw_stopped && |
2289 | (port->type != PORT_16550A) && | 2294 | (port->type != PORT_16550A) && |
2290 | (!port->board->chip_flag))) { | 2295 | (!port->board->chip_flag))) { |
2291 | port->IER &= ~UART_IER_THRI; | 2296 | port->IER &= ~UART_IER_THRI; |
@@ -2302,14 +2307,14 @@ static void mxser_transmit_chars(struct mxser_port *port) | |||
2302 | if (--port->xmit_cnt <= 0) | 2307 | if (--port->xmit_cnt <= 0) |
2303 | break; | 2308 | break; |
2304 | } while (--count > 0); | 2309 | } while (--count > 0); |
2305 | mxvar_log.txcnt[port->port.tty->index] += (cnt - port->xmit_cnt); | 2310 | mxvar_log.txcnt[tty->index] += (cnt - port->xmit_cnt); |
2306 | 2311 | ||
2307 | port->mon_data.txcnt += (cnt - port->xmit_cnt); | 2312 | port->mon_data.txcnt += (cnt - port->xmit_cnt); |
2308 | port->mon_data.up_txcnt += (cnt - port->xmit_cnt); | 2313 | port->mon_data.up_txcnt += (cnt - port->xmit_cnt); |
2309 | port->icount.tx += (cnt - port->xmit_cnt); | 2314 | port->icount.tx += (cnt - port->xmit_cnt); |
2310 | 2315 | ||
2311 | if (port->xmit_cnt < WAKEUP_CHARS) | 2316 | if (port->xmit_cnt < WAKEUP_CHARS && tty) |
2312 | tty_wakeup(port->port.tty); | 2317 | tty_wakeup(tty); |
2313 | 2318 | ||
2314 | if (port->xmit_cnt <= 0) { | 2319 | if (port->xmit_cnt <= 0) { |
2315 | port->IER &= ~UART_IER_THRI; | 2320 | port->IER &= ~UART_IER_THRI; |
@@ -2328,6 +2333,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) | |||
2328 | int max, irqbits, bits, msr; | 2333 | int max, irqbits, bits, msr; |
2329 | unsigned int int_cnt, pass_counter = 0; | 2334 | unsigned int int_cnt, pass_counter = 0; |
2330 | int handled = IRQ_NONE; | 2335 | int handled = IRQ_NONE; |
2336 | struct tty_struct *tty; | ||
2331 | 2337 | ||
2332 | for (i = 0; i < MXSER_BOARDS; i++) | 2338 | for (i = 0; i < MXSER_BOARDS; i++) |
2333 | if (dev_id == &mxser_boards[i]) { | 2339 | if (dev_id == &mxser_boards[i]) { |
@@ -2360,13 +2366,15 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) | |||
2360 | if (iir & UART_IIR_NO_INT) | 2366 | if (iir & UART_IIR_NO_INT) |
2361 | break; | 2367 | break; |
2362 | iir &= MOXA_MUST_IIR_MASK; | 2368 | iir &= MOXA_MUST_IIR_MASK; |
2363 | if (!port->port.tty || | 2369 | tty = tty_port_tty_get(&port->port); |
2370 | if (!tty || | ||
2364 | (port->port.flags & ASYNC_CLOSING) || | 2371 | (port->port.flags & ASYNC_CLOSING) || |
2365 | !(port->port.flags & | 2372 | !(port->port.flags & |
2366 | ASYNC_INITIALIZED)) { | 2373 | ASYNC_INITIALIZED)) { |
2367 | status = inb(port->ioaddr + UART_LSR); | 2374 | status = inb(port->ioaddr + UART_LSR); |
2368 | outb(0x27, port->ioaddr + UART_FCR); | 2375 | outb(0x27, port->ioaddr + UART_FCR); |
2369 | inb(port->ioaddr + UART_MSR); | 2376 | inb(port->ioaddr + UART_MSR); |
2377 | tty_kref_put(tty); | ||
2370 | break; | 2378 | break; |
2371 | } | 2379 | } |
2372 | 2380 | ||
@@ -2387,27 +2395,28 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) | |||
2387 | iir == MOXA_MUST_IIR_RDA || | 2395 | iir == MOXA_MUST_IIR_RDA || |
2388 | iir == MOXA_MUST_IIR_RTO || | 2396 | iir == MOXA_MUST_IIR_RTO || |
2389 | iir == MOXA_MUST_IIR_LSR) | 2397 | iir == MOXA_MUST_IIR_LSR) |
2390 | mxser_receive_chars(port, | 2398 | mxser_receive_chars(tty, port, |
2391 | &status); | 2399 | &status); |
2392 | 2400 | ||
2393 | } else { | 2401 | } else { |
2394 | status &= port->read_status_mask; | 2402 | status &= port->read_status_mask; |
2395 | if (status & UART_LSR_DR) | 2403 | if (status & UART_LSR_DR) |
2396 | mxser_receive_chars(port, | 2404 | mxser_receive_chars(tty, port, |
2397 | &status); | 2405 | &status); |
2398 | } | 2406 | } |
2399 | msr = inb(port->ioaddr + UART_MSR); | 2407 | msr = inb(port->ioaddr + UART_MSR); |
2400 | if (msr & UART_MSR_ANY_DELTA) | 2408 | if (msr & UART_MSR_ANY_DELTA) |
2401 | mxser_check_modem_status(port, msr); | 2409 | mxser_check_modem_status(tty, port, msr); |
2402 | 2410 | ||
2403 | if (port->board->chip_flag) { | 2411 | if (port->board->chip_flag) { |
2404 | if (iir == 0x02 && (status & | 2412 | if (iir == 0x02 && (status & |
2405 | UART_LSR_THRE)) | 2413 | UART_LSR_THRE)) |
2406 | mxser_transmit_chars(port); | 2414 | mxser_transmit_chars(tty, port); |
2407 | } else { | 2415 | } else { |
2408 | if (status & UART_LSR_THRE) | 2416 | if (status & UART_LSR_THRE) |
2409 | mxser_transmit_chars(port); | 2417 | mxser_transmit_chars(tty, port); |
2410 | } | 2418 | } |
2419 | tty_kref_put(tty); | ||
2411 | } while (int_cnt++ < MXSER_ISR_PASS_LIMIT); | 2420 | } while (int_cnt++ < MXSER_ISR_PASS_LIMIT); |
2412 | spin_unlock(&port->slock); | 2421 | spin_unlock(&port->slock); |
2413 | } | 2422 | } |
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index 69ec6399c714..bacb3e2872ae 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c | |||
@@ -764,7 +764,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, | |||
764 | break; | 764 | break; |
765 | 765 | ||
766 | default: | 766 | default: |
767 | error = n_tty_ioctl (tty, file, cmd, arg); | 767 | error = n_tty_ioctl_helper(tty, file, cmd, arg); |
768 | break; | 768 | break; |
769 | } | 769 | } |
770 | return error; | 770 | return error; |
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index ae377aa473ba..4a8215a89ad3 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
@@ -372,14 +372,8 @@ static void remove_from_rx_queue(struct r3964_info *pInfo, | |||
372 | static void put_char(struct r3964_info *pInfo, unsigned char ch) | 372 | static void put_char(struct r3964_info *pInfo, unsigned char ch) |
373 | { | 373 | { |
374 | struct tty_struct *tty = pInfo->tty; | 374 | struct tty_struct *tty = pInfo->tty; |
375 | |||
376 | if (tty == NULL) | ||
377 | return; | ||
378 | |||
379 | /* FIXME: put_char should not be called from an IRQ */ | 375 | /* FIXME: put_char should not be called from an IRQ */ |
380 | if (tty->ops->put_char) { | 376 | tty_put_char(tty, ch); |
381 | tty->ops->put_char(tty, ch); | ||
382 | } | ||
383 | pInfo->bcc ^= ch; | 377 | pInfo->bcc ^= ch; |
384 | } | 378 | } |
385 | 379 | ||
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 708c2b1dbe51..efbfe9612658 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -26,7 +26,7 @@ | |||
26 | * | 26 | * |
27 | * 2002/03/18 Implemented n_tty_wakeup to send SIGIO POLL_OUTs to | 27 | * 2002/03/18 Implemented n_tty_wakeup to send SIGIO POLL_OUTs to |
28 | * waiting writing processes-Sapan Bhatia <sapan@corewars.org>. | 28 | * waiting writing processes-Sapan Bhatia <sapan@corewars.org>. |
29 | * Also fixed a bug in BLOCKING mode where write_chan returns | 29 | * Also fixed a bug in BLOCKING mode where n_tty_write returns |
30 | * EAGAIN | 30 | * EAGAIN |
31 | */ | 31 | */ |
32 | 32 | ||
@@ -99,6 +99,7 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x, | |||
99 | 99 | ||
100 | static void n_tty_set_room(struct tty_struct *tty) | 100 | static void n_tty_set_room(struct tty_struct *tty) |
101 | { | 101 | { |
102 | /* tty->read_cnt is not read locked ? */ | ||
102 | int left = N_TTY_BUF_SIZE - tty->read_cnt - 1; | 103 | int left = N_TTY_BUF_SIZE - tty->read_cnt - 1; |
103 | 104 | ||
104 | /* | 105 | /* |
@@ -121,6 +122,16 @@ static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty) | |||
121 | } | 122 | } |
122 | } | 123 | } |
123 | 124 | ||
125 | /** | ||
126 | * put_tty_queue - add character to tty | ||
127 | * @c: character | ||
128 | * @tty: tty device | ||
129 | * | ||
130 | * Add a character to the tty read_buf queue. This is done under the | ||
131 | * read_lock to serialize character addition and also to protect us | ||
132 | * against parallel reads or flushes | ||
133 | */ | ||
134 | |||
124 | static void put_tty_queue(unsigned char c, struct tty_struct *tty) | 135 | static void put_tty_queue(unsigned char c, struct tty_struct *tty) |
125 | { | 136 | { |
126 | unsigned long flags; | 137 | unsigned long flags; |
@@ -137,14 +148,11 @@ static void put_tty_queue(unsigned char c, struct tty_struct *tty) | |||
137 | * check_unthrottle - allow new receive data | 148 | * check_unthrottle - allow new receive data |
138 | * @tty; tty device | 149 | * @tty; tty device |
139 | * | 150 | * |
140 | * Check whether to call the driver.unthrottle function. | 151 | * Check whether to call the driver unthrottle functions |
141 | * We test the TTY_THROTTLED bit first so that it always | 152 | * |
142 | * indicates the current state. The decision about whether | ||
143 | * it is worth allowing more input has been taken by the caller. | ||
144 | * Can sleep, may be called under the atomic_read_lock mutex but | 153 | * Can sleep, may be called under the atomic_read_lock mutex but |
145 | * this is not guaranteed. | 154 | * this is not guaranteed. |
146 | */ | 155 | */ |
147 | |||
148 | static void check_unthrottle(struct tty_struct *tty) | 156 | static void check_unthrottle(struct tty_struct *tty) |
149 | { | 157 | { |
150 | if (tty->count) | 158 | if (tty->count) |
@@ -158,6 +166,8 @@ static void check_unthrottle(struct tty_struct *tty) | |||
158 | * Reset the read buffer counters, clear the flags, | 166 | * Reset the read buffer counters, clear the flags, |
159 | * and make sure the driver is unthrottled. Called | 167 | * and make sure the driver is unthrottled. Called |
160 | * from n_tty_open() and n_tty_flush_buffer(). | 168 | * from n_tty_open() and n_tty_flush_buffer(). |
169 | * | ||
170 | * Locking: tty_read_lock for read fields. | ||
161 | */ | 171 | */ |
162 | static void reset_buffer_flags(struct tty_struct *tty) | 172 | static void reset_buffer_flags(struct tty_struct *tty) |
163 | { | 173 | { |
@@ -181,7 +191,7 @@ static void reset_buffer_flags(struct tty_struct *tty) | |||
181 | * at hangup) or when the N_TTY line discipline internally has to | 191 | * at hangup) or when the N_TTY line discipline internally has to |
182 | * clean the pending queue (for example some signals). | 192 | * clean the pending queue (for example some signals). |
183 | * | 193 | * |
184 | * Locking: ctrl_lock | 194 | * Locking: ctrl_lock, read_lock. |
185 | */ | 195 | */ |
186 | 196 | ||
187 | static void n_tty_flush_buffer(struct tty_struct *tty) | 197 | static void n_tty_flush_buffer(struct tty_struct *tty) |
@@ -207,6 +217,8 @@ static void n_tty_flush_buffer(struct tty_struct *tty) | |||
207 | * | 217 | * |
208 | * Report the number of characters buffered to be delivered to user | 218 | * Report the number of characters buffered to be delivered to user |
209 | * at this instant in time. | 219 | * at this instant in time. |
220 | * | ||
221 | * Locking: read_lock | ||
210 | */ | 222 | */ |
211 | 223 | ||
212 | static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty) | 224 | static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty) |
@@ -346,7 +358,7 @@ static int opost(unsigned char c, struct tty_struct *tty) | |||
346 | * the simple cases normally found and helps to generate blocks of | 358 | * the simple cases normally found and helps to generate blocks of |
347 | * symbols for the console driver and thus improve performance. | 359 | * symbols for the console driver and thus improve performance. |
348 | * | 360 | * |
349 | * Called from write_chan under the tty layer write lock. Relies | 361 | * Called from n_tty_write under the tty layer write lock. Relies |
350 | * on lock_kernel for the tty->column state. | 362 | * on lock_kernel for the tty->column state. |
351 | */ | 363 | */ |
352 | 364 | ||
@@ -410,6 +422,8 @@ break_out: | |||
410 | * | 422 | * |
411 | * Echo user input back onto the screen. This must be called only when | 423 | * Echo user input back onto the screen. This must be called only when |
412 | * L_ECHO(tty) is true. Called from the driver receive_buf path. | 424 | * L_ECHO(tty) is true. Called from the driver receive_buf path. |
425 | * | ||
426 | * Relies on BKL for tty column locking | ||
413 | */ | 427 | */ |
414 | 428 | ||
415 | static void echo_char(unsigned char c, struct tty_struct *tty) | 429 | static void echo_char(unsigned char c, struct tty_struct *tty) |
@@ -422,6 +436,12 @@ static void echo_char(unsigned char c, struct tty_struct *tty) | |||
422 | opost(c, tty); | 436 | opost(c, tty); |
423 | } | 437 | } |
424 | 438 | ||
439 | /** | ||
440 | * finsh_erasing - complete erase | ||
441 | * @tty: tty doing the erase | ||
442 | * | ||
443 | * Relies on BKL for tty column locking | ||
444 | */ | ||
425 | static inline void finish_erasing(struct tty_struct *tty) | 445 | static inline void finish_erasing(struct tty_struct *tty) |
426 | { | 446 | { |
427 | if (tty->erasing) { | 447 | if (tty->erasing) { |
@@ -439,6 +459,8 @@ static inline void finish_erasing(struct tty_struct *tty) | |||
439 | * Perform erase and necessary output when an erase character is | 459 | * Perform erase and necessary output when an erase character is |
440 | * present in the stream from the driver layer. Handles the complexities | 460 | * present in the stream from the driver layer. Handles the complexities |
441 | * of UTF-8 multibyte symbols. | 461 | * of UTF-8 multibyte symbols. |
462 | * | ||
463 | * Locking: read_lock for tty buffers, BKL for column/erasing state | ||
442 | */ | 464 | */ |
443 | 465 | ||
444 | static void eraser(unsigned char c, struct tty_struct *tty) | 466 | static void eraser(unsigned char c, struct tty_struct *tty) |
@@ -447,6 +469,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) | |||
447 | int head, seen_alnums, cnt; | 469 | int head, seen_alnums, cnt; |
448 | unsigned long flags; | 470 | unsigned long flags; |
449 | 471 | ||
472 | /* FIXME: locking needed ? */ | ||
450 | if (tty->read_head == tty->canon_head) { | 473 | if (tty->read_head == tty->canon_head) { |
451 | /* opost('\a', tty); */ /* what do you think? */ | 474 | /* opost('\a', tty); */ /* what do you think? */ |
452 | return; | 475 | return; |
@@ -481,6 +504,7 @@ static void eraser(unsigned char c, struct tty_struct *tty) | |||
481 | } | 504 | } |
482 | 505 | ||
483 | seen_alnums = 0; | 506 | seen_alnums = 0; |
507 | /* FIXME: Locking ?? */ | ||
484 | while (tty->read_head != tty->canon_head) { | 508 | while (tty->read_head != tty->canon_head) { |
485 | head = tty->read_head; | 509 | head = tty->read_head; |
486 | 510 | ||
@@ -583,6 +607,8 @@ static void eraser(unsigned char c, struct tty_struct *tty) | |||
583 | * may caus terminal flushing to take place according to the termios | 607 | * may caus terminal flushing to take place according to the termios |
584 | * settings and character used. Called from the driver receive_buf | 608 | * settings and character used. Called from the driver receive_buf |
585 | * path so serialized. | 609 | * path so serialized. |
610 | * | ||
611 | * Locking: ctrl_lock, read_lock (both via flush buffer) | ||
586 | */ | 612 | */ |
587 | 613 | ||
588 | static inline void isig(int sig, struct tty_struct *tty, int flush) | 614 | static inline void isig(int sig, struct tty_struct *tty, int flush) |
@@ -1007,12 +1033,26 @@ int is_ignored(int sig) | |||
1007 | * and is protected from re-entry by the tty layer. The user is | 1033 | * and is protected from re-entry by the tty layer. The user is |
1008 | * guaranteed that this function will not be re-entered or in progress | 1034 | * guaranteed that this function will not be re-entered or in progress |
1009 | * when the ldisc is closed. | 1035 | * when the ldisc is closed. |
1036 | * | ||
1037 | * Locking: Caller holds tty->termios_mutex | ||
1010 | */ | 1038 | */ |
1011 | 1039 | ||
1012 | static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) | 1040 | static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) |
1013 | { | 1041 | { |
1014 | if (!tty) | 1042 | int canon_change = 1; |
1015 | return; | 1043 | BUG_ON(!tty); |
1044 | |||
1045 | if (old) | ||
1046 | canon_change = (old->c_lflag ^ tty->termios->c_lflag) & ICANON; | ||
1047 | if (canon_change) { | ||
1048 | memset(&tty->read_flags, 0, sizeof tty->read_flags); | ||
1049 | tty->canon_head = tty->read_tail; | ||
1050 | tty->canon_data = 0; | ||
1051 | tty->erasing = 0; | ||
1052 | } | ||
1053 | |||
1054 | if (canon_change && !L_ICANON(tty) && tty->read_cnt) | ||
1055 | wake_up_interruptible(&tty->read_wait); | ||
1016 | 1056 | ||
1017 | tty->icanon = (L_ICANON(tty) != 0); | 1057 | tty->icanon = (L_ICANON(tty) != 0); |
1018 | if (test_bit(TTY_HW_COOK_IN, &tty->flags)) { | 1058 | if (test_bit(TTY_HW_COOK_IN, &tty->flags)) { |
@@ -1143,7 +1183,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt) | |||
1143 | * @b: user data | 1183 | * @b: user data |
1144 | * @nr: size of data | 1184 | * @nr: size of data |
1145 | * | 1185 | * |
1146 | * Helper function to speed up read_chan. It is only called when | 1186 | * Helper function to speed up n_tty_read. It is only called when |
1147 | * ICANON is off; it copies characters straight from the tty queue to | 1187 | * ICANON is off; it copies characters straight from the tty queue to |
1148 | * user space directly. It can be profitably called twice; once to | 1188 | * user space directly. It can be profitably called twice; once to |
1149 | * drain the space from the tail pointer to the (physical) end of the | 1189 | * drain the space from the tail pointer to the (physical) end of the |
@@ -1210,7 +1250,7 @@ static int job_control(struct tty_struct *tty, struct file *file) | |||
1210 | if (file->f_op->write != redirected_tty_write && | 1250 | if (file->f_op->write != redirected_tty_write && |
1211 | current->signal->tty == tty) { | 1251 | current->signal->tty == tty) { |
1212 | if (!tty->pgrp) | 1252 | if (!tty->pgrp) |
1213 | printk(KERN_ERR "read_chan: no tty->pgrp!\n"); | 1253 | printk(KERN_ERR "n_tty_read: no tty->pgrp!\n"); |
1214 | else if (task_pgrp(current) != tty->pgrp) { | 1254 | else if (task_pgrp(current) != tty->pgrp) { |
1215 | if (is_ignored(SIGTTIN) || | 1255 | if (is_ignored(SIGTTIN) || |
1216 | is_current_pgrp_orphaned()) | 1256 | is_current_pgrp_orphaned()) |
@@ -1225,7 +1265,7 @@ static int job_control(struct tty_struct *tty, struct file *file) | |||
1225 | 1265 | ||
1226 | 1266 | ||
1227 | /** | 1267 | /** |
1228 | * read_chan - read function for tty | 1268 | * n_tty_read - read function for tty |
1229 | * @tty: tty device | 1269 | * @tty: tty device |
1230 | * @file: file object | 1270 | * @file: file object |
1231 | * @buf: userspace buffer pointer | 1271 | * @buf: userspace buffer pointer |
@@ -1239,7 +1279,7 @@ static int job_control(struct tty_struct *tty, struct file *file) | |||
1239 | * This code must be sure never to sleep through a hangup. | 1279 | * This code must be sure never to sleep through a hangup. |
1240 | */ | 1280 | */ |
1241 | 1281 | ||
1242 | static ssize_t read_chan(struct tty_struct *tty, struct file *file, | 1282 | static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, |
1243 | unsigned char __user *buf, size_t nr) | 1283 | unsigned char __user *buf, size_t nr) |
1244 | { | 1284 | { |
1245 | unsigned char __user *b = buf; | 1285 | unsigned char __user *b = buf; |
@@ -1254,10 +1294,7 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file, | |||
1254 | 1294 | ||
1255 | do_it_again: | 1295 | do_it_again: |
1256 | 1296 | ||
1257 | if (!tty->read_buf) { | 1297 | BUG_ON(!tty->read_buf); |
1258 | printk(KERN_ERR "n_tty_read_chan: read_buf == NULL?!?\n"); | ||
1259 | return -EIO; | ||
1260 | } | ||
1261 | 1298 | ||
1262 | c = job_control(tty, file); | 1299 | c = job_control(tty, file); |
1263 | if (c < 0) | 1300 | if (c < 0) |
@@ -1444,7 +1481,7 @@ do_it_again: | |||
1444 | } | 1481 | } |
1445 | 1482 | ||
1446 | /** | 1483 | /** |
1447 | * write_chan - write function for tty | 1484 | * n_tty_write - write function for tty |
1448 | * @tty: tty device | 1485 | * @tty: tty device |
1449 | * @file: file object | 1486 | * @file: file object |
1450 | * @buf: userspace buffer pointer | 1487 | * @buf: userspace buffer pointer |
@@ -1458,7 +1495,7 @@ do_it_again: | |||
1458 | * This code must be sure never to sleep through a hangup. | 1495 | * This code must be sure never to sleep through a hangup. |
1459 | */ | 1496 | */ |
1460 | 1497 | ||
1461 | static ssize_t write_chan(struct tty_struct *tty, struct file *file, | 1498 | static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, |
1462 | const unsigned char *buf, size_t nr) | 1499 | const unsigned char *buf, size_t nr) |
1463 | { | 1500 | { |
1464 | const unsigned char *b = buf; | 1501 | const unsigned char *b = buf; |
@@ -1532,7 +1569,7 @@ break_out: | |||
1532 | } | 1569 | } |
1533 | 1570 | ||
1534 | /** | 1571 | /** |
1535 | * normal_poll - poll method for N_TTY | 1572 | * n_tty_poll - poll method for N_TTY |
1536 | * @tty: terminal device | 1573 | * @tty: terminal device |
1537 | * @file: file accessing it | 1574 | * @file: file accessing it |
1538 | * @wait: poll table | 1575 | * @wait: poll table |
@@ -1545,7 +1582,7 @@ break_out: | |||
1545 | * Called without the kernel lock held - fine | 1582 | * Called without the kernel lock held - fine |
1546 | */ | 1583 | */ |
1547 | 1584 | ||
1548 | static unsigned int normal_poll(struct tty_struct *tty, struct file *file, | 1585 | static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file, |
1549 | poll_table *wait) | 1586 | poll_table *wait) |
1550 | { | 1587 | { |
1551 | unsigned int mask = 0; | 1588 | unsigned int mask = 0; |
@@ -1573,6 +1610,44 @@ static unsigned int normal_poll(struct tty_struct *tty, struct file *file, | |||
1573 | return mask; | 1610 | return mask; |
1574 | } | 1611 | } |
1575 | 1612 | ||
1613 | static unsigned long inq_canon(struct tty_struct *tty) | ||
1614 | { | ||
1615 | int nr, head, tail; | ||
1616 | |||
1617 | if (!tty->canon_data) | ||
1618 | return 0; | ||
1619 | head = tty->canon_head; | ||
1620 | tail = tty->read_tail; | ||
1621 | nr = (head - tail) & (N_TTY_BUF_SIZE-1); | ||
1622 | /* Skip EOF-chars.. */ | ||
1623 | while (head != tail) { | ||
1624 | if (test_bit(tail, tty->read_flags) && | ||
1625 | tty->read_buf[tail] == __DISABLED_CHAR) | ||
1626 | nr--; | ||
1627 | tail = (tail+1) & (N_TTY_BUF_SIZE-1); | ||
1628 | } | ||
1629 | return nr; | ||
1630 | } | ||
1631 | |||
1632 | static int n_tty_ioctl(struct tty_struct *tty, struct file *file, | ||
1633 | unsigned int cmd, unsigned long arg) | ||
1634 | { | ||
1635 | int retval; | ||
1636 | |||
1637 | switch (cmd) { | ||
1638 | case TIOCOUTQ: | ||
1639 | return put_user(tty_chars_in_buffer(tty), (int __user *) arg); | ||
1640 | case TIOCINQ: | ||
1641 | /* FIXME: Locking */ | ||
1642 | retval = tty->read_cnt; | ||
1643 | if (L_ICANON(tty)) | ||
1644 | retval = inq_canon(tty); | ||
1645 | return put_user(retval, (unsigned int __user *) arg); | ||
1646 | default: | ||
1647 | return n_tty_ioctl_helper(tty, file, cmd, arg); | ||
1648 | } | ||
1649 | } | ||
1650 | |||
1576 | struct tty_ldisc_ops tty_ldisc_N_TTY = { | 1651 | struct tty_ldisc_ops tty_ldisc_N_TTY = { |
1577 | .magic = TTY_LDISC_MAGIC, | 1652 | .magic = TTY_LDISC_MAGIC, |
1578 | .name = "n_tty", | 1653 | .name = "n_tty", |
@@ -1580,11 +1655,11 @@ struct tty_ldisc_ops tty_ldisc_N_TTY = { | |||
1580 | .close = n_tty_close, | 1655 | .close = n_tty_close, |
1581 | .flush_buffer = n_tty_flush_buffer, | 1656 | .flush_buffer = n_tty_flush_buffer, |
1582 | .chars_in_buffer = n_tty_chars_in_buffer, | 1657 | .chars_in_buffer = n_tty_chars_in_buffer, |
1583 | .read = read_chan, | 1658 | .read = n_tty_read, |
1584 | .write = write_chan, | 1659 | .write = n_tty_write, |
1585 | .ioctl = n_tty_ioctl, | 1660 | .ioctl = n_tty_ioctl, |
1586 | .set_termios = n_tty_set_termios, | 1661 | .set_termios = n_tty_set_termios, |
1587 | .poll = normal_poll, | 1662 | .poll = n_tty_poll, |
1588 | .receive_buf = n_tty_receive_buf, | 1663 | .receive_buf = n_tty_receive_buf, |
1589 | .write_wakeup = n_tty_write_wakeup | 1664 | .write_wakeup = n_tty_write_wakeup |
1590 | }; | 1665 | }; |
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 66a0f931c66c..9a34a1935283 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c | |||
@@ -1599,7 +1599,10 @@ static int ntty_open(struct tty_struct *tty, struct file *file) | |||
1599 | return 0; | 1599 | return 0; |
1600 | } | 1600 | } |
1601 | 1601 | ||
1602 | /* Called when the userspace process close the tty, /dev/noz*. */ | 1602 | /* Called when the userspace process close the tty, /dev/noz*. Also |
1603 | called immediately if ntty_open fails in which case tty->driver_data | ||
1604 | will be NULL an we exit by the first return */ | ||
1605 | |||
1603 | static void ntty_close(struct tty_struct *tty, struct file *file) | 1606 | static void ntty_close(struct tty_struct *tty, struct file *file) |
1604 | { | 1607 | { |
1605 | struct nozomi *dc = get_dc_by_tty(tty); | 1608 | struct nozomi *dc = get_dc_by_tty(tty); |
diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index 3a23e7694d55..569f2f7743a7 100644 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ b/drivers/char/pcmcia/ipwireless/tty.c | |||
@@ -276,6 +276,7 @@ static int ipw_write_room(struct tty_struct *linux_tty) | |||
276 | struct ipw_tty *tty = linux_tty->driver_data; | 276 | struct ipw_tty *tty = linux_tty->driver_data; |
277 | int room; | 277 | int room; |
278 | 278 | ||
279 | /* FIXME: Exactly how is the tty object locked here .. */ | ||
279 | if (!tty) | 280 | if (!tty) |
280 | return -ENODEV; | 281 | return -ENODEV; |
281 | 282 | ||
@@ -397,6 +398,7 @@ static int set_control_lines(struct ipw_tty *tty, unsigned int set, | |||
397 | static int ipw_tiocmget(struct tty_struct *linux_tty, struct file *file) | 398 | static int ipw_tiocmget(struct tty_struct *linux_tty, struct file *file) |
398 | { | 399 | { |
399 | struct ipw_tty *tty = linux_tty->driver_data; | 400 | struct ipw_tty *tty = linux_tty->driver_data; |
401 | /* FIXME: Exactly how is the tty object locked here .. */ | ||
400 | 402 | ||
401 | if (!tty) | 403 | if (!tty) |
402 | return -ENODEV; | 404 | return -ENODEV; |
@@ -412,6 +414,7 @@ ipw_tiocmset(struct tty_struct *linux_tty, struct file *file, | |||
412 | unsigned int set, unsigned int clear) | 414 | unsigned int set, unsigned int clear) |
413 | { | 415 | { |
414 | struct ipw_tty *tty = linux_tty->driver_data; | 416 | struct ipw_tty *tty = linux_tty->driver_data; |
417 | /* FIXME: Exactly how is the tty object locked here .. */ | ||
415 | 418 | ||
416 | if (!tty) | 419 | if (!tty) |
417 | return -ENODEV; | 420 | return -ENODEV; |
@@ -433,6 +436,8 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file, | |||
433 | if (!tty->open_count) | 436 | if (!tty->open_count) |
434 | return -EINVAL; | 437 | return -EINVAL; |
435 | 438 | ||
439 | /* FIXME: Exactly how is the tty object locked here .. */ | ||
440 | |||
436 | switch (cmd) { | 441 | switch (cmd) { |
437 | case TIOCGSERIAL: | 442 | case TIOCGSERIAL: |
438 | return ipwireless_get_serial_info(tty, (void __user *) arg); | 443 | return ipwireless_get_serial_info(tty, (void __user *) arg); |
@@ -467,13 +472,6 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file, | |||
467 | } | 472 | } |
468 | return 0; | 473 | return 0; |
469 | 474 | ||
470 | case TCGETS: | ||
471 | case TCGETA: | ||
472 | return n_tty_ioctl(linux_tty, file, cmd, arg); | ||
473 | |||
474 | case TCFLSH: | ||
475 | return n_tty_ioctl(linux_tty, file, cmd, arg); | ||
476 | |||
477 | case FIONREAD: | 475 | case FIONREAD: |
478 | { | 476 | { |
479 | int val = 0; | 477 | int val = 0; |
@@ -482,10 +480,11 @@ static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file, | |||
482 | return -EFAULT; | 480 | return -EFAULT; |
483 | } | 481 | } |
484 | return 0; | 482 | return 0; |
483 | case TCFLSH: | ||
484 | return tty_perform_flush(linux_tty, arg); | ||
485 | } | 485 | } |
486 | } | 486 | } |
487 | 487 | return tty_mode_ioctl(linux_tty, file, cmd , arg); | |
488 | return -ENOIOCTLCMD; | ||
489 | } | 488 | } |
490 | 489 | ||
491 | static int add_tty(dev_node_t *nodesp, int j, | 490 | static int add_tty(dev_node_t *nodesp, int j, |
@@ -588,6 +587,8 @@ void ipwireless_tty_free(struct ipw_tty *tty) | |||
588 | tty_hangup(ttyj->linux_tty); | 587 | tty_hangup(ttyj->linux_tty); |
589 | /* Wait till the tty_hangup has completed */ | 588 | /* Wait till the tty_hangup has completed */ |
590 | flush_scheduled_work(); | 589 | flush_scheduled_work(); |
590 | /* FIXME: Exactly how is the tty object locked here | ||
591 | against a parallel ioctl etc */ | ||
591 | mutex_lock(&ttyj->ipw_tty_mutex); | 592 | mutex_lock(&ttyj->ipw_tty_mutex); |
592 | } | 593 | } |
593 | while (ttyj->open_count) | 594 | while (ttyj->open_count) |
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 76b27932d229..6d4582712b1f 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -8,10 +8,12 @@ | |||
8 | * Added TTY_DO_WRITE_WAKEUP to enable n_tty to send POLL_OUT to | 8 | * Added TTY_DO_WRITE_WAKEUP to enable n_tty to send POLL_OUT to |
9 | * waiting writers -- Sapan Bhatia <sapan@corewars.org> | 9 | * waiting writers -- Sapan Bhatia <sapan@corewars.org> |
10 | * | 10 | * |
11 | * | 11 | * When reading this code see also fs/devpts. In particular note that the |
12 | * driver_data field is used by the devpts side as a binding to the devpts | ||
13 | * inode. | ||
12 | */ | 14 | */ |
13 | 15 | ||
14 | #include <linux/module.h> /* For EXPORT_SYMBOL */ | 16 | #include <linux/module.h> |
15 | 17 | ||
16 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
17 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
@@ -23,26 +25,25 @@ | |||
23 | #include <linux/mm.h> | 25 | #include <linux/mm.h> |
24 | #include <linux/init.h> | 26 | #include <linux/init.h> |
25 | #include <linux/sysctl.h> | 27 | #include <linux/sysctl.h> |
26 | 28 | #include <linux/device.h> | |
27 | #include <asm/uaccess.h> | 29 | #include <linux/uaccess.h> |
28 | #include <asm/system.h> | ||
29 | #include <linux/bitops.h> | 30 | #include <linux/bitops.h> |
30 | #include <linux/devpts_fs.h> | 31 | #include <linux/devpts_fs.h> |
31 | 32 | ||
33 | #include <asm/system.h> | ||
34 | |||
32 | /* These are global because they are accessed in tty_io.c */ | 35 | /* These are global because they are accessed in tty_io.c */ |
33 | #ifdef CONFIG_UNIX98_PTYS | 36 | #ifdef CONFIG_UNIX98_PTYS |
34 | struct tty_driver *ptm_driver; | 37 | struct tty_driver *ptm_driver; |
35 | static struct tty_driver *pts_driver; | 38 | static struct tty_driver *pts_driver; |
36 | #endif | 39 | #endif |
37 | 40 | ||
38 | static void pty_close(struct tty_struct * tty, struct file * filp) | 41 | static void pty_close(struct tty_struct *tty, struct file *filp) |
39 | { | 42 | { |
40 | if (!tty) | 43 | BUG_ON(!tty); |
41 | return; | 44 | if (tty->driver->subtype == PTY_TYPE_MASTER) |
42 | if (tty->driver->subtype == PTY_TYPE_MASTER) { | 45 | WARN_ON(tty->count > 1); |
43 | if (tty->count > 1) | 46 | else { |
44 | printk("master pty_close: count = %d!!\n", tty->count); | ||
45 | } else { | ||
46 | if (tty->count > 2) | 47 | if (tty->count > 2) |
47 | return; | 48 | return; |
48 | } | 49 | } |
@@ -59,7 +60,7 @@ static void pty_close(struct tty_struct * tty, struct file * filp) | |||
59 | set_bit(TTY_OTHER_CLOSED, &tty->flags); | 60 | set_bit(TTY_OTHER_CLOSED, &tty->flags); |
60 | #ifdef CONFIG_UNIX98_PTYS | 61 | #ifdef CONFIG_UNIX98_PTYS |
61 | if (tty->driver == ptm_driver) | 62 | if (tty->driver == ptm_driver) |
62 | devpts_pty_kill(tty->index); | 63 | devpts_pty_kill(tty->link); |
63 | #endif | 64 | #endif |
64 | tty_vhangup(tty->link); | 65 | tty_vhangup(tty->link); |
65 | } | 66 | } |
@@ -69,13 +70,13 @@ static void pty_close(struct tty_struct * tty, struct file * filp) | |||
69 | * The unthrottle routine is called by the line discipline to signal | 70 | * The unthrottle routine is called by the line discipline to signal |
70 | * that it can receive more characters. For PTY's, the TTY_THROTTLED | 71 | * that it can receive more characters. For PTY's, the TTY_THROTTLED |
71 | * flag is always set, to force the line discipline to always call the | 72 | * flag is always set, to force the line discipline to always call the |
72 | * unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE | 73 | * unthrottle routine when there are fewer than TTY_THRESHOLD_UNTHROTTLE |
73 | * characters in the queue. This is necessary since each time this | 74 | * characters in the queue. This is necessary since each time this |
74 | * happens, we need to wake up any sleeping processes that could be | 75 | * happens, we need to wake up any sleeping processes that could be |
75 | * (1) trying to send data to the pty, or (2) waiting in wait_until_sent() | 76 | * (1) trying to send data to the pty, or (2) waiting in wait_until_sent() |
76 | * for the pty buffer to be drained. | 77 | * for the pty buffer to be drained. |
77 | */ | 78 | */ |
78 | static void pty_unthrottle(struct tty_struct * tty) | 79 | static void pty_unthrottle(struct tty_struct *tty) |
79 | { | 80 | { |
80 | struct tty_struct *o_tty = tty->link; | 81 | struct tty_struct *o_tty = tty->link; |
81 | 82 | ||
@@ -87,7 +88,7 @@ static void pty_unthrottle(struct tty_struct * tty) | |||
87 | } | 88 | } |
88 | 89 | ||
89 | /* | 90 | /* |
90 | * WSH 05/24/97: modified to | 91 | * WSH 05/24/97: modified to |
91 | * (1) use space in tty->flip instead of a shared temp buffer | 92 | * (1) use space in tty->flip instead of a shared temp buffer |
92 | * The flip buffers aren't being used for a pty, so there's lots | 93 | * The flip buffers aren't being used for a pty, so there's lots |
93 | * of space available. The buffer is protected by a per-pty | 94 | * of space available. The buffer is protected by a per-pty |
@@ -100,7 +101,8 @@ static void pty_unthrottle(struct tty_struct * tty) | |||
100 | * not our partners. We can't just take the other one blindly without | 101 | * not our partners. We can't just take the other one blindly without |
101 | * risking deadlocks. | 102 | * risking deadlocks. |
102 | */ | 103 | */ |
103 | static int pty_write(struct tty_struct * tty, const unsigned char *buf, int count) | 104 | static int pty_write(struct tty_struct *tty, const unsigned char *buf, |
105 | int count) | ||
104 | { | 106 | { |
105 | struct tty_struct *to = tty->link; | 107 | struct tty_struct *to = tty->link; |
106 | int c; | 108 | int c; |
@@ -112,7 +114,7 @@ static int pty_write(struct tty_struct * tty, const unsigned char *buf, int coun | |||
112 | if (c > count) | 114 | if (c > count) |
113 | c = count; | 115 | c = count; |
114 | to->ldisc.ops->receive_buf(to, buf, NULL, c); | 116 | to->ldisc.ops->receive_buf(to, buf, NULL, c); |
115 | 117 | ||
116 | return c; | 118 | return c; |
117 | } | 119 | } |
118 | 120 | ||
@@ -128,17 +130,17 @@ static int pty_write_room(struct tty_struct *tty) | |||
128 | 130 | ||
129 | /* | 131 | /* |
130 | * WSH 05/24/97: Modified for asymmetric MASTER/SLAVE behavior | 132 | * WSH 05/24/97: Modified for asymmetric MASTER/SLAVE behavior |
131 | * The chars_in_buffer() value is used by the ldisc select() function | 133 | * The chars_in_buffer() value is used by the ldisc select() function |
132 | * to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256). | 134 | * to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256). |
133 | * The pty driver chars_in_buffer() Master/Slave must behave differently: | 135 | * The pty driver chars_in_buffer() Master/Slave must behave differently: |
134 | * | 136 | * |
135 | * The Master side needs to allow typed-ahead commands to accumulate | 137 | * The Master side needs to allow typed-ahead commands to accumulate |
136 | * while being canonicalized, so we report "our buffer" as empty until | 138 | * while being canonicalized, so we report "our buffer" as empty until |
137 | * some threshold is reached, and then report the count. (Any count > | 139 | * some threshold is reached, and then report the count. (Any count > |
138 | * WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock | 140 | * WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock |
139 | * the count returned must be 0 if no canonical data is available to be | 141 | * the count returned must be 0 if no canonical data is available to be |
140 | * read. (The N_TTY ldisc.chars_in_buffer now knows this.) | 142 | * read. (The N_TTY ldisc.chars_in_buffer now knows this.) |
141 | * | 143 | * |
142 | * The Slave side passes all characters in raw mode to the Master side's | 144 | * The Slave side passes all characters in raw mode to the Master side's |
143 | * buffer where they can be read immediately, so in this case we can | 145 | * buffer where they can be read immediately, so in this case we can |
144 | * return the true count in the buffer. | 146 | * return the true count in the buffer. |
@@ -155,21 +157,22 @@ static int pty_chars_in_buffer(struct tty_struct *tty) | |||
155 | /* The ldisc must report 0 if no characters available to be read */ | 157 | /* The ldisc must report 0 if no characters available to be read */ |
156 | count = to->ldisc.ops->chars_in_buffer(to); | 158 | count = to->ldisc.ops->chars_in_buffer(to); |
157 | 159 | ||
158 | if (tty->driver->subtype == PTY_TYPE_SLAVE) return count; | 160 | if (tty->driver->subtype == PTY_TYPE_SLAVE) |
161 | return count; | ||
159 | 162 | ||
160 | /* Master side driver ... if the other side's read buffer is less than | 163 | /* Master side driver ... if the other side's read buffer is less than |
161 | * half full, return 0 to allow writers to proceed; otherwise return | 164 | * half full, return 0 to allow writers to proceed; otherwise return |
162 | * the count. This leaves a comfortable margin to avoid overflow, | 165 | * the count. This leaves a comfortable margin to avoid overflow, |
163 | * and still allows half a buffer's worth of typed-ahead commands. | 166 | * and still allows half a buffer's worth of typed-ahead commands. |
164 | */ | 167 | */ |
165 | return ((count < N_TTY_BUF_SIZE/2) ? 0 : count); | 168 | return (count < N_TTY_BUF_SIZE/2) ? 0 : count; |
166 | } | 169 | } |
167 | 170 | ||
168 | /* Set the lock flag on a pty */ | 171 | /* Set the lock flag on a pty */ |
169 | static int pty_set_lock(struct tty_struct *tty, int __user * arg) | 172 | static int pty_set_lock(struct tty_struct *tty, int __user *arg) |
170 | { | 173 | { |
171 | int val; | 174 | int val; |
172 | if (get_user(val,arg)) | 175 | if (get_user(val, arg)) |
173 | return -EFAULT; | 176 | return -EFAULT; |
174 | if (val) | 177 | if (val) |
175 | set_bit(TTY_PTY_LOCK, &tty->flags); | 178 | set_bit(TTY_PTY_LOCK, &tty->flags); |
@@ -182,13 +185,13 @@ static void pty_flush_buffer(struct tty_struct *tty) | |||
182 | { | 185 | { |
183 | struct tty_struct *to = tty->link; | 186 | struct tty_struct *to = tty->link; |
184 | unsigned long flags; | 187 | unsigned long flags; |
185 | 188 | ||
186 | if (!to) | 189 | if (!to) |
187 | return; | 190 | return; |
188 | 191 | ||
189 | if (to->ldisc.ops->flush_buffer) | 192 | if (to->ldisc.ops->flush_buffer) |
190 | to->ldisc.ops->flush_buffer(to); | 193 | to->ldisc.ops->flush_buffer(to); |
191 | 194 | ||
192 | if (to->packet) { | 195 | if (to->packet) { |
193 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 196 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
194 | tty->ctrl_status |= TIOCPKT_FLUSHWRITE; | 197 | tty->ctrl_status |= TIOCPKT_FLUSHWRITE; |
@@ -197,7 +200,7 @@ static void pty_flush_buffer(struct tty_struct *tty) | |||
197 | } | 200 | } |
198 | } | 201 | } |
199 | 202 | ||
200 | static int pty_open(struct tty_struct *tty, struct file * filp) | 203 | static int pty_open(struct tty_struct *tty, struct file *filp) |
201 | { | 204 | { |
202 | int retval = -ENODEV; | 205 | int retval = -ENODEV; |
203 | 206 | ||
@@ -220,13 +223,65 @@ out: | |||
220 | return retval; | 223 | return retval; |
221 | } | 224 | } |
222 | 225 | ||
223 | static void pty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | 226 | static void pty_set_termios(struct tty_struct *tty, |
227 | struct ktermios *old_termios) | ||
228 | { | ||
229 | tty->termios->c_cflag &= ~(CSIZE | PARENB); | ||
230 | tty->termios->c_cflag |= (CS8 | CREAD); | ||
231 | } | ||
232 | |||
233 | static int pty_install(struct tty_driver *driver, struct tty_struct *tty) | ||
224 | { | 234 | { |
225 | tty->termios->c_cflag &= ~(CSIZE | PARENB); | 235 | struct tty_struct *o_tty; |
226 | tty->termios->c_cflag |= (CS8 | CREAD); | 236 | int idx = tty->index; |
237 | int retval; | ||
238 | |||
239 | o_tty = alloc_tty_struct(); | ||
240 | if (!o_tty) | ||
241 | return -ENOMEM; | ||
242 | if (!try_module_get(driver->other->owner)) { | ||
243 | /* This cannot in fact currently happen */ | ||
244 | free_tty_struct(o_tty); | ||
245 | return -ENOMEM; | ||
246 | } | ||
247 | initialize_tty_struct(o_tty, driver->other, idx); | ||
248 | |||
249 | /* We always use new tty termios data so we can do this | ||
250 | the easy way .. */ | ||
251 | retval = tty_init_termios(tty); | ||
252 | if (retval) | ||
253 | goto free_mem_out; | ||
254 | |||
255 | retval = tty_init_termios(o_tty); | ||
256 | if (retval) { | ||
257 | tty_free_termios(tty); | ||
258 | goto free_mem_out; | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * Everything allocated ... set up the o_tty structure. | ||
263 | */ | ||
264 | driver->other->ttys[idx] = o_tty; | ||
265 | tty_driver_kref_get(driver->other); | ||
266 | if (driver->subtype == PTY_TYPE_MASTER) | ||
267 | o_tty->count++; | ||
268 | /* Establish the links in both directions */ | ||
269 | tty->link = o_tty; | ||
270 | o_tty->link = tty; | ||
271 | |||
272 | tty_driver_kref_get(driver); | ||
273 | tty->count++; | ||
274 | driver->ttys[idx] = tty; | ||
275 | return 0; | ||
276 | free_mem_out: | ||
277 | module_put(o_tty->driver->owner); | ||
278 | free_tty_struct(o_tty); | ||
279 | return -ENOMEM; | ||
227 | } | 280 | } |
228 | 281 | ||
282 | |||
229 | static const struct tty_operations pty_ops = { | 283 | static const struct tty_operations pty_ops = { |
284 | .install = pty_install, | ||
230 | .open = pty_open, | 285 | .open = pty_open, |
231 | .close = pty_close, | 286 | .close = pty_close, |
232 | .write = pty_write, | 287 | .write = pty_write, |
@@ -329,8 +384,11 @@ static inline void legacy_pty_init(void) { } | |||
329 | * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. | 384 | * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. |
330 | */ | 385 | */ |
331 | int pty_limit = NR_UNIX98_PTY_DEFAULT; | 386 | int pty_limit = NR_UNIX98_PTY_DEFAULT; |
332 | static int pty_limit_min = 0; | 387 | static int pty_limit_min; |
333 | static int pty_limit_max = NR_UNIX98_PTY_MAX; | 388 | static int pty_limit_max = NR_UNIX98_PTY_MAX; |
389 | static int pty_count; | ||
390 | |||
391 | static struct cdev ptmx_cdev; | ||
334 | 392 | ||
335 | static struct ctl_table pty_table[] = { | 393 | static struct ctl_table pty_table[] = { |
336 | { | 394 | { |
@@ -348,6 +406,7 @@ static struct ctl_table pty_table[] = { | |||
348 | .procname = "nr", | 406 | .procname = "nr", |
349 | .maxlen = sizeof(int), | 407 | .maxlen = sizeof(int), |
350 | .mode = 0444, | 408 | .mode = 0444, |
409 | .data = &pty_count, | ||
351 | .proc_handler = &proc_dointvec, | 410 | .proc_handler = &proc_dointvec, |
352 | }, { | 411 | }, { |
353 | .ctl_name = 0 | 412 | .ctl_name = 0 |
@@ -388,7 +447,127 @@ static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, | |||
388 | return -ENOIOCTLCMD; | 447 | return -ENOIOCTLCMD; |
389 | } | 448 | } |
390 | 449 | ||
450 | /** | ||
451 | * ptm_unix98_lookup - find a pty master | ||
452 | * @driver: ptm driver | ||
453 | * @idx: tty index | ||
454 | * | ||
455 | * Look up a pty master device. Called under the tty_mutex for now. | ||
456 | * This provides our locking. | ||
457 | */ | ||
458 | |||
459 | static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver, | ||
460 | struct inode *ptm_inode, int idx) | ||
461 | { | ||
462 | struct tty_struct *tty = devpts_get_tty(ptm_inode, idx); | ||
463 | if (tty) | ||
464 | tty = tty->link; | ||
465 | return tty; | ||
466 | } | ||
467 | |||
468 | /** | ||
469 | * pts_unix98_lookup - find a pty slave | ||
470 | * @driver: pts driver | ||
471 | * @idx: tty index | ||
472 | * | ||
473 | * Look up a pty master device. Called under the tty_mutex for now. | ||
474 | * This provides our locking. | ||
475 | */ | ||
476 | |||
477 | static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver, | ||
478 | struct inode *pts_inode, int idx) | ||
479 | { | ||
480 | struct tty_struct *tty = devpts_get_tty(pts_inode, idx); | ||
481 | /* Master must be open before slave */ | ||
482 | if (!tty) | ||
483 | return ERR_PTR(-EIO); | ||
484 | return tty; | ||
485 | } | ||
486 | |||
487 | static void pty_unix98_shutdown(struct tty_struct *tty) | ||
488 | { | ||
489 | /* We have our own method as we don't use the tty index */ | ||
490 | kfree(tty->termios); | ||
491 | } | ||
492 | |||
493 | /* We have no need to install and remove our tty objects as devpts does all | ||
494 | the work for us */ | ||
495 | |||
496 | static int pty_unix98_install(struct tty_driver *driver, struct tty_struct *tty) | ||
497 | { | ||
498 | struct tty_struct *o_tty; | ||
499 | int idx = tty->index; | ||
500 | |||
501 | o_tty = alloc_tty_struct(); | ||
502 | if (!o_tty) | ||
503 | return -ENOMEM; | ||
504 | if (!try_module_get(driver->other->owner)) { | ||
505 | /* This cannot in fact currently happen */ | ||
506 | free_tty_struct(o_tty); | ||
507 | return -ENOMEM; | ||
508 | } | ||
509 | initialize_tty_struct(o_tty, driver->other, idx); | ||
510 | |||
511 | tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); | ||
512 | if (tty->termios == NULL) | ||
513 | goto free_mem_out; | ||
514 | *tty->termios = driver->init_termios; | ||
515 | tty->termios_locked = tty->termios + 1; | ||
516 | |||
517 | o_tty->termios = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); | ||
518 | if (o_tty->termios == NULL) | ||
519 | goto free_mem_out; | ||
520 | *o_tty->termios = driver->other->init_termios; | ||
521 | o_tty->termios_locked = o_tty->termios + 1; | ||
522 | |||
523 | tty_driver_kref_get(driver->other); | ||
524 | if (driver->subtype == PTY_TYPE_MASTER) | ||
525 | o_tty->count++; | ||
526 | /* Establish the links in both directions */ | ||
527 | tty->link = o_tty; | ||
528 | o_tty->link = tty; | ||
529 | /* | ||
530 | * All structures have been allocated, so now we install them. | ||
531 | * Failures after this point use release_tty to clean up, so | ||
532 | * there's no need to null out the local pointers. | ||
533 | */ | ||
534 | tty_driver_kref_get(driver); | ||
535 | tty->count++; | ||
536 | pty_count++; | ||
537 | return 0; | ||
538 | free_mem_out: | ||
539 | kfree(o_tty->termios); | ||
540 | module_put(o_tty->driver->owner); | ||
541 | free_tty_struct(o_tty); | ||
542 | kfree(tty->termios); | ||
543 | return -ENOMEM; | ||
544 | } | ||
545 | |||
546 | static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty) | ||
547 | { | ||
548 | pty_count--; | ||
549 | } | ||
550 | |||
551 | static const struct tty_operations ptm_unix98_ops = { | ||
552 | .lookup = ptm_unix98_lookup, | ||
553 | .install = pty_unix98_install, | ||
554 | .remove = pty_unix98_remove, | ||
555 | .open = pty_open, | ||
556 | .close = pty_close, | ||
557 | .write = pty_write, | ||
558 | .write_room = pty_write_room, | ||
559 | .flush_buffer = pty_flush_buffer, | ||
560 | .chars_in_buffer = pty_chars_in_buffer, | ||
561 | .unthrottle = pty_unthrottle, | ||
562 | .set_termios = pty_set_termios, | ||
563 | .ioctl = pty_unix98_ioctl, | ||
564 | .shutdown = pty_unix98_shutdown | ||
565 | }; | ||
566 | |||
391 | static const struct tty_operations pty_unix98_ops = { | 567 | static const struct tty_operations pty_unix98_ops = { |
568 | .lookup = pts_unix98_lookup, | ||
569 | .install = pty_unix98_install, | ||
570 | .remove = pty_unix98_remove, | ||
392 | .open = pty_open, | 571 | .open = pty_open, |
393 | .close = pty_close, | 572 | .close = pty_close, |
394 | .write = pty_write, | 573 | .write = pty_write, |
@@ -397,9 +576,73 @@ static const struct tty_operations pty_unix98_ops = { | |||
397 | .chars_in_buffer = pty_chars_in_buffer, | 576 | .chars_in_buffer = pty_chars_in_buffer, |
398 | .unthrottle = pty_unthrottle, | 577 | .unthrottle = pty_unthrottle, |
399 | .set_termios = pty_set_termios, | 578 | .set_termios = pty_set_termios, |
400 | .ioctl = pty_unix98_ioctl | 579 | .shutdown = pty_unix98_shutdown |
401 | }; | 580 | }; |
402 | 581 | ||
582 | /** | ||
583 | * ptmx_open - open a unix 98 pty master | ||
584 | * @inode: inode of device file | ||
585 | * @filp: file pointer to tty | ||
586 | * | ||
587 | * Allocate a unix98 pty master device from the ptmx driver. | ||
588 | * | ||
589 | * Locking: tty_mutex protects the init_dev work. tty->count should | ||
590 | * protect the rest. | ||
591 | * allocated_ptys_lock handles the list of free pty numbers | ||
592 | */ | ||
593 | |||
594 | static int __ptmx_open(struct inode *inode, struct file *filp) | ||
595 | { | ||
596 | struct tty_struct *tty; | ||
597 | int retval; | ||
598 | int index; | ||
599 | |||
600 | nonseekable_open(inode, filp); | ||
601 | |||
602 | /* find a device that is not in use. */ | ||
603 | index = devpts_new_index(inode); | ||
604 | if (index < 0) | ||
605 | return index; | ||
606 | |||
607 | mutex_lock(&tty_mutex); | ||
608 | tty = tty_init_dev(ptm_driver, index, 1); | ||
609 | mutex_unlock(&tty_mutex); | ||
610 | |||
611 | if (IS_ERR(tty)) { | ||
612 | retval = PTR_ERR(tty); | ||
613 | goto out; | ||
614 | } | ||
615 | |||
616 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ | ||
617 | filp->private_data = tty; | ||
618 | file_move(filp, &tty->tty_files); | ||
619 | |||
620 | retval = devpts_pty_new(inode, tty->link); | ||
621 | if (retval) | ||
622 | goto out1; | ||
623 | |||
624 | retval = ptm_driver->ops->open(tty, filp); | ||
625 | if (!retval) | ||
626 | return 0; | ||
627 | out1: | ||
628 | tty_release_dev(filp); | ||
629 | return retval; | ||
630 | out: | ||
631 | devpts_kill_index(inode, index); | ||
632 | return retval; | ||
633 | } | ||
634 | |||
635 | static int ptmx_open(struct inode *inode, struct file *filp) | ||
636 | { | ||
637 | int ret; | ||
638 | |||
639 | lock_kernel(); | ||
640 | ret = __ptmx_open(inode, filp); | ||
641 | unlock_kernel(); | ||
642 | return ret; | ||
643 | } | ||
644 | |||
645 | static struct file_operations ptmx_fops; | ||
403 | 646 | ||
404 | static void __init unix98_pty_init(void) | 647 | static void __init unix98_pty_init(void) |
405 | { | 648 | { |
@@ -427,7 +670,7 @@ static void __init unix98_pty_init(void) | |||
427 | ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | | 670 | ptm_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | |
428 | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; | 671 | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; |
429 | ptm_driver->other = pts_driver; | 672 | ptm_driver->other = pts_driver; |
430 | tty_set_operations(ptm_driver, &pty_unix98_ops); | 673 | tty_set_operations(ptm_driver, &ptm_unix98_ops); |
431 | 674 | ||
432 | pts_driver->owner = THIS_MODULE; | 675 | pts_driver->owner = THIS_MODULE; |
433 | pts_driver->driver_name = "pty_slave"; | 676 | pts_driver->driver_name = "pty_slave"; |
@@ -443,16 +686,26 @@ static void __init unix98_pty_init(void) | |||
443 | pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | | 686 | pts_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | |
444 | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; | 687 | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_DEVPTS_MEM; |
445 | pts_driver->other = ptm_driver; | 688 | pts_driver->other = ptm_driver; |
446 | tty_set_operations(pts_driver, &pty_ops); | 689 | tty_set_operations(pts_driver, &pty_unix98_ops); |
447 | 690 | ||
448 | if (tty_register_driver(ptm_driver)) | 691 | if (tty_register_driver(ptm_driver)) |
449 | panic("Couldn't register Unix98 ptm driver"); | 692 | panic("Couldn't register Unix98 ptm driver"); |
450 | if (tty_register_driver(pts_driver)) | 693 | if (tty_register_driver(pts_driver)) |
451 | panic("Couldn't register Unix98 pts driver"); | 694 | panic("Couldn't register Unix98 pts driver"); |
452 | 695 | ||
453 | pty_table[1].data = &ptm_driver->refcount; | ||
454 | register_sysctl_table(pty_root_table); | 696 | register_sysctl_table(pty_root_table); |
697 | |||
698 | /* Now create the /dev/ptmx special device */ | ||
699 | tty_default_fops(&ptmx_fops); | ||
700 | ptmx_fops.open = ptmx_open; | ||
701 | |||
702 | cdev_init(&ptmx_cdev, &ptmx_fops); | ||
703 | if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || | ||
704 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) | ||
705 | panic("Couldn't register /dev/ptmx driver\n"); | ||
706 | device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); | ||
455 | } | 707 | } |
708 | |||
456 | #else | 709 | #else |
457 | static inline void unix98_pty_init(void) { } | 710 | static inline void unix98_pty_init(void) { } |
458 | #endif | 711 | #endif |
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 19db1eb87c26..8b8f07a7f505 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -405,9 +405,9 @@ static unsigned int stl_baudrates[] = { | |||
405 | 405 | ||
406 | static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); | 406 | static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); |
407 | static int stl_brdinit(struct stlbrd *brdp); | 407 | static int stl_brdinit(struct stlbrd *brdp); |
408 | static int stl_getportstats(struct stlport *portp, comstats_t __user *cp); | 408 | static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); |
409 | static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); | 409 | static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); |
410 | static int stl_waitcarrier(struct stlport *portp, struct file *filp); | 410 | static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp, struct file *filp); |
411 | 411 | ||
412 | /* | 412 | /* |
413 | * CD1400 uart specific handling functions. | 413 | * CD1400 uart specific handling functions. |
@@ -612,8 +612,9 @@ static struct class *stallion_class; | |||
612 | static void stl_cd_change(struct stlport *portp) | 612 | static void stl_cd_change(struct stlport *portp) |
613 | { | 613 | { |
614 | unsigned int oldsigs = portp->sigs; | 614 | unsigned int oldsigs = portp->sigs; |
615 | struct tty_struct *tty = tty_port_tty_get(&portp->port); | ||
615 | 616 | ||
616 | if (!portp->port.tty) | 617 | if (!tty) |
617 | return; | 618 | return; |
618 | 619 | ||
619 | portp->sigs = stl_getsignals(portp); | 620 | portp->sigs = stl_getsignals(portp); |
@@ -623,7 +624,8 @@ static void stl_cd_change(struct stlport *portp) | |||
623 | 624 | ||
624 | if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) | 625 | if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) |
625 | if (portp->port.flags & ASYNC_CHECK_CD) | 626 | if (portp->port.flags & ASYNC_CHECK_CD) |
626 | tty_hangup(portp->port.tty); | 627 | tty_hangup(tty); |
628 | tty_kref_put(tty); | ||
627 | } | 629 | } |
628 | 630 | ||
629 | /* | 631 | /* |
@@ -734,7 +736,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
734 | * On the first open of the device setup the port hardware, and | 736 | * On the first open of the device setup the port hardware, and |
735 | * initialize the per port data structure. | 737 | * initialize the per port data structure. |
736 | */ | 738 | */ |
737 | portp->port.tty = tty; | 739 | tty_port_tty_set(&portp->port, tty); |
738 | tty->driver_data = portp; | 740 | tty->driver_data = portp; |
739 | portp->port.count++; | 741 | portp->port.count++; |
740 | 742 | ||
@@ -774,7 +776,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
774 | * then also we might have to wait for carrier. | 776 | * then also we might have to wait for carrier. |
775 | */ | 777 | */ |
776 | if (!(filp->f_flags & O_NONBLOCK)) | 778 | if (!(filp->f_flags & O_NONBLOCK)) |
777 | if ((rc = stl_waitcarrier(portp, filp)) != 0) | 779 | if ((rc = stl_waitcarrier(tty, portp, filp)) != 0) |
778 | return rc; | 780 | return rc; |
779 | 781 | ||
780 | portp->port.flags |= ASYNC_NORMAL_ACTIVE; | 782 | portp->port.flags |= ASYNC_NORMAL_ACTIVE; |
@@ -789,7 +791,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
789 | * maybe because if we are clocal then we don't need to wait... | 791 | * maybe because if we are clocal then we don't need to wait... |
790 | */ | 792 | */ |
791 | 793 | ||
792 | static int stl_waitcarrier(struct stlport *portp, struct file *filp) | 794 | static int stl_waitcarrier(struct tty_struct *tty, struct stlport *portp, |
795 | struct file *filp) | ||
793 | { | 796 | { |
794 | unsigned long flags; | 797 | unsigned long flags; |
795 | int rc, doclocal; | 798 | int rc, doclocal; |
@@ -801,7 +804,7 @@ static int stl_waitcarrier(struct stlport *portp, struct file *filp) | |||
801 | 804 | ||
802 | spin_lock_irqsave(&stallion_lock, flags); | 805 | spin_lock_irqsave(&stallion_lock, flags); |
803 | 806 | ||
804 | if (portp->port.tty->termios->c_cflag & CLOCAL) | 807 | if (tty->termios->c_cflag & CLOCAL) |
805 | doclocal++; | 808 | doclocal++; |
806 | 809 | ||
807 | portp->openwaitcnt++; | 810 | portp->openwaitcnt++; |
@@ -846,8 +849,6 @@ static void stl_flushbuffer(struct tty_struct *tty) | |||
846 | 849 | ||
847 | pr_debug("stl_flushbuffer(tty=%p)\n", tty); | 850 | pr_debug("stl_flushbuffer(tty=%p)\n", tty); |
848 | 851 | ||
849 | if (tty == NULL) | ||
850 | return; | ||
851 | portp = tty->driver_data; | 852 | portp = tty->driver_data; |
852 | if (portp == NULL) | 853 | if (portp == NULL) |
853 | return; | 854 | return; |
@@ -865,8 +866,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) | |||
865 | 866 | ||
866 | pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout); | 867 | pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout); |
867 | 868 | ||
868 | if (tty == NULL) | ||
869 | return; | ||
870 | portp = tty->driver_data; | 869 | portp = tty->driver_data; |
871 | if (portp == NULL) | 870 | if (portp == NULL) |
872 | return; | 871 | return; |
@@ -949,7 +948,7 @@ static void stl_close(struct tty_struct *tty, struct file *filp) | |||
949 | tty_ldisc_flush(tty); | 948 | tty_ldisc_flush(tty); |
950 | 949 | ||
951 | tty->closing = 0; | 950 | tty->closing = 0; |
952 | portp->port.tty = NULL; | 951 | tty_port_tty_set(&portp->port, NULL); |
953 | 952 | ||
954 | if (portp->openwaitcnt) { | 953 | if (portp->openwaitcnt) { |
955 | if (portp->close_delay) | 954 | if (portp->close_delay) |
@@ -1033,8 +1032,6 @@ static int stl_putchar(struct tty_struct *tty, unsigned char ch) | |||
1033 | 1032 | ||
1034 | pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch); | 1033 | pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch); |
1035 | 1034 | ||
1036 | if (tty == NULL) | ||
1037 | return -EINVAL; | ||
1038 | portp = tty->driver_data; | 1035 | portp = tty->driver_data; |
1039 | if (portp == NULL) | 1036 | if (portp == NULL) |
1040 | return -EINVAL; | 1037 | return -EINVAL; |
@@ -1070,8 +1067,6 @@ static void stl_flushchars(struct tty_struct *tty) | |||
1070 | 1067 | ||
1071 | pr_debug("stl_flushchars(tty=%p)\n", tty); | 1068 | pr_debug("stl_flushchars(tty=%p)\n", tty); |
1072 | 1069 | ||
1073 | if (tty == NULL) | ||
1074 | return; | ||
1075 | portp = tty->driver_data; | 1070 | portp = tty->driver_data; |
1076 | if (portp == NULL) | 1071 | if (portp == NULL) |
1077 | return; | 1072 | return; |
@@ -1090,8 +1085,6 @@ static int stl_writeroom(struct tty_struct *tty) | |||
1090 | 1085 | ||
1091 | pr_debug("stl_writeroom(tty=%p)\n", tty); | 1086 | pr_debug("stl_writeroom(tty=%p)\n", tty); |
1092 | 1087 | ||
1093 | if (tty == NULL) | ||
1094 | return 0; | ||
1095 | portp = tty->driver_data; | 1088 | portp = tty->driver_data; |
1096 | if (portp == NULL) | 1089 | if (portp == NULL) |
1097 | return 0; | 1090 | return 0; |
@@ -1122,8 +1115,6 @@ static int stl_charsinbuffer(struct tty_struct *tty) | |||
1122 | 1115 | ||
1123 | pr_debug("stl_charsinbuffer(tty=%p)\n", tty); | 1116 | pr_debug("stl_charsinbuffer(tty=%p)\n", tty); |
1124 | 1117 | ||
1125 | if (tty == NULL) | ||
1126 | return 0; | ||
1127 | portp = tty->driver_data; | 1118 | portp = tty->driver_data; |
1128 | if (portp == NULL) | 1119 | if (portp == NULL) |
1129 | return 0; | 1120 | return 0; |
@@ -1183,8 +1174,9 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp) | |||
1183 | * just quietly ignore any requests to change irq, etc. | 1174 | * just quietly ignore any requests to change irq, etc. |
1184 | */ | 1175 | */ |
1185 | 1176 | ||
1186 | static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp) | 1177 | static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp) |
1187 | { | 1178 | { |
1179 | struct stlport * portp = tty->driver_data; | ||
1188 | struct serial_struct sio; | 1180 | struct serial_struct sio; |
1189 | 1181 | ||
1190 | pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp); | 1182 | pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp); |
@@ -1205,7 +1197,7 @@ static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp) | |||
1205 | portp->close_delay = sio.close_delay; | 1197 | portp->close_delay = sio.close_delay; |
1206 | portp->closing_wait = sio.closing_wait; | 1198 | portp->closing_wait = sio.closing_wait; |
1207 | portp->custom_divisor = sio.custom_divisor; | 1199 | portp->custom_divisor = sio.custom_divisor; |
1208 | stl_setport(portp, portp->port.tty->termios); | 1200 | stl_setport(portp, tty->termios); |
1209 | return 0; | 1201 | return 0; |
1210 | } | 1202 | } |
1211 | 1203 | ||
@@ -1215,8 +1207,6 @@ static int stl_tiocmget(struct tty_struct *tty, struct file *file) | |||
1215 | { | 1207 | { |
1216 | struct stlport *portp; | 1208 | struct stlport *portp; |
1217 | 1209 | ||
1218 | if (tty == NULL) | ||
1219 | return -ENODEV; | ||
1220 | portp = tty->driver_data; | 1210 | portp = tty->driver_data; |
1221 | if (portp == NULL) | 1211 | if (portp == NULL) |
1222 | return -ENODEV; | 1212 | return -ENODEV; |
@@ -1232,8 +1222,6 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file, | |||
1232 | struct stlport *portp; | 1222 | struct stlport *portp; |
1233 | int rts = -1, dtr = -1; | 1223 | int rts = -1, dtr = -1; |
1234 | 1224 | ||
1235 | if (tty == NULL) | ||
1236 | return -ENODEV; | ||
1237 | portp = tty->driver_data; | 1225 | portp = tty->driver_data; |
1238 | if (portp == NULL) | 1226 | if (portp == NULL) |
1239 | return -ENODEV; | 1227 | return -ENODEV; |
@@ -1262,8 +1250,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd | |||
1262 | pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd, | 1250 | pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd, |
1263 | arg); | 1251 | arg); |
1264 | 1252 | ||
1265 | if (tty == NULL) | ||
1266 | return -ENODEV; | ||
1267 | portp = tty->driver_data; | 1253 | portp = tty->driver_data; |
1268 | if (portp == NULL) | 1254 | if (portp == NULL) |
1269 | return -ENODEV; | 1255 | return -ENODEV; |
@@ -1282,10 +1268,10 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd | |||
1282 | rc = stl_getserial(portp, argp); | 1268 | rc = stl_getserial(portp, argp); |
1283 | break; | 1269 | break; |
1284 | case TIOCSSERIAL: | 1270 | case TIOCSSERIAL: |
1285 | rc = stl_setserial(portp, argp); | 1271 | rc = stl_setserial(tty, argp); |
1286 | break; | 1272 | break; |
1287 | case COM_GETPORTSTATS: | 1273 | case COM_GETPORTSTATS: |
1288 | rc = stl_getportstats(portp, argp); | 1274 | rc = stl_getportstats(tty, portp, argp); |
1289 | break; | 1275 | break; |
1290 | case COM_CLRPORTSTATS: | 1276 | case COM_CLRPORTSTATS: |
1291 | rc = stl_clrportstats(portp, argp); | 1277 | rc = stl_clrportstats(portp, argp); |
@@ -1317,8 +1303,6 @@ static void stl_start(struct tty_struct *tty) | |||
1317 | 1303 | ||
1318 | pr_debug("stl_start(tty=%p)\n", tty); | 1304 | pr_debug("stl_start(tty=%p)\n", tty); |
1319 | 1305 | ||
1320 | if (tty == NULL) | ||
1321 | return; | ||
1322 | portp = tty->driver_data; | 1306 | portp = tty->driver_data; |
1323 | if (portp == NULL) | 1307 | if (portp == NULL) |
1324 | return; | 1308 | return; |
@@ -1334,8 +1318,6 @@ static void stl_settermios(struct tty_struct *tty, struct ktermios *old) | |||
1334 | 1318 | ||
1335 | pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old); | 1319 | pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old); |
1336 | 1320 | ||
1337 | if (tty == NULL) | ||
1338 | return; | ||
1339 | portp = tty->driver_data; | 1321 | portp = tty->driver_data; |
1340 | if (portp == NULL) | 1322 | if (portp == NULL) |
1341 | return; | 1323 | return; |
@@ -1369,8 +1351,6 @@ static void stl_throttle(struct tty_struct *tty) | |||
1369 | 1351 | ||
1370 | pr_debug("stl_throttle(tty=%p)\n", tty); | 1352 | pr_debug("stl_throttle(tty=%p)\n", tty); |
1371 | 1353 | ||
1372 | if (tty == NULL) | ||
1373 | return; | ||
1374 | portp = tty->driver_data; | 1354 | portp = tty->driver_data; |
1375 | if (portp == NULL) | 1355 | if (portp == NULL) |
1376 | return; | 1356 | return; |
@@ -1389,8 +1369,6 @@ static void stl_unthrottle(struct tty_struct *tty) | |||
1389 | 1369 | ||
1390 | pr_debug("stl_unthrottle(tty=%p)\n", tty); | 1370 | pr_debug("stl_unthrottle(tty=%p)\n", tty); |
1391 | 1371 | ||
1392 | if (tty == NULL) | ||
1393 | return; | ||
1394 | portp = tty->driver_data; | 1372 | portp = tty->driver_data; |
1395 | if (portp == NULL) | 1373 | if (portp == NULL) |
1396 | return; | 1374 | return; |
@@ -1410,8 +1388,6 @@ static void stl_stop(struct tty_struct *tty) | |||
1410 | 1388 | ||
1411 | pr_debug("stl_stop(tty=%p)\n", tty); | 1389 | pr_debug("stl_stop(tty=%p)\n", tty); |
1412 | 1390 | ||
1413 | if (tty == NULL) | ||
1414 | return; | ||
1415 | portp = tty->driver_data; | 1391 | portp = tty->driver_data; |
1416 | if (portp == NULL) | 1392 | if (portp == NULL) |
1417 | return; | 1393 | return; |
@@ -1432,8 +1408,6 @@ static void stl_hangup(struct tty_struct *tty) | |||
1432 | 1408 | ||
1433 | pr_debug("stl_hangup(tty=%p)\n", tty); | 1409 | pr_debug("stl_hangup(tty=%p)\n", tty); |
1434 | 1410 | ||
1435 | if (tty == NULL) | ||
1436 | return; | ||
1437 | portp = tty->driver_data; | 1411 | portp = tty->driver_data; |
1438 | if (portp == NULL) | 1412 | if (portp == NULL) |
1439 | return; | 1413 | return; |
@@ -1452,7 +1426,7 @@ static void stl_hangup(struct tty_struct *tty) | |||
1452 | portp->tx.head = NULL; | 1426 | portp->tx.head = NULL; |
1453 | portp->tx.tail = NULL; | 1427 | portp->tx.tail = NULL; |
1454 | } | 1428 | } |
1455 | portp->port.tty = NULL; | 1429 | tty_port_tty_set(&portp->port, NULL); |
1456 | portp->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 1430 | portp->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
1457 | portp->port.count = 0; | 1431 | portp->port.count = 0; |
1458 | wake_up_interruptible(&portp->port.open_wait); | 1432 | wake_up_interruptible(&portp->port.open_wait); |
@@ -1466,8 +1440,6 @@ static int stl_breakctl(struct tty_struct *tty, int state) | |||
1466 | 1440 | ||
1467 | pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state); | 1441 | pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state); |
1468 | 1442 | ||
1469 | if (tty == NULL) | ||
1470 | return -EINVAL; | ||
1471 | portp = tty->driver_data; | 1443 | portp = tty->driver_data; |
1472 | if (portp == NULL) | 1444 | if (portp == NULL) |
1473 | return -EINVAL; | 1445 | return -EINVAL; |
@@ -1484,8 +1456,6 @@ static void stl_sendxchar(struct tty_struct *tty, char ch) | |||
1484 | 1456 | ||
1485 | pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch); | 1457 | pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch); |
1486 | 1458 | ||
1487 | if (tty == NULL) | ||
1488 | return; | ||
1489 | portp = tty->driver_data; | 1459 | portp = tty->driver_data; |
1490 | if (portp == NULL) | 1460 | if (portp == NULL) |
1491 | return; | 1461 | return; |
@@ -1805,7 +1775,7 @@ static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp) | |||
1805 | "(size=%Zd)\n", sizeof(struct stlport)); | 1775 | "(size=%Zd)\n", sizeof(struct stlport)); |
1806 | break; | 1776 | break; |
1807 | } | 1777 | } |
1808 | 1778 | tty_port_init(&portp->port); | |
1809 | portp->magic = STL_PORTMAGIC; | 1779 | portp->magic = STL_PORTMAGIC; |
1810 | portp->portnr = i; | 1780 | portp->portnr = i; |
1811 | portp->brdnr = panelp->brdnr; | 1781 | portp->brdnr = panelp->brdnr; |
@@ -1832,6 +1802,7 @@ static void stl_cleanup_panels(struct stlbrd *brdp) | |||
1832 | struct stlpanel *panelp; | 1802 | struct stlpanel *panelp; |
1833 | struct stlport *portp; | 1803 | struct stlport *portp; |
1834 | unsigned int j, k; | 1804 | unsigned int j, k; |
1805 | struct tty_struct *tty; | ||
1835 | 1806 | ||
1836 | for (j = 0; j < STL_MAXPANELS; j++) { | 1807 | for (j = 0; j < STL_MAXPANELS; j++) { |
1837 | panelp = brdp->panels[j]; | 1808 | panelp = brdp->panels[j]; |
@@ -1841,8 +1812,11 @@ static void stl_cleanup_panels(struct stlbrd *brdp) | |||
1841 | portp = panelp->ports[k]; | 1812 | portp = panelp->ports[k]; |
1842 | if (portp == NULL) | 1813 | if (portp == NULL) |
1843 | continue; | 1814 | continue; |
1844 | if (portp->port.tty != NULL) | 1815 | tty = tty_port_tty_get(&portp->port); |
1845 | stl_hangup(portp->port.tty); | 1816 | if (tty != NULL) { |
1817 | stl_hangup(tty); | ||
1818 | tty_kref_put(tty); | ||
1819 | } | ||
1846 | kfree(portp->tx.buf); | 1820 | kfree(portp->tx.buf); |
1847 | kfree(portp); | 1821 | kfree(portp); |
1848 | } | 1822 | } |
@@ -2498,7 +2472,7 @@ static struct stlport *stl_getport(int brdnr, int panelnr, int portnr) | |||
2498 | * what port to get stats for (used through board control device). | 2472 | * what port to get stats for (used through board control device). |
2499 | */ | 2473 | */ |
2500 | 2474 | ||
2501 | static int stl_getportstats(struct stlport *portp, comstats_t __user *cp) | 2475 | static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp) |
2502 | { | 2476 | { |
2503 | comstats_t stl_comstats; | 2477 | comstats_t stl_comstats; |
2504 | unsigned char *head, *tail; | 2478 | unsigned char *head, *tail; |
@@ -2525,18 +2499,17 @@ static int stl_getportstats(struct stlport *portp, comstats_t __user *cp) | |||
2525 | portp->stats.rxbuffered = 0; | 2499 | portp->stats.rxbuffered = 0; |
2526 | 2500 | ||
2527 | spin_lock_irqsave(&stallion_lock, flags); | 2501 | spin_lock_irqsave(&stallion_lock, flags); |
2528 | if (portp->port.tty != NULL) | 2502 | if (tty != NULL && portp->port.tty == tty) { |
2529 | if (portp->port.tty->driver_data == portp) { | 2503 | portp->stats.ttystate = tty->flags; |
2530 | portp->stats.ttystate = portp->port.tty->flags; | 2504 | /* No longer available as a statistic */ |
2531 | /* No longer available as a statistic */ | 2505 | portp->stats.rxbuffered = 1; /*tty->flip.count; */ |
2532 | portp->stats.rxbuffered = 1; /*portp->port.tty->flip.count; */ | 2506 | if (tty->termios != NULL) { |
2533 | if (portp->port.tty->termios != NULL) { | 2507 | portp->stats.cflags = tty->termios->c_cflag; |
2534 | portp->stats.cflags = portp->port.tty->termios->c_cflag; | 2508 | portp->stats.iflags = tty->termios->c_iflag; |
2535 | portp->stats.iflags = portp->port.tty->termios->c_iflag; | 2509 | portp->stats.oflags = tty->termios->c_oflag; |
2536 | portp->stats.oflags = portp->port.tty->termios->c_oflag; | 2510 | portp->stats.lflags = tty->termios->c_lflag; |
2537 | portp->stats.lflags = portp->port.tty->termios->c_lflag; | ||
2538 | } | ||
2539 | } | 2511 | } |
2512 | } | ||
2540 | spin_unlock_irqrestore(&stallion_lock, flags); | 2513 | spin_unlock_irqrestore(&stallion_lock, flags); |
2541 | 2514 | ||
2542 | head = portp->tx.head; | 2515 | head = portp->tx.head; |
@@ -2640,7 +2613,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns | |||
2640 | 2613 | ||
2641 | switch (cmd) { | 2614 | switch (cmd) { |
2642 | case COM_GETPORTSTATS: | 2615 | case COM_GETPORTSTATS: |
2643 | rc = stl_getportstats(NULL, argp); | 2616 | rc = stl_getportstats(NULL, NULL, argp); |
2644 | break; | 2617 | break; |
2645 | case COM_CLRPORTSTATS: | 2618 | case COM_CLRPORTSTATS: |
2646 | rc = stl_clrportstats(NULL, argp); | 2619 | rc = stl_clrportstats(NULL, argp); |
@@ -3243,7 +3216,7 @@ static void stl_cd1400flowctrl(struct stlport *portp, int state) | |||
3243 | 3216 | ||
3244 | if (portp == NULL) | 3217 | if (portp == NULL) |
3245 | return; | 3218 | return; |
3246 | tty = portp->port.tty; | 3219 | tty = tty_port_tty_get(&portp->port); |
3247 | if (tty == NULL) | 3220 | if (tty == NULL) |
3248 | return; | 3221 | return; |
3249 | 3222 | ||
@@ -3288,6 +3261,7 @@ static void stl_cd1400flowctrl(struct stlport *portp, int state) | |||
3288 | 3261 | ||
3289 | BRDDISABLE(portp->brdnr); | 3262 | BRDDISABLE(portp->brdnr); |
3290 | spin_unlock_irqrestore(&brd_lock, flags); | 3263 | spin_unlock_irqrestore(&brd_lock, flags); |
3264 | tty_kref_put(tty); | ||
3291 | } | 3265 | } |
3292 | 3266 | ||
3293 | /*****************************************************************************/ | 3267 | /*****************************************************************************/ |
@@ -3305,7 +3279,7 @@ static void stl_cd1400sendflow(struct stlport *portp, int state) | |||
3305 | 3279 | ||
3306 | if (portp == NULL) | 3280 | if (portp == NULL) |
3307 | return; | 3281 | return; |
3308 | tty = portp->port.tty; | 3282 | tty = tty_port_tty_get(&portp->port); |
3309 | if (tty == NULL) | 3283 | if (tty == NULL) |
3310 | return; | 3284 | return; |
3311 | 3285 | ||
@@ -3325,6 +3299,7 @@ static void stl_cd1400sendflow(struct stlport *portp, int state) | |||
3325 | } | 3299 | } |
3326 | BRDDISABLE(portp->brdnr); | 3300 | BRDDISABLE(portp->brdnr); |
3327 | spin_unlock_irqrestore(&brd_lock, flags); | 3301 | spin_unlock_irqrestore(&brd_lock, flags); |
3302 | tty_kref_put(tty); | ||
3328 | } | 3303 | } |
3329 | 3304 | ||
3330 | /*****************************************************************************/ | 3305 | /*****************************************************************************/ |
@@ -3478,6 +3453,7 @@ static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr) | |||
3478 | int len, stlen; | 3453 | int len, stlen; |
3479 | char *head, *tail; | 3454 | char *head, *tail; |
3480 | unsigned char ioack, srer; | 3455 | unsigned char ioack, srer; |
3456 | struct tty_struct *tty; | ||
3481 | 3457 | ||
3482 | pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr); | 3458 | pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr); |
3483 | 3459 | ||
@@ -3504,8 +3480,11 @@ static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr) | |||
3504 | if ((len == 0) || ((len < STL_TXBUFLOW) && | 3480 | if ((len == 0) || ((len < STL_TXBUFLOW) && |
3505 | (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { | 3481 | (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { |
3506 | set_bit(ASYI_TXLOW, &portp->istate); | 3482 | set_bit(ASYI_TXLOW, &portp->istate); |
3507 | if (portp->port.tty) | 3483 | tty = tty_port_tty_get(&portp->port); |
3508 | tty_wakeup(portp->port.tty); | 3484 | if (tty) { |
3485 | tty_wakeup(tty); | ||
3486 | tty_kref_put(tty); | ||
3487 | } | ||
3509 | } | 3488 | } |
3510 | 3489 | ||
3511 | if (len == 0) { | 3490 | if (len == 0) { |
@@ -3569,7 +3548,7 @@ static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr) | |||
3569 | return; | 3548 | return; |
3570 | } | 3549 | } |
3571 | portp = panelp->ports[(ioack >> 3)]; | 3550 | portp = panelp->ports[(ioack >> 3)]; |
3572 | tty = portp->port.tty; | 3551 | tty = tty_port_tty_get(&portp->port); |
3573 | 3552 | ||
3574 | if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) { | 3553 | if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) { |
3575 | outb((RDCR + portp->uartaddr), ioaddr); | 3554 | outb((RDCR + portp->uartaddr), ioaddr); |
@@ -3633,10 +3612,12 @@ static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr) | |||
3633 | } | 3612 | } |
3634 | } else { | 3613 | } else { |
3635 | printk("STALLION: bad RX interrupt ack value=%x\n", ioack); | 3614 | printk("STALLION: bad RX interrupt ack value=%x\n", ioack); |
3615 | tty_kref_put(tty); | ||
3636 | return; | 3616 | return; |
3637 | } | 3617 | } |
3638 | 3618 | ||
3639 | stl_rxalldone: | 3619 | stl_rxalldone: |
3620 | tty_kref_put(tty); | ||
3640 | outb((EOSRR + portp->uartaddr), ioaddr); | 3621 | outb((EOSRR + portp->uartaddr), ioaddr); |
3641 | outb(0, (ioaddr + EREG_DATA)); | 3622 | outb(0, (ioaddr + EREG_DATA)); |
3642 | } | 3623 | } |
@@ -4175,7 +4156,7 @@ static void stl_sc26198flowctrl(struct stlport *portp, int state) | |||
4175 | 4156 | ||
4176 | if (portp == NULL) | 4157 | if (portp == NULL) |
4177 | return; | 4158 | return; |
4178 | tty = portp->port.tty; | 4159 | tty = tty_port_tty_get(&portp->port); |
4179 | if (tty == NULL) | 4160 | if (tty == NULL) |
4180 | return; | 4161 | return; |
4181 | 4162 | ||
@@ -4226,6 +4207,7 @@ static void stl_sc26198flowctrl(struct stlport *portp, int state) | |||
4226 | 4207 | ||
4227 | BRDDISABLE(portp->brdnr); | 4208 | BRDDISABLE(portp->brdnr); |
4228 | spin_unlock_irqrestore(&brd_lock, flags); | 4209 | spin_unlock_irqrestore(&brd_lock, flags); |
4210 | tty_kref_put(tty); | ||
4229 | } | 4211 | } |
4230 | 4212 | ||
4231 | /*****************************************************************************/ | 4213 | /*****************************************************************************/ |
@@ -4244,7 +4226,7 @@ static void stl_sc26198sendflow(struct stlport *portp, int state) | |||
4244 | 4226 | ||
4245 | if (portp == NULL) | 4227 | if (portp == NULL) |
4246 | return; | 4228 | return; |
4247 | tty = portp->port.tty; | 4229 | tty = tty_port_tty_get(&portp->port); |
4248 | if (tty == NULL) | 4230 | if (tty == NULL) |
4249 | return; | 4231 | return; |
4250 | 4232 | ||
@@ -4269,6 +4251,7 @@ static void stl_sc26198sendflow(struct stlport *portp, int state) | |||
4269 | } | 4251 | } |
4270 | BRDDISABLE(portp->brdnr); | 4252 | BRDDISABLE(portp->brdnr); |
4271 | spin_unlock_irqrestore(&brd_lock, flags); | 4253 | spin_unlock_irqrestore(&brd_lock, flags); |
4254 | tty_kref_put(tty); | ||
4272 | } | 4255 | } |
4273 | 4256 | ||
4274 | /*****************************************************************************/ | 4257 | /*****************************************************************************/ |
@@ -4408,6 +4391,7 @@ static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase) | |||
4408 | 4391 | ||
4409 | static void stl_sc26198txisr(struct stlport *portp) | 4392 | static void stl_sc26198txisr(struct stlport *portp) |
4410 | { | 4393 | { |
4394 | struct tty_struct *tty; | ||
4411 | unsigned int ioaddr; | 4395 | unsigned int ioaddr; |
4412 | unsigned char mr0; | 4396 | unsigned char mr0; |
4413 | int len, stlen; | 4397 | int len, stlen; |
@@ -4422,8 +4406,11 @@ static void stl_sc26198txisr(struct stlport *portp) | |||
4422 | if ((len == 0) || ((len < STL_TXBUFLOW) && | 4406 | if ((len == 0) || ((len < STL_TXBUFLOW) && |
4423 | (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { | 4407 | (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { |
4424 | set_bit(ASYI_TXLOW, &portp->istate); | 4408 | set_bit(ASYI_TXLOW, &portp->istate); |
4425 | if (portp->port.tty) | 4409 | tty = tty_port_tty_get(&portp->port); |
4426 | tty_wakeup(portp->port.tty); | 4410 | if (tty) { |
4411 | tty_wakeup(tty); | ||
4412 | tty_kref_put(tty); | ||
4413 | } | ||
4427 | } | 4414 | } |
4428 | 4415 | ||
4429 | if (len == 0) { | 4416 | if (len == 0) { |
@@ -4476,7 +4463,7 @@ static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack) | |||
4476 | 4463 | ||
4477 | pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack); | 4464 | pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack); |
4478 | 4465 | ||
4479 | tty = portp->port.tty; | 4466 | tty = tty_port_tty_get(&portp->port); |
4480 | ioaddr = portp->ioaddr; | 4467 | ioaddr = portp->ioaddr; |
4481 | outb(GIBCR, (ioaddr + XP_ADDR)); | 4468 | outb(GIBCR, (ioaddr + XP_ADDR)); |
4482 | len = inb(ioaddr + XP_DATA) + 1; | 4469 | len = inb(ioaddr + XP_DATA) + 1; |
@@ -4515,6 +4502,7 @@ static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack) | |||
4515 | stl_sc26198txunflow(portp, tty); | 4502 | stl_sc26198txunflow(portp, tty); |
4516 | } | 4503 | } |
4517 | } | 4504 | } |
4505 | tty_kref_put(tty); | ||
4518 | } | 4506 | } |
4519 | 4507 | ||
4520 | /*****************************************************************************/ | 4508 | /*****************************************************************************/ |
@@ -4528,7 +4516,7 @@ static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char | |||
4528 | struct tty_struct *tty; | 4516 | struct tty_struct *tty; |
4529 | unsigned int ioaddr; | 4517 | unsigned int ioaddr; |
4530 | 4518 | ||
4531 | tty = portp->port.tty; | 4519 | tty = tty_port_tty_get(&portp->port); |
4532 | ioaddr = portp->ioaddr; | 4520 | ioaddr = portp->ioaddr; |
4533 | 4521 | ||
4534 | if (status & SR_RXPARITY) | 4522 | if (status & SR_RXPARITY) |
@@ -4566,6 +4554,7 @@ static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char | |||
4566 | if (status == 0) | 4554 | if (status == 0) |
4567 | portp->stats.rxtotal++; | 4555 | portp->stats.rxtotal++; |
4568 | } | 4556 | } |
4557 | tty_kref_put(tty); | ||
4569 | } | 4558 | } |
4570 | 4559 | ||
4571 | /*****************************************************************************/ | 4560 | /*****************************************************************************/ |
diff --git a/drivers/char/sx.c b/drivers/char/sx.c index c385206f9db5..5b8d7a1aa3e6 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c | |||
@@ -2504,7 +2504,7 @@ static void __devexit sx_remove_card(struct sx_board *board, | |||
2504 | del_timer(&board->timer); | 2504 | del_timer(&board->timer); |
2505 | if (pdev) { | 2505 | if (pdev) { |
2506 | #ifdef CONFIG_PCI | 2506 | #ifdef CONFIG_PCI |
2507 | pci_iounmap(pdev, board->base); | 2507 | pci_iounmap(pdev, board->base2); |
2508 | pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2); | 2508 | pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2); |
2509 | #endif | 2509 | #endif |
2510 | } else { | 2510 | } else { |
@@ -2703,7 +2703,7 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev, | |||
2703 | 2703 | ||
2704 | return 0; | 2704 | return 0; |
2705 | err_unmap: | 2705 | err_unmap: |
2706 | pci_iounmap(pdev, board->base); | 2706 | pci_iounmap(pdev, board->base2); |
2707 | err_reg: | 2707 | err_reg: |
2708 | pci_release_region(pdev, reg); | 2708 | pci_release_region(pdev, reg); |
2709 | err_flag: | 2709 | err_flag: |
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c index 3582f43345a8..5787249934c8 100644 --- a/drivers/char/tty_audit.c +++ b/drivers/char/tty_audit.c | |||
@@ -93,7 +93,7 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid, | |||
93 | get_task_comm(name, tsk); | 93 | get_task_comm(name, tsk); |
94 | audit_log_untrustedstring(ab, name); | 94 | audit_log_untrustedstring(ab, name); |
95 | audit_log_format(ab, " data="); | 95 | audit_log_format(ab, " data="); |
96 | audit_log_n_untrustedstring(ab, buf->data, buf->valid); | 96 | audit_log_n_hex(ab, buf->data, buf->valid); |
97 | audit_log_end(ab); | 97 | audit_log_end(ab); |
98 | } | 98 | } |
99 | buf->valid = 0; | 99 | buf->valid = 0; |
diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c new file mode 100644 index 000000000000..810ee25d66a4 --- /dev/null +++ b/drivers/char/tty_buffer.c | |||
@@ -0,0 +1,511 @@ | |||
1 | /* | ||
2 | * Tty buffer allocation management | ||
3 | */ | ||
4 | |||
5 | #include <linux/types.h> | ||
6 | #include <linux/errno.h> | ||
7 | #include <linux/tty.h> | ||
8 | #include <linux/tty_driver.h> | ||
9 | #include <linux/tty_flip.h> | ||
10 | #include <linux/timer.h> | ||
11 | #include <linux/string.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/wait.h> | ||
16 | #include <linux/bitops.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/module.h> | ||
19 | |||
20 | /** | ||
21 | * tty_buffer_free_all - free buffers used by a tty | ||
22 | * @tty: tty to free from | ||
23 | * | ||
24 | * Remove all the buffers pending on a tty whether queued with data | ||
25 | * or in the free ring. Must be called when the tty is no longer in use | ||
26 | * | ||
27 | * Locking: none | ||
28 | */ | ||
29 | |||
30 | void tty_buffer_free_all(struct tty_struct *tty) | ||
31 | { | ||
32 | struct tty_buffer *thead; | ||
33 | while ((thead = tty->buf.head) != NULL) { | ||
34 | tty->buf.head = thead->next; | ||
35 | kfree(thead); | ||
36 | } | ||
37 | while ((thead = tty->buf.free) != NULL) { | ||
38 | tty->buf.free = thead->next; | ||
39 | kfree(thead); | ||
40 | } | ||
41 | tty->buf.tail = NULL; | ||
42 | tty->buf.memory_used = 0; | ||
43 | } | ||
44 | |||
45 | /** | ||
46 | * tty_buffer_alloc - allocate a tty buffer | ||
47 | * @tty: tty device | ||
48 | * @size: desired size (characters) | ||
49 | * | ||
50 | * Allocate a new tty buffer to hold the desired number of characters. | ||
51 | * Return NULL if out of memory or the allocation would exceed the | ||
52 | * per device queue | ||
53 | * | ||
54 | * Locking: Caller must hold tty->buf.lock | ||
55 | */ | ||
56 | |||
57 | static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size) | ||
58 | { | ||
59 | struct tty_buffer *p; | ||
60 | |||
61 | if (tty->buf.memory_used + size > 65536) | ||
62 | return NULL; | ||
63 | p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); | ||
64 | if (p == NULL) | ||
65 | return NULL; | ||
66 | p->used = 0; | ||
67 | p->size = size; | ||
68 | p->next = NULL; | ||
69 | p->commit = 0; | ||
70 | p->read = 0; | ||
71 | p->char_buf_ptr = (char *)(p->data); | ||
72 | p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; | ||
73 | tty->buf.memory_used += size; | ||
74 | return p; | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * tty_buffer_free - free a tty buffer | ||
79 | * @tty: tty owning the buffer | ||
80 | * @b: the buffer to free | ||
81 | * | ||
82 | * Free a tty buffer, or add it to the free list according to our | ||
83 | * internal strategy | ||
84 | * | ||
85 | * Locking: Caller must hold tty->buf.lock | ||
86 | */ | ||
87 | |||
88 | static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) | ||
89 | { | ||
90 | /* Dumb strategy for now - should keep some stats */ | ||
91 | tty->buf.memory_used -= b->size; | ||
92 | WARN_ON(tty->buf.memory_used < 0); | ||
93 | |||
94 | if (b->size >= 512) | ||
95 | kfree(b); | ||
96 | else { | ||
97 | b->next = tty->buf.free; | ||
98 | tty->buf.free = b; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * __tty_buffer_flush - flush full tty buffers | ||
104 | * @tty: tty to flush | ||
105 | * | ||
106 | * flush all the buffers containing receive data. Caller must | ||
107 | * hold the buffer lock and must have ensured no parallel flush to | ||
108 | * ldisc is running. | ||
109 | * | ||
110 | * Locking: Caller must hold tty->buf.lock | ||
111 | */ | ||
112 | |||
113 | static void __tty_buffer_flush(struct tty_struct *tty) | ||
114 | { | ||
115 | struct tty_buffer *thead; | ||
116 | |||
117 | while ((thead = tty->buf.head) != NULL) { | ||
118 | tty->buf.head = thead->next; | ||
119 | tty_buffer_free(tty, thead); | ||
120 | } | ||
121 | tty->buf.tail = NULL; | ||
122 | } | ||
123 | |||
124 | /** | ||
125 | * tty_buffer_flush - flush full tty buffers | ||
126 | * @tty: tty to flush | ||
127 | * | ||
128 | * flush all the buffers containing receive data. If the buffer is | ||
129 | * being processed by flush_to_ldisc then we defer the processing | ||
130 | * to that function | ||
131 | * | ||
132 | * Locking: none | ||
133 | */ | ||
134 | |||
135 | void tty_buffer_flush(struct tty_struct *tty) | ||
136 | { | ||
137 | unsigned long flags; | ||
138 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
139 | |||
140 | /* If the data is being pushed to the tty layer then we can't | ||
141 | process it here. Instead set a flag and the flush_to_ldisc | ||
142 | path will process the flush request before it exits */ | ||
143 | if (test_bit(TTY_FLUSHING, &tty->flags)) { | ||
144 | set_bit(TTY_FLUSHPENDING, &tty->flags); | ||
145 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
146 | wait_event(tty->read_wait, | ||
147 | test_bit(TTY_FLUSHPENDING, &tty->flags) == 0); | ||
148 | return; | ||
149 | } else | ||
150 | __tty_buffer_flush(tty); | ||
151 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * tty_buffer_find - find a free tty buffer | ||
156 | * @tty: tty owning the buffer | ||
157 | * @size: characters wanted | ||
158 | * | ||
159 | * Locate an existing suitable tty buffer or if we are lacking one then | ||
160 | * allocate a new one. We round our buffers off in 256 character chunks | ||
161 | * to get better allocation behaviour. | ||
162 | * | ||
163 | * Locking: Caller must hold tty->buf.lock | ||
164 | */ | ||
165 | |||
166 | static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) | ||
167 | { | ||
168 | struct tty_buffer **tbh = &tty->buf.free; | ||
169 | while ((*tbh) != NULL) { | ||
170 | struct tty_buffer *t = *tbh; | ||
171 | if (t->size >= size) { | ||
172 | *tbh = t->next; | ||
173 | t->next = NULL; | ||
174 | t->used = 0; | ||
175 | t->commit = 0; | ||
176 | t->read = 0; | ||
177 | tty->buf.memory_used += t->size; | ||
178 | return t; | ||
179 | } | ||
180 | tbh = &((*tbh)->next); | ||
181 | } | ||
182 | /* Round the buffer size out */ | ||
183 | size = (size + 0xFF) & ~0xFF; | ||
184 | return tty_buffer_alloc(tty, size); | ||
185 | /* Should possibly check if this fails for the largest buffer we | ||
186 | have queued and recycle that ? */ | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * tty_buffer_request_room - grow tty buffer if needed | ||
191 | * @tty: tty structure | ||
192 | * @size: size desired | ||
193 | * | ||
194 | * Make at least size bytes of linear space available for the tty | ||
195 | * buffer. If we fail return the size we managed to find. | ||
196 | * | ||
197 | * Locking: Takes tty->buf.lock | ||
198 | */ | ||
199 | int tty_buffer_request_room(struct tty_struct *tty, size_t size) | ||
200 | { | ||
201 | struct tty_buffer *b, *n; | ||
202 | int left; | ||
203 | unsigned long flags; | ||
204 | |||
205 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
206 | |||
207 | /* OPTIMISATION: We could keep a per tty "zero" sized buffer to | ||
208 | remove this conditional if its worth it. This would be invisible | ||
209 | to the callers */ | ||
210 | if ((b = tty->buf.tail) != NULL) | ||
211 | left = b->size - b->used; | ||
212 | else | ||
213 | left = 0; | ||
214 | |||
215 | if (left < size) { | ||
216 | /* This is the slow path - looking for new buffers to use */ | ||
217 | if ((n = tty_buffer_find(tty, size)) != NULL) { | ||
218 | if (b != NULL) { | ||
219 | b->next = n; | ||
220 | b->commit = b->used; | ||
221 | } else | ||
222 | tty->buf.head = n; | ||
223 | tty->buf.tail = n; | ||
224 | } else | ||
225 | size = left; | ||
226 | } | ||
227 | |||
228 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
229 | return size; | ||
230 | } | ||
231 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); | ||
232 | |||
233 | /** | ||
234 | * tty_insert_flip_string - Add characters to the tty buffer | ||
235 | * @tty: tty structure | ||
236 | * @chars: characters | ||
237 | * @size: size | ||
238 | * | ||
239 | * Queue a series of bytes to the tty buffering. All the characters | ||
240 | * passed are marked as without error. Returns the number added. | ||
241 | * | ||
242 | * Locking: Called functions may take tty->buf.lock | ||
243 | */ | ||
244 | |||
245 | int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, | ||
246 | size_t size) | ||
247 | { | ||
248 | int copied = 0; | ||
249 | do { | ||
250 | int space = tty_buffer_request_room(tty, size - copied); | ||
251 | struct tty_buffer *tb = tty->buf.tail; | ||
252 | /* If there is no space then tb may be NULL */ | ||
253 | if (unlikely(space == 0)) | ||
254 | break; | ||
255 | memcpy(tb->char_buf_ptr + tb->used, chars, space); | ||
256 | memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); | ||
257 | tb->used += space; | ||
258 | copied += space; | ||
259 | chars += space; | ||
260 | /* There is a small chance that we need to split the data over | ||
261 | several buffers. If this is the case we must loop */ | ||
262 | } while (unlikely(size > copied)); | ||
263 | return copied; | ||
264 | } | ||
265 | EXPORT_SYMBOL(tty_insert_flip_string); | ||
266 | |||
267 | /** | ||
268 | * tty_insert_flip_string_flags - Add characters to the tty buffer | ||
269 | * @tty: tty structure | ||
270 | * @chars: characters | ||
271 | * @flags: flag bytes | ||
272 | * @size: size | ||
273 | * | ||
274 | * Queue a series of bytes to the tty buffering. For each character | ||
275 | * the flags array indicates the status of the character. Returns the | ||
276 | * number added. | ||
277 | * | ||
278 | * Locking: Called functions may take tty->buf.lock | ||
279 | */ | ||
280 | |||
281 | int tty_insert_flip_string_flags(struct tty_struct *tty, | ||
282 | const unsigned char *chars, const char *flags, size_t size) | ||
283 | { | ||
284 | int copied = 0; | ||
285 | do { | ||
286 | int space = tty_buffer_request_room(tty, size - copied); | ||
287 | struct tty_buffer *tb = tty->buf.tail; | ||
288 | /* If there is no space then tb may be NULL */ | ||
289 | if (unlikely(space == 0)) | ||
290 | break; | ||
291 | memcpy(tb->char_buf_ptr + tb->used, chars, space); | ||
292 | memcpy(tb->flag_buf_ptr + tb->used, flags, space); | ||
293 | tb->used += space; | ||
294 | copied += space; | ||
295 | chars += space; | ||
296 | flags += space; | ||
297 | /* There is a small chance that we need to split the data over | ||
298 | several buffers. If this is the case we must loop */ | ||
299 | } while (unlikely(size > copied)); | ||
300 | return copied; | ||
301 | } | ||
302 | EXPORT_SYMBOL(tty_insert_flip_string_flags); | ||
303 | |||
304 | /** | ||
305 | * tty_schedule_flip - push characters to ldisc | ||
306 | * @tty: tty to push from | ||
307 | * | ||
308 | * Takes any pending buffers and transfers their ownership to the | ||
309 | * ldisc side of the queue. It then schedules those characters for | ||
310 | * processing by the line discipline. | ||
311 | * | ||
312 | * Locking: Takes tty->buf.lock | ||
313 | */ | ||
314 | |||
315 | void tty_schedule_flip(struct tty_struct *tty) | ||
316 | { | ||
317 | unsigned long flags; | ||
318 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
319 | if (tty->buf.tail != NULL) | ||
320 | tty->buf.tail->commit = tty->buf.tail->used; | ||
321 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
322 | schedule_delayed_work(&tty->buf.work, 1); | ||
323 | } | ||
324 | EXPORT_SYMBOL(tty_schedule_flip); | ||
325 | |||
326 | /** | ||
327 | * tty_prepare_flip_string - make room for characters | ||
328 | * @tty: tty | ||
329 | * @chars: return pointer for character write area | ||
330 | * @size: desired size | ||
331 | * | ||
332 | * Prepare a block of space in the buffer for data. Returns the length | ||
333 | * available and buffer pointer to the space which is now allocated and | ||
334 | * accounted for as ready for normal characters. This is used for drivers | ||
335 | * that need their own block copy routines into the buffer. There is no | ||
336 | * guarantee the buffer is a DMA target! | ||
337 | * | ||
338 | * Locking: May call functions taking tty->buf.lock | ||
339 | */ | ||
340 | |||
341 | int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, | ||
342 | size_t size) | ||
343 | { | ||
344 | int space = tty_buffer_request_room(tty, size); | ||
345 | if (likely(space)) { | ||
346 | struct tty_buffer *tb = tty->buf.tail; | ||
347 | *chars = tb->char_buf_ptr + tb->used; | ||
348 | memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); | ||
349 | tb->used += space; | ||
350 | } | ||
351 | return space; | ||
352 | } | ||
353 | EXPORT_SYMBOL_GPL(tty_prepare_flip_string); | ||
354 | |||
355 | /** | ||
356 | * tty_prepare_flip_string_flags - make room for characters | ||
357 | * @tty: tty | ||
358 | * @chars: return pointer for character write area | ||
359 | * @flags: return pointer for status flag write area | ||
360 | * @size: desired size | ||
361 | * | ||
362 | * Prepare a block of space in the buffer for data. Returns the length | ||
363 | * available and buffer pointer to the space which is now allocated and | ||
364 | * accounted for as ready for characters. This is used for drivers | ||
365 | * that need their own block copy routines into the buffer. There is no | ||
366 | * guarantee the buffer is a DMA target! | ||
367 | * | ||
368 | * Locking: May call functions taking tty->buf.lock | ||
369 | */ | ||
370 | |||
371 | int tty_prepare_flip_string_flags(struct tty_struct *tty, | ||
372 | unsigned char **chars, char **flags, size_t size) | ||
373 | { | ||
374 | int space = tty_buffer_request_room(tty, size); | ||
375 | if (likely(space)) { | ||
376 | struct tty_buffer *tb = tty->buf.tail; | ||
377 | *chars = tb->char_buf_ptr + tb->used; | ||
378 | *flags = tb->flag_buf_ptr + tb->used; | ||
379 | tb->used += space; | ||
380 | } | ||
381 | return space; | ||
382 | } | ||
383 | EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); | ||
384 | |||
385 | |||
386 | |||
387 | /** | ||
388 | * flush_to_ldisc | ||
389 | * @work: tty structure passed from work queue. | ||
390 | * | ||
391 | * This routine is called out of the software interrupt to flush data | ||
392 | * from the buffer chain to the line discipline. | ||
393 | * | ||
394 | * Locking: holds tty->buf.lock to guard buffer list. Drops the lock | ||
395 | * while invoking the line discipline receive_buf method. The | ||
396 | * receive_buf method is single threaded for each tty instance. | ||
397 | */ | ||
398 | |||
399 | static void flush_to_ldisc(struct work_struct *work) | ||
400 | { | ||
401 | struct tty_struct *tty = | ||
402 | container_of(work, struct tty_struct, buf.work.work); | ||
403 | unsigned long flags; | ||
404 | struct tty_ldisc *disc; | ||
405 | struct tty_buffer *tbuf, *head; | ||
406 | char *char_buf; | ||
407 | unsigned char *flag_buf; | ||
408 | |||
409 | disc = tty_ldisc_ref(tty); | ||
410 | if (disc == NULL) /* !TTY_LDISC */ | ||
411 | return; | ||
412 | |||
413 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
414 | /* So we know a flush is running */ | ||
415 | set_bit(TTY_FLUSHING, &tty->flags); | ||
416 | head = tty->buf.head; | ||
417 | if (head != NULL) { | ||
418 | tty->buf.head = NULL; | ||
419 | for (;;) { | ||
420 | int count = head->commit - head->read; | ||
421 | if (!count) { | ||
422 | if (head->next == NULL) | ||
423 | break; | ||
424 | tbuf = head; | ||
425 | head = head->next; | ||
426 | tty_buffer_free(tty, tbuf); | ||
427 | continue; | ||
428 | } | ||
429 | /* Ldisc or user is trying to flush the buffers | ||
430 | we are feeding to the ldisc, stop feeding the | ||
431 | line discipline as we want to empty the queue */ | ||
432 | if (test_bit(TTY_FLUSHPENDING, &tty->flags)) | ||
433 | break; | ||
434 | if (!tty->receive_room) { | ||
435 | schedule_delayed_work(&tty->buf.work, 1); | ||
436 | break; | ||
437 | } | ||
438 | if (count > tty->receive_room) | ||
439 | count = tty->receive_room; | ||
440 | char_buf = head->char_buf_ptr + head->read; | ||
441 | flag_buf = head->flag_buf_ptr + head->read; | ||
442 | head->read += count; | ||
443 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
444 | disc->ops->receive_buf(tty, char_buf, | ||
445 | flag_buf, count); | ||
446 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
447 | } | ||
448 | /* Restore the queue head */ | ||
449 | tty->buf.head = head; | ||
450 | } | ||
451 | /* We may have a deferred request to flush the input buffer, | ||
452 | if so pull the chain under the lock and empty the queue */ | ||
453 | if (test_bit(TTY_FLUSHPENDING, &tty->flags)) { | ||
454 | __tty_buffer_flush(tty); | ||
455 | clear_bit(TTY_FLUSHPENDING, &tty->flags); | ||
456 | wake_up(&tty->read_wait); | ||
457 | } | ||
458 | clear_bit(TTY_FLUSHING, &tty->flags); | ||
459 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
460 | |||
461 | tty_ldisc_deref(disc); | ||
462 | } | ||
463 | |||
464 | /** | ||
465 | * tty_flip_buffer_push - terminal | ||
466 | * @tty: tty to push | ||
467 | * | ||
468 | * Queue a push of the terminal flip buffers to the line discipline. This | ||
469 | * function must not be called from IRQ context if tty->low_latency is set. | ||
470 | * | ||
471 | * In the event of the queue being busy for flipping the work will be | ||
472 | * held off and retried later. | ||
473 | * | ||
474 | * Locking: tty buffer lock. Driver locks in low latency mode. | ||
475 | */ | ||
476 | |||
477 | void tty_flip_buffer_push(struct tty_struct *tty) | ||
478 | { | ||
479 | unsigned long flags; | ||
480 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
481 | if (tty->buf.tail != NULL) | ||
482 | tty->buf.tail->commit = tty->buf.tail->used; | ||
483 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
484 | |||
485 | if (tty->low_latency) | ||
486 | flush_to_ldisc(&tty->buf.work.work); | ||
487 | else | ||
488 | schedule_delayed_work(&tty->buf.work, 1); | ||
489 | } | ||
490 | EXPORT_SYMBOL(tty_flip_buffer_push); | ||
491 | |||
492 | /** | ||
493 | * tty_buffer_init - prepare a tty buffer structure | ||
494 | * @tty: tty to initialise | ||
495 | * | ||
496 | * Set up the initial state of the buffer management for a tty device. | ||
497 | * Must be called before the other tty buffer functions are used. | ||
498 | * | ||
499 | * Locking: none | ||
500 | */ | ||
501 | |||
502 | void tty_buffer_init(struct tty_struct *tty) | ||
503 | { | ||
504 | spin_lock_init(&tty->buf.lock); | ||
505 | tty->buf.head = NULL; | ||
506 | tty->buf.tail = NULL; | ||
507 | tty->buf.free = NULL; | ||
508 | tty->buf.memory_used = 0; | ||
509 | INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc); | ||
510 | } | ||
511 | |||
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index e4dce8709541..7053d6333692 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -49,7 +49,7 @@ | |||
49 | * implement CONFIG_VT and generalize console device interface. | 49 | * implement CONFIG_VT and generalize console device interface. |
50 | * -- Marko Kohtala <Marko.Kohtala@hut.fi>, March 97 | 50 | * -- Marko Kohtala <Marko.Kohtala@hut.fi>, March 97 |
51 | * | 51 | * |
52 | * Rewrote init_dev and release_dev to eliminate races. | 52 | * Rewrote tty_init_dev and tty_release_dev to eliminate races. |
53 | * -- Bill Hawes <whawes@star.net>, June 97 | 53 | * -- Bill Hawes <whawes@star.net>, June 97 |
54 | * | 54 | * |
55 | * Added devfs support. | 55 | * Added devfs support. |
@@ -136,13 +136,6 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ | |||
136 | DEFINE_MUTEX(tty_mutex); | 136 | DEFINE_MUTEX(tty_mutex); |
137 | EXPORT_SYMBOL(tty_mutex); | 137 | EXPORT_SYMBOL(tty_mutex); |
138 | 138 | ||
139 | #ifdef CONFIG_UNIX98_PTYS | ||
140 | extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ | ||
141 | static int ptmx_open(struct inode *, struct file *); | ||
142 | #endif | ||
143 | |||
144 | static void initialize_tty_struct(struct tty_struct *tty); | ||
145 | |||
146 | static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); | 139 | static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); |
147 | static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); | 140 | static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); |
148 | ssize_t redirected_tty_write(struct file *, const char __user *, | 141 | ssize_t redirected_tty_write(struct file *, const char __user *, |
@@ -171,13 +164,11 @@ static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); | |||
171 | * Locking: none | 164 | * Locking: none |
172 | */ | 165 | */ |
173 | 166 | ||
174 | static struct tty_struct *alloc_tty_struct(void) | 167 | struct tty_struct *alloc_tty_struct(void) |
175 | { | 168 | { |
176 | return kzalloc(sizeof(struct tty_struct), GFP_KERNEL); | 169 | return kzalloc(sizeof(struct tty_struct), GFP_KERNEL); |
177 | } | 170 | } |
178 | 171 | ||
179 | static void tty_buffer_free_all(struct tty_struct *); | ||
180 | |||
181 | /** | 172 | /** |
182 | * free_tty_struct - free a disused tty | 173 | * free_tty_struct - free a disused tty |
183 | * @tty: tty struct to free | 174 | * @tty: tty struct to free |
@@ -187,7 +178,7 @@ static void tty_buffer_free_all(struct tty_struct *); | |||
187 | * Locking: none. Must be called after tty is definitely unused | 178 | * Locking: none. Must be called after tty is definitely unused |
188 | */ | 179 | */ |
189 | 180 | ||
190 | static inline void free_tty_struct(struct tty_struct *tty) | 181 | void free_tty_struct(struct tty_struct *tty) |
191 | { | 182 | { |
192 | kfree(tty->write_buf); | 183 | kfree(tty->write_buf); |
193 | tty_buffer_free_all(tty); | 184 | tty_buffer_free_all(tty); |
@@ -263,398 +254,6 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) | |||
263 | return 0; | 254 | return 0; |
264 | } | 255 | } |
265 | 256 | ||
266 | /* | ||
267 | * Tty buffer allocation management | ||
268 | */ | ||
269 | |||
270 | /** | ||
271 | * tty_buffer_free_all - free buffers used by a tty | ||
272 | * @tty: tty to free from | ||
273 | * | ||
274 | * Remove all the buffers pending on a tty whether queued with data | ||
275 | * or in the free ring. Must be called when the tty is no longer in use | ||
276 | * | ||
277 | * Locking: none | ||
278 | */ | ||
279 | |||
280 | static void tty_buffer_free_all(struct tty_struct *tty) | ||
281 | { | ||
282 | struct tty_buffer *thead; | ||
283 | while ((thead = tty->buf.head) != NULL) { | ||
284 | tty->buf.head = thead->next; | ||
285 | kfree(thead); | ||
286 | } | ||
287 | while ((thead = tty->buf.free) != NULL) { | ||
288 | tty->buf.free = thead->next; | ||
289 | kfree(thead); | ||
290 | } | ||
291 | tty->buf.tail = NULL; | ||
292 | tty->buf.memory_used = 0; | ||
293 | } | ||
294 | |||
295 | /** | ||
296 | * tty_buffer_init - prepare a tty buffer structure | ||
297 | * @tty: tty to initialise | ||
298 | * | ||
299 | * Set up the initial state of the buffer management for a tty device. | ||
300 | * Must be called before the other tty buffer functions are used. | ||
301 | * | ||
302 | * Locking: none | ||
303 | */ | ||
304 | |||
305 | static void tty_buffer_init(struct tty_struct *tty) | ||
306 | { | ||
307 | spin_lock_init(&tty->buf.lock); | ||
308 | tty->buf.head = NULL; | ||
309 | tty->buf.tail = NULL; | ||
310 | tty->buf.free = NULL; | ||
311 | tty->buf.memory_used = 0; | ||
312 | } | ||
313 | |||
314 | /** | ||
315 | * tty_buffer_alloc - allocate a tty buffer | ||
316 | * @tty: tty device | ||
317 | * @size: desired size (characters) | ||
318 | * | ||
319 | * Allocate a new tty buffer to hold the desired number of characters. | ||
320 | * Return NULL if out of memory or the allocation would exceed the | ||
321 | * per device queue | ||
322 | * | ||
323 | * Locking: Caller must hold tty->buf.lock | ||
324 | */ | ||
325 | |||
326 | static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size) | ||
327 | { | ||
328 | struct tty_buffer *p; | ||
329 | |||
330 | if (tty->buf.memory_used + size > 65536) | ||
331 | return NULL; | ||
332 | p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); | ||
333 | if (p == NULL) | ||
334 | return NULL; | ||
335 | p->used = 0; | ||
336 | p->size = size; | ||
337 | p->next = NULL; | ||
338 | p->commit = 0; | ||
339 | p->read = 0; | ||
340 | p->char_buf_ptr = (char *)(p->data); | ||
341 | p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; | ||
342 | tty->buf.memory_used += size; | ||
343 | return p; | ||
344 | } | ||
345 | |||
346 | /** | ||
347 | * tty_buffer_free - free a tty buffer | ||
348 | * @tty: tty owning the buffer | ||
349 | * @b: the buffer to free | ||
350 | * | ||
351 | * Free a tty buffer, or add it to the free list according to our | ||
352 | * internal strategy | ||
353 | * | ||
354 | * Locking: Caller must hold tty->buf.lock | ||
355 | */ | ||
356 | |||
357 | static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) | ||
358 | { | ||
359 | /* Dumb strategy for now - should keep some stats */ | ||
360 | tty->buf.memory_used -= b->size; | ||
361 | WARN_ON(tty->buf.memory_used < 0); | ||
362 | |||
363 | if (b->size >= 512) | ||
364 | kfree(b); | ||
365 | else { | ||
366 | b->next = tty->buf.free; | ||
367 | tty->buf.free = b; | ||
368 | } | ||
369 | } | ||
370 | |||
371 | /** | ||
372 | * __tty_buffer_flush - flush full tty buffers | ||
373 | * @tty: tty to flush | ||
374 | * | ||
375 | * flush all the buffers containing receive data. Caller must | ||
376 | * hold the buffer lock and must have ensured no parallel flush to | ||
377 | * ldisc is running. | ||
378 | * | ||
379 | * Locking: Caller must hold tty->buf.lock | ||
380 | */ | ||
381 | |||
382 | static void __tty_buffer_flush(struct tty_struct *tty) | ||
383 | { | ||
384 | struct tty_buffer *thead; | ||
385 | |||
386 | while ((thead = tty->buf.head) != NULL) { | ||
387 | tty->buf.head = thead->next; | ||
388 | tty_buffer_free(tty, thead); | ||
389 | } | ||
390 | tty->buf.tail = NULL; | ||
391 | } | ||
392 | |||
393 | /** | ||
394 | * tty_buffer_flush - flush full tty buffers | ||
395 | * @tty: tty to flush | ||
396 | * | ||
397 | * flush all the buffers containing receive data. If the buffer is | ||
398 | * being processed by flush_to_ldisc then we defer the processing | ||
399 | * to that function | ||
400 | * | ||
401 | * Locking: none | ||
402 | */ | ||
403 | |||
404 | static void tty_buffer_flush(struct tty_struct *tty) | ||
405 | { | ||
406 | unsigned long flags; | ||
407 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
408 | |||
409 | /* If the data is being pushed to the tty layer then we can't | ||
410 | process it here. Instead set a flag and the flush_to_ldisc | ||
411 | path will process the flush request before it exits */ | ||
412 | if (test_bit(TTY_FLUSHING, &tty->flags)) { | ||
413 | set_bit(TTY_FLUSHPENDING, &tty->flags); | ||
414 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
415 | wait_event(tty->read_wait, | ||
416 | test_bit(TTY_FLUSHPENDING, &tty->flags) == 0); | ||
417 | return; | ||
418 | } else | ||
419 | __tty_buffer_flush(tty); | ||
420 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
421 | } | ||
422 | |||
423 | /** | ||
424 | * tty_buffer_find - find a free tty buffer | ||
425 | * @tty: tty owning the buffer | ||
426 | * @size: characters wanted | ||
427 | * | ||
428 | * Locate an existing suitable tty buffer or if we are lacking one then | ||
429 | * allocate a new one. We round our buffers off in 256 character chunks | ||
430 | * to get better allocation behaviour. | ||
431 | * | ||
432 | * Locking: Caller must hold tty->buf.lock | ||
433 | */ | ||
434 | |||
435 | static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) | ||
436 | { | ||
437 | struct tty_buffer **tbh = &tty->buf.free; | ||
438 | while ((*tbh) != NULL) { | ||
439 | struct tty_buffer *t = *tbh; | ||
440 | if (t->size >= size) { | ||
441 | *tbh = t->next; | ||
442 | t->next = NULL; | ||
443 | t->used = 0; | ||
444 | t->commit = 0; | ||
445 | t->read = 0; | ||
446 | tty->buf.memory_used += t->size; | ||
447 | return t; | ||
448 | } | ||
449 | tbh = &((*tbh)->next); | ||
450 | } | ||
451 | /* Round the buffer size out */ | ||
452 | size = (size + 0xFF) & ~0xFF; | ||
453 | return tty_buffer_alloc(tty, size); | ||
454 | /* Should possibly check if this fails for the largest buffer we | ||
455 | have queued and recycle that ? */ | ||
456 | } | ||
457 | |||
458 | /** | ||
459 | * tty_buffer_request_room - grow tty buffer if needed | ||
460 | * @tty: tty structure | ||
461 | * @size: size desired | ||
462 | * | ||
463 | * Make at least size bytes of linear space available for the tty | ||
464 | * buffer. If we fail return the size we managed to find. | ||
465 | * | ||
466 | * Locking: Takes tty->buf.lock | ||
467 | */ | ||
468 | int tty_buffer_request_room(struct tty_struct *tty, size_t size) | ||
469 | { | ||
470 | struct tty_buffer *b, *n; | ||
471 | int left; | ||
472 | unsigned long flags; | ||
473 | |||
474 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
475 | |||
476 | /* OPTIMISATION: We could keep a per tty "zero" sized buffer to | ||
477 | remove this conditional if its worth it. This would be invisible | ||
478 | to the callers */ | ||
479 | if ((b = tty->buf.tail) != NULL) | ||
480 | left = b->size - b->used; | ||
481 | else | ||
482 | left = 0; | ||
483 | |||
484 | if (left < size) { | ||
485 | /* This is the slow path - looking for new buffers to use */ | ||
486 | if ((n = tty_buffer_find(tty, size)) != NULL) { | ||
487 | if (b != NULL) { | ||
488 | b->next = n; | ||
489 | b->commit = b->used; | ||
490 | } else | ||
491 | tty->buf.head = n; | ||
492 | tty->buf.tail = n; | ||
493 | } else | ||
494 | size = left; | ||
495 | } | ||
496 | |||
497 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
498 | return size; | ||
499 | } | ||
500 | EXPORT_SYMBOL_GPL(tty_buffer_request_room); | ||
501 | |||
502 | /** | ||
503 | * tty_insert_flip_string - Add characters to the tty buffer | ||
504 | * @tty: tty structure | ||
505 | * @chars: characters | ||
506 | * @size: size | ||
507 | * | ||
508 | * Queue a series of bytes to the tty buffering. All the characters | ||
509 | * passed are marked as without error. Returns the number added. | ||
510 | * | ||
511 | * Locking: Called functions may take tty->buf.lock | ||
512 | */ | ||
513 | |||
514 | int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, | ||
515 | size_t size) | ||
516 | { | ||
517 | int copied = 0; | ||
518 | do { | ||
519 | int space = tty_buffer_request_room(tty, size - copied); | ||
520 | struct tty_buffer *tb = tty->buf.tail; | ||
521 | /* If there is no space then tb may be NULL */ | ||
522 | if (unlikely(space == 0)) | ||
523 | break; | ||
524 | memcpy(tb->char_buf_ptr + tb->used, chars, space); | ||
525 | memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); | ||
526 | tb->used += space; | ||
527 | copied += space; | ||
528 | chars += space; | ||
529 | /* There is a small chance that we need to split the data over | ||
530 | several buffers. If this is the case we must loop */ | ||
531 | } while (unlikely(size > copied)); | ||
532 | return copied; | ||
533 | } | ||
534 | EXPORT_SYMBOL(tty_insert_flip_string); | ||
535 | |||
536 | /** | ||
537 | * tty_insert_flip_string_flags - Add characters to the tty buffer | ||
538 | * @tty: tty structure | ||
539 | * @chars: characters | ||
540 | * @flags: flag bytes | ||
541 | * @size: size | ||
542 | * | ||
543 | * Queue a series of bytes to the tty buffering. For each character | ||
544 | * the flags array indicates the status of the character. Returns the | ||
545 | * number added. | ||
546 | * | ||
547 | * Locking: Called functions may take tty->buf.lock | ||
548 | */ | ||
549 | |||
550 | int tty_insert_flip_string_flags(struct tty_struct *tty, | ||
551 | const unsigned char *chars, const char *flags, size_t size) | ||
552 | { | ||
553 | int copied = 0; | ||
554 | do { | ||
555 | int space = tty_buffer_request_room(tty, size - copied); | ||
556 | struct tty_buffer *tb = tty->buf.tail; | ||
557 | /* If there is no space then tb may be NULL */ | ||
558 | if (unlikely(space == 0)) | ||
559 | break; | ||
560 | memcpy(tb->char_buf_ptr + tb->used, chars, space); | ||
561 | memcpy(tb->flag_buf_ptr + tb->used, flags, space); | ||
562 | tb->used += space; | ||
563 | copied += space; | ||
564 | chars += space; | ||
565 | flags += space; | ||
566 | /* There is a small chance that we need to split the data over | ||
567 | several buffers. If this is the case we must loop */ | ||
568 | } while (unlikely(size > copied)); | ||
569 | return copied; | ||
570 | } | ||
571 | EXPORT_SYMBOL(tty_insert_flip_string_flags); | ||
572 | |||
573 | /** | ||
574 | * tty_schedule_flip - push characters to ldisc | ||
575 | * @tty: tty to push from | ||
576 | * | ||
577 | * Takes any pending buffers and transfers their ownership to the | ||
578 | * ldisc side of the queue. It then schedules those characters for | ||
579 | * processing by the line discipline. | ||
580 | * | ||
581 | * Locking: Takes tty->buf.lock | ||
582 | */ | ||
583 | |||
584 | void tty_schedule_flip(struct tty_struct *tty) | ||
585 | { | ||
586 | unsigned long flags; | ||
587 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
588 | if (tty->buf.tail != NULL) | ||
589 | tty->buf.tail->commit = tty->buf.tail->used; | ||
590 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
591 | schedule_delayed_work(&tty->buf.work, 1); | ||
592 | } | ||
593 | EXPORT_SYMBOL(tty_schedule_flip); | ||
594 | |||
595 | /** | ||
596 | * tty_prepare_flip_string - make room for characters | ||
597 | * @tty: tty | ||
598 | * @chars: return pointer for character write area | ||
599 | * @size: desired size | ||
600 | * | ||
601 | * Prepare a block of space in the buffer for data. Returns the length | ||
602 | * available and buffer pointer to the space which is now allocated and | ||
603 | * accounted for as ready for normal characters. This is used for drivers | ||
604 | * that need their own block copy routines into the buffer. There is no | ||
605 | * guarantee the buffer is a DMA target! | ||
606 | * | ||
607 | * Locking: May call functions taking tty->buf.lock | ||
608 | */ | ||
609 | |||
610 | int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, | ||
611 | size_t size) | ||
612 | { | ||
613 | int space = tty_buffer_request_room(tty, size); | ||
614 | if (likely(space)) { | ||
615 | struct tty_buffer *tb = tty->buf.tail; | ||
616 | *chars = tb->char_buf_ptr + tb->used; | ||
617 | memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space); | ||
618 | tb->used += space; | ||
619 | } | ||
620 | return space; | ||
621 | } | ||
622 | |||
623 | EXPORT_SYMBOL_GPL(tty_prepare_flip_string); | ||
624 | |||
625 | /** | ||
626 | * tty_prepare_flip_string_flags - make room for characters | ||
627 | * @tty: tty | ||
628 | * @chars: return pointer for character write area | ||
629 | * @flags: return pointer for status flag write area | ||
630 | * @size: desired size | ||
631 | * | ||
632 | * Prepare a block of space in the buffer for data. Returns the length | ||
633 | * available and buffer pointer to the space which is now allocated and | ||
634 | * accounted for as ready for characters. This is used for drivers | ||
635 | * that need their own block copy routines into the buffer. There is no | ||
636 | * guarantee the buffer is a DMA target! | ||
637 | * | ||
638 | * Locking: May call functions taking tty->buf.lock | ||
639 | */ | ||
640 | |||
641 | int tty_prepare_flip_string_flags(struct tty_struct *tty, | ||
642 | unsigned char **chars, char **flags, size_t size) | ||
643 | { | ||
644 | int space = tty_buffer_request_room(tty, size); | ||
645 | if (likely(space)) { | ||
646 | struct tty_buffer *tb = tty->buf.tail; | ||
647 | *chars = tb->char_buf_ptr + tb->used; | ||
648 | *flags = tb->flag_buf_ptr + tb->used; | ||
649 | tb->used += space; | ||
650 | } | ||
651 | return space; | ||
652 | } | ||
653 | |||
654 | EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); | ||
655 | |||
656 | |||
657 | |||
658 | /** | 257 | /** |
659 | * get_tty_driver - find device of a tty | 258 | * get_tty_driver - find device of a tty |
660 | * @dev_t: device identifier | 259 | * @dev_t: device identifier |
@@ -675,7 +274,7 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index) | |||
675 | if (device < base || device >= base + p->num) | 274 | if (device < base || device >= base + p->num) |
676 | continue; | 275 | continue; |
677 | *index = device - base; | 276 | *index = device - base; |
678 | return p; | 277 | return tty_driver_kref_get(p); |
679 | } | 278 | } |
680 | return NULL; | 279 | return NULL; |
681 | } | 280 | } |
@@ -719,7 +318,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) | |||
719 | 318 | ||
720 | if (tty_line >= 0 && tty_line <= p->num && p->ops && | 319 | if (tty_line >= 0 && tty_line <= p->num && p->ops && |
721 | p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) { | 320 | p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) { |
722 | res = p; | 321 | res = tty_driver_kref_get(p); |
723 | *line = tty_line; | 322 | *line = tty_line; |
724 | break; | 323 | break; |
725 | } | 324 | } |
@@ -819,20 +418,6 @@ static const struct file_operations tty_fops = { | |||
819 | .fasync = tty_fasync, | 418 | .fasync = tty_fasync, |
820 | }; | 419 | }; |
821 | 420 | ||
822 | #ifdef CONFIG_UNIX98_PTYS | ||
823 | static const struct file_operations ptmx_fops = { | ||
824 | .llseek = no_llseek, | ||
825 | .read = tty_read, | ||
826 | .write = tty_write, | ||
827 | .poll = tty_poll, | ||
828 | .unlocked_ioctl = tty_ioctl, | ||
829 | .compat_ioctl = tty_compat_ioctl, | ||
830 | .open = ptmx_open, | ||
831 | .release = tty_release, | ||
832 | .fasync = tty_fasync, | ||
833 | }; | ||
834 | #endif | ||
835 | |||
836 | static const struct file_operations console_fops = { | 421 | static const struct file_operations console_fops = { |
837 | .llseek = no_llseek, | 422 | .llseek = no_llseek, |
838 | .read = tty_read, | 423 | .read = tty_read, |
@@ -953,6 +538,7 @@ static void do_tty_hangup(struct work_struct *work) | |||
953 | struct tty_ldisc *ld; | 538 | struct tty_ldisc *ld; |
954 | int closecount = 0, n; | 539 | int closecount = 0, n; |
955 | unsigned long flags; | 540 | unsigned long flags; |
541 | int refs = 0; | ||
956 | 542 | ||
957 | if (!tty) | 543 | if (!tty) |
958 | return; | 544 | return; |
@@ -1019,8 +605,12 @@ static void do_tty_hangup(struct work_struct *work) | |||
1019 | if (tty->session) { | 605 | if (tty->session) { |
1020 | do_each_pid_task(tty->session, PIDTYPE_SID, p) { | 606 | do_each_pid_task(tty->session, PIDTYPE_SID, p) { |
1021 | spin_lock_irq(&p->sighand->siglock); | 607 | spin_lock_irq(&p->sighand->siglock); |
1022 | if (p->signal->tty == tty) | 608 | if (p->signal->tty == tty) { |
1023 | p->signal->tty = NULL; | 609 | p->signal->tty = NULL; |
610 | /* We defer the dereferences outside fo | ||
611 | the tasklist lock */ | ||
612 | refs++; | ||
613 | } | ||
1024 | if (!p->signal->leader) { | 614 | if (!p->signal->leader) { |
1025 | spin_unlock_irq(&p->sighand->siglock); | 615 | spin_unlock_irq(&p->sighand->siglock); |
1026 | continue; | 616 | continue; |
@@ -1046,6 +636,10 @@ static void do_tty_hangup(struct work_struct *work) | |||
1046 | tty->ctrl_status = 0; | 636 | tty->ctrl_status = 0; |
1047 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 637 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
1048 | 638 | ||
639 | /* Account for the p->signal references we killed */ | ||
640 | while (refs--) | ||
641 | tty_kref_put(tty); | ||
642 | |||
1049 | /* | 643 | /* |
1050 | * If one of the devices matches a console pointer, we | 644 | * If one of the devices matches a console pointer, we |
1051 | * cannot just call hangup() because that will cause | 645 | * cannot just call hangup() because that will cause |
@@ -1115,6 +709,23 @@ void tty_vhangup(struct tty_struct *tty) | |||
1115 | EXPORT_SYMBOL(tty_vhangup); | 709 | EXPORT_SYMBOL(tty_vhangup); |
1116 | 710 | ||
1117 | /** | 711 | /** |
712 | * tty_vhangup_self - process vhangup for own ctty | ||
713 | * | ||
714 | * Perform a vhangup on the current controlling tty | ||
715 | */ | ||
716 | |||
717 | void tty_vhangup_self(void) | ||
718 | { | ||
719 | struct tty_struct *tty; | ||
720 | |||
721 | tty = get_current_tty(); | ||
722 | if (tty) { | ||
723 | tty_vhangup(tty); | ||
724 | tty_kref_put(tty); | ||
725 | } | ||
726 | } | ||
727 | |||
728 | /** | ||
1118 | * tty_hung_up_p - was tty hung up | 729 | * tty_hung_up_p - was tty hung up |
1119 | * @filp: file pointer of tty | 730 | * @filp: file pointer of tty |
1120 | * | 731 | * |
@@ -1167,16 +778,14 @@ void disassociate_ctty(int on_exit) | |||
1167 | struct pid *tty_pgrp = NULL; | 778 | struct pid *tty_pgrp = NULL; |
1168 | 779 | ||
1169 | 780 | ||
1170 | mutex_lock(&tty_mutex); | ||
1171 | tty = get_current_tty(); | 781 | tty = get_current_tty(); |
1172 | if (tty) { | 782 | if (tty) { |
1173 | tty_pgrp = get_pid(tty->pgrp); | 783 | tty_pgrp = get_pid(tty->pgrp); |
1174 | lock_kernel(); | 784 | lock_kernel(); |
1175 | mutex_unlock(&tty_mutex); | ||
1176 | /* XXX: here we race, there is nothing protecting tty */ | ||
1177 | if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) | 785 | if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) |
1178 | tty_vhangup(tty); | 786 | tty_vhangup(tty); |
1179 | unlock_kernel(); | 787 | unlock_kernel(); |
788 | tty_kref_put(tty); | ||
1180 | } else if (on_exit) { | 789 | } else if (on_exit) { |
1181 | struct pid *old_pgrp; | 790 | struct pid *old_pgrp; |
1182 | spin_lock_irq(¤t->sighand->siglock); | 791 | spin_lock_irq(¤t->sighand->siglock); |
@@ -1188,7 +797,6 @@ void disassociate_ctty(int on_exit) | |||
1188 | kill_pgrp(old_pgrp, SIGCONT, on_exit); | 797 | kill_pgrp(old_pgrp, SIGCONT, on_exit); |
1189 | put_pid(old_pgrp); | 798 | put_pid(old_pgrp); |
1190 | } | 799 | } |
1191 | mutex_unlock(&tty_mutex); | ||
1192 | return; | 800 | return; |
1193 | } | 801 | } |
1194 | if (tty_pgrp) { | 802 | if (tty_pgrp) { |
@@ -1203,8 +811,6 @@ void disassociate_ctty(int on_exit) | |||
1203 | current->signal->tty_old_pgrp = NULL; | 811 | current->signal->tty_old_pgrp = NULL; |
1204 | spin_unlock_irq(¤t->sighand->siglock); | 812 | spin_unlock_irq(¤t->sighand->siglock); |
1205 | 813 | ||
1206 | mutex_lock(&tty_mutex); | ||
1207 | /* It is possible that do_tty_hangup has free'd this tty */ | ||
1208 | tty = get_current_tty(); | 814 | tty = get_current_tty(); |
1209 | if (tty) { | 815 | if (tty) { |
1210 | unsigned long flags; | 816 | unsigned long flags; |
@@ -1214,13 +820,13 @@ void disassociate_ctty(int on_exit) | |||
1214 | tty->session = NULL; | 820 | tty->session = NULL; |
1215 | tty->pgrp = NULL; | 821 | tty->pgrp = NULL; |
1216 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 822 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
823 | tty_kref_put(tty); | ||
1217 | } else { | 824 | } else { |
1218 | #ifdef TTY_DEBUG_HANGUP | 825 | #ifdef TTY_DEBUG_HANGUP |
1219 | printk(KERN_DEBUG "error attempted to write to tty [0x%p]" | 826 | printk(KERN_DEBUG "error attempted to write to tty [0x%p]" |
1220 | " = NULL", tty); | 827 | " = NULL", tty); |
1221 | #endif | 828 | #endif |
1222 | } | 829 | } |
1223 | mutex_unlock(&tty_mutex); | ||
1224 | 830 | ||
1225 | /* Now clear signal->tty under the lock */ | 831 | /* Now clear signal->tty under the lock */ |
1226 | read_lock(&tasklist_lock); | 832 | read_lock(&tasklist_lock); |
@@ -1420,19 +1026,19 @@ static inline ssize_t do_tty_write( | |||
1420 | 1026 | ||
1421 | /* write_buf/write_cnt is protected by the atomic_write_lock mutex */ | 1027 | /* write_buf/write_cnt is protected by the atomic_write_lock mutex */ |
1422 | if (tty->write_cnt < chunk) { | 1028 | if (tty->write_cnt < chunk) { |
1423 | unsigned char *buf; | 1029 | unsigned char *buf_chunk; |
1424 | 1030 | ||
1425 | if (chunk < 1024) | 1031 | if (chunk < 1024) |
1426 | chunk = 1024; | 1032 | chunk = 1024; |
1427 | 1033 | ||
1428 | buf = kmalloc(chunk, GFP_KERNEL); | 1034 | buf_chunk = kmalloc(chunk, GFP_KERNEL); |
1429 | if (!buf) { | 1035 | if (!buf_chunk) { |
1430 | ret = -ENOMEM; | 1036 | ret = -ENOMEM; |
1431 | goto out; | 1037 | goto out; |
1432 | } | 1038 | } |
1433 | kfree(tty->write_buf); | 1039 | kfree(tty->write_buf); |
1434 | tty->write_cnt = chunk; | 1040 | tty->write_cnt = chunk; |
1435 | tty->write_buf = buf; | 1041 | tty->write_buf = buf_chunk; |
1436 | } | 1042 | } |
1437 | 1043 | ||
1438 | /* Do the write .. */ | 1044 | /* Do the write .. */ |
@@ -1466,6 +1072,31 @@ out: | |||
1466 | return ret; | 1072 | return ret; |
1467 | } | 1073 | } |
1468 | 1074 | ||
1075 | /** | ||
1076 | * tty_write_message - write a message to a certain tty, not just the console. | ||
1077 | * @tty: the destination tty_struct | ||
1078 | * @msg: the message to write | ||
1079 | * | ||
1080 | * This is used for messages that need to be redirected to a specific tty. | ||
1081 | * We don't put it into the syslog queue right now maybe in the future if | ||
1082 | * really needed. | ||
1083 | * | ||
1084 | * We must still hold the BKL and test the CLOSING flag for the moment. | ||
1085 | */ | ||
1086 | |||
1087 | void tty_write_message(struct tty_struct *tty, char *msg) | ||
1088 | { | ||
1089 | lock_kernel(); | ||
1090 | if (tty) { | ||
1091 | mutex_lock(&tty->atomic_write_lock); | ||
1092 | if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) | ||
1093 | tty->ops->write(tty, msg, strlen(msg)); | ||
1094 | tty_write_unlock(tty); | ||
1095 | } | ||
1096 | unlock_kernel(); | ||
1097 | return; | ||
1098 | } | ||
1099 | |||
1469 | 1100 | ||
1470 | /** | 1101 | /** |
1471 | * tty_write - write method for tty device file | 1102 | * tty_write - write method for tty device file |
@@ -1533,42 +1164,6 @@ ssize_t redirected_tty_write(struct file *file, const char __user *buf, | |||
1533 | return tty_write(file, buf, count, ppos); | 1164 | return tty_write(file, buf, count, ppos); |
1534 | } | 1165 | } |
1535 | 1166 | ||
1536 | void tty_port_init(struct tty_port *port) | ||
1537 | { | ||
1538 | memset(port, 0, sizeof(*port)); | ||
1539 | init_waitqueue_head(&port->open_wait); | ||
1540 | init_waitqueue_head(&port->close_wait); | ||
1541 | mutex_init(&port->mutex); | ||
1542 | port->close_delay = (50 * HZ) / 100; | ||
1543 | port->closing_wait = (3000 * HZ) / 100; | ||
1544 | } | ||
1545 | EXPORT_SYMBOL(tty_port_init); | ||
1546 | |||
1547 | int tty_port_alloc_xmit_buf(struct tty_port *port) | ||
1548 | { | ||
1549 | /* We may sleep in get_zeroed_page() */ | ||
1550 | mutex_lock(&port->mutex); | ||
1551 | if (port->xmit_buf == NULL) | ||
1552 | port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); | ||
1553 | mutex_unlock(&port->mutex); | ||
1554 | if (port->xmit_buf == NULL) | ||
1555 | return -ENOMEM; | ||
1556 | return 0; | ||
1557 | } | ||
1558 | EXPORT_SYMBOL(tty_port_alloc_xmit_buf); | ||
1559 | |||
1560 | void tty_port_free_xmit_buf(struct tty_port *port) | ||
1561 | { | ||
1562 | mutex_lock(&port->mutex); | ||
1563 | if (port->xmit_buf != NULL) { | ||
1564 | free_page((unsigned long)port->xmit_buf); | ||
1565 | port->xmit_buf = NULL; | ||
1566 | } | ||
1567 | mutex_unlock(&port->mutex); | ||
1568 | } | ||
1569 | EXPORT_SYMBOL(tty_port_free_xmit_buf); | ||
1570 | |||
1571 | |||
1572 | static char ptychar[] = "pqrstuvwxyzabcde"; | 1167 | static char ptychar[] = "pqrstuvwxyzabcde"; |
1573 | 1168 | ||
1574 | /** | 1169 | /** |
@@ -1592,7 +1187,7 @@ static void pty_line_name(struct tty_driver *driver, int index, char *p) | |||
1592 | } | 1187 | } |
1593 | 1188 | ||
1594 | /** | 1189 | /** |
1595 | * pty_line_name - generate name for a tty | 1190 | * tty_line_name - generate name for a tty |
1596 | * @driver: the tty driver in use | 1191 | * @driver: the tty driver in use |
1597 | * @index: the minor number | 1192 | * @index: the minor number |
1598 | * @p: output buffer of at least 7 bytes | 1193 | * @p: output buffer of at least 7 bytes |
@@ -1608,10 +1203,148 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p) | |||
1608 | } | 1203 | } |
1609 | 1204 | ||
1610 | /** | 1205 | /** |
1611 | * init_dev - initialise a tty device | 1206 | * tty_driver_lookup_tty() - find an existing tty, if any |
1207 | * @driver: the driver for the tty | ||
1208 | * @idx: the minor number | ||
1209 | * | ||
1210 | * Return the tty, if found or ERR_PTR() otherwise. | ||
1211 | * | ||
1212 | * Locking: tty_mutex must be held. If tty is found, the mutex must | ||
1213 | * be held until the 'fast-open' is also done. Will change once we | ||
1214 | * have refcounting in the driver and per driver locking | ||
1215 | */ | ||
1216 | struct tty_struct *tty_driver_lookup_tty(struct tty_driver *driver, | ||
1217 | struct inode *inode, int idx) | ||
1218 | { | ||
1219 | struct tty_struct *tty; | ||
1220 | |||
1221 | if (driver->ops->lookup) | ||
1222 | return driver->ops->lookup(driver, inode, idx); | ||
1223 | |||
1224 | tty = driver->ttys[idx]; | ||
1225 | return tty; | ||
1226 | } | ||
1227 | |||
1228 | /** | ||
1229 | * tty_init_termios - helper for termios setup | ||
1230 | * @tty: the tty to set up | ||
1231 | * | ||
1232 | * Initialise the termios structures for this tty. Thus runs under | ||
1233 | * the tty_mutex currently so we can be relaxed about ordering. | ||
1234 | */ | ||
1235 | |||
1236 | int tty_init_termios(struct tty_struct *tty) | ||
1237 | { | ||
1238 | struct ktermios *tp; | ||
1239 | int idx = tty->index; | ||
1240 | |||
1241 | tp = tty->driver->termios[idx]; | ||
1242 | if (tp == NULL) { | ||
1243 | tp = kzalloc(sizeof(struct ktermios[2]), GFP_KERNEL); | ||
1244 | if (tp == NULL) | ||
1245 | return -ENOMEM; | ||
1246 | memcpy(tp, &tty->driver->init_termios, | ||
1247 | sizeof(struct ktermios)); | ||
1248 | tty->driver->termios[idx] = tp; | ||
1249 | } | ||
1250 | tty->termios = tp; | ||
1251 | tty->termios_locked = tp + 1; | ||
1252 | |||
1253 | /* Compatibility until drivers always set this */ | ||
1254 | tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); | ||
1255 | tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); | ||
1256 | return 0; | ||
1257 | } | ||
1258 | |||
1259 | /** | ||
1260 | * tty_driver_install_tty() - install a tty entry in the driver | ||
1261 | * @driver: the driver for the tty | ||
1262 | * @tty: the tty | ||
1263 | * | ||
1264 | * Install a tty object into the driver tables. The tty->index field | ||
1265 | * will be set by the time this is called. This method is responsible | ||
1266 | * for ensuring any need additional structures are allocated and | ||
1267 | * configured. | ||
1268 | * | ||
1269 | * Locking: tty_mutex for now | ||
1270 | */ | ||
1271 | static int tty_driver_install_tty(struct tty_driver *driver, | ||
1272 | struct tty_struct *tty) | ||
1273 | { | ||
1274 | int idx = tty->index; | ||
1275 | |||
1276 | if (driver->ops->install) | ||
1277 | return driver->ops->install(driver, tty); | ||
1278 | |||
1279 | if (tty_init_termios(tty) == 0) { | ||
1280 | tty_driver_kref_get(driver); | ||
1281 | tty->count++; | ||
1282 | driver->ttys[idx] = tty; | ||
1283 | return 0; | ||
1284 | } | ||
1285 | return -ENOMEM; | ||
1286 | } | ||
1287 | |||
1288 | /** | ||
1289 | * tty_driver_remove_tty() - remove a tty from the driver tables | ||
1290 | * @driver: the driver for the tty | ||
1291 | * @idx: the minor number | ||
1292 | * | ||
1293 | * Remvoe a tty object from the driver tables. The tty->index field | ||
1294 | * will be set by the time this is called. | ||
1295 | * | ||
1296 | * Locking: tty_mutex for now | ||
1297 | */ | ||
1298 | static void tty_driver_remove_tty(struct tty_driver *driver, | ||
1299 | struct tty_struct *tty) | ||
1300 | { | ||
1301 | if (driver->ops->remove) | ||
1302 | driver->ops->remove(driver, tty); | ||
1303 | else | ||
1304 | driver->ttys[tty->index] = NULL; | ||
1305 | } | ||
1306 | |||
1307 | /* | ||
1308 | * tty_reopen() - fast re-open of an open tty | ||
1309 | * @tty - the tty to open | ||
1310 | * | ||
1311 | * Return 0 on success, -errno on error. | ||
1312 | * | ||
1313 | * Locking: tty_mutex must be held from the time the tty was found | ||
1314 | * till this open completes. | ||
1315 | */ | ||
1316 | static int tty_reopen(struct tty_struct *tty) | ||
1317 | { | ||
1318 | struct tty_driver *driver = tty->driver; | ||
1319 | |||
1320 | if (test_bit(TTY_CLOSING, &tty->flags)) | ||
1321 | return -EIO; | ||
1322 | |||
1323 | if (driver->type == TTY_DRIVER_TYPE_PTY && | ||
1324 | driver->subtype == PTY_TYPE_MASTER) { | ||
1325 | /* | ||
1326 | * special case for PTY masters: only one open permitted, | ||
1327 | * and the slave side open count is incremented as well. | ||
1328 | */ | ||
1329 | if (tty->count) | ||
1330 | return -EIO; | ||
1331 | |||
1332 | tty->link->count++; | ||
1333 | } | ||
1334 | tty->count++; | ||
1335 | tty->driver = driver; /* N.B. why do this every time?? */ | ||
1336 | |||
1337 | WARN_ON(!test_bit(TTY_LDISC, &tty->flags)); | ||
1338 | |||
1339 | return 0; | ||
1340 | } | ||
1341 | |||
1342 | /** | ||
1343 | * tty_init_dev - initialise a tty device | ||
1612 | * @driver: tty driver we are opening a device on | 1344 | * @driver: tty driver we are opening a device on |
1613 | * @idx: device index | 1345 | * @idx: device index |
1614 | * @tty: returned tty structure | 1346 | * @ret_tty: returned tty structure |
1347 | * @first_ok: ok to open a new device (used by ptmx) | ||
1615 | * | 1348 | * |
1616 | * Prepare a tty device. This may not be a "new" clean device but | 1349 | * Prepare a tty device. This may not be a "new" clean device but |
1617 | * could also be an active device. The pty drivers require special | 1350 | * could also be an active device. The pty drivers require special |
@@ -1631,37 +1364,16 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p) | |||
1631 | * relaxed for the (most common) case of reopening a tty. | 1364 | * relaxed for the (most common) case of reopening a tty. |
1632 | */ | 1365 | */ |
1633 | 1366 | ||
1634 | static int init_dev(struct tty_driver *driver, int idx, | 1367 | struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, |
1635 | struct tty_struct **ret_tty) | 1368 | int first_ok) |
1636 | { | 1369 | { |
1637 | struct tty_struct *tty, *o_tty; | 1370 | struct tty_struct *tty; |
1638 | struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc; | 1371 | int retval; |
1639 | struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; | ||
1640 | int retval = 0; | ||
1641 | 1372 | ||
1642 | /* check whether we're reopening an existing tty */ | 1373 | /* Check if pty master is being opened multiple times */ |
1643 | if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { | 1374 | if (driver->subtype == PTY_TYPE_MASTER && |
1644 | tty = devpts_get_tty(idx); | 1375 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) |
1645 | /* | 1376 | return ERR_PTR(-EIO); |
1646 | * If we don't have a tty here on a slave open, it's because | ||
1647 | * the master already started the close process and there's | ||
1648 | * no relation between devpts file and tty anymore. | ||
1649 | */ | ||
1650 | if (!tty && driver->subtype == PTY_TYPE_SLAVE) { | ||
1651 | retval = -EIO; | ||
1652 | goto end_init; | ||
1653 | } | ||
1654 | /* | ||
1655 | * It's safe from now on because init_dev() is called with | ||
1656 | * tty_mutex held and release_dev() won't change tty->count | ||
1657 | * or tty->flags without having to grab tty_mutex | ||
1658 | */ | ||
1659 | if (tty && driver->subtype == PTY_TYPE_MASTER) | ||
1660 | tty = tty->link; | ||
1661 | } else { | ||
1662 | tty = driver->ttys[idx]; | ||
1663 | } | ||
1664 | if (tty) goto fast_track; | ||
1665 | 1377 | ||
1666 | /* | 1378 | /* |
1667 | * First time open is complex, especially for PTY devices. | 1379 | * First time open is complex, especially for PTY devices. |
@@ -1671,189 +1383,69 @@ static int init_dev(struct tty_driver *driver, int idx, | |||
1671 | * and locked termios may be retained.) | 1383 | * and locked termios may be retained.) |
1672 | */ | 1384 | */ |
1673 | 1385 | ||
1674 | if (!try_module_get(driver->owner)) { | 1386 | if (!try_module_get(driver->owner)) |
1675 | retval = -ENODEV; | 1387 | return ERR_PTR(-ENODEV); |
1676 | goto end_init; | ||
1677 | } | ||
1678 | |||
1679 | o_tty = NULL; | ||
1680 | tp = o_tp = NULL; | ||
1681 | ltp = o_ltp = NULL; | ||
1682 | 1388 | ||
1683 | tty = alloc_tty_struct(); | 1389 | tty = alloc_tty_struct(); |
1684 | if (!tty) | 1390 | if (!tty) |
1685 | goto fail_no_mem; | 1391 | goto fail_no_mem; |
1686 | initialize_tty_struct(tty); | 1392 | initialize_tty_struct(tty, driver, idx); |
1687 | tty->driver = driver; | ||
1688 | tty->ops = driver->ops; | ||
1689 | tty->index = idx; | ||
1690 | tty_line_name(driver, idx, tty->name); | ||
1691 | |||
1692 | if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { | ||
1693 | tp_loc = &tty->termios; | ||
1694 | ltp_loc = &tty->termios_locked; | ||
1695 | } else { | ||
1696 | tp_loc = &driver->termios[idx]; | ||
1697 | ltp_loc = &driver->termios_locked[idx]; | ||
1698 | } | ||
1699 | |||
1700 | if (!*tp_loc) { | ||
1701 | tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL); | ||
1702 | if (!tp) | ||
1703 | goto free_mem_out; | ||
1704 | *tp = driver->init_termios; | ||
1705 | } | ||
1706 | |||
1707 | if (!*ltp_loc) { | ||
1708 | ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL); | ||
1709 | if (!ltp) | ||
1710 | goto free_mem_out; | ||
1711 | } | ||
1712 | |||
1713 | if (driver->type == TTY_DRIVER_TYPE_PTY) { | ||
1714 | o_tty = alloc_tty_struct(); | ||
1715 | if (!o_tty) | ||
1716 | goto free_mem_out; | ||
1717 | initialize_tty_struct(o_tty); | ||
1718 | o_tty->driver = driver->other; | ||
1719 | o_tty->ops = driver->ops; | ||
1720 | o_tty->index = idx; | ||
1721 | tty_line_name(driver->other, idx, o_tty->name); | ||
1722 | 1393 | ||
1723 | if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { | 1394 | retval = tty_driver_install_tty(driver, tty); |
1724 | o_tp_loc = &o_tty->termios; | 1395 | if (retval < 0) { |
1725 | o_ltp_loc = &o_tty->termios_locked; | 1396 | free_tty_struct(tty); |
1726 | } else { | 1397 | module_put(driver->owner); |
1727 | o_tp_loc = &driver->other->termios[idx]; | 1398 | return ERR_PTR(retval); |
1728 | o_ltp_loc = &driver->other->termios_locked[idx]; | ||
1729 | } | ||
1730 | |||
1731 | if (!*o_tp_loc) { | ||
1732 | o_tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL); | ||
1733 | if (!o_tp) | ||
1734 | goto free_mem_out; | ||
1735 | *o_tp = driver->other->init_termios; | ||
1736 | } | ||
1737 | |||
1738 | if (!*o_ltp_loc) { | ||
1739 | o_ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL); | ||
1740 | if (!o_ltp) | ||
1741 | goto free_mem_out; | ||
1742 | } | ||
1743 | |||
1744 | /* | ||
1745 | * Everything allocated ... set up the o_tty structure. | ||
1746 | */ | ||
1747 | if (!(driver->other->flags & TTY_DRIVER_DEVPTS_MEM)) | ||
1748 | driver->other->ttys[idx] = o_tty; | ||
1749 | if (!*o_tp_loc) | ||
1750 | *o_tp_loc = o_tp; | ||
1751 | if (!*o_ltp_loc) | ||
1752 | *o_ltp_loc = o_ltp; | ||
1753 | o_tty->termios = *o_tp_loc; | ||
1754 | o_tty->termios_locked = *o_ltp_loc; | ||
1755 | driver->other->refcount++; | ||
1756 | if (driver->subtype == PTY_TYPE_MASTER) | ||
1757 | o_tty->count++; | ||
1758 | |||
1759 | /* Establish the links in both directions */ | ||
1760 | tty->link = o_tty; | ||
1761 | o_tty->link = tty; | ||
1762 | } | 1399 | } |
1763 | 1400 | ||
1764 | /* | 1401 | /* |
1765 | * All structures have been allocated, so now we install them. | ||
1766 | * Failures after this point use release_tty to clean up, so | ||
1767 | * there's no need to null out the local pointers. | ||
1768 | */ | ||
1769 | if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM)) | ||
1770 | driver->ttys[idx] = tty; | ||
1771 | |||
1772 | if (!*tp_loc) | ||
1773 | *tp_loc = tp; | ||
1774 | if (!*ltp_loc) | ||
1775 | *ltp_loc = ltp; | ||
1776 | tty->termios = *tp_loc; | ||
1777 | tty->termios_locked = *ltp_loc; | ||
1778 | /* Compatibility until drivers always set this */ | ||
1779 | tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); | ||
1780 | tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); | ||
1781 | driver->refcount++; | ||
1782 | tty->count++; | ||
1783 | |||
1784 | /* | ||
1785 | * Structures all installed ... call the ldisc open routines. | 1402 | * Structures all installed ... call the ldisc open routines. |
1786 | * If we fail here just call release_tty to clean up. No need | 1403 | * If we fail here just call release_tty to clean up. No need |
1787 | * to decrement the use counts, as release_tty doesn't care. | 1404 | * to decrement the use counts, as release_tty doesn't care. |
1788 | */ | 1405 | */ |
1789 | 1406 | ||
1790 | retval = tty_ldisc_setup(tty, o_tty); | 1407 | retval = tty_ldisc_setup(tty, tty->link); |
1791 | |||
1792 | if (retval) | 1408 | if (retval) |
1793 | goto release_mem_out; | 1409 | goto release_mem_out; |
1794 | goto success; | 1410 | return tty; |
1795 | |||
1796 | /* | ||
1797 | * This fast open can be used if the tty is already open. | ||
1798 | * No memory is allocated, and the only failures are from | ||
1799 | * attempting to open a closing tty or attempting multiple | ||
1800 | * opens on a pty master. | ||
1801 | */ | ||
1802 | fast_track: | ||
1803 | if (test_bit(TTY_CLOSING, &tty->flags)) { | ||
1804 | retval = -EIO; | ||
1805 | goto end_init; | ||
1806 | } | ||
1807 | if (driver->type == TTY_DRIVER_TYPE_PTY && | ||
1808 | driver->subtype == PTY_TYPE_MASTER) { | ||
1809 | /* | ||
1810 | * special case for PTY masters: only one open permitted, | ||
1811 | * and the slave side open count is incremented as well. | ||
1812 | */ | ||
1813 | if (tty->count) { | ||
1814 | retval = -EIO; | ||
1815 | goto end_init; | ||
1816 | } | ||
1817 | tty->link->count++; | ||
1818 | } | ||
1819 | tty->count++; | ||
1820 | tty->driver = driver; /* N.B. why do this every time?? */ | ||
1821 | |||
1822 | /* FIXME */ | ||
1823 | if (!test_bit(TTY_LDISC, &tty->flags)) | ||
1824 | printk(KERN_ERR "init_dev but no ldisc\n"); | ||
1825 | success: | ||
1826 | *ret_tty = tty; | ||
1827 | |||
1828 | /* All paths come through here to release the mutex */ | ||
1829 | end_init: | ||
1830 | return retval; | ||
1831 | |||
1832 | /* Release locally allocated memory ... nothing placed in slots */ | ||
1833 | free_mem_out: | ||
1834 | kfree(o_tp); | ||
1835 | if (o_tty) | ||
1836 | free_tty_struct(o_tty); | ||
1837 | kfree(ltp); | ||
1838 | kfree(tp); | ||
1839 | free_tty_struct(tty); | ||
1840 | 1411 | ||
1841 | fail_no_mem: | 1412 | fail_no_mem: |
1842 | module_put(driver->owner); | 1413 | module_put(driver->owner); |
1843 | retval = -ENOMEM; | 1414 | return ERR_PTR(-ENOMEM); |
1844 | goto end_init; | ||
1845 | 1415 | ||
1846 | /* call the tty release_tty routine to clean out this slot */ | 1416 | /* call the tty release_tty routine to clean out this slot */ |
1847 | release_mem_out: | 1417 | release_mem_out: |
1848 | if (printk_ratelimit()) | 1418 | if (printk_ratelimit()) |
1849 | printk(KERN_INFO "init_dev: ldisc open failed, " | 1419 | printk(KERN_INFO "tty_init_dev: ldisc open failed, " |
1850 | "clearing slot %d\n", idx); | 1420 | "clearing slot %d\n", idx); |
1851 | release_tty(tty, idx); | 1421 | release_tty(tty, idx); |
1852 | goto end_init; | 1422 | return ERR_PTR(retval); |
1853 | } | 1423 | } |
1854 | 1424 | ||
1425 | void tty_free_termios(struct tty_struct *tty) | ||
1426 | { | ||
1427 | struct ktermios *tp; | ||
1428 | int idx = tty->index; | ||
1429 | /* Kill this flag and push into drivers for locking etc */ | ||
1430 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { | ||
1431 | /* FIXME: Locking on ->termios array */ | ||
1432 | tp = tty->termios; | ||
1433 | tty->driver->termios[idx] = NULL; | ||
1434 | kfree(tp); | ||
1435 | } | ||
1436 | } | ||
1437 | EXPORT_SYMBOL(tty_free_termios); | ||
1438 | |||
1439 | void tty_shutdown(struct tty_struct *tty) | ||
1440 | { | ||
1441 | tty_driver_remove_tty(tty->driver, tty); | ||
1442 | tty_free_termios(tty); | ||
1443 | } | ||
1444 | EXPORT_SYMBOL(tty_shutdown); | ||
1445 | |||
1855 | /** | 1446 | /** |
1856 | * release_one_tty - release tty structure memory | 1447 | * release_one_tty - release tty structure memory |
1448 | * @kref: kref of tty we are obliterating | ||
1857 | * | 1449 | * |
1858 | * Releases memory associated with a tty structure, and clears out the | 1450 | * Releases memory associated with a tty structure, and clears out the |
1859 | * driver table slots. This function is called when a device is no longer | 1451 | * driver table slots. This function is called when a device is no longer |
@@ -1863,31 +1455,19 @@ release_mem_out: | |||
1863 | * tty_mutex - sometimes only | 1455 | * tty_mutex - sometimes only |
1864 | * takes the file list lock internally when working on the list | 1456 | * takes the file list lock internally when working on the list |
1865 | * of ttys that the driver keeps. | 1457 | * of ttys that the driver keeps. |
1866 | * FIXME: should we require tty_mutex is held here ?? | ||
1867 | */ | 1458 | */ |
1868 | static void release_one_tty(struct tty_struct *tty, int idx) | 1459 | static void release_one_tty(struct kref *kref) |
1869 | { | 1460 | { |
1870 | int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM; | 1461 | struct tty_struct *tty = container_of(kref, struct tty_struct, kref); |
1871 | struct ktermios *tp; | 1462 | struct tty_driver *driver = tty->driver; |
1872 | |||
1873 | if (!devpts) | ||
1874 | tty->driver->ttys[idx] = NULL; | ||
1875 | |||
1876 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { | ||
1877 | tp = tty->termios; | ||
1878 | if (!devpts) | ||
1879 | tty->driver->termios[idx] = NULL; | ||
1880 | kfree(tp); | ||
1881 | |||
1882 | tp = tty->termios_locked; | ||
1883 | if (!devpts) | ||
1884 | tty->driver->termios_locked[idx] = NULL; | ||
1885 | kfree(tp); | ||
1886 | } | ||
1887 | |||
1888 | 1463 | ||
1464 | if (tty->ops->shutdown) | ||
1465 | tty->ops->shutdown(tty); | ||
1466 | else | ||
1467 | tty_shutdown(tty); | ||
1889 | tty->magic = 0; | 1468 | tty->magic = 0; |
1890 | tty->driver->refcount--; | 1469 | tty_driver_kref_put(driver); |
1470 | module_put(driver->owner); | ||
1891 | 1471 | ||
1892 | file_list_lock(); | 1472 | file_list_lock(); |
1893 | list_del_init(&tty->tty_files); | 1473 | list_del_init(&tty->tty_files); |
@@ -1897,6 +1477,21 @@ static void release_one_tty(struct tty_struct *tty, int idx) | |||
1897 | } | 1477 | } |
1898 | 1478 | ||
1899 | /** | 1479 | /** |
1480 | * tty_kref_put - release a tty kref | ||
1481 | * @tty: tty device | ||
1482 | * | ||
1483 | * Release a reference to a tty device and if need be let the kref | ||
1484 | * layer destruct the object for us | ||
1485 | */ | ||
1486 | |||
1487 | void tty_kref_put(struct tty_struct *tty) | ||
1488 | { | ||
1489 | if (tty) | ||
1490 | kref_put(&tty->kref, release_one_tty); | ||
1491 | } | ||
1492 | EXPORT_SYMBOL(tty_kref_put); | ||
1493 | |||
1494 | /** | ||
1900 | * release_tty - release tty structure memory | 1495 | * release_tty - release tty structure memory |
1901 | * | 1496 | * |
1902 | * Release both @tty and a possible linked partner (think pty pair), | 1497 | * Release both @tty and a possible linked partner (think pty pair), |
@@ -1907,15 +1502,16 @@ static void release_one_tty(struct tty_struct *tty, int idx) | |||
1907 | * takes the file list lock internally when working on the list | 1502 | * takes the file list lock internally when working on the list |
1908 | * of ttys that the driver keeps. | 1503 | * of ttys that the driver keeps. |
1909 | * FIXME: should we require tty_mutex is held here ?? | 1504 | * FIXME: should we require tty_mutex is held here ?? |
1505 | * | ||
1910 | */ | 1506 | */ |
1911 | static void release_tty(struct tty_struct *tty, int idx) | 1507 | static void release_tty(struct tty_struct *tty, int idx) |
1912 | { | 1508 | { |
1913 | struct tty_driver *driver = tty->driver; | 1509 | /* This should always be true but check for the moment */ |
1510 | WARN_ON(tty->index != idx); | ||
1914 | 1511 | ||
1915 | if (tty->link) | 1512 | if (tty->link) |
1916 | release_one_tty(tty->link, idx); | 1513 | tty_kref_put(tty->link); |
1917 | release_one_tty(tty, idx); | 1514 | tty_kref_put(tty); |
1918 | module_put(driver->owner); | ||
1919 | } | 1515 | } |
1920 | 1516 | ||
1921 | /* | 1517 | /* |
@@ -1926,20 +1522,21 @@ static void release_tty(struct tty_struct *tty, int idx) | |||
1926 | * WSH 09/09/97: rewritten to avoid some nasty race conditions that could | 1522 | * WSH 09/09/97: rewritten to avoid some nasty race conditions that could |
1927 | * lead to double frees or releasing memory still in use. | 1523 | * lead to double frees or releasing memory still in use. |
1928 | */ | 1524 | */ |
1929 | static void release_dev(struct file *filp) | 1525 | void tty_release_dev(struct file *filp) |
1930 | { | 1526 | { |
1931 | struct tty_struct *tty, *o_tty; | 1527 | struct tty_struct *tty, *o_tty; |
1932 | int pty_master, tty_closing, o_tty_closing, do_sleep; | 1528 | int pty_master, tty_closing, o_tty_closing, do_sleep; |
1933 | int devpts; | 1529 | int devpts; |
1934 | int idx; | 1530 | int idx; |
1935 | char buf[64]; | 1531 | char buf[64]; |
1532 | struct inode *inode; | ||
1936 | 1533 | ||
1534 | inode = filp->f_path.dentry->d_inode; | ||
1937 | tty = (struct tty_struct *)filp->private_data; | 1535 | tty = (struct tty_struct *)filp->private_data; |
1938 | if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, | 1536 | if (tty_paranoia_check(tty, inode, "tty_release_dev")) |
1939 | "release_dev")) | ||
1940 | return; | 1537 | return; |
1941 | 1538 | ||
1942 | check_tty_count(tty, "release_dev"); | 1539 | check_tty_count(tty, "tty_release_dev"); |
1943 | 1540 | ||
1944 | tty_fasync(-1, filp, 0); | 1541 | tty_fasync(-1, filp, 0); |
1945 | 1542 | ||
@@ -1951,33 +1548,27 @@ static void release_dev(struct file *filp) | |||
1951 | 1548 | ||
1952 | #ifdef TTY_PARANOIA_CHECK | 1549 | #ifdef TTY_PARANOIA_CHECK |
1953 | if (idx < 0 || idx >= tty->driver->num) { | 1550 | if (idx < 0 || idx >= tty->driver->num) { |
1954 | printk(KERN_DEBUG "release_dev: bad idx when trying to " | 1551 | printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " |
1955 | "free (%s)\n", tty->name); | 1552 | "free (%s)\n", tty->name); |
1956 | return; | 1553 | return; |
1957 | } | 1554 | } |
1958 | if (!(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { | 1555 | if (!devpts) { |
1959 | if (tty != tty->driver->ttys[idx]) { | 1556 | if (tty != tty->driver->ttys[idx]) { |
1960 | printk(KERN_DEBUG "release_dev: driver.table[%d] not tty " | 1557 | printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " |
1961 | "for (%s)\n", idx, tty->name); | 1558 | "for (%s)\n", idx, tty->name); |
1962 | return; | 1559 | return; |
1963 | } | 1560 | } |
1964 | if (tty->termios != tty->driver->termios[idx]) { | 1561 | if (tty->termios != tty->driver->termios[idx]) { |
1965 | printk(KERN_DEBUG "release_dev: driver.termios[%d] not termios " | 1562 | printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " |
1966 | "for (%s)\n", | 1563 | "for (%s)\n", |
1967 | idx, tty->name); | 1564 | idx, tty->name); |
1968 | return; | 1565 | return; |
1969 | } | 1566 | } |
1970 | if (tty->termios_locked != tty->driver->termios_locked[idx]) { | ||
1971 | printk(KERN_DEBUG "release_dev: driver.termios_locked[%d] not " | ||
1972 | "termios_locked for (%s)\n", | ||
1973 | idx, tty->name); | ||
1974 | return; | ||
1975 | } | ||
1976 | } | 1567 | } |
1977 | #endif | 1568 | #endif |
1978 | 1569 | ||
1979 | #ifdef TTY_DEBUG_HANGUP | 1570 | #ifdef TTY_DEBUG_HANGUP |
1980 | printk(KERN_DEBUG "release_dev of %s (tty count=%d)...", | 1571 | printk(KERN_DEBUG "tty_release_dev of %s (tty count=%d)...", |
1981 | tty_name(tty, buf), tty->count); | 1572 | tty_name(tty, buf), tty->count); |
1982 | #endif | 1573 | #endif |
1983 | 1574 | ||
@@ -1985,26 +1576,19 @@ static void release_dev(struct file *filp) | |||
1985 | if (tty->driver->other && | 1576 | if (tty->driver->other && |
1986 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { | 1577 | !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { |
1987 | if (o_tty != tty->driver->other->ttys[idx]) { | 1578 | if (o_tty != tty->driver->other->ttys[idx]) { |
1988 | printk(KERN_DEBUG "release_dev: other->table[%d] " | 1579 | printk(KERN_DEBUG "tty_release_dev: other->table[%d] " |
1989 | "not o_tty for (%s)\n", | 1580 | "not o_tty for (%s)\n", |
1990 | idx, tty->name); | 1581 | idx, tty->name); |
1991 | return; | 1582 | return; |
1992 | } | 1583 | } |
1993 | if (o_tty->termios != tty->driver->other->termios[idx]) { | 1584 | if (o_tty->termios != tty->driver->other->termios[idx]) { |
1994 | printk(KERN_DEBUG "release_dev: other->termios[%d] " | 1585 | printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " |
1995 | "not o_termios for (%s)\n", | 1586 | "not o_termios for (%s)\n", |
1996 | idx, tty->name); | 1587 | idx, tty->name); |
1997 | return; | 1588 | return; |
1998 | } | 1589 | } |
1999 | if (o_tty->termios_locked != | ||
2000 | tty->driver->other->termios_locked[idx]) { | ||
2001 | printk(KERN_DEBUG "release_dev: other->termios_locked[" | ||
2002 | "%d] not o_termios_locked for (%s)\n", | ||
2003 | idx, tty->name); | ||
2004 | return; | ||
2005 | } | ||
2006 | if (o_tty->link != tty) { | 1590 | if (o_tty->link != tty) { |
2007 | printk(KERN_DEBUG "release_dev: bad pty pointers\n"); | 1591 | printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); |
2008 | return; | 1592 | return; |
2009 | } | 1593 | } |
2010 | } | 1594 | } |
@@ -2062,7 +1646,7 @@ static void release_dev(struct file *filp) | |||
2062 | if (!do_sleep) | 1646 | if (!do_sleep) |
2063 | break; | 1647 | break; |
2064 | 1648 | ||
2065 | printk(KERN_WARNING "release_dev: %s: read/write wait queue " | 1649 | printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " |
2066 | "active!\n", tty_name(tty, buf)); | 1650 | "active!\n", tty_name(tty, buf)); |
2067 | mutex_unlock(&tty_mutex); | 1651 | mutex_unlock(&tty_mutex); |
2068 | schedule(); | 1652 | schedule(); |
@@ -2075,14 +1659,14 @@ static void release_dev(struct file *filp) | |||
2075 | */ | 1659 | */ |
2076 | if (pty_master) { | 1660 | if (pty_master) { |
2077 | if (--o_tty->count < 0) { | 1661 | if (--o_tty->count < 0) { |
2078 | printk(KERN_WARNING "release_dev: bad pty slave count " | 1662 | printk(KERN_WARNING "tty_release_dev: bad pty slave count " |
2079 | "(%d) for %s\n", | 1663 | "(%d) for %s\n", |
2080 | o_tty->count, tty_name(o_tty, buf)); | 1664 | o_tty->count, tty_name(o_tty, buf)); |
2081 | o_tty->count = 0; | 1665 | o_tty->count = 0; |
2082 | } | 1666 | } |
2083 | } | 1667 | } |
2084 | if (--tty->count < 0) { | 1668 | if (--tty->count < 0) { |
2085 | printk(KERN_WARNING "release_dev: bad tty->count (%d) for %s\n", | 1669 | printk(KERN_WARNING "tty_release_dev: bad tty->count (%d) for %s\n", |
2086 | tty->count, tty_name(tty, buf)); | 1670 | tty->count, tty_name(tty, buf)); |
2087 | tty->count = 0; | 1671 | tty->count = 0; |
2088 | } | 1672 | } |
@@ -2145,11 +1729,11 @@ static void release_dev(struct file *filp) | |||
2145 | 1729 | ||
2146 | /* Make this pty number available for reallocation */ | 1730 | /* Make this pty number available for reallocation */ |
2147 | if (devpts) | 1731 | if (devpts) |
2148 | devpts_kill_index(idx); | 1732 | devpts_kill_index(inode, idx); |
2149 | } | 1733 | } |
2150 | 1734 | ||
2151 | /** | 1735 | /** |
2152 | * tty_open - open a tty device | 1736 | * __tty_open - open a tty device |
2153 | * @inode: inode of device file | 1737 | * @inode: inode of device file |
2154 | * @filp: file pointer to tty | 1738 | * @filp: file pointer to tty |
2155 | * | 1739 | * |
@@ -2164,14 +1748,14 @@ static void release_dev(struct file *filp) | |||
2164 | * The termios state of a pty is reset on first open so that | 1748 | * The termios state of a pty is reset on first open so that |
2165 | * settings don't persist across reuse. | 1749 | * settings don't persist across reuse. |
2166 | * | 1750 | * |
2167 | * Locking: tty_mutex protects tty, get_tty_driver and init_dev work. | 1751 | * Locking: tty_mutex protects tty, get_tty_driver and tty_init_dev work. |
2168 | * tty->count should protect the rest. | 1752 | * tty->count should protect the rest. |
2169 | * ->siglock protects ->signal/->sighand | 1753 | * ->siglock protects ->signal/->sighand |
2170 | */ | 1754 | */ |
2171 | 1755 | ||
2172 | static int __tty_open(struct inode *inode, struct file *filp) | 1756 | static int __tty_open(struct inode *inode, struct file *filp) |
2173 | { | 1757 | { |
2174 | struct tty_struct *tty; | 1758 | struct tty_struct *tty = NULL; |
2175 | int noctty, retval; | 1759 | int noctty, retval; |
2176 | struct tty_driver *driver; | 1760 | struct tty_driver *driver; |
2177 | int index; | 1761 | int index; |
@@ -2193,23 +1777,25 @@ retry_open: | |||
2193 | mutex_unlock(&tty_mutex); | 1777 | mutex_unlock(&tty_mutex); |
2194 | return -ENXIO; | 1778 | return -ENXIO; |
2195 | } | 1779 | } |
2196 | driver = tty->driver; | 1780 | driver = tty_driver_kref_get(tty->driver); |
2197 | index = tty->index; | 1781 | index = tty->index; |
2198 | filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ | 1782 | filp->f_flags |= O_NONBLOCK; /* Don't let /dev/tty block */ |
2199 | /* noctty = 1; */ | 1783 | /* noctty = 1; */ |
1784 | /* FIXME: Should we take a driver reference ? */ | ||
1785 | tty_kref_put(tty); | ||
2200 | goto got_driver; | 1786 | goto got_driver; |
2201 | } | 1787 | } |
2202 | #ifdef CONFIG_VT | 1788 | #ifdef CONFIG_VT |
2203 | if (device == MKDEV(TTY_MAJOR, 0)) { | 1789 | if (device == MKDEV(TTY_MAJOR, 0)) { |
2204 | extern struct tty_driver *console_driver; | 1790 | extern struct tty_driver *console_driver; |
2205 | driver = console_driver; | 1791 | driver = tty_driver_kref_get(console_driver); |
2206 | index = fg_console; | 1792 | index = fg_console; |
2207 | noctty = 1; | 1793 | noctty = 1; |
2208 | goto got_driver; | 1794 | goto got_driver; |
2209 | } | 1795 | } |
2210 | #endif | 1796 | #endif |
2211 | if (device == MKDEV(TTYAUX_MAJOR, 1)) { | 1797 | if (device == MKDEV(TTYAUX_MAJOR, 1)) { |
2212 | driver = console_device(&index); | 1798 | driver = tty_driver_kref_get(console_device(&index)); |
2213 | if (driver) { | 1799 | if (driver) { |
2214 | /* Don't let /dev/console block */ | 1800 | /* Don't let /dev/console block */ |
2215 | filp->f_flags |= O_NONBLOCK; | 1801 | filp->f_flags |= O_NONBLOCK; |
@@ -2226,10 +1812,25 @@ retry_open: | |||
2226 | return -ENODEV; | 1812 | return -ENODEV; |
2227 | } | 1813 | } |
2228 | got_driver: | 1814 | got_driver: |
2229 | retval = init_dev(driver, index, &tty); | 1815 | if (!tty) { |
1816 | /* check whether we're reopening an existing tty */ | ||
1817 | tty = tty_driver_lookup_tty(driver, inode, index); | ||
1818 | |||
1819 | if (IS_ERR(tty)) | ||
1820 | return PTR_ERR(tty); | ||
1821 | } | ||
1822 | |||
1823 | if (tty) { | ||
1824 | retval = tty_reopen(tty); | ||
1825 | if (retval) | ||
1826 | tty = ERR_PTR(retval); | ||
1827 | } else | ||
1828 | tty = tty_init_dev(driver, index, 0); | ||
1829 | |||
2230 | mutex_unlock(&tty_mutex); | 1830 | mutex_unlock(&tty_mutex); |
2231 | if (retval) | 1831 | tty_driver_kref_put(driver); |
2232 | return retval; | 1832 | if (IS_ERR(tty)) |
1833 | return PTR_ERR(tty); | ||
2233 | 1834 | ||
2234 | filp->private_data = tty; | 1835 | filp->private_data = tty; |
2235 | file_move(filp, &tty->tty_files); | 1836 | file_move(filp, &tty->tty_files); |
@@ -2257,7 +1858,7 @@ got_driver: | |||
2257 | printk(KERN_DEBUG "error %d in opening %s...", retval, | 1858 | printk(KERN_DEBUG "error %d in opening %s...", retval, |
2258 | tty->name); | 1859 | tty->name); |
2259 | #endif | 1860 | #endif |
2260 | release_dev(filp); | 1861 | tty_release_dev(filp); |
2261 | if (retval != -ERESTARTSYS) | 1862 | if (retval != -ERESTARTSYS) |
2262 | return retval; | 1863 | return retval; |
2263 | if (signal_pending(current)) | 1864 | if (signal_pending(current)) |
@@ -2296,69 +1897,6 @@ static int tty_open(struct inode *inode, struct file *filp) | |||
2296 | 1897 | ||
2297 | 1898 | ||
2298 | 1899 | ||
2299 | #ifdef CONFIG_UNIX98_PTYS | ||
2300 | /** | ||
2301 | * ptmx_open - open a unix 98 pty master | ||
2302 | * @inode: inode of device file | ||
2303 | * @filp: file pointer to tty | ||
2304 | * | ||
2305 | * Allocate a unix98 pty master device from the ptmx driver. | ||
2306 | * | ||
2307 | * Locking: tty_mutex protects theinit_dev work. tty->count should | ||
2308 | * protect the rest. | ||
2309 | * allocated_ptys_lock handles the list of free pty numbers | ||
2310 | */ | ||
2311 | |||
2312 | static int __ptmx_open(struct inode *inode, struct file *filp) | ||
2313 | { | ||
2314 | struct tty_struct *tty; | ||
2315 | int retval; | ||
2316 | int index; | ||
2317 | |||
2318 | nonseekable_open(inode, filp); | ||
2319 | |||
2320 | /* find a device that is not in use. */ | ||
2321 | index = devpts_new_index(); | ||
2322 | if (index < 0) | ||
2323 | return index; | ||
2324 | |||
2325 | mutex_lock(&tty_mutex); | ||
2326 | retval = init_dev(ptm_driver, index, &tty); | ||
2327 | mutex_unlock(&tty_mutex); | ||
2328 | |||
2329 | if (retval) | ||
2330 | goto out; | ||
2331 | |||
2332 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ | ||
2333 | filp->private_data = tty; | ||
2334 | file_move(filp, &tty->tty_files); | ||
2335 | |||
2336 | retval = devpts_pty_new(tty->link); | ||
2337 | if (retval) | ||
2338 | goto out1; | ||
2339 | |||
2340 | check_tty_count(tty, "ptmx_open"); | ||
2341 | retval = ptm_driver->ops->open(tty, filp); | ||
2342 | if (!retval) | ||
2343 | return 0; | ||
2344 | out1: | ||
2345 | release_dev(filp); | ||
2346 | return retval; | ||
2347 | out: | ||
2348 | devpts_kill_index(index); | ||
2349 | return retval; | ||
2350 | } | ||
2351 | |||
2352 | static int ptmx_open(struct inode *inode, struct file *filp) | ||
2353 | { | ||
2354 | int ret; | ||
2355 | |||
2356 | lock_kernel(); | ||
2357 | ret = __ptmx_open(inode, filp); | ||
2358 | unlock_kernel(); | ||
2359 | return ret; | ||
2360 | } | ||
2361 | #endif | ||
2362 | 1900 | ||
2363 | /** | 1901 | /** |
2364 | * tty_release - vfs callback for close | 1902 | * tty_release - vfs callback for close |
@@ -2369,13 +1907,13 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
2369 | * this tty. There may however be several such references. | 1907 | * this tty. There may however be several such references. |
2370 | * | 1908 | * |
2371 | * Locking: | 1909 | * Locking: |
2372 | * Takes bkl. See release_dev | 1910 | * Takes bkl. See tty_release_dev |
2373 | */ | 1911 | */ |
2374 | 1912 | ||
2375 | static int tty_release(struct inode *inode, struct file *filp) | 1913 | static int tty_release(struct inode *inode, struct file *filp) |
2376 | { | 1914 | { |
2377 | lock_kernel(); | 1915 | lock_kernel(); |
2378 | release_dev(filp); | 1916 | tty_release_dev(filp); |
2379 | unlock_kernel(); | 1917 | unlock_kernel(); |
2380 | return 0; | 1918 | return 0; |
2381 | } | 1919 | } |
@@ -2524,7 +2062,7 @@ int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, | |||
2524 | 2062 | ||
2525 | /* For a PTY we need to lock the tty side */ | 2063 | /* For a PTY we need to lock the tty side */ |
2526 | mutex_lock(&real_tty->termios_mutex); | 2064 | mutex_lock(&real_tty->termios_mutex); |
2527 | if (!memcmp(ws, &tty->winsize, sizeof(*ws))) | 2065 | if (!memcmp(ws, &real_tty->winsize, sizeof(*ws))) |
2528 | goto done; | 2066 | goto done; |
2529 | /* Get the PID values and reference them so we can | 2067 | /* Get the PID values and reference them so we can |
2530 | avoid holding the tty ctrl lock while sending signals */ | 2068 | avoid holding the tty ctrl lock while sending signals */ |
@@ -2996,7 +2534,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2996 | case TIOCSTI: | 2534 | case TIOCSTI: |
2997 | return tiocsti(tty, p); | 2535 | return tiocsti(tty, p); |
2998 | case TIOCGWINSZ: | 2536 | case TIOCGWINSZ: |
2999 | return tiocgwinsz(tty, p); | 2537 | return tiocgwinsz(real_tty, p); |
3000 | case TIOCSWINSZ: | 2538 | case TIOCSWINSZ: |
3001 | return tiocswinsz(tty, real_tty, p); | 2539 | return tiocswinsz(tty, real_tty, p); |
3002 | case TIOCCONS: | 2540 | case TIOCCONS: |
@@ -3026,10 +2564,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
3026 | return put_user(tty->ldisc.ops->num, (int __user *)p); | 2564 | return put_user(tty->ldisc.ops->num, (int __user *)p); |
3027 | case TIOCSETD: | 2565 | case TIOCSETD: |
3028 | return tiocsetd(tty, p); | 2566 | return tiocsetd(tty, p); |
3029 | #ifdef CONFIG_VT | ||
3030 | case TIOCLINUX: | ||
3031 | return tioclinux(tty, arg); | ||
3032 | #endif | ||
3033 | /* | 2567 | /* |
3034 | * Break handling | 2568 | * Break handling |
3035 | */ | 2569 | */ |
@@ -3220,113 +2754,6 @@ void do_SAK(struct tty_struct *tty) | |||
3220 | EXPORT_SYMBOL(do_SAK); | 2754 | EXPORT_SYMBOL(do_SAK); |
3221 | 2755 | ||
3222 | /** | 2756 | /** |
3223 | * flush_to_ldisc | ||
3224 | * @work: tty structure passed from work queue. | ||
3225 | * | ||
3226 | * This routine is called out of the software interrupt to flush data | ||
3227 | * from the buffer chain to the line discipline. | ||
3228 | * | ||
3229 | * Locking: holds tty->buf.lock to guard buffer list. Drops the lock | ||
3230 | * while invoking the line discipline receive_buf method. The | ||
3231 | * receive_buf method is single threaded for each tty instance. | ||
3232 | */ | ||
3233 | |||
3234 | static void flush_to_ldisc(struct work_struct *work) | ||
3235 | { | ||
3236 | struct tty_struct *tty = | ||
3237 | container_of(work, struct tty_struct, buf.work.work); | ||
3238 | unsigned long flags; | ||
3239 | struct tty_ldisc *disc; | ||
3240 | struct tty_buffer *tbuf, *head; | ||
3241 | char *char_buf; | ||
3242 | unsigned char *flag_buf; | ||
3243 | |||
3244 | disc = tty_ldisc_ref(tty); | ||
3245 | if (disc == NULL) /* !TTY_LDISC */ | ||
3246 | return; | ||
3247 | |||
3248 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
3249 | /* So we know a flush is running */ | ||
3250 | set_bit(TTY_FLUSHING, &tty->flags); | ||
3251 | head = tty->buf.head; | ||
3252 | if (head != NULL) { | ||
3253 | tty->buf.head = NULL; | ||
3254 | for (;;) { | ||
3255 | int count = head->commit - head->read; | ||
3256 | if (!count) { | ||
3257 | if (head->next == NULL) | ||
3258 | break; | ||
3259 | tbuf = head; | ||
3260 | head = head->next; | ||
3261 | tty_buffer_free(tty, tbuf); | ||
3262 | continue; | ||
3263 | } | ||
3264 | /* Ldisc or user is trying to flush the buffers | ||
3265 | we are feeding to the ldisc, stop feeding the | ||
3266 | line discipline as we want to empty the queue */ | ||
3267 | if (test_bit(TTY_FLUSHPENDING, &tty->flags)) | ||
3268 | break; | ||
3269 | if (!tty->receive_room) { | ||
3270 | schedule_delayed_work(&tty->buf.work, 1); | ||
3271 | break; | ||
3272 | } | ||
3273 | if (count > tty->receive_room) | ||
3274 | count = tty->receive_room; | ||
3275 | char_buf = head->char_buf_ptr + head->read; | ||
3276 | flag_buf = head->flag_buf_ptr + head->read; | ||
3277 | head->read += count; | ||
3278 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
3279 | disc->ops->receive_buf(tty, char_buf, | ||
3280 | flag_buf, count); | ||
3281 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
3282 | } | ||
3283 | /* Restore the queue head */ | ||
3284 | tty->buf.head = head; | ||
3285 | } | ||
3286 | /* We may have a deferred request to flush the input buffer, | ||
3287 | if so pull the chain under the lock and empty the queue */ | ||
3288 | if (test_bit(TTY_FLUSHPENDING, &tty->flags)) { | ||
3289 | __tty_buffer_flush(tty); | ||
3290 | clear_bit(TTY_FLUSHPENDING, &tty->flags); | ||
3291 | wake_up(&tty->read_wait); | ||
3292 | } | ||
3293 | clear_bit(TTY_FLUSHING, &tty->flags); | ||
3294 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
3295 | |||
3296 | tty_ldisc_deref(disc); | ||
3297 | } | ||
3298 | |||
3299 | /** | ||
3300 | * tty_flip_buffer_push - terminal | ||
3301 | * @tty: tty to push | ||
3302 | * | ||
3303 | * Queue a push of the terminal flip buffers to the line discipline. This | ||
3304 | * function must not be called from IRQ context if tty->low_latency is set. | ||
3305 | * | ||
3306 | * In the event of the queue being busy for flipping the work will be | ||
3307 | * held off and retried later. | ||
3308 | * | ||
3309 | * Locking: tty buffer lock. Driver locks in low latency mode. | ||
3310 | */ | ||
3311 | |||
3312 | void tty_flip_buffer_push(struct tty_struct *tty) | ||
3313 | { | ||
3314 | unsigned long flags; | ||
3315 | spin_lock_irqsave(&tty->buf.lock, flags); | ||
3316 | if (tty->buf.tail != NULL) | ||
3317 | tty->buf.tail->commit = tty->buf.tail->used; | ||
3318 | spin_unlock_irqrestore(&tty->buf.lock, flags); | ||
3319 | |||
3320 | if (tty->low_latency) | ||
3321 | flush_to_ldisc(&tty->buf.work.work); | ||
3322 | else | ||
3323 | schedule_delayed_work(&tty->buf.work, 1); | ||
3324 | } | ||
3325 | |||
3326 | EXPORT_SYMBOL(tty_flip_buffer_push); | ||
3327 | |||
3328 | |||
3329 | /** | ||
3330 | * initialize_tty_struct | 2757 | * initialize_tty_struct |
3331 | * @tty: tty to initialize | 2758 | * @tty: tty to initialize |
3332 | * | 2759 | * |
@@ -3336,9 +2763,11 @@ EXPORT_SYMBOL(tty_flip_buffer_push); | |||
3336 | * Locking: none - tty in question must not be exposed at this point | 2763 | * Locking: none - tty in question must not be exposed at this point |
3337 | */ | 2764 | */ |
3338 | 2765 | ||
3339 | static void initialize_tty_struct(struct tty_struct *tty) | 2766 | void initialize_tty_struct(struct tty_struct *tty, |
2767 | struct tty_driver *driver, int idx) | ||
3340 | { | 2768 | { |
3341 | memset(tty, 0, sizeof(struct tty_struct)); | 2769 | memset(tty, 0, sizeof(struct tty_struct)); |
2770 | kref_init(&tty->kref); | ||
3342 | tty->magic = TTY_MAGIC; | 2771 | tty->magic = TTY_MAGIC; |
3343 | tty_ldisc_init(tty); | 2772 | tty_ldisc_init(tty); |
3344 | tty->session = NULL; | 2773 | tty->session = NULL; |
@@ -3346,7 +2775,6 @@ static void initialize_tty_struct(struct tty_struct *tty) | |||
3346 | tty->overrun_time = jiffies; | 2775 | tty->overrun_time = jiffies; |
3347 | tty->buf.head = tty->buf.tail = NULL; | 2776 | tty->buf.head = tty->buf.tail = NULL; |
3348 | tty_buffer_init(tty); | 2777 | tty_buffer_init(tty); |
3349 | INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc); | ||
3350 | mutex_init(&tty->termios_mutex); | 2778 | mutex_init(&tty->termios_mutex); |
3351 | init_waitqueue_head(&tty->write_wait); | 2779 | init_waitqueue_head(&tty->write_wait); |
3352 | init_waitqueue_head(&tty->read_wait); | 2780 | init_waitqueue_head(&tty->read_wait); |
@@ -3357,6 +2785,11 @@ static void initialize_tty_struct(struct tty_struct *tty) | |||
3357 | spin_lock_init(&tty->ctrl_lock); | 2785 | spin_lock_init(&tty->ctrl_lock); |
3358 | INIT_LIST_HEAD(&tty->tty_files); | 2786 | INIT_LIST_HEAD(&tty->tty_files); |
3359 | INIT_WORK(&tty->SAK_work, do_SAK_work); | 2787 | INIT_WORK(&tty->SAK_work, do_SAK_work); |
2788 | |||
2789 | tty->driver = driver; | ||
2790 | tty->ops = driver->ops; | ||
2791 | tty->index = idx; | ||
2792 | tty_line_name(driver, idx, tty->name); | ||
3360 | } | 2793 | } |
3361 | 2794 | ||
3362 | /** | 2795 | /** |
@@ -3377,10 +2810,9 @@ int tty_put_char(struct tty_struct *tty, unsigned char ch) | |||
3377 | return tty->ops->put_char(tty, ch); | 2810 | return tty->ops->put_char(tty, ch); |
3378 | return tty->ops->write(tty, &ch, 1); | 2811 | return tty->ops->write(tty, &ch, 1); |
3379 | } | 2812 | } |
3380 | |||
3381 | EXPORT_SYMBOL_GPL(tty_put_char); | 2813 | EXPORT_SYMBOL_GPL(tty_put_char); |
3382 | 2814 | ||
3383 | static struct class *tty_class; | 2815 | struct class *tty_class; |
3384 | 2816 | ||
3385 | /** | 2817 | /** |
3386 | * tty_register_device - register a tty device | 2818 | * tty_register_device - register a tty device |
@@ -3420,6 +2852,7 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index, | |||
3420 | 2852 | ||
3421 | return device_create_drvdata(tty_class, device, dev, NULL, name); | 2853 | return device_create_drvdata(tty_class, device, dev, NULL, name); |
3422 | } | 2854 | } |
2855 | EXPORT_SYMBOL(tty_register_device); | ||
3423 | 2856 | ||
3424 | /** | 2857 | /** |
3425 | * tty_unregister_device - unregister a tty device | 2858 | * tty_unregister_device - unregister a tty device |
@@ -3437,8 +2870,6 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index) | |||
3437 | device_destroy(tty_class, | 2870 | device_destroy(tty_class, |
3438 | MKDEV(driver->major, driver->minor_start) + index); | 2871 | MKDEV(driver->major, driver->minor_start) + index); |
3439 | } | 2872 | } |
3440 | |||
3441 | EXPORT_SYMBOL(tty_register_device); | ||
3442 | EXPORT_SYMBOL(tty_unregister_device); | 2873 | EXPORT_SYMBOL(tty_unregister_device); |
3443 | 2874 | ||
3444 | struct tty_driver *alloc_tty_driver(int lines) | 2875 | struct tty_driver *alloc_tty_driver(int lines) |
@@ -3447,27 +2878,65 @@ struct tty_driver *alloc_tty_driver(int lines) | |||
3447 | 2878 | ||
3448 | driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL); | 2879 | driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL); |
3449 | if (driver) { | 2880 | if (driver) { |
2881 | kref_init(&driver->kref); | ||
3450 | driver->magic = TTY_DRIVER_MAGIC; | 2882 | driver->magic = TTY_DRIVER_MAGIC; |
3451 | driver->num = lines; | 2883 | driver->num = lines; |
3452 | /* later we'll move allocation of tables here */ | 2884 | /* later we'll move allocation of tables here */ |
3453 | } | 2885 | } |
3454 | return driver; | 2886 | return driver; |
3455 | } | 2887 | } |
2888 | EXPORT_SYMBOL(alloc_tty_driver); | ||
3456 | 2889 | ||
3457 | void put_tty_driver(struct tty_driver *driver) | 2890 | static void destruct_tty_driver(struct kref *kref) |
3458 | { | 2891 | { |
2892 | struct tty_driver *driver = container_of(kref, struct tty_driver, kref); | ||
2893 | int i; | ||
2894 | struct ktermios *tp; | ||
2895 | void *p; | ||
2896 | |||
2897 | if (driver->flags & TTY_DRIVER_INSTALLED) { | ||
2898 | /* | ||
2899 | * Free the termios and termios_locked structures because | ||
2900 | * we don't want to get memory leaks when modular tty | ||
2901 | * drivers are removed from the kernel. | ||
2902 | */ | ||
2903 | for (i = 0; i < driver->num; i++) { | ||
2904 | tp = driver->termios[i]; | ||
2905 | if (tp) { | ||
2906 | driver->termios[i] = NULL; | ||
2907 | kfree(tp); | ||
2908 | } | ||
2909 | if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) | ||
2910 | tty_unregister_device(driver, i); | ||
2911 | } | ||
2912 | p = driver->ttys; | ||
2913 | proc_tty_unregister_driver(driver); | ||
2914 | driver->ttys = NULL; | ||
2915 | driver->termios = NULL; | ||
2916 | kfree(p); | ||
2917 | cdev_del(&driver->cdev); | ||
2918 | } | ||
3459 | kfree(driver); | 2919 | kfree(driver); |
3460 | } | 2920 | } |
3461 | 2921 | ||
2922 | void tty_driver_kref_put(struct tty_driver *driver) | ||
2923 | { | ||
2924 | kref_put(&driver->kref, destruct_tty_driver); | ||
2925 | } | ||
2926 | EXPORT_SYMBOL(tty_driver_kref_put); | ||
2927 | |||
3462 | void tty_set_operations(struct tty_driver *driver, | 2928 | void tty_set_operations(struct tty_driver *driver, |
3463 | const struct tty_operations *op) | 2929 | const struct tty_operations *op) |
3464 | { | 2930 | { |
3465 | driver->ops = op; | 2931 | driver->ops = op; |
3466 | }; | 2932 | }; |
2933 | EXPORT_SYMBOL(tty_set_operations); | ||
3467 | 2934 | ||
3468 | EXPORT_SYMBOL(alloc_tty_driver); | 2935 | void put_tty_driver(struct tty_driver *d) |
2936 | { | ||
2937 | tty_driver_kref_put(d); | ||
2938 | } | ||
3469 | EXPORT_SYMBOL(put_tty_driver); | 2939 | EXPORT_SYMBOL(put_tty_driver); |
3470 | EXPORT_SYMBOL(tty_set_operations); | ||
3471 | 2940 | ||
3472 | /* | 2941 | /* |
3473 | * Called by a tty driver to register itself. | 2942 | * Called by a tty driver to register itself. |
@@ -3479,11 +2948,8 @@ int tty_register_driver(struct tty_driver *driver) | |||
3479 | dev_t dev; | 2948 | dev_t dev; |
3480 | void **p = NULL; | 2949 | void **p = NULL; |
3481 | 2950 | ||
3482 | if (driver->flags & TTY_DRIVER_INSTALLED) | ||
3483 | return 0; | ||
3484 | |||
3485 | if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) { | 2951 | if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) { |
3486 | p = kzalloc(driver->num * 3 * sizeof(void *), GFP_KERNEL); | 2952 | p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL); |
3487 | if (!p) | 2953 | if (!p) |
3488 | return -ENOMEM; | 2954 | return -ENOMEM; |
3489 | } | 2955 | } |
@@ -3507,12 +2973,9 @@ int tty_register_driver(struct tty_driver *driver) | |||
3507 | if (p) { | 2973 | if (p) { |
3508 | driver->ttys = (struct tty_struct **)p; | 2974 | driver->ttys = (struct tty_struct **)p; |
3509 | driver->termios = (struct ktermios **)(p + driver->num); | 2975 | driver->termios = (struct ktermios **)(p + driver->num); |
3510 | driver->termios_locked = (struct ktermios **) | ||
3511 | (p + driver->num * 2); | ||
3512 | } else { | 2976 | } else { |
3513 | driver->ttys = NULL; | 2977 | driver->ttys = NULL; |
3514 | driver->termios = NULL; | 2978 | driver->termios = NULL; |
3515 | driver->termios_locked = NULL; | ||
3516 | } | 2979 | } |
3517 | 2980 | ||
3518 | cdev_init(&driver->cdev, &tty_fops); | 2981 | cdev_init(&driver->cdev, &tty_fops); |
@@ -3521,7 +2984,7 @@ int tty_register_driver(struct tty_driver *driver) | |||
3521 | if (error) { | 2984 | if (error) { |
3522 | unregister_chrdev_region(dev, driver->num); | 2985 | unregister_chrdev_region(dev, driver->num); |
3523 | driver->ttys = NULL; | 2986 | driver->ttys = NULL; |
3524 | driver->termios = driver->termios_locked = NULL; | 2987 | driver->termios = NULL; |
3525 | kfree(p); | 2988 | kfree(p); |
3526 | return error; | 2989 | return error; |
3527 | } | 2990 | } |
@@ -3535,6 +2998,7 @@ int tty_register_driver(struct tty_driver *driver) | |||
3535 | tty_register_device(driver, i, NULL); | 2998 | tty_register_device(driver, i, NULL); |
3536 | } | 2999 | } |
3537 | proc_tty_register_driver(driver); | 3000 | proc_tty_register_driver(driver); |
3001 | driver->flags |= TTY_DRIVER_INSTALLED; | ||
3538 | return 0; | 3002 | return 0; |
3539 | } | 3003 | } |
3540 | 3004 | ||
@@ -3545,46 +3009,19 @@ EXPORT_SYMBOL(tty_register_driver); | |||
3545 | */ | 3009 | */ |
3546 | int tty_unregister_driver(struct tty_driver *driver) | 3010 | int tty_unregister_driver(struct tty_driver *driver) |
3547 | { | 3011 | { |
3548 | int i; | 3012 | #if 0 |
3549 | struct ktermios *tp; | 3013 | /* FIXME */ |
3550 | void *p; | ||
3551 | |||
3552 | if (driver->refcount) | 3014 | if (driver->refcount) |
3553 | return -EBUSY; | 3015 | return -EBUSY; |
3554 | 3016 | #endif | |
3555 | unregister_chrdev_region(MKDEV(driver->major, driver->minor_start), | 3017 | unregister_chrdev_region(MKDEV(driver->major, driver->minor_start), |
3556 | driver->num); | 3018 | driver->num); |
3557 | mutex_lock(&tty_mutex); | 3019 | mutex_lock(&tty_mutex); |
3558 | list_del(&driver->tty_drivers); | 3020 | list_del(&driver->tty_drivers); |
3559 | mutex_unlock(&tty_mutex); | 3021 | mutex_unlock(&tty_mutex); |
3560 | |||
3561 | /* | ||
3562 | * Free the termios and termios_locked structures because | ||
3563 | * we don't want to get memory leaks when modular tty | ||
3564 | * drivers are removed from the kernel. | ||
3565 | */ | ||
3566 | for (i = 0; i < driver->num; i++) { | ||
3567 | tp = driver->termios[i]; | ||
3568 | if (tp) { | ||
3569 | driver->termios[i] = NULL; | ||
3570 | kfree(tp); | ||
3571 | } | ||
3572 | tp = driver->termios_locked[i]; | ||
3573 | if (tp) { | ||
3574 | driver->termios_locked[i] = NULL; | ||
3575 | kfree(tp); | ||
3576 | } | ||
3577 | if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) | ||
3578 | tty_unregister_device(driver, i); | ||
3579 | } | ||
3580 | p = driver->ttys; | ||
3581 | proc_tty_unregister_driver(driver); | ||
3582 | driver->ttys = NULL; | ||
3583 | driver->termios = driver->termios_locked = NULL; | ||
3584 | kfree(p); | ||
3585 | cdev_del(&driver->cdev); | ||
3586 | return 0; | 3022 | return 0; |
3587 | } | 3023 | } |
3024 | |||
3588 | EXPORT_SYMBOL(tty_unregister_driver); | 3025 | EXPORT_SYMBOL(tty_unregister_driver); |
3589 | 3026 | ||
3590 | dev_t tty_devnum(struct tty_struct *tty) | 3027 | dev_t tty_devnum(struct tty_struct *tty) |
@@ -3595,9 +3032,12 @@ EXPORT_SYMBOL(tty_devnum); | |||
3595 | 3032 | ||
3596 | void proc_clear_tty(struct task_struct *p) | 3033 | void proc_clear_tty(struct task_struct *p) |
3597 | { | 3034 | { |
3035 | struct tty_struct *tty; | ||
3598 | spin_lock_irq(&p->sighand->siglock); | 3036 | spin_lock_irq(&p->sighand->siglock); |
3037 | tty = p->signal->tty; | ||
3599 | p->signal->tty = NULL; | 3038 | p->signal->tty = NULL; |
3600 | spin_unlock_irq(&p->sighand->siglock); | 3039 | spin_unlock_irq(&p->sighand->siglock); |
3040 | tty_kref_put(tty); | ||
3601 | } | 3041 | } |
3602 | 3042 | ||
3603 | /* Called under the sighand lock */ | 3043 | /* Called under the sighand lock */ |
@@ -3613,9 +3053,13 @@ static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) | |||
3613 | tty->pgrp = get_pid(task_pgrp(tsk)); | 3053 | tty->pgrp = get_pid(task_pgrp(tsk)); |
3614 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 3054 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
3615 | tty->session = get_pid(task_session(tsk)); | 3055 | tty->session = get_pid(task_session(tsk)); |
3056 | if (tsk->signal->tty) { | ||
3057 | printk(KERN_DEBUG "tty not NULL!!\n"); | ||
3058 | tty_kref_put(tsk->signal->tty); | ||
3059 | } | ||
3616 | } | 3060 | } |
3617 | put_pid(tsk->signal->tty_old_pgrp); | 3061 | put_pid(tsk->signal->tty_old_pgrp); |
3618 | tsk->signal->tty = tty; | 3062 | tsk->signal->tty = tty_kref_get(tty); |
3619 | tsk->signal->tty_old_pgrp = NULL; | 3063 | tsk->signal->tty_old_pgrp = NULL; |
3620 | } | 3064 | } |
3621 | 3065 | ||
@@ -3629,18 +3073,20 @@ static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) | |||
3629 | struct tty_struct *get_current_tty(void) | 3073 | struct tty_struct *get_current_tty(void) |
3630 | { | 3074 | { |
3631 | struct tty_struct *tty; | 3075 | struct tty_struct *tty; |
3632 | WARN_ON_ONCE(!mutex_is_locked(&tty_mutex)); | 3076 | unsigned long flags; |
3633 | tty = current->signal->tty; | 3077 | |
3634 | /* | 3078 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
3635 | * session->tty can be changed/cleared from under us, make sure we | 3079 | tty = tty_kref_get(current->signal->tty); |
3636 | * issue the load. The obtained pointer, when not NULL, is valid as | 3080 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
3637 | * long as we hold tty_mutex. | ||
3638 | */ | ||
3639 | barrier(); | ||
3640 | return tty; | 3081 | return tty; |
3641 | } | 3082 | } |
3642 | EXPORT_SYMBOL_GPL(get_current_tty); | 3083 | EXPORT_SYMBOL_GPL(get_current_tty); |
3643 | 3084 | ||
3085 | void tty_default_fops(struct file_operations *fops) | ||
3086 | { | ||
3087 | *fops = tty_fops; | ||
3088 | } | ||
3089 | |||
3644 | /* | 3090 | /* |
3645 | * Initialize the console device. This is called *early*, so | 3091 | * Initialize the console device. This is called *early*, so |
3646 | * we can't necessarily depend on lots of kernel help here. | 3092 | * we can't necessarily depend on lots of kernel help here. |
@@ -3678,12 +3124,6 @@ postcore_initcall(tty_class_init); | |||
3678 | /* 3/2004 jmc: why do these devices exist? */ | 3124 | /* 3/2004 jmc: why do these devices exist? */ |
3679 | 3125 | ||
3680 | static struct cdev tty_cdev, console_cdev; | 3126 | static struct cdev tty_cdev, console_cdev; |
3681 | #ifdef CONFIG_UNIX98_PTYS | ||
3682 | static struct cdev ptmx_cdev; | ||
3683 | #endif | ||
3684 | #ifdef CONFIG_VT | ||
3685 | static struct cdev vc0_cdev; | ||
3686 | #endif | ||
3687 | 3127 | ||
3688 | /* | 3128 | /* |
3689 | * Ok, now we can initialize the rest of the tty devices and can count | 3129 | * Ok, now we can initialize the rest of the tty devices and can count |
@@ -3695,32 +3135,18 @@ static int __init tty_init(void) | |||
3695 | if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || | 3135 | if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || |
3696 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) | 3136 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) |
3697 | panic("Couldn't register /dev/tty driver\n"); | 3137 | panic("Couldn't register /dev/tty driver\n"); |
3698 | device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, | 3138 | device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, |
3699 | "tty"); | 3139 | "tty"); |
3700 | 3140 | ||
3701 | cdev_init(&console_cdev, &console_fops); | 3141 | cdev_init(&console_cdev, &console_fops); |
3702 | if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || | 3142 | if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || |
3703 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) | 3143 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) |
3704 | panic("Couldn't register /dev/console driver\n"); | 3144 | panic("Couldn't register /dev/console driver\n"); |
3705 | device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, | 3145 | device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, |
3706 | "console"); | 3146 | "console"); |
3707 | 3147 | ||
3708 | #ifdef CONFIG_UNIX98_PTYS | ||
3709 | cdev_init(&ptmx_cdev, &ptmx_fops); | ||
3710 | if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || | ||
3711 | register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) | ||
3712 | panic("Couldn't register /dev/ptmx driver\n"); | ||
3713 | device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); | ||
3714 | #endif | ||
3715 | |||
3716 | #ifdef CONFIG_VT | 3148 | #ifdef CONFIG_VT |
3717 | cdev_init(&vc0_cdev, &console_fops); | 3149 | vty_init(&console_fops); |
3718 | if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) || | ||
3719 | register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) | ||
3720 | panic("Couldn't register /dev/tty0 driver\n"); | ||
3721 | device_create_drvdata(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0"); | ||
3722 | |||
3723 | vty_init(); | ||
3724 | #endif | 3150 | #endif |
3725 | return 0; | 3151 | return 0; |
3726 | } | 3152 | } |
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index bf34e4597421..a408c8e487ec 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -40,6 +40,15 @@ | |||
40 | #define TERMIOS_OLD 8 | 40 | #define TERMIOS_OLD 8 |
41 | 41 | ||
42 | 42 | ||
43 | /** | ||
44 | * tty_chars_in_buffer - characters pending | ||
45 | * @tty: terminal | ||
46 | * | ||
47 | * Return the number of bytes of data in the device private | ||
48 | * output queue. If no private method is supplied there is assumed | ||
49 | * to be no queue on the device. | ||
50 | */ | ||
51 | |||
43 | int tty_chars_in_buffer(struct tty_struct *tty) | 52 | int tty_chars_in_buffer(struct tty_struct *tty) |
44 | { | 53 | { |
45 | if (tty->ops->chars_in_buffer) | 54 | if (tty->ops->chars_in_buffer) |
@@ -47,26 +56,49 @@ int tty_chars_in_buffer(struct tty_struct *tty) | |||
47 | else | 56 | else |
48 | return 0; | 57 | return 0; |
49 | } | 58 | } |
50 | |||
51 | EXPORT_SYMBOL(tty_chars_in_buffer); | 59 | EXPORT_SYMBOL(tty_chars_in_buffer); |
52 | 60 | ||
61 | /** | ||
62 | * tty_write_room - write queue space | ||
63 | * @tty: terminal | ||
64 | * | ||
65 | * Return the number of bytes that can be queued to this device | ||
66 | * at the present time. The result should be treated as a guarantee | ||
67 | * and the driver cannot offer a value it later shrinks by more than | ||
68 | * the number of bytes written. If no method is provided 2K is always | ||
69 | * returned and data may be lost as there will be no flow control. | ||
70 | */ | ||
71 | |||
53 | int tty_write_room(struct tty_struct *tty) | 72 | int tty_write_room(struct tty_struct *tty) |
54 | { | 73 | { |
55 | if (tty->ops->write_room) | 74 | if (tty->ops->write_room) |
56 | return tty->ops->write_room(tty); | 75 | return tty->ops->write_room(tty); |
57 | return 2048; | 76 | return 2048; |
58 | } | 77 | } |
59 | |||
60 | EXPORT_SYMBOL(tty_write_room); | 78 | EXPORT_SYMBOL(tty_write_room); |
61 | 79 | ||
80 | /** | ||
81 | * tty_driver_flush_buffer - discard internal buffer | ||
82 | * @tty: terminal | ||
83 | * | ||
84 | * Discard the internal output buffer for this device. If no method | ||
85 | * is provided then either the buffer cannot be hardware flushed or | ||
86 | * there is no buffer driver side. | ||
87 | */ | ||
62 | void tty_driver_flush_buffer(struct tty_struct *tty) | 88 | void tty_driver_flush_buffer(struct tty_struct *tty) |
63 | { | 89 | { |
64 | if (tty->ops->flush_buffer) | 90 | if (tty->ops->flush_buffer) |
65 | tty->ops->flush_buffer(tty); | 91 | tty->ops->flush_buffer(tty); |
66 | } | 92 | } |
67 | |||
68 | EXPORT_SYMBOL(tty_driver_flush_buffer); | 93 | EXPORT_SYMBOL(tty_driver_flush_buffer); |
69 | 94 | ||
95 | /** | ||
96 | * tty_throttle - flow control | ||
97 | * @tty: terminal | ||
98 | * | ||
99 | * Indicate that a tty should stop transmitting data down the stack. | ||
100 | */ | ||
101 | |||
70 | void tty_throttle(struct tty_struct *tty) | 102 | void tty_throttle(struct tty_struct *tty) |
71 | { | 103 | { |
72 | /* check TTY_THROTTLED first so it indicates our state */ | 104 | /* check TTY_THROTTLED first so it indicates our state */ |
@@ -76,6 +108,13 @@ void tty_throttle(struct tty_struct *tty) | |||
76 | } | 108 | } |
77 | EXPORT_SYMBOL(tty_throttle); | 109 | EXPORT_SYMBOL(tty_throttle); |
78 | 110 | ||
111 | /** | ||
112 | * tty_unthrottle - flow control | ||
113 | * @tty: terminal | ||
114 | * | ||
115 | * Indicate that a tty may continue transmitting data down the stack. | ||
116 | */ | ||
117 | |||
79 | void tty_unthrottle(struct tty_struct *tty) | 118 | void tty_unthrottle(struct tty_struct *tty) |
80 | { | 119 | { |
81 | if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) && | 120 | if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) && |
@@ -112,6 +151,11 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout) | |||
112 | } | 151 | } |
113 | EXPORT_SYMBOL(tty_wait_until_sent); | 152 | EXPORT_SYMBOL(tty_wait_until_sent); |
114 | 153 | ||
154 | |||
155 | /* | ||
156 | * Termios Helper Methods | ||
157 | */ | ||
158 | |||
115 | static void unset_locked_termios(struct ktermios *termios, | 159 | static void unset_locked_termios(struct ktermios *termios, |
116 | struct ktermios *old, | 160 | struct ktermios *old, |
117 | struct ktermios *locked) | 161 | struct ktermios *locked) |
@@ -346,6 +390,16 @@ void tty_termios_encode_baud_rate(struct ktermios *termios, | |||
346 | } | 390 | } |
347 | EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate); | 391 | EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate); |
348 | 392 | ||
393 | /** | ||
394 | * tty_encode_baud_rate - set baud rate of the tty | ||
395 | * @ibaud: input baud rate | ||
396 | * @obad: output baud rate | ||
397 | * | ||
398 | * Update the current termios data for the tty with the new speed | ||
399 | * settings. The caller must hold the termios_mutex for the tty in | ||
400 | * question. | ||
401 | */ | ||
402 | |||
349 | void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud) | 403 | void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud) |
350 | { | 404 | { |
351 | tty_termios_encode_baud_rate(tty->termios, ibaud, obaud); | 405 | tty_termios_encode_baud_rate(tty->termios, ibaud, obaud); |
@@ -430,12 +484,11 @@ EXPORT_SYMBOL(tty_termios_hw_change); | |||
430 | * is a bit of layering violation here with n_tty in terms of the | 484 | * is a bit of layering violation here with n_tty in terms of the |
431 | * internal knowledge of this function. | 485 | * internal knowledge of this function. |
432 | * | 486 | * |
433 | * Locking: termios_sem | 487 | * Locking: termios_mutex |
434 | */ | 488 | */ |
435 | 489 | ||
436 | static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) | 490 | static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) |
437 | { | 491 | { |
438 | int canon_change; | ||
439 | struct ktermios old_termios; | 492 | struct ktermios old_termios; |
440 | struct tty_ldisc *ld; | 493 | struct tty_ldisc *ld; |
441 | unsigned long flags; | 494 | unsigned long flags; |
@@ -451,18 +504,6 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) | |||
451 | old_termios = *tty->termios; | 504 | old_termios = *tty->termios; |
452 | *tty->termios = *new_termios; | 505 | *tty->termios = *new_termios; |
453 | unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); | 506 | unset_locked_termios(tty->termios, &old_termios, tty->termios_locked); |
454 | canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON; | ||
455 | if (canon_change) { | ||
456 | memset(&tty->read_flags, 0, sizeof tty->read_flags); | ||
457 | tty->canon_head = tty->read_tail; | ||
458 | tty->canon_data = 0; | ||
459 | tty->erasing = 0; | ||
460 | } | ||
461 | |||
462 | /* This bit should be in the ldisc code */ | ||
463 | if (canon_change && !L_ICANON(tty) && tty->read_cnt) | ||
464 | /* Get characters left over from canonical mode. */ | ||
465 | wake_up_interruptible(&tty->read_wait); | ||
466 | 507 | ||
467 | /* See if packet mode change of state. */ | 508 | /* See if packet mode change of state. */ |
468 | if (tty->link && tty->link->packet) { | 509 | if (tty->link && tty->link->packet) { |
@@ -508,7 +549,7 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios) | |||
508 | * functions before using change_termios to do the actual changes. | 549 | * functions before using change_termios to do the actual changes. |
509 | * | 550 | * |
510 | * Locking: | 551 | * Locking: |
511 | * Called functions take ldisc and termios_sem locks | 552 | * Called functions take ldisc and termios_mutex locks |
512 | */ | 553 | */ |
513 | 554 | ||
514 | static int set_termios(struct tty_struct *tty, void __user *arg, int opt) | 555 | static int set_termios(struct tty_struct *tty, void __user *arg, int opt) |
@@ -579,25 +620,51 @@ static int get_termio(struct tty_struct *tty, struct termio __user *termio) | |||
579 | return 0; | 620 | return 0; |
580 | } | 621 | } |
581 | 622 | ||
582 | static unsigned long inq_canon(struct tty_struct *tty) | 623 | |
624 | #ifdef TCGETX | ||
625 | |||
626 | /** | ||
627 | * set_termiox - set termiox fields if possible | ||
628 | * @tty: terminal | ||
629 | * @arg: termiox structure from user | ||
630 | * @opt: option flags for ioctl type | ||
631 | * | ||
632 | * Implement the device calling points for the SYS5 termiox ioctl | ||
633 | * interface in Linux | ||
634 | */ | ||
635 | |||
636 | static int set_termiox(struct tty_struct *tty, void __user *arg, int opt) | ||
583 | { | 637 | { |
584 | int nr, head, tail; | 638 | struct termiox tnew; |
639 | struct tty_ldisc *ld; | ||
585 | 640 | ||
586 | if (!tty->canon_data || !tty->read_buf) | 641 | if (tty->termiox == NULL) |
587 | return 0; | 642 | return -EINVAL; |
588 | head = tty->canon_head; | 643 | if (copy_from_user(&tnew, arg, sizeof(struct termiox))) |
589 | tail = tty->read_tail; | 644 | return -EFAULT; |
590 | nr = (head - tail) & (N_TTY_BUF_SIZE-1); | 645 | |
591 | /* Skip EOF-chars.. */ | 646 | ld = tty_ldisc_ref(tty); |
592 | while (head != tail) { | 647 | if (ld != NULL) { |
593 | if (test_bit(tail, tty->read_flags) && | 648 | if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer) |
594 | tty->read_buf[tail] == __DISABLED_CHAR) | 649 | ld->ops->flush_buffer(tty); |
595 | nr--; | 650 | tty_ldisc_deref(ld); |
596 | tail = (tail+1) & (N_TTY_BUF_SIZE-1); | ||
597 | } | 651 | } |
598 | return nr; | 652 | if (opt & TERMIOS_WAIT) { |
653 | tty_wait_until_sent(tty, 0); | ||
654 | if (signal_pending(current)) | ||
655 | return -EINTR; | ||
656 | } | ||
657 | |||
658 | mutex_lock(&tty->termios_mutex); | ||
659 | if (tty->ops->set_termiox) | ||
660 | tty->ops->set_termiox(tty, &tnew); | ||
661 | mutex_unlock(&tty->termios_mutex); | ||
662 | return 0; | ||
599 | } | 663 | } |
600 | 664 | ||
665 | #endif | ||
666 | |||
667 | |||
601 | #ifdef TIOCGETP | 668 | #ifdef TIOCGETP |
602 | /* | 669 | /* |
603 | * These are deprecated, but there is limited support.. | 670 | * These are deprecated, but there is limited support.. |
@@ -671,7 +738,7 @@ static void set_sgflags(struct ktermios *termios, int flags) | |||
671 | * Updates a terminal from the legacy BSD style terminal information | 738 | * Updates a terminal from the legacy BSD style terminal information |
672 | * structure. | 739 | * structure. |
673 | * | 740 | * |
674 | * Locking: termios_sem | 741 | * Locking: termios_mutex |
675 | */ | 742 | */ |
676 | 743 | ||
677 | static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb) | 744 | static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb) |
@@ -849,6 +916,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
849 | { | 916 | { |
850 | struct tty_struct *real_tty; | 917 | struct tty_struct *real_tty; |
851 | void __user *p = (void __user *)arg; | 918 | void __user *p = (void __user *)arg; |
919 | int ret = 0; | ||
852 | 920 | ||
853 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 921 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
854 | tty->driver->subtype == PTY_TYPE_MASTER) | 922 | tty->driver->subtype == PTY_TYPE_MASTER) |
@@ -884,18 +952,24 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
884 | return set_termios(real_tty, p, TERMIOS_OLD); | 952 | return set_termios(real_tty, p, TERMIOS_OLD); |
885 | #ifndef TCGETS2 | 953 | #ifndef TCGETS2 |
886 | case TCGETS: | 954 | case TCGETS: |
955 | mutex_lock(&real_tty->termios_mutex); | ||
887 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) | 956 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) |
888 | return -EFAULT; | 957 | ret = -EFAULT; |
889 | return 0; | 958 | mutex_unlock(&real_tty->termios_mutex); |
959 | return ret; | ||
890 | #else | 960 | #else |
891 | case TCGETS: | 961 | case TCGETS: |
962 | mutex_lock(&real_tty->termios_mutex); | ||
892 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios)) | 963 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios)) |
893 | return -EFAULT; | 964 | ret = -EFAULT; |
894 | return 0; | 965 | mutex_unlock(&real_tty->termios_mutex); |
966 | return ret; | ||
895 | case TCGETS2: | 967 | case TCGETS2: |
968 | mutex_lock(&real_tty->termios_mutex); | ||
896 | if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios)) | 969 | if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios)) |
897 | return -EFAULT; | 970 | ret = -EFAULT; |
898 | return 0; | 971 | mutex_unlock(&real_tty->termios_mutex); |
972 | return ret; | ||
899 | case TCSETSF2: | 973 | case TCSETSF2: |
900 | return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); | 974 | return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); |
901 | case TCSETSW2: | 975 | case TCSETSW2: |
@@ -913,34 +987,59 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
913 | return set_termios(real_tty, p, TERMIOS_TERMIO); | 987 | return set_termios(real_tty, p, TERMIOS_TERMIO); |
914 | #ifndef TCGETS2 | 988 | #ifndef TCGETS2 |
915 | case TIOCGLCKTRMIOS: | 989 | case TIOCGLCKTRMIOS: |
990 | mutex_lock(&real_tty->termios_mutex); | ||
916 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) | 991 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) |
917 | return -EFAULT; | 992 | ret = -EFAULT; |
918 | return 0; | 993 | mutex_unlock(&real_tty->termios_mutex); |
994 | return ret; | ||
919 | case TIOCSLCKTRMIOS: | 995 | case TIOCSLCKTRMIOS: |
920 | if (!capable(CAP_SYS_ADMIN)) | 996 | if (!capable(CAP_SYS_ADMIN)) |
921 | return -EPERM; | 997 | return -EPERM; |
998 | mutex_lock(&real_tty->termios_mutex); | ||
922 | if (user_termios_to_kernel_termios(real_tty->termios_locked, | 999 | if (user_termios_to_kernel_termios(real_tty->termios_locked, |
923 | (struct termios __user *) arg)) | 1000 | (struct termios __user *) arg)) |
924 | return -EFAULT; | 1001 | ret = -EFAULT; |
925 | return 0; | 1002 | mutex_unlock(&real_tty->termios_mutex); |
1003 | return ret; | ||
926 | #else | 1004 | #else |
927 | case TIOCGLCKTRMIOS: | 1005 | case TIOCGLCKTRMIOS: |
1006 | mutex_lock(&real_tty->termios_mutex); | ||
928 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) | 1007 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) |
929 | return -EFAULT; | 1008 | ret = -EFAULT; |
930 | return 0; | 1009 | mutex_unlock(&real_tty->termios_mutex); |
1010 | return ret; | ||
931 | case TIOCSLCKTRMIOS: | 1011 | case TIOCSLCKTRMIOS: |
932 | if (!capable(CAP_SYS_ADMIN)) | 1012 | if (!capable(CAP_SYS_ADMIN)) |
933 | return -EPERM; | 1013 | ret = -EPERM; |
1014 | mutex_lock(&real_tty->termios_mutex); | ||
934 | if (user_termios_to_kernel_termios_1(real_tty->termios_locked, | 1015 | if (user_termios_to_kernel_termios_1(real_tty->termios_locked, |
935 | (struct termios __user *) arg)) | 1016 | (struct termios __user *) arg)) |
936 | return -EFAULT; | 1017 | ret = -EFAULT; |
937 | return 0; | 1018 | mutex_unlock(&real_tty->termios_mutex); |
1019 | return ret; | ||
938 | #endif | 1020 | #endif |
1021 | #ifdef TCGETX | ||
1022 | case TCGETX: | ||
1023 | if (real_tty->termiox == NULL) | ||
1024 | return -EINVAL; | ||
1025 | mutex_lock(&real_tty->termios_mutex); | ||
1026 | if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox))) | ||
1027 | ret = -EFAULT; | ||
1028 | mutex_unlock(&real_tty->termios_mutex); | ||
1029 | return ret; | ||
1030 | case TCSETX: | ||
1031 | return set_termiox(real_tty, p, 0); | ||
1032 | case TCSETXW: | ||
1033 | return set_termiox(real_tty, p, TERMIOS_WAIT); | ||
1034 | case TCSETXF: | ||
1035 | return set_termiox(real_tty, p, TERMIOS_FLUSH); | ||
1036 | #endif | ||
939 | case TIOCGSOFTCAR: | 1037 | case TIOCGSOFTCAR: |
940 | /* FIXME: for correctness we may need to take the termios | 1038 | mutex_lock(&real_tty->termios_mutex); |
941 | lock here - review */ | 1039 | ret = put_user(C_CLOCAL(real_tty) ? 1 : 0, |
942 | return put_user(C_CLOCAL(real_tty) ? 1 : 0, | ||
943 | (int __user *)arg); | 1040 | (int __user *)arg); |
1041 | mutex_unlock(&real_tty->termios_mutex); | ||
1042 | return ret; | ||
944 | case TIOCSSOFTCAR: | 1043 | case TIOCSSOFTCAR: |
945 | if (get_user(arg, (unsigned int __user *) arg)) | 1044 | if (get_user(arg, (unsigned int __user *) arg)) |
946 | return -EFAULT; | 1045 | return -EFAULT; |
@@ -980,7 +1079,7 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg) | |||
980 | } | 1079 | } |
981 | EXPORT_SYMBOL_GPL(tty_perform_flush); | 1080 | EXPORT_SYMBOL_GPL(tty_perform_flush); |
982 | 1081 | ||
983 | int n_tty_ioctl(struct tty_struct *tty, struct file *file, | 1082 | int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, |
984 | unsigned int cmd, unsigned long arg) | 1083 | unsigned int cmd, unsigned long arg) |
985 | { | 1084 | { |
986 | unsigned long flags; | 1085 | unsigned long flags; |
@@ -1018,13 +1117,6 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file, | |||
1018 | return 0; | 1117 | return 0; |
1019 | case TCFLSH: | 1118 | case TCFLSH: |
1020 | return tty_perform_flush(tty, arg); | 1119 | return tty_perform_flush(tty, arg); |
1021 | case TIOCOUTQ: | ||
1022 | return put_user(tty_chars_in_buffer(tty), (int __user *) arg); | ||
1023 | case TIOCINQ: | ||
1024 | retval = tty->read_cnt; | ||
1025 | if (L_ICANON(tty)) | ||
1026 | retval = inq_canon(tty); | ||
1027 | return put_user(retval, (unsigned int __user *) arg); | ||
1028 | case TIOCPKT: | 1120 | case TIOCPKT: |
1029 | { | 1121 | { |
1030 | int pktmode; | 1122 | int pktmode; |
@@ -1050,4 +1142,4 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file, | |||
1050 | return tty_mode_ioctl(tty, file, cmd, arg); | 1142 | return tty_mode_ioctl(tty, file, cmd, arg); |
1051 | } | 1143 | } |
1052 | } | 1144 | } |
1053 | EXPORT_SYMBOL(n_tty_ioctl); | 1145 | EXPORT_SYMBOL(n_tty_ioctl_helper); |
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c new file mode 100644 index 000000000000..553b0e9d8d17 --- /dev/null +++ b/drivers/char/tty_port.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * Tty port functions | ||
3 | */ | ||
4 | |||
5 | #include <linux/types.h> | ||
6 | #include <linux/errno.h> | ||
7 | #include <linux/tty.h> | ||
8 | #include <linux/tty_driver.h> | ||
9 | #include <linux/tty_flip.h> | ||
10 | #include <linux/timer.h> | ||
11 | #include <linux/string.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/wait.h> | ||
16 | #include <linux/bitops.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/module.h> | ||
19 | |||
20 | void tty_port_init(struct tty_port *port) | ||
21 | { | ||
22 | memset(port, 0, sizeof(*port)); | ||
23 | init_waitqueue_head(&port->open_wait); | ||
24 | init_waitqueue_head(&port->close_wait); | ||
25 | mutex_init(&port->mutex); | ||
26 | spin_lock_init(&port->lock); | ||
27 | port->close_delay = (50 * HZ) / 100; | ||
28 | port->closing_wait = (3000 * HZ) / 100; | ||
29 | } | ||
30 | EXPORT_SYMBOL(tty_port_init); | ||
31 | |||
32 | int tty_port_alloc_xmit_buf(struct tty_port *port) | ||
33 | { | ||
34 | /* We may sleep in get_zeroed_page() */ | ||
35 | mutex_lock(&port->mutex); | ||
36 | if (port->xmit_buf == NULL) | ||
37 | port->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); | ||
38 | mutex_unlock(&port->mutex); | ||
39 | if (port->xmit_buf == NULL) | ||
40 | return -ENOMEM; | ||
41 | return 0; | ||
42 | } | ||
43 | EXPORT_SYMBOL(tty_port_alloc_xmit_buf); | ||
44 | |||
45 | void tty_port_free_xmit_buf(struct tty_port *port) | ||
46 | { | ||
47 | mutex_lock(&port->mutex); | ||
48 | if (port->xmit_buf != NULL) { | ||
49 | free_page((unsigned long)port->xmit_buf); | ||
50 | port->xmit_buf = NULL; | ||
51 | } | ||
52 | mutex_unlock(&port->mutex); | ||
53 | } | ||
54 | EXPORT_SYMBOL(tty_port_free_xmit_buf); | ||
55 | |||
56 | |||
57 | /** | ||
58 | * tty_port_tty_get - get a tty reference | ||
59 | * @port: tty port | ||
60 | * | ||
61 | * Return a refcount protected tty instance or NULL if the port is not | ||
62 | * associated with a tty (eg due to close or hangup) | ||
63 | */ | ||
64 | |||
65 | struct tty_struct *tty_port_tty_get(struct tty_port *port) | ||
66 | { | ||
67 | unsigned long flags; | ||
68 | struct tty_struct *tty; | ||
69 | |||
70 | spin_lock_irqsave(&port->lock, flags); | ||
71 | tty = tty_kref_get(port->tty); | ||
72 | spin_unlock_irqrestore(&port->lock, flags); | ||
73 | return tty; | ||
74 | } | ||
75 | EXPORT_SYMBOL(tty_port_tty_get); | ||
76 | |||
77 | /** | ||
78 | * tty_port_tty_set - set the tty of a port | ||
79 | * @port: tty port | ||
80 | * @tty: the tty | ||
81 | * | ||
82 | * Associate the port and tty pair. Manages any internal refcounts. | ||
83 | * Pass NULL to deassociate a port | ||
84 | */ | ||
85 | |||
86 | void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty) | ||
87 | { | ||
88 | unsigned long flags; | ||
89 | |||
90 | spin_lock_irqsave(&port->lock, flags); | ||
91 | if (port->tty) | ||
92 | tty_kref_put(port->tty); | ||
93 | port->tty = tty; | ||
94 | spin_unlock_irqrestore(&port->lock, flags); | ||
95 | } | ||
96 | EXPORT_SYMBOL(tty_port_tty_set); | ||
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 60359c360912..57029fefd64a 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -100,10 +100,10 @@ | |||
100 | #include <linux/font.h> | 100 | #include <linux/font.h> |
101 | #include <linux/bitops.h> | 101 | #include <linux/bitops.h> |
102 | #include <linux/notifier.h> | 102 | #include <linux/notifier.h> |
103 | 103 | #include <linux/device.h> | |
104 | #include <asm/io.h> | 104 | #include <linux/io.h> |
105 | #include <asm/system.h> | 105 | #include <asm/system.h> |
106 | #include <asm/uaccess.h> | 106 | #include <linux/uaccess.h> |
107 | 107 | ||
108 | #define MAX_NR_CON_DRIVER 16 | 108 | #define MAX_NR_CON_DRIVER 16 |
109 | 109 | ||
@@ -2136,27 +2136,9 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co | |||
2136 | release_console_sem(); | 2136 | release_console_sem(); |
2137 | return 0; | 2137 | return 0; |
2138 | } | 2138 | } |
2139 | release_console_sem(); | ||
2140 | |||
2141 | orig_buf = buf; | 2139 | orig_buf = buf; |
2142 | orig_count = count; | 2140 | orig_count = count; |
2143 | 2141 | ||
2144 | /* At this point 'buf' is guaranteed to be a kernel buffer | ||
2145 | * and therefore no access to userspace (and therefore sleeping) | ||
2146 | * will be needed. The con_buf_mtx serializes all tty based | ||
2147 | * console rendering and vcs write/read operations. We hold | ||
2148 | * the console spinlock during the entire write. | ||
2149 | */ | ||
2150 | |||
2151 | acquire_console_sem(); | ||
2152 | |||
2153 | vc = tty->driver_data; | ||
2154 | if (vc == NULL) { | ||
2155 | printk(KERN_ERR "vt: argh, driver_data _became_ NULL !\n"); | ||
2156 | release_console_sem(); | ||
2157 | goto out; | ||
2158 | } | ||
2159 | |||
2160 | himask = vc->vc_hi_font_mask; | 2142 | himask = vc->vc_hi_font_mask; |
2161 | charmask = himask ? 0x1ff : 0xff; | 2143 | charmask = himask ? 0x1ff : 0xff; |
2162 | 2144 | ||
@@ -2370,8 +2352,6 @@ rescan_last_byte: | |||
2370 | FLUSH | 2352 | FLUSH |
2371 | console_conditional_schedule(); | 2353 | console_conditional_schedule(); |
2372 | release_console_sem(); | 2354 | release_console_sem(); |
2373 | |||
2374 | out: | ||
2375 | notify_update(vc); | 2355 | notify_update(vc); |
2376 | return n; | 2356 | return n; |
2377 | #undef FLUSH | 2357 | #undef FLUSH |
@@ -2583,8 +2563,6 @@ int tioclinux(struct tty_struct *tty, unsigned long arg) | |||
2583 | int lines; | 2563 | int lines; |
2584 | int ret; | 2564 | int ret; |
2585 | 2565 | ||
2586 | if (tty->driver->type != TTY_DRIVER_TYPE_CONSOLE) | ||
2587 | return -EINVAL; | ||
2588 | if (current->signal->tty != tty && !capable(CAP_SYS_ADMIN)) | 2566 | if (current->signal->tty != tty && !capable(CAP_SYS_ADMIN)) |
2589 | return -EPERM; | 2567 | return -EPERM; |
2590 | if (get_user(type, p)) | 2568 | if (get_user(type, p)) |
@@ -2778,6 +2756,12 @@ static int con_open(struct tty_struct *tty, struct file *filp) | |||
2778 | ret = vc_allocate(currcons); | 2756 | ret = vc_allocate(currcons); |
2779 | if (ret == 0) { | 2757 | if (ret == 0) { |
2780 | struct vc_data *vc = vc_cons[currcons].d; | 2758 | struct vc_data *vc = vc_cons[currcons].d; |
2759 | |||
2760 | /* Still being freed */ | ||
2761 | if (vc->vc_tty) { | ||
2762 | release_console_sem(); | ||
2763 | return -ERESTARTSYS; | ||
2764 | } | ||
2781 | tty->driver_data = vc; | 2765 | tty->driver_data = vc; |
2782 | vc->vc_tty = tty; | 2766 | vc->vc_tty = tty; |
2783 | 2767 | ||
@@ -2798,34 +2782,20 @@ static int con_open(struct tty_struct *tty, struct file *filp) | |||
2798 | return ret; | 2782 | return ret; |
2799 | } | 2783 | } |
2800 | 2784 | ||
2801 | /* | ||
2802 | * We take tty_mutex in here to prevent another thread from coming in via init_dev | ||
2803 | * and taking a ref against the tty while we're in the process of forgetting | ||
2804 | * about it and cleaning things up. | ||
2805 | * | ||
2806 | * This is because vcs_remove_sysfs() can sleep and will drop the BKL. | ||
2807 | */ | ||
2808 | static void con_close(struct tty_struct *tty, struct file *filp) | 2785 | static void con_close(struct tty_struct *tty, struct file *filp) |
2809 | { | 2786 | { |
2810 | mutex_lock(&tty_mutex); | 2787 | /* Nothing to do - we defer to shutdown */ |
2811 | acquire_console_sem(); | 2788 | } |
2812 | if (tty && tty->count == 1) { | ||
2813 | struct vc_data *vc = tty->driver_data; | ||
2814 | 2789 | ||
2815 | if (vc) | 2790 | static void con_shutdown(struct tty_struct *tty) |
2816 | vc->vc_tty = NULL; | 2791 | { |
2817 | tty->driver_data = NULL; | 2792 | struct vc_data *vc = tty->driver_data; |
2818 | vcs_remove_sysfs(tty); | 2793 | BUG_ON(vc == NULL); |
2819 | release_console_sem(); | 2794 | acquire_console_sem(); |
2820 | mutex_unlock(&tty_mutex); | 2795 | vc->vc_tty = NULL; |
2821 | /* | 2796 | vcs_remove_sysfs(tty); |
2822 | * tty_mutex is released, but we still hold BKL, so there is | ||
2823 | * still exclusion against init_dev() | ||
2824 | */ | ||
2825 | return; | ||
2826 | } | ||
2827 | release_console_sem(); | 2797 | release_console_sem(); |
2828 | mutex_unlock(&tty_mutex); | 2798 | tty_shutdown(tty); |
2829 | } | 2799 | } |
2830 | 2800 | ||
2831 | static int default_italic_color = 2; // green (ASCII) | 2801 | static int default_italic_color = 2; // green (ASCII) |
@@ -2950,10 +2920,19 @@ static const struct tty_operations con_ops = { | |||
2950 | .throttle = con_throttle, | 2920 | .throttle = con_throttle, |
2951 | .unthrottle = con_unthrottle, | 2921 | .unthrottle = con_unthrottle, |
2952 | .resize = vt_resize, | 2922 | .resize = vt_resize, |
2923 | .shutdown = con_shutdown | ||
2953 | }; | 2924 | }; |
2954 | 2925 | ||
2955 | int __init vty_init(void) | 2926 | static struct cdev vc0_cdev; |
2927 | |||
2928 | int __init vty_init(const struct file_operations *console_fops) | ||
2956 | { | 2929 | { |
2930 | cdev_init(&vc0_cdev, console_fops); | ||
2931 | if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) || | ||
2932 | register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) | ||
2933 | panic("Couldn't register /dev/tty0 driver\n"); | ||
2934 | device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0"); | ||
2935 | |||
2957 | vcs_init(); | 2936 | vcs_init(); |
2958 | 2937 | ||
2959 | console_driver = alloc_tty_driver(MAX_NR_CONSOLES); | 2938 | console_driver = alloc_tty_driver(MAX_NR_CONSOLES); |
@@ -2972,7 +2951,6 @@ int __init vty_init(void) | |||
2972 | tty_set_operations(console_driver, &con_ops); | 2951 | tty_set_operations(console_driver, &con_ops); |
2973 | if (tty_register_driver(console_driver)) | 2952 | if (tty_register_driver(console_driver)) |
2974 | panic("Couldn't register console driver\n"); | 2953 | panic("Couldn't register console driver\n"); |
2975 | |||
2976 | kbd_init(); | 2954 | kbd_init(); |
2977 | console_map_init(); | 2955 | console_map_init(); |
2978 | #ifdef CONFIG_PROM_CONSOLE | 2956 | #ifdef CONFIG_PROM_CONSOLE |
@@ -3466,7 +3444,7 @@ int register_con_driver(const struct consw *csw, int first, int last) | |||
3466 | if (retval) | 3444 | if (retval) |
3467 | goto err; | 3445 | goto err; |
3468 | 3446 | ||
3469 | con_driver->dev = device_create_drvdata(vtconsole_class, NULL, | 3447 | con_driver->dev = device_create(vtconsole_class, NULL, |
3470 | MKDEV(0, con_driver->node), | 3448 | MKDEV(0, con_driver->node), |
3471 | NULL, "vtcon%i", | 3449 | NULL, "vtcon%i", |
3472 | con_driver->node); | 3450 | con_driver->node); |
@@ -3577,7 +3555,7 @@ static int __init vtconsole_class_init(void) | |||
3577 | struct con_driver *con = ®istered_con_driver[i]; | 3555 | struct con_driver *con = ®istered_con_driver[i]; |
3578 | 3556 | ||
3579 | if (con->con && !con->dev) { | 3557 | if (con->con && !con->dev) { |
3580 | con->dev = device_create_drvdata(vtconsole_class, NULL, | 3558 | con->dev = device_create(vtconsole_class, NULL, |
3581 | MKDEV(0, con->node), | 3559 | MKDEV(0, con->node), |
3582 | NULL, "vtcon%i", | 3560 | NULL, "vtcon%i", |
3583 | con->node); | 3561 | con->node); |
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index c904e9ad4a71..8944ce508e2f 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c | |||
@@ -395,6 +395,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, | |||
395 | 395 | ||
396 | kbd = kbd_table + console; | 396 | kbd = kbd_table + console; |
397 | switch (cmd) { | 397 | switch (cmd) { |
398 | case TIOCLINUX: | ||
399 | return tioclinux(tty, arg); | ||
398 | case KIOCSOUND: | 400 | case KIOCSOUND: |
399 | if (!perm) | 401 | if (!perm) |
400 | goto eperm; | 402 | goto eperm; |
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 871b0cbca5e4..798d7f3e42ef 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c | |||
@@ -1231,7 +1231,7 @@ static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file, | |||
1231 | int error = 0; | 1231 | int error = 0; |
1232 | switch (cmd) { | 1232 | switch (cmd) { |
1233 | default: | 1233 | default: |
1234 | error = n_tty_ioctl (tty, file, cmd, arg); | 1234 | error = n_tty_ioctl_helper(tty, file, cmd, arg); |
1235 | break; | 1235 | break; |
1236 | } | 1236 | } |
1237 | return error; | 1237 | return error; |
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 5e89fa177816..07052ed2a0c5 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c | |||
@@ -571,6 +571,7 @@ gigaset_tty_close(struct tty_struct *tty) | |||
571 | } | 571 | } |
572 | 572 | ||
573 | /* prevent other callers from entering ldisc methods */ | 573 | /* prevent other callers from entering ldisc methods */ |
574 | /* FIXME: should use the tty state flags */ | ||
574 | tty->disc_data = NULL; | 575 | tty->disc_data = NULL; |
575 | 576 | ||
576 | if (!cs->hw.ser) | 577 | if (!cs->hw.ser) |
@@ -642,10 +643,11 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file, | |||
642 | return -ENXIO; | 643 | return -ENXIO; |
643 | 644 | ||
644 | switch (cmd) { | 645 | switch (cmd) { |
645 | case TCGETS: | 646 | |
646 | case TCGETA: | 647 | case FIONREAD: |
647 | /* pass through to underlying serial device */ | 648 | /* unused, always return zero */ |
648 | rc = n_tty_ioctl(tty, file, cmd, arg); | 649 | val = 0; |
650 | rc = put_user(val, p); | ||
649 | break; | 651 | break; |
650 | 652 | ||
651 | case TCFLSH: | 653 | case TCFLSH: |
@@ -659,20 +661,13 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file, | |||
659 | flush_send_queue(cs); | 661 | flush_send_queue(cs); |
660 | break; | 662 | break; |
661 | } | 663 | } |
662 | /* flush the serial port's buffer */ | 664 | /* Pass through */ |
663 | rc = n_tty_ioctl(tty, file, cmd, arg); | ||
664 | break; | ||
665 | |||
666 | case FIONREAD: | ||
667 | /* unused, always return zero */ | ||
668 | val = 0; | ||
669 | rc = put_user(val, p); | ||
670 | break; | ||
671 | 665 | ||
672 | default: | 666 | default: |
673 | rc = -ENOIOCTLCMD; | 667 | /* pass through to underlying serial device */ |
668 | rc = n_tty_ioctl_helper(tty, file, cmd, arg); | ||
669 | break; | ||
674 | } | 670 | } |
675 | |||
676 | cs_put(cs); | 671 | cs_put(cs); |
677 | return rc; | 672 | return rc; |
678 | } | 673 | } |
@@ -680,6 +675,8 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file, | |||
680 | /* | 675 | /* |
681 | * Poll on the tty. | 676 | * Poll on the tty. |
682 | * Unused, always return zero. | 677 | * Unused, always return zero. |
678 | * | ||
679 | * FIXME: should probably return an exception - especially on hangup | ||
683 | */ | 680 | */ |
684 | static unsigned int | 681 | static unsigned int |
685 | gigaset_tty_poll(struct tty_struct *tty, struct file *file, poll_table *wait) | 682 | gigaset_tty_poll(struct tty_struct *tty, struct file *file, poll_table *wait) |
diff --git a/drivers/media/video/cafe_ccic.c b/drivers/media/video/cafe_ccic.c index 5405c30dbb04..08efbe7254ff 100644 --- a/drivers/media/video/cafe_ccic.c +++ b/drivers/media/video/cafe_ccic.c | |||
@@ -2092,15 +2092,8 @@ static int cafe_pci_probe(struct pci_dev *pdev, | |||
2092 | const struct pci_device_id *id) | 2092 | const struct pci_device_id *id) |
2093 | { | 2093 | { |
2094 | int ret; | 2094 | int ret; |
2095 | u16 classword; | ||
2096 | struct cafe_camera *cam; | 2095 | struct cafe_camera *cam; |
2097 | /* | 2096 | |
2098 | * Make sure we have a camera here - we'll get calls for | ||
2099 | * the other cafe devices as well. | ||
2100 | */ | ||
2101 | pci_read_config_word(pdev, PCI_CLASS_DEVICE, &classword); | ||
2102 | if (classword != PCI_CLASS_MULTIMEDIA_VIDEO) | ||
2103 | return -ENODEV; | ||
2104 | /* | 2097 | /* |
2105 | * Start putting together one of our big camera structures. | 2098 | * Start putting together one of our big camera structures. |
2106 | */ | 2099 | */ |
@@ -2288,8 +2281,8 @@ static int cafe_pci_resume(struct pci_dev *pdev) | |||
2288 | 2281 | ||
2289 | 2282 | ||
2290 | static struct pci_device_id cafe_ids[] = { | 2283 | static struct pci_device_id cafe_ids[] = { |
2291 | { PCI_DEVICE(0x11ab, 0x4100) }, /* Eventual real ID */ | 2284 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, |
2292 | { PCI_DEVICE(0x11ab, 0x4102) }, /* Really eventual real ID */ | 2285 | PCI_DEVICE_ID_MARVELL_88ALP01_CCIC) }, |
2293 | { 0, } | 2286 | { 0, } |
2294 | }; | 2287 | }; |
2295 | 2288 | ||
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 0a84f10d719c..9bd7026b0021 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -327,7 +327,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = { | |||
327 | 327 | ||
328 | { | 328 | { |
329 | .vendor = PCI_VENDOR_ID_MARVELL, | 329 | .vendor = PCI_VENDOR_ID_MARVELL, |
330 | .device = PCI_DEVICE_ID_MARVELL_CAFE_SD, | 330 | .device = PCI_DEVICE_ID_MARVELL_88ALP01_SD, |
331 | .subvendor = PCI_ANY_ID, | 331 | .subvendor = PCI_ANY_ID, |
332 | .subdevice = PCI_ANY_ID, | 332 | .subdevice = PCI_ANY_ID, |
333 | .driver_data = (kernel_ulong_t)&sdhci_cafe, | 333 | .driver_data = (kernel_ulong_t)&sdhci_cafe, |
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index 95345d051579..b8064bf3aee4 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c | |||
@@ -1,6 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for One Laptop Per Child ‘CAFÉ’ controller, aka Marvell 88ALP01 | 2 | * Driver for One Laptop Per Child ‘CAFÉ’ controller, aka Marvell 88ALP01 |
3 | * | 3 | * |
4 | * The data sheet for this device can be found at: | ||
5 | * http://www.marvell.com/products/pcconn/88ALP01.jsp | ||
6 | * | ||
4 | * Copyright © 2006 Red Hat, Inc. | 7 | * Copyright © 2006 Red Hat, Inc. |
5 | * Copyright © 2006 David Woodhouse <dwmw2@infradead.org> | 8 | * Copyright © 2006 David Woodhouse <dwmw2@infradead.org> |
6 | */ | 9 | */ |
@@ -842,7 +845,8 @@ static void __devexit cafe_nand_remove(struct pci_dev *pdev) | |||
842 | } | 845 | } |
843 | 846 | ||
844 | static struct pci_device_id cafe_nand_tbl[] = { | 847 | static struct pci_device_id cafe_nand_tbl[] = { |
845 | { 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID }, | 848 | { PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_88ALP01_NAND, |
849 | PCI_ANY_ID, PCI_ANY_ID }, | ||
846 | { } | 850 | { } |
847 | }; | 851 | }; |
848 | 852 | ||
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 2ae2ec40015d..21efd99b9294 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig | |||
@@ -205,7 +205,7 @@ config WANXL_BUILD_FIRMWARE | |||
205 | 205 | ||
206 | config PC300 | 206 | config PC300 |
207 | tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)" | 207 | tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)" |
208 | depends on HDLC && PCI | 208 | depends on HDLC && PCI && BROKEN |
209 | ---help--- | 209 | ---help--- |
210 | Driver for the Cyclades-PC300 synchronous communication boards. | 210 | Driver for the Cyclades-PC300 synchronous communication boards. |
211 | 211 | ||
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 9304c4555079..ed982273fb8b 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * @remark Read the file COPYING | 5 | * @remark Read the file COPYING |
6 | * | 6 | * |
7 | * @author John Levon <levon@movementarian.org> | 7 | * @author John Levon <levon@movementarian.org> |
8 | * @author Barry Kasindorf | ||
8 | * | 9 | * |
9 | * This is the core of the buffer management. Each | 10 | * This is the core of the buffer management. Each |
10 | * CPU buffer is processed and entered into the | 11 | * CPU buffer is processed and entered into the |
@@ -33,7 +34,7 @@ | |||
33 | #include "event_buffer.h" | 34 | #include "event_buffer.h" |
34 | #include "cpu_buffer.h" | 35 | #include "cpu_buffer.h" |
35 | #include "buffer_sync.h" | 36 | #include "buffer_sync.h" |
36 | 37 | ||
37 | static LIST_HEAD(dying_tasks); | 38 | static LIST_HEAD(dying_tasks); |
38 | static LIST_HEAD(dead_tasks); | 39 | static LIST_HEAD(dead_tasks); |
39 | static cpumask_t marked_cpus = CPU_MASK_NONE; | 40 | static cpumask_t marked_cpus = CPU_MASK_NONE; |
@@ -48,10 +49,11 @@ static void process_task_mortuary(void); | |||
48 | * Can be invoked from softirq via RCU callback due to | 49 | * Can be invoked from softirq via RCU callback due to |
49 | * call_rcu() of the task struct, hence the _irqsave. | 50 | * call_rcu() of the task struct, hence the _irqsave. |
50 | */ | 51 | */ |
51 | static int task_free_notify(struct notifier_block * self, unsigned long val, void * data) | 52 | static int |
53 | task_free_notify(struct notifier_block *self, unsigned long val, void *data) | ||
52 | { | 54 | { |
53 | unsigned long flags; | 55 | unsigned long flags; |
54 | struct task_struct * task = data; | 56 | struct task_struct *task = data; |
55 | spin_lock_irqsave(&task_mortuary, flags); | 57 | spin_lock_irqsave(&task_mortuary, flags); |
56 | list_add(&task->tasks, &dying_tasks); | 58 | list_add(&task->tasks, &dying_tasks); |
57 | spin_unlock_irqrestore(&task_mortuary, flags); | 59 | spin_unlock_irqrestore(&task_mortuary, flags); |
@@ -62,13 +64,14 @@ static int task_free_notify(struct notifier_block * self, unsigned long val, voi | |||
62 | /* The task is on its way out. A sync of the buffer means we can catch | 64 | /* The task is on its way out. A sync of the buffer means we can catch |
63 | * any remaining samples for this task. | 65 | * any remaining samples for this task. |
64 | */ | 66 | */ |
65 | static int task_exit_notify(struct notifier_block * self, unsigned long val, void * data) | 67 | static int |
68 | task_exit_notify(struct notifier_block *self, unsigned long val, void *data) | ||
66 | { | 69 | { |
67 | /* To avoid latency problems, we only process the current CPU, | 70 | /* To avoid latency problems, we only process the current CPU, |
68 | * hoping that most samples for the task are on this CPU | 71 | * hoping that most samples for the task are on this CPU |
69 | */ | 72 | */ |
70 | sync_buffer(raw_smp_processor_id()); | 73 | sync_buffer(raw_smp_processor_id()); |
71 | return 0; | 74 | return 0; |
72 | } | 75 | } |
73 | 76 | ||
74 | 77 | ||
@@ -77,11 +80,12 @@ static int task_exit_notify(struct notifier_block * self, unsigned long val, voi | |||
77 | * we don't lose any. This does not have to be exact, it's a QoI issue | 80 | * we don't lose any. This does not have to be exact, it's a QoI issue |
78 | * only. | 81 | * only. |
79 | */ | 82 | */ |
80 | static int munmap_notify(struct notifier_block * self, unsigned long val, void * data) | 83 | static int |
84 | munmap_notify(struct notifier_block *self, unsigned long val, void *data) | ||
81 | { | 85 | { |
82 | unsigned long addr = (unsigned long)data; | 86 | unsigned long addr = (unsigned long)data; |
83 | struct mm_struct * mm = current->mm; | 87 | struct mm_struct *mm = current->mm; |
84 | struct vm_area_struct * mpnt; | 88 | struct vm_area_struct *mpnt; |
85 | 89 | ||
86 | down_read(&mm->mmap_sem); | 90 | down_read(&mm->mmap_sem); |
87 | 91 | ||
@@ -99,11 +103,12 @@ static int munmap_notify(struct notifier_block * self, unsigned long val, void * | |||
99 | return 0; | 103 | return 0; |
100 | } | 104 | } |
101 | 105 | ||
102 | 106 | ||
103 | /* We need to be told about new modules so we don't attribute to a previously | 107 | /* We need to be told about new modules so we don't attribute to a previously |
104 | * loaded module, or drop the samples on the floor. | 108 | * loaded module, or drop the samples on the floor. |
105 | */ | 109 | */ |
106 | static int module_load_notify(struct notifier_block * self, unsigned long val, void * data) | 110 | static int |
111 | module_load_notify(struct notifier_block *self, unsigned long val, void *data) | ||
107 | { | 112 | { |
108 | #ifdef CONFIG_MODULES | 113 | #ifdef CONFIG_MODULES |
109 | if (val != MODULE_STATE_COMING) | 114 | if (val != MODULE_STATE_COMING) |
@@ -118,7 +123,7 @@ static int module_load_notify(struct notifier_block * self, unsigned long val, v | |||
118 | return 0; | 123 | return 0; |
119 | } | 124 | } |
120 | 125 | ||
121 | 126 | ||
122 | static struct notifier_block task_free_nb = { | 127 | static struct notifier_block task_free_nb = { |
123 | .notifier_call = task_free_notify, | 128 | .notifier_call = task_free_notify, |
124 | }; | 129 | }; |
@@ -135,7 +140,7 @@ static struct notifier_block module_load_nb = { | |||
135 | .notifier_call = module_load_notify, | 140 | .notifier_call = module_load_notify, |
136 | }; | 141 | }; |
137 | 142 | ||
138 | 143 | ||
139 | static void end_sync(void) | 144 | static void end_sync(void) |
140 | { | 145 | { |
141 | end_cpu_work(); | 146 | end_cpu_work(); |
@@ -208,14 +213,14 @@ static inline unsigned long fast_get_dcookie(struct path *path) | |||
208 | * not strictly necessary but allows oprofile to associate | 213 | * not strictly necessary but allows oprofile to associate |
209 | * shared-library samples with particular applications | 214 | * shared-library samples with particular applications |
210 | */ | 215 | */ |
211 | static unsigned long get_exec_dcookie(struct mm_struct * mm) | 216 | static unsigned long get_exec_dcookie(struct mm_struct *mm) |
212 | { | 217 | { |
213 | unsigned long cookie = NO_COOKIE; | 218 | unsigned long cookie = NO_COOKIE; |
214 | struct vm_area_struct * vma; | 219 | struct vm_area_struct *vma; |
215 | 220 | ||
216 | if (!mm) | 221 | if (!mm) |
217 | goto out; | 222 | goto out; |
218 | 223 | ||
219 | for (vma = mm->mmap; vma; vma = vma->vm_next) { | 224 | for (vma = mm->mmap; vma; vma = vma->vm_next) { |
220 | if (!vma->vm_file) | 225 | if (!vma->vm_file) |
221 | continue; | 226 | continue; |
@@ -235,13 +240,14 @@ out: | |||
235 | * sure to do this lookup before a mm->mmap modification happens so | 240 | * sure to do this lookup before a mm->mmap modification happens so |
236 | * we don't lose track. | 241 | * we don't lose track. |
237 | */ | 242 | */ |
238 | static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, off_t * offset) | 243 | static unsigned long |
244 | lookup_dcookie(struct mm_struct *mm, unsigned long addr, off_t *offset) | ||
239 | { | 245 | { |
240 | unsigned long cookie = NO_COOKIE; | 246 | unsigned long cookie = NO_COOKIE; |
241 | struct vm_area_struct * vma; | 247 | struct vm_area_struct *vma; |
242 | 248 | ||
243 | for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) { | 249 | for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) { |
244 | 250 | ||
245 | if (addr < vma->vm_start || addr >= vma->vm_end) | 251 | if (addr < vma->vm_start || addr >= vma->vm_end) |
246 | continue; | 252 | continue; |
247 | 253 | ||
@@ -263,9 +269,20 @@ static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, o | |||
263 | return cookie; | 269 | return cookie; |
264 | } | 270 | } |
265 | 271 | ||
272 | static void increment_tail(struct oprofile_cpu_buffer *b) | ||
273 | { | ||
274 | unsigned long new_tail = b->tail_pos + 1; | ||
275 | |||
276 | rmb(); /* be sure fifo pointers are synchromized */ | ||
277 | |||
278 | if (new_tail < b->buffer_size) | ||
279 | b->tail_pos = new_tail; | ||
280 | else | ||
281 | b->tail_pos = 0; | ||
282 | } | ||
266 | 283 | ||
267 | static unsigned long last_cookie = INVALID_COOKIE; | 284 | static unsigned long last_cookie = INVALID_COOKIE; |
268 | 285 | ||
269 | static void add_cpu_switch(int i) | 286 | static void add_cpu_switch(int i) |
270 | { | 287 | { |
271 | add_event_entry(ESCAPE_CODE); | 288 | add_event_entry(ESCAPE_CODE); |
@@ -278,16 +295,16 @@ static void add_kernel_ctx_switch(unsigned int in_kernel) | |||
278 | { | 295 | { |
279 | add_event_entry(ESCAPE_CODE); | 296 | add_event_entry(ESCAPE_CODE); |
280 | if (in_kernel) | 297 | if (in_kernel) |
281 | add_event_entry(KERNEL_ENTER_SWITCH_CODE); | 298 | add_event_entry(KERNEL_ENTER_SWITCH_CODE); |
282 | else | 299 | else |
283 | add_event_entry(KERNEL_EXIT_SWITCH_CODE); | 300 | add_event_entry(KERNEL_EXIT_SWITCH_CODE); |
284 | } | 301 | } |
285 | 302 | ||
286 | static void | 303 | static void |
287 | add_user_ctx_switch(struct task_struct const * task, unsigned long cookie) | 304 | add_user_ctx_switch(struct task_struct const *task, unsigned long cookie) |
288 | { | 305 | { |
289 | add_event_entry(ESCAPE_CODE); | 306 | add_event_entry(ESCAPE_CODE); |
290 | add_event_entry(CTX_SWITCH_CODE); | 307 | add_event_entry(CTX_SWITCH_CODE); |
291 | add_event_entry(task->pid); | 308 | add_event_entry(task->pid); |
292 | add_event_entry(cookie); | 309 | add_event_entry(cookie); |
293 | /* Another code for daemon back-compat */ | 310 | /* Another code for daemon back-compat */ |
@@ -296,7 +313,7 @@ add_user_ctx_switch(struct task_struct const * task, unsigned long cookie) | |||
296 | add_event_entry(task->tgid); | 313 | add_event_entry(task->tgid); |
297 | } | 314 | } |
298 | 315 | ||
299 | 316 | ||
300 | static void add_cookie_switch(unsigned long cookie) | 317 | static void add_cookie_switch(unsigned long cookie) |
301 | { | 318 | { |
302 | add_event_entry(ESCAPE_CODE); | 319 | add_event_entry(ESCAPE_CODE); |
@@ -304,13 +321,78 @@ static void add_cookie_switch(unsigned long cookie) | |||
304 | add_event_entry(cookie); | 321 | add_event_entry(cookie); |
305 | } | 322 | } |
306 | 323 | ||
307 | 324 | ||
308 | static void add_trace_begin(void) | 325 | static void add_trace_begin(void) |
309 | { | 326 | { |
310 | add_event_entry(ESCAPE_CODE); | 327 | add_event_entry(ESCAPE_CODE); |
311 | add_event_entry(TRACE_BEGIN_CODE); | 328 | add_event_entry(TRACE_BEGIN_CODE); |
312 | } | 329 | } |
313 | 330 | ||
331 | #ifdef CONFIG_OPROFILE_IBS | ||
332 | |||
333 | #define IBS_FETCH_CODE_SIZE 2 | ||
334 | #define IBS_OP_CODE_SIZE 5 | ||
335 | #define IBS_EIP(offset) \ | ||
336 | (((struct op_sample *)&cpu_buf->buffer[(offset)])->eip) | ||
337 | #define IBS_EVENT(offset) \ | ||
338 | (((struct op_sample *)&cpu_buf->buffer[(offset)])->event) | ||
339 | |||
340 | /* | ||
341 | * Add IBS fetch and op entries to event buffer | ||
342 | */ | ||
343 | static void add_ibs_begin(struct oprofile_cpu_buffer *cpu_buf, int code, | ||
344 | int in_kernel, struct mm_struct *mm) | ||
345 | { | ||
346 | unsigned long rip; | ||
347 | int i, count; | ||
348 | unsigned long ibs_cookie = 0; | ||
349 | off_t offset; | ||
350 | |||
351 | increment_tail(cpu_buf); /* move to RIP entry */ | ||
352 | |||
353 | rip = IBS_EIP(cpu_buf->tail_pos); | ||
354 | |||
355 | #ifdef __LP64__ | ||
356 | rip += IBS_EVENT(cpu_buf->tail_pos) << 32; | ||
357 | #endif | ||
358 | |||
359 | if (mm) { | ||
360 | ibs_cookie = lookup_dcookie(mm, rip, &offset); | ||
361 | |||
362 | if (ibs_cookie == NO_COOKIE) | ||
363 | offset = rip; | ||
364 | if (ibs_cookie == INVALID_COOKIE) { | ||
365 | atomic_inc(&oprofile_stats.sample_lost_no_mapping); | ||
366 | offset = rip; | ||
367 | } | ||
368 | if (ibs_cookie != last_cookie) { | ||
369 | add_cookie_switch(ibs_cookie); | ||
370 | last_cookie = ibs_cookie; | ||
371 | } | ||
372 | } else | ||
373 | offset = rip; | ||
374 | |||
375 | add_event_entry(ESCAPE_CODE); | ||
376 | add_event_entry(code); | ||
377 | add_event_entry(offset); /* Offset from Dcookie */ | ||
378 | |||
379 | /* we send the Dcookie offset, but send the raw Linear Add also*/ | ||
380 | add_event_entry(IBS_EIP(cpu_buf->tail_pos)); | ||
381 | add_event_entry(IBS_EVENT(cpu_buf->tail_pos)); | ||
382 | |||
383 | if (code == IBS_FETCH_CODE) | ||
384 | count = IBS_FETCH_CODE_SIZE; /*IBS FETCH is 2 int64s*/ | ||
385 | else | ||
386 | count = IBS_OP_CODE_SIZE; /*IBS OP is 5 int64s*/ | ||
387 | |||
388 | for (i = 0; i < count; i++) { | ||
389 | increment_tail(cpu_buf); | ||
390 | add_event_entry(IBS_EIP(cpu_buf->tail_pos)); | ||
391 | add_event_entry(IBS_EVENT(cpu_buf->tail_pos)); | ||
392 | } | ||
393 | } | ||
394 | |||
395 | #endif | ||
314 | 396 | ||
315 | static void add_sample_entry(unsigned long offset, unsigned long event) | 397 | static void add_sample_entry(unsigned long offset, unsigned long event) |
316 | { | 398 | { |
@@ -319,13 +401,13 @@ static void add_sample_entry(unsigned long offset, unsigned long event) | |||
319 | } | 401 | } |
320 | 402 | ||
321 | 403 | ||
322 | static int add_us_sample(struct mm_struct * mm, struct op_sample * s) | 404 | static int add_us_sample(struct mm_struct *mm, struct op_sample *s) |
323 | { | 405 | { |
324 | unsigned long cookie; | 406 | unsigned long cookie; |
325 | off_t offset; | 407 | off_t offset; |
326 | 408 | ||
327 | cookie = lookup_dcookie(mm, s->eip, &offset); | 409 | cookie = lookup_dcookie(mm, s->eip, &offset); |
328 | 410 | ||
329 | if (cookie == INVALID_COOKIE) { | 411 | if (cookie == INVALID_COOKIE) { |
330 | atomic_inc(&oprofile_stats.sample_lost_no_mapping); | 412 | atomic_inc(&oprofile_stats.sample_lost_no_mapping); |
331 | return 0; | 413 | return 0; |
@@ -341,13 +423,13 @@ static int add_us_sample(struct mm_struct * mm, struct op_sample * s) | |||
341 | return 1; | 423 | return 1; |
342 | } | 424 | } |
343 | 425 | ||
344 | 426 | ||
345 | /* Add a sample to the global event buffer. If possible the | 427 | /* Add a sample to the global event buffer. If possible the |
346 | * sample is converted into a persistent dentry/offset pair | 428 | * sample is converted into a persistent dentry/offset pair |
347 | * for later lookup from userspace. | 429 | * for later lookup from userspace. |
348 | */ | 430 | */ |
349 | static int | 431 | static int |
350 | add_sample(struct mm_struct * mm, struct op_sample * s, int in_kernel) | 432 | add_sample(struct mm_struct *mm, struct op_sample *s, int in_kernel) |
351 | { | 433 | { |
352 | if (in_kernel) { | 434 | if (in_kernel) { |
353 | add_sample_entry(s->eip, s->event); | 435 | add_sample_entry(s->eip, s->event); |
@@ -359,9 +441,9 @@ add_sample(struct mm_struct * mm, struct op_sample * s, int in_kernel) | |||
359 | } | 441 | } |
360 | return 0; | 442 | return 0; |
361 | } | 443 | } |
362 | |||
363 | 444 | ||
364 | static void release_mm(struct mm_struct * mm) | 445 | |
446 | static void release_mm(struct mm_struct *mm) | ||
365 | { | 447 | { |
366 | if (!mm) | 448 | if (!mm) |
367 | return; | 449 | return; |
@@ -370,9 +452,9 @@ static void release_mm(struct mm_struct * mm) | |||
370 | } | 452 | } |
371 | 453 | ||
372 | 454 | ||
373 | static struct mm_struct * take_tasks_mm(struct task_struct * task) | 455 | static struct mm_struct *take_tasks_mm(struct task_struct *task) |
374 | { | 456 | { |
375 | struct mm_struct * mm = get_task_mm(task); | 457 | struct mm_struct *mm = get_task_mm(task); |
376 | if (mm) | 458 | if (mm) |
377 | down_read(&mm->mmap_sem); | 459 | down_read(&mm->mmap_sem); |
378 | return mm; | 460 | return mm; |
@@ -383,10 +465,10 @@ static inline int is_code(unsigned long val) | |||
383 | { | 465 | { |
384 | return val == ESCAPE_CODE; | 466 | return val == ESCAPE_CODE; |
385 | } | 467 | } |
386 | 468 | ||
387 | 469 | ||
388 | /* "acquire" as many cpu buffer slots as we can */ | 470 | /* "acquire" as many cpu buffer slots as we can */ |
389 | static unsigned long get_slots(struct oprofile_cpu_buffer * b) | 471 | static unsigned long get_slots(struct oprofile_cpu_buffer *b) |
390 | { | 472 | { |
391 | unsigned long head = b->head_pos; | 473 | unsigned long head = b->head_pos; |
392 | unsigned long tail = b->tail_pos; | 474 | unsigned long tail = b->tail_pos; |
@@ -412,19 +494,6 @@ static unsigned long get_slots(struct oprofile_cpu_buffer * b) | |||
412 | } | 494 | } |
413 | 495 | ||
414 | 496 | ||
415 | static void increment_tail(struct oprofile_cpu_buffer * b) | ||
416 | { | ||
417 | unsigned long new_tail = b->tail_pos + 1; | ||
418 | |||
419 | rmb(); | ||
420 | |||
421 | if (new_tail < b->buffer_size) | ||
422 | b->tail_pos = new_tail; | ||
423 | else | ||
424 | b->tail_pos = 0; | ||
425 | } | ||
426 | |||
427 | |||
428 | /* Move tasks along towards death. Any tasks on dead_tasks | 497 | /* Move tasks along towards death. Any tasks on dead_tasks |
429 | * will definitely have no remaining references in any | 498 | * will definitely have no remaining references in any |
430 | * CPU buffers at this point, because we use two lists, | 499 | * CPU buffers at this point, because we use two lists, |
@@ -435,8 +504,8 @@ static void process_task_mortuary(void) | |||
435 | { | 504 | { |
436 | unsigned long flags; | 505 | unsigned long flags; |
437 | LIST_HEAD(local_dead_tasks); | 506 | LIST_HEAD(local_dead_tasks); |
438 | struct task_struct * task; | 507 | struct task_struct *task; |
439 | struct task_struct * ttask; | 508 | struct task_struct *ttask; |
440 | 509 | ||
441 | spin_lock_irqsave(&task_mortuary, flags); | 510 | spin_lock_irqsave(&task_mortuary, flags); |
442 | 511 | ||
@@ -493,7 +562,7 @@ void sync_buffer(int cpu) | |||
493 | { | 562 | { |
494 | struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu); | 563 | struct oprofile_cpu_buffer *cpu_buf = &per_cpu(cpu_buffer, cpu); |
495 | struct mm_struct *mm = NULL; | 564 | struct mm_struct *mm = NULL; |
496 | struct task_struct * new; | 565 | struct task_struct *new; |
497 | unsigned long cookie = 0; | 566 | unsigned long cookie = 0; |
498 | int in_kernel = 1; | 567 | int in_kernel = 1; |
499 | unsigned int i; | 568 | unsigned int i; |
@@ -501,7 +570,7 @@ void sync_buffer(int cpu) | |||
501 | unsigned long available; | 570 | unsigned long available; |
502 | 571 | ||
503 | mutex_lock(&buffer_mutex); | 572 | mutex_lock(&buffer_mutex); |
504 | 573 | ||
505 | add_cpu_switch(cpu); | 574 | add_cpu_switch(cpu); |
506 | 575 | ||
507 | /* Remember, only we can modify tail_pos */ | 576 | /* Remember, only we can modify tail_pos */ |
@@ -509,8 +578,8 @@ void sync_buffer(int cpu) | |||
509 | available = get_slots(cpu_buf); | 578 | available = get_slots(cpu_buf); |
510 | 579 | ||
511 | for (i = 0; i < available; ++i) { | 580 | for (i = 0; i < available; ++i) { |
512 | struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos]; | 581 | struct op_sample *s = &cpu_buf->buffer[cpu_buf->tail_pos]; |
513 | 582 | ||
514 | if (is_code(s->eip)) { | 583 | if (is_code(s->eip)) { |
515 | if (s->event <= CPU_IS_KERNEL) { | 584 | if (s->event <= CPU_IS_KERNEL) { |
516 | /* kernel/userspace switch */ | 585 | /* kernel/userspace switch */ |
@@ -521,8 +590,18 @@ void sync_buffer(int cpu) | |||
521 | } else if (s->event == CPU_TRACE_BEGIN) { | 590 | } else if (s->event == CPU_TRACE_BEGIN) { |
522 | state = sb_bt_start; | 591 | state = sb_bt_start; |
523 | add_trace_begin(); | 592 | add_trace_begin(); |
593 | #ifdef CONFIG_OPROFILE_IBS | ||
594 | } else if (s->event == IBS_FETCH_BEGIN) { | ||
595 | state = sb_bt_start; | ||
596 | add_ibs_begin(cpu_buf, | ||
597 | IBS_FETCH_CODE, in_kernel, mm); | ||
598 | } else if (s->event == IBS_OP_BEGIN) { | ||
599 | state = sb_bt_start; | ||
600 | add_ibs_begin(cpu_buf, | ||
601 | IBS_OP_CODE, in_kernel, mm); | ||
602 | #endif | ||
524 | } else { | 603 | } else { |
525 | struct mm_struct * oldmm = mm; | 604 | struct mm_struct *oldmm = mm; |
526 | 605 | ||
527 | /* userspace context switch */ | 606 | /* userspace context switch */ |
528 | new = (struct task_struct *)s->event; | 607 | new = (struct task_struct *)s->event; |
@@ -533,13 +612,11 @@ void sync_buffer(int cpu) | |||
533 | cookie = get_exec_dcookie(mm); | 612 | cookie = get_exec_dcookie(mm); |
534 | add_user_ctx_switch(new, cookie); | 613 | add_user_ctx_switch(new, cookie); |
535 | } | 614 | } |
536 | } else { | 615 | } else if (state >= sb_bt_start && |
537 | if (state >= sb_bt_start && | 616 | !add_sample(mm, s, in_kernel)) { |
538 | !add_sample(mm, s, in_kernel)) { | 617 | if (state == sb_bt_start) { |
539 | if (state == sb_bt_start) { | 618 | state = sb_bt_ignore; |
540 | state = sb_bt_ignore; | 619 | atomic_inc(&oprofile_stats.bt_lost_no_mapping); |
541 | atomic_inc(&oprofile_stats.bt_lost_no_mapping); | ||
542 | } | ||
543 | } | 620 | } |
544 | } | 621 | } |
545 | 622 | ||
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 7ba78e6d210e..e1bd5a937f6c 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * @remark Read the file COPYING | 5 | * @remark Read the file COPYING |
6 | * | 6 | * |
7 | * @author John Levon <levon@movementarian.org> | 7 | * @author John Levon <levon@movementarian.org> |
8 | * @author Barry Kasindorf <barry.kasindorf@amd.com> | ||
8 | * | 9 | * |
9 | * Each CPU has a local buffer that stores PC value/event | 10 | * Each CPU has a local buffer that stores PC value/event |
10 | * pairs. We also log context switches when we notice them. | 11 | * pairs. We also log context switches when we notice them. |
@@ -209,7 +210,7 @@ static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc, | |||
209 | return 1; | 210 | return 1; |
210 | } | 211 | } |
211 | 212 | ||
212 | static int oprofile_begin_trace(struct oprofile_cpu_buffer * cpu_buf) | 213 | static int oprofile_begin_trace(struct oprofile_cpu_buffer *cpu_buf) |
213 | { | 214 | { |
214 | if (nr_available_slots(cpu_buf) < 4) { | 215 | if (nr_available_slots(cpu_buf) < 4) { |
215 | cpu_buf->sample_lost_overflow++; | 216 | cpu_buf->sample_lost_overflow++; |
@@ -254,6 +255,75 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) | |||
254 | oprofile_add_ext_sample(pc, regs, event, is_kernel); | 255 | oprofile_add_ext_sample(pc, regs, event, is_kernel); |
255 | } | 256 | } |
256 | 257 | ||
258 | #ifdef CONFIG_OPROFILE_IBS | ||
259 | |||
260 | #define MAX_IBS_SAMPLE_SIZE 14 | ||
261 | static int log_ibs_sample(struct oprofile_cpu_buffer *cpu_buf, | ||
262 | unsigned long pc, int is_kernel, unsigned int *ibs, int ibs_code) | ||
263 | { | ||
264 | struct task_struct *task; | ||
265 | |||
266 | cpu_buf->sample_received++; | ||
267 | |||
268 | if (nr_available_slots(cpu_buf) < MAX_IBS_SAMPLE_SIZE) { | ||
269 | cpu_buf->sample_lost_overflow++; | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | is_kernel = !!is_kernel; | ||
274 | |||
275 | /* notice a switch from user->kernel or vice versa */ | ||
276 | if (cpu_buf->last_is_kernel != is_kernel) { | ||
277 | cpu_buf->last_is_kernel = is_kernel; | ||
278 | add_code(cpu_buf, is_kernel); | ||
279 | } | ||
280 | |||
281 | /* notice a task switch */ | ||
282 | if (!is_kernel) { | ||
283 | task = current; | ||
284 | |||
285 | if (cpu_buf->last_task != task) { | ||
286 | cpu_buf->last_task = task; | ||
287 | add_code(cpu_buf, (unsigned long)task); | ||
288 | } | ||
289 | } | ||
290 | |||
291 | add_code(cpu_buf, ibs_code); | ||
292 | add_sample(cpu_buf, ibs[0], ibs[1]); | ||
293 | add_sample(cpu_buf, ibs[2], ibs[3]); | ||
294 | add_sample(cpu_buf, ibs[4], ibs[5]); | ||
295 | |||
296 | if (ibs_code == IBS_OP_BEGIN) { | ||
297 | add_sample(cpu_buf, ibs[6], ibs[7]); | ||
298 | add_sample(cpu_buf, ibs[8], ibs[9]); | ||
299 | add_sample(cpu_buf, ibs[10], ibs[11]); | ||
300 | } | ||
301 | |||
302 | return 1; | ||
303 | } | ||
304 | |||
305 | void oprofile_add_ibs_sample(struct pt_regs *const regs, | ||
306 | unsigned int * const ibs_sample, u8 code) | ||
307 | { | ||
308 | int is_kernel = !user_mode(regs); | ||
309 | unsigned long pc = profile_pc(regs); | ||
310 | |||
311 | struct oprofile_cpu_buffer *cpu_buf = | ||
312 | &per_cpu(cpu_buffer, smp_processor_id()); | ||
313 | |||
314 | if (!backtrace_depth) { | ||
315 | log_ibs_sample(cpu_buf, pc, is_kernel, ibs_sample, code); | ||
316 | return; | ||
317 | } | ||
318 | |||
319 | /* if log_sample() fails we can't backtrace since we lost the source | ||
320 | * of this event */ | ||
321 | if (log_ibs_sample(cpu_buf, pc, is_kernel, ibs_sample, code)) | ||
322 | oprofile_ops.backtrace(regs, backtrace_depth); | ||
323 | } | ||
324 | |||
325 | #endif | ||
326 | |||
257 | void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event) | 327 | void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event) |
258 | { | 328 | { |
259 | struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); | 329 | struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(cpu_buffer); |
@@ -296,7 +366,7 @@ static void wq_sync_buffer(struct work_struct *work) | |||
296 | struct oprofile_cpu_buffer * b = | 366 | struct oprofile_cpu_buffer * b = |
297 | container_of(work, struct oprofile_cpu_buffer, work.work); | 367 | container_of(work, struct oprofile_cpu_buffer, work.work); |
298 | if (b->cpu != smp_processor_id()) { | 368 | if (b->cpu != smp_processor_id()) { |
299 | printk("WQ on CPU%d, prefer CPU%d\n", | 369 | printk(KERN_DEBUG "WQ on CPU%d, prefer CPU%d\n", |
300 | smp_processor_id(), b->cpu); | 370 | smp_processor_id(), b->cpu); |
301 | } | 371 | } |
302 | sync_buffer(b->cpu); | 372 | sync_buffer(b->cpu); |
diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index c3e366b52261..9c44d004da69 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h | |||
@@ -55,5 +55,7 @@ void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf); | |||
55 | /* transient events for the CPU buffer -> event buffer */ | 55 | /* transient events for the CPU buffer -> event buffer */ |
56 | #define CPU_IS_KERNEL 1 | 56 | #define CPU_IS_KERNEL 1 |
57 | #define CPU_TRACE_BEGIN 2 | 57 | #define CPU_TRACE_BEGIN 2 |
58 | #define IBS_FETCH_BEGIN 3 | ||
59 | #define IBS_OP_BEGIN 4 | ||
58 | 60 | ||
59 | #endif /* OPROFILE_CPU_BUFFER_H */ | 61 | #endif /* OPROFILE_CPU_BUFFER_H */ |
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index d18e6d2e0b49..40759c33477d 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c | |||
@@ -418,25 +418,22 @@ fs3270_open(struct inode *inode, struct file *filp) | |||
418 | { | 418 | { |
419 | struct fs3270 *fp; | 419 | struct fs3270 *fp; |
420 | struct idal_buffer *ib; | 420 | struct idal_buffer *ib; |
421 | int minor, rc; | 421 | int minor, rc = 0; |
422 | 422 | ||
423 | if (imajor(filp->f_path.dentry->d_inode) != IBM_FS3270_MAJOR) | 423 | if (imajor(filp->f_path.dentry->d_inode) != IBM_FS3270_MAJOR) |
424 | return -ENODEV; | 424 | return -ENODEV; |
425 | lock_kernel(); | ||
426 | minor = iminor(filp->f_path.dentry->d_inode); | 425 | minor = iminor(filp->f_path.dentry->d_inode); |
427 | /* Check for minor 0 multiplexer. */ | 426 | /* Check for minor 0 multiplexer. */ |
428 | if (minor == 0) { | 427 | if (minor == 0) { |
429 | struct tty_struct *tty; | 428 | struct tty_struct *tty = get_current_tty(); |
430 | mutex_lock(&tty_mutex); | ||
431 | tty = get_current_tty(); | ||
432 | if (!tty || tty->driver->major != IBM_TTY3270_MAJOR) { | 429 | if (!tty || tty->driver->major != IBM_TTY3270_MAJOR) { |
433 | mutex_unlock(&tty_mutex); | 430 | tty_kref_put(tty); |
434 | rc = -ENODEV; | 431 | return -ENODEV; |
435 | goto out; | ||
436 | } | 432 | } |
437 | minor = tty->index + RAW3270_FIRSTMINOR; | 433 | minor = tty->index + RAW3270_FIRSTMINOR; |
438 | mutex_unlock(&tty_mutex); | 434 | tty_kref_put(tty); |
439 | } | 435 | } |
436 | lock_kernel(); | ||
440 | /* Check if some other program is already using fullscreen mode. */ | 437 | /* Check if some other program is already using fullscreen mode. */ |
441 | fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor); | 438 | fp = (struct fs3270 *) raw3270_find_view(&fs3270_fn, minor); |
442 | if (!IS_ERR(fp)) { | 439 | if (!IS_ERR(fp)) { |
@@ -478,7 +475,7 @@ fs3270_open(struct inode *inode, struct file *filp) | |||
478 | filp->private_data = fp; | 475 | filp->private_data = fp; |
479 | out: | 476 | out: |
480 | unlock_kernel(); | 477 | unlock_kernel(); |
481 | return 0; | 478 | return rc; |
482 | } | 479 | } |
483 | 480 | ||
484 | /* | 481 | /* |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 9ccc563d8730..d4104a3bbe87 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -44,6 +44,10 @@ | |||
44 | 44 | ||
45 | #include "8250.h" | 45 | #include "8250.h" |
46 | 46 | ||
47 | #ifdef CONFIG_SPARC | ||
48 | #include "suncore.h" | ||
49 | #endif | ||
50 | |||
47 | /* | 51 | /* |
48 | * Configuration: | 52 | * Configuration: |
49 | * share_irqs - whether we pass IRQF_SHARED to request_irq(). This option | 53 | * share_irqs - whether we pass IRQF_SHARED to request_irq(). This option |
@@ -53,6 +57,13 @@ static unsigned int share_irqs = SERIAL8250_SHARE_IRQS; | |||
53 | 57 | ||
54 | static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS; | 58 | static unsigned int nr_uarts = CONFIG_SERIAL_8250_RUNTIME_UARTS; |
55 | 59 | ||
60 | static struct uart_driver serial8250_reg; | ||
61 | |||
62 | static int serial_index(struct uart_port *port) | ||
63 | { | ||
64 | return (serial8250_reg.minor - 64) + port->line; | ||
65 | } | ||
66 | |||
56 | /* | 67 | /* |
57 | * Debugging. | 68 | * Debugging. |
58 | */ | 69 | */ |
@@ -536,7 +547,7 @@ static unsigned int serial_icr_read(struct uart_8250_port *up, int offset) | |||
536 | /* | 547 | /* |
537 | * FIFO support. | 548 | * FIFO support. |
538 | */ | 549 | */ |
539 | static inline void serial8250_clear_fifos(struct uart_8250_port *p) | 550 | static void serial8250_clear_fifos(struct uart_8250_port *p) |
540 | { | 551 | { |
541 | if (p->capabilities & UART_CAP_FIFO) { | 552 | if (p->capabilities & UART_CAP_FIFO) { |
542 | serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO); | 553 | serial_outp(p, UART_FCR, UART_FCR_ENABLE_FIFO); |
@@ -551,7 +562,7 @@ static inline void serial8250_clear_fifos(struct uart_8250_port *p) | |||
551 | * capability" bit enabled. Note that on XR16C850s, we need to | 562 | * capability" bit enabled. Note that on XR16C850s, we need to |
552 | * reset LCR to write to IER. | 563 | * reset LCR to write to IER. |
553 | */ | 564 | */ |
554 | static inline void serial8250_set_sleep(struct uart_8250_port *p, int sleep) | 565 | static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) |
555 | { | 566 | { |
556 | if (p->capabilities & UART_CAP_SLEEP) { | 567 | if (p->capabilities & UART_CAP_SLEEP) { |
557 | if (p->capabilities & UART_CAP_EFR) { | 568 | if (p->capabilities & UART_CAP_EFR) { |
@@ -993,7 +1004,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) | |||
993 | return; | 1004 | return; |
994 | 1005 | ||
995 | DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%p): ", | 1006 | DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04x, 0x%p): ", |
996 | up->port.line, up->port.iobase, up->port.membase); | 1007 | serial_index(&up->port), up->port.iobase, up->port.membase); |
997 | 1008 | ||
998 | /* | 1009 | /* |
999 | * We really do need global IRQs disabled here - we're going to | 1010 | * We really do need global IRQs disabled here - we're going to |
@@ -1128,8 +1139,8 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) | |||
1128 | if (up->capabilities != uart_config[up->port.type].flags) { | 1139 | if (up->capabilities != uart_config[up->port.type].flags) { |
1129 | printk(KERN_WARNING | 1140 | printk(KERN_WARNING |
1130 | "ttyS%d: detected caps %08x should be %08x\n", | 1141 | "ttyS%d: detected caps %08x should be %08x\n", |
1131 | up->port.line, up->capabilities, | 1142 | serial_index(&up->port), up->capabilities, |
1132 | uart_config[up->port.type].flags); | 1143 | uart_config[up->port.type].flags); |
1133 | } | 1144 | } |
1134 | 1145 | ||
1135 | up->port.fifosize = uart_config[up->port.type].fifo_size; | 1146 | up->port.fifosize = uart_config[up->port.type].fifo_size; |
@@ -1424,8 +1435,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up) | |||
1424 | /* | 1435 | /* |
1425 | * This handles the interrupt from one port. | 1436 | * This handles the interrupt from one port. |
1426 | */ | 1437 | */ |
1427 | static inline void | 1438 | static void serial8250_handle_port(struct uart_8250_port *up) |
1428 | serial8250_handle_port(struct uart_8250_port *up) | ||
1429 | { | 1439 | { |
1430 | unsigned int status; | 1440 | unsigned int status; |
1431 | unsigned long flags; | 1441 | unsigned long flags; |
@@ -1719,7 +1729,7 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state) | |||
1719 | /* | 1729 | /* |
1720 | * Wait for transmitter & holding register to empty | 1730 | * Wait for transmitter & holding register to empty |
1721 | */ | 1731 | */ |
1722 | static inline void wait_for_xmitr(struct uart_8250_port *up, int bits) | 1732 | static void wait_for_xmitr(struct uart_8250_port *up, int bits) |
1723 | { | 1733 | { |
1724 | unsigned int status, tmout = 10000; | 1734 | unsigned int status, tmout = 10000; |
1725 | 1735 | ||
@@ -1854,7 +1864,8 @@ static int serial8250_startup(struct uart_port *port) | |||
1854 | */ | 1864 | */ |
1855 | if (!(up->port.flags & UPF_BUGGY_UART) && | 1865 | if (!(up->port.flags & UPF_BUGGY_UART) && |
1856 | (serial_inp(up, UART_LSR) == 0xff)) { | 1866 | (serial_inp(up, UART_LSR) == 0xff)) { |
1857 | printk("ttyS%d: LSR safety check engaged!\n", up->port.line); | 1867 | printk(KERN_INFO "ttyS%d: LSR safety check engaged!\n", |
1868 | serial_index(&up->port)); | ||
1858 | return -ENODEV; | 1869 | return -ENODEV; |
1859 | } | 1870 | } |
1860 | 1871 | ||
@@ -1909,7 +1920,8 @@ static int serial8250_startup(struct uart_port *port) | |||
1909 | */ | 1920 | */ |
1910 | if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) { | 1921 | if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) { |
1911 | up->bugs |= UART_BUG_THRE; | 1922 | up->bugs |= UART_BUG_THRE; |
1912 | pr_debug("ttyS%d - using backup timer\n", port->line); | 1923 | pr_debug("ttyS%d - using backup timer\n", |
1924 | serial_index(port)); | ||
1913 | } | 1925 | } |
1914 | } | 1926 | } |
1915 | 1927 | ||
@@ -1969,7 +1981,7 @@ static int serial8250_startup(struct uart_port *port) | |||
1969 | if (!(up->bugs & UART_BUG_TXEN)) { | 1981 | if (!(up->bugs & UART_BUG_TXEN)) { |
1970 | up->bugs |= UART_BUG_TXEN; | 1982 | up->bugs |= UART_BUG_TXEN; |
1971 | pr_debug("ttyS%d - enabling bad tx status workarounds\n", | 1983 | pr_debug("ttyS%d - enabling bad tx status workarounds\n", |
1972 | port->line); | 1984 | serial_index(port)); |
1973 | } | 1985 | } |
1974 | } else { | 1986 | } else { |
1975 | up->bugs &= ~UART_BUG_TXEN; | 1987 | up->bugs &= ~UART_BUG_TXEN; |
@@ -2630,7 +2642,6 @@ static int serial8250_console_early_setup(void) | |||
2630 | return serial8250_find_port_for_earlycon(); | 2642 | return serial8250_find_port_for_earlycon(); |
2631 | } | 2643 | } |
2632 | 2644 | ||
2633 | static struct uart_driver serial8250_reg; | ||
2634 | static struct console serial8250_console = { | 2645 | static struct console serial8250_console = { |
2635 | .name = "ttyS", | 2646 | .name = "ttyS", |
2636 | .write = serial8250_console_write, | 2647 | .write = serial8250_console_write, |
@@ -2677,7 +2688,6 @@ static struct uart_driver serial8250_reg = { | |||
2677 | .dev_name = "ttyS", | 2688 | .dev_name = "ttyS", |
2678 | .major = TTY_MAJOR, | 2689 | .major = TTY_MAJOR, |
2679 | .minor = 64, | 2690 | .minor = 64, |
2680 | .nr = UART_NR, | ||
2681 | .cons = SERIAL8250_CONSOLE, | 2691 | .cons = SERIAL8250_CONSOLE, |
2682 | }; | 2692 | }; |
2683 | 2693 | ||
@@ -2959,10 +2969,12 @@ static int __init serial8250_init(void) | |||
2959 | "%d ports, IRQ sharing %sabled\n", nr_uarts, | 2969 | "%d ports, IRQ sharing %sabled\n", nr_uarts, |
2960 | share_irqs ? "en" : "dis"); | 2970 | share_irqs ? "en" : "dis"); |
2961 | 2971 | ||
2962 | for (i = 0; i < NR_IRQS; i++) | 2972 | #ifdef CONFIG_SPARC |
2963 | spin_lock_init(&irq_lists[i].lock); | 2973 | ret = sunserial_register_minors(&serial8250_reg, UART_NR); |
2964 | 2974 | #else | |
2975 | serial8250_reg.nr = UART_NR; | ||
2965 | ret = uart_register_driver(&serial8250_reg); | 2976 | ret = uart_register_driver(&serial8250_reg); |
2977 | #endif | ||
2966 | if (ret) | 2978 | if (ret) |
2967 | goto out; | 2979 | goto out; |
2968 | 2980 | ||
@@ -2987,7 +2999,11 @@ static int __init serial8250_init(void) | |||
2987 | put_dev: | 2999 | put_dev: |
2988 | platform_device_put(serial8250_isa_devs); | 3000 | platform_device_put(serial8250_isa_devs); |
2989 | unreg_uart_drv: | 3001 | unreg_uart_drv: |
3002 | #ifdef CONFIG_SPARC | ||
3003 | sunserial_unregister_minors(&serial8250_reg, UART_NR); | ||
3004 | #else | ||
2990 | uart_unregister_driver(&serial8250_reg); | 3005 | uart_unregister_driver(&serial8250_reg); |
3006 | #endif | ||
2991 | out: | 3007 | out: |
2992 | return ret; | 3008 | return ret; |
2993 | } | 3009 | } |
@@ -3006,7 +3022,11 @@ static void __exit serial8250_exit(void) | |||
3006 | platform_driver_unregister(&serial8250_isa_driver); | 3022 | platform_driver_unregister(&serial8250_isa_driver); |
3007 | platform_device_unregister(isa_dev); | 3023 | platform_device_unregister(isa_dev); |
3008 | 3024 | ||
3025 | #ifdef CONFIG_SPARC | ||
3026 | sunserial_unregister_minors(&serial8250_reg, UART_NR); | ||
3027 | #else | ||
3009 | uart_unregister_driver(&serial8250_reg); | 3028 | uart_unregister_driver(&serial8250_reg); |
3029 | #endif | ||
3010 | } | 3030 | } |
3011 | 3031 | ||
3012 | module_init(serial8250_init); | 3032 | module_init(serial8250_init); |
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index c2f23933155b..c014ffb110e9 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c | |||
@@ -2041,9 +2041,9 @@ static int pciserial_resume_one(struct pci_dev *dev) | |||
2041 | * The device may have been disabled. Re-enable it. | 2041 | * The device may have been disabled. Re-enable it. |
2042 | */ | 2042 | */ |
2043 | err = pci_enable_device(dev); | 2043 | err = pci_enable_device(dev); |
2044 | /* FIXME: We cannot simply error out here */ | ||
2044 | if (err) | 2045 | if (err) |
2045 | return err; | 2046 | printk(KERN_ERR "pciserial: Unable to re-enable ports, trying to continue.\n"); |
2046 | |||
2047 | pciserial_resume_ports(priv); | 2047 | pciserial_resume_ports(priv); |
2048 | } | 2048 | } |
2049 | return 0; | 2049 | return 0; |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 77cb34270fc1..31786b3b0a68 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -9,7 +9,6 @@ menu "Serial drivers" | |||
9 | # The new 8250/16550 serial drivers | 9 | # The new 8250/16550 serial drivers |
10 | config SERIAL_8250 | 10 | config SERIAL_8250 |
11 | tristate "8250/16550 and compatible serial support" | 11 | tristate "8250/16550 and compatible serial support" |
12 | depends on (BROKEN || !SPARC) | ||
13 | select SERIAL_CORE | 12 | select SERIAL_CORE |
14 | ---help--- | 13 | ---help--- |
15 | This selects whether you want to include the driver for the standard | 14 | This selects whether you want to include the driver for the standard |
@@ -994,24 +993,12 @@ config SERIAL_68328_RTS_CTS | |||
994 | bool "Support RTS/CTS on 68328 serial port" | 993 | bool "Support RTS/CTS on 68328 serial port" |
995 | depends on SERIAL_68328 | 994 | depends on SERIAL_68328 |
996 | 995 | ||
997 | config SERIAL_COLDFIRE | ||
998 | bool "ColdFire serial support (DEPRECATED)" | ||
999 | depends on COLDFIRE | ||
1000 | help | ||
1001 | This driver supports the built-in serial ports of the Motorola ColdFire | ||
1002 | family of CPUs. | ||
1003 | This driver is deprecated because it supports only the old interface | ||
1004 | for serial drivers and features like magic keys are not working. | ||
1005 | Please switch to the new style driver because this driver will be | ||
1006 | removed soon. | ||
1007 | |||
1008 | config SERIAL_MCF | 996 | config SERIAL_MCF |
1009 | bool "Coldfire serial support (new style driver)" | 997 | bool "Coldfire serial support" |
1010 | depends on COLDFIRE | 998 | depends on COLDFIRE |
1011 | select SERIAL_CORE | 999 | select SERIAL_CORE |
1012 | help | 1000 | help |
1013 | This new serial driver supports the Freescale Coldfire serial ports | 1001 | This serial driver supports the Freescale Coldfire serial ports. |
1014 | using the new serial driver subsystem. | ||
1015 | 1002 | ||
1016 | config SERIAL_MCF_BAUDRATE | 1003 | config SERIAL_MCF_BAUDRATE |
1017 | int "Default baudrate for Coldfire serial ports" | 1004 | int "Default baudrate for Coldfire serial ports" |
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 7e7383e890d8..0c17c8ddb19d 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile | |||
@@ -4,6 +4,16 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_SERIAL_CORE) += serial_core.o | 5 | obj-$(CONFIG_SERIAL_CORE) += serial_core.o |
6 | obj-$(CONFIG_SERIAL_21285) += 21285.o | 6 | obj-$(CONFIG_SERIAL_21285) += 21285.o |
7 | |||
8 | # These Sparc drivers have to appear before others such as 8250 | ||
9 | # which share ttySx minor node space. Otherwise console device | ||
10 | # names change and other unplesantries. | ||
11 | obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o | ||
12 | obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o | ||
13 | obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o | ||
14 | obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o | ||
15 | obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o | ||
16 | |||
7 | obj-$(CONFIG_SERIAL_8250) += 8250.o | 17 | obj-$(CONFIG_SERIAL_8250) += 8250.o |
8 | obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o | 18 | obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o |
9 | obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o | 19 | obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o |
@@ -31,16 +41,10 @@ obj-$(CONFIG_SERIAL_S3C2400) += s3c2400.o | |||
31 | obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o | 41 | obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o |
32 | obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o | 42 | obj-$(CONFIG_SERIAL_S3C2412) += s3c2412.o |
33 | obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o | 43 | obj-$(CONFIG_SERIAL_S3C2440) += s3c2440.o |
34 | obj-$(CONFIG_SERIAL_SUNCORE) += suncore.o | ||
35 | obj-$(CONFIG_SERIAL_SUNHV) += sunhv.o | ||
36 | obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o | ||
37 | obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o | 44 | obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o |
38 | obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o | ||
39 | obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o | ||
40 | obj-$(CONFIG_SERIAL_MUX) += mux.o | 45 | obj-$(CONFIG_SERIAL_MUX) += mux.o |
41 | obj-$(CONFIG_SERIAL_68328) += 68328serial.o | 46 | obj-$(CONFIG_SERIAL_68328) += 68328serial.o |
42 | obj-$(CONFIG_SERIAL_68360) += 68360serial.o | 47 | obj-$(CONFIG_SERIAL_68360) += 68360serial.o |
43 | obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o | ||
44 | obj-$(CONFIG_SERIAL_MCF) += mcf.o | 48 | obj-$(CONFIG_SERIAL_MCF) += mcf.o |
45 | obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o | 49 | obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o |
46 | obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o | 50 | obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o |
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 4a0d30bed9f1..569f0e2476c6 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Blackfin On-Chip Serial Driver | 2 | * Blackfin On-Chip Serial Driver |
3 | * | 3 | * |
4 | * Copyright 2006-2007 Analog Devices Inc. | 4 | * Copyright 2006-2008 Analog Devices Inc. |
5 | * | 5 | * |
6 | * Enter bugs at http://blackfin.uclinux.org/ | 6 | * Enter bugs at http://blackfin.uclinux.org/ |
7 | * | 7 | * |
@@ -42,6 +42,9 @@ | |||
42 | #define BFIN_SERIAL_MAJOR 204 | 42 | #define BFIN_SERIAL_MAJOR 204 |
43 | #define BFIN_SERIAL_MINOR 64 | 43 | #define BFIN_SERIAL_MINOR 64 |
44 | 44 | ||
45 | static struct bfin_serial_port bfin_serial_ports[BFIN_UART_NR_PORTS]; | ||
46 | static int nr_active_ports = ARRAY_SIZE(bfin_serial_resource); | ||
47 | |||
45 | /* | 48 | /* |
46 | * Setup for console. Argument comes from the menuconfig | 49 | * Setup for console. Argument comes from the menuconfig |
47 | */ | 50 | */ |
@@ -126,13 +129,13 @@ static int kgdb_entry_state; | |||
126 | void kgdb_put_debug_char(int chr) | 129 | void kgdb_put_debug_char(int chr) |
127 | { | 130 | { |
128 | struct bfin_serial_port *uart; | 131 | struct bfin_serial_port *uart; |
129 | 132 | ||
130 | if (CONFIG_KGDB_UART_PORT < 0 | 133 | if (CONFIG_KGDB_UART_PORT < 0 |
131 | || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS) | 134 | || CONFIG_KGDB_UART_PORT >= BFIN_UART_NR_PORTS) |
132 | uart = &bfin_serial_ports[0]; | 135 | uart = &bfin_serial_ports[0]; |
133 | else | 136 | else |
134 | uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; | 137 | uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; |
135 | 138 | ||
136 | while (!(UART_GET_LSR(uart) & THRE)) { | 139 | while (!(UART_GET_LSR(uart) & THRE)) { |
137 | SSYNC(); | 140 | SSYNC(); |
138 | } | 141 | } |
@@ -152,7 +155,7 @@ int kgdb_get_debug_char(void) | |||
152 | uart = &bfin_serial_ports[0]; | 155 | uart = &bfin_serial_ports[0]; |
153 | else | 156 | else |
154 | uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; | 157 | uart = &bfin_serial_ports[CONFIG_KGDB_UART_PORT]; |
155 | 158 | ||
156 | while(!(UART_GET_LSR(uart) & DR)) { | 159 | while(!(UART_GET_LSR(uart) & DR)) { |
157 | SSYNC(); | 160 | SSYNC(); |
158 | } | 161 | } |
@@ -298,7 +301,11 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart) | |||
298 | bfin_serial_mctrl_check(uart); | 301 | bfin_serial_mctrl_check(uart); |
299 | 302 | ||
300 | if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { | 303 | if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { |
301 | bfin_serial_stop_tx(&uart->port); | 304 | #ifdef CONFIG_BF54x |
305 | /* Clear TFI bit */ | ||
306 | UART_PUT_LSR(uart, TFI); | ||
307 | #endif | ||
308 | UART_CLEAR_IER(uart, ETBEI); | ||
302 | return; | 309 | return; |
303 | } | 310 | } |
304 | 311 | ||
@@ -317,9 +324,6 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart) | |||
317 | 324 | ||
318 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 325 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
319 | uart_write_wakeup(&uart->port); | 326 | uart_write_wakeup(&uart->port); |
320 | |||
321 | if (uart_circ_empty(xmit)) | ||
322 | bfin_serial_stop_tx(&uart->port); | ||
323 | } | 327 | } |
324 | 328 | ||
325 | static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id) | 329 | static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id) |
@@ -645,6 +649,42 @@ static int bfin_serial_startup(struct uart_port *port) | |||
645 | free_irq(uart->port.irq, uart); | 649 | free_irq(uart->port.irq, uart); |
646 | return -EBUSY; | 650 | return -EBUSY; |
647 | } | 651 | } |
652 | |||
653 | # ifdef CONFIG_BF54x | ||
654 | { | ||
655 | unsigned uart_dma_ch_rx, uart_dma_ch_tx; | ||
656 | |||
657 | switch (uart->port.irq) { | ||
658 | case IRQ_UART3_RX: | ||
659 | uart_dma_ch_rx = CH_UART3_RX; | ||
660 | uart_dma_ch_tx = CH_UART3_TX; | ||
661 | break; | ||
662 | case IRQ_UART2_RX: | ||
663 | uart_dma_ch_rx = CH_UART2_RX; | ||
664 | uart_dma_ch_tx = CH_UART2_TX; | ||
665 | break; | ||
666 | default: | ||
667 | uart_dma_ch_rx = uart_dma_ch_tx = 0; | ||
668 | break; | ||
669 | }; | ||
670 | |||
671 | if (uart_dma_ch_rx && | ||
672 | request_dma(uart_dma_ch_rx, "BFIN_UART_RX") < 0) { | ||
673 | printk(KERN_NOTICE"Fail to attach UART interrupt\n"); | ||
674 | free_irq(uart->port.irq, uart); | ||
675 | free_irq(uart->port.irq + 1, uart); | ||
676 | return -EBUSY; | ||
677 | } | ||
678 | if (uart_dma_ch_tx && | ||
679 | request_dma(uart_dma_ch_tx, "BFIN_UART_TX") < 0) { | ||
680 | printk(KERN_NOTICE "Fail to attach UART interrupt\n"); | ||
681 | free_dma(uart_dma_ch_rx); | ||
682 | free_irq(uart->port.irq, uart); | ||
683 | free_irq(uart->port.irq + 1, uart); | ||
684 | return -EBUSY; | ||
685 | } | ||
686 | } | ||
687 | # endif | ||
648 | #endif | 688 | #endif |
649 | UART_SET_IER(uart, ERBFI); | 689 | UART_SET_IER(uart, ERBFI); |
650 | return 0; | 690 | return 0; |
@@ -662,6 +702,20 @@ static void bfin_serial_shutdown(struct uart_port *port) | |||
662 | del_timer(&(uart->rx_dma_timer)); | 702 | del_timer(&(uart->rx_dma_timer)); |
663 | dma_free_coherent(NULL, PAGE_SIZE, uart->rx_dma_buf.buf, 0); | 703 | dma_free_coherent(NULL, PAGE_SIZE, uart->rx_dma_buf.buf, 0); |
664 | #else | 704 | #else |
705 | #ifdef CONFIG_BF54x | ||
706 | switch (uart->port.irq) { | ||
707 | case IRQ_UART3_RX: | ||
708 | free_dma(CH_UART3_RX); | ||
709 | free_dma(CH_UART3_TX); | ||
710 | break; | ||
711 | case IRQ_UART2_RX: | ||
712 | free_dma(CH_UART2_RX); | ||
713 | free_dma(CH_UART2_TX); | ||
714 | break; | ||
715 | default: | ||
716 | break; | ||
717 | }; | ||
718 | #endif | ||
665 | #ifdef CONFIG_KGDB_UART | 719 | #ifdef CONFIG_KGDB_UART |
666 | if (uart->port.line != CONFIG_KGDB_UART_PORT) | 720 | if (uart->port.line != CONFIG_KGDB_UART_PORT) |
667 | #endif | 721 | #endif |
@@ -757,6 +811,9 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios, | |||
757 | val |= UCEN; | 811 | val |= UCEN; |
758 | UART_PUT_GCTL(uart, val); | 812 | UART_PUT_GCTL(uart, val); |
759 | 813 | ||
814 | /* Port speed changed, update the per-port timeout. */ | ||
815 | uart_update_timeout(port, termios->c_cflag, baud); | ||
816 | |||
760 | spin_unlock_irqrestore(&uart->port.lock, flags); | 817 | spin_unlock_irqrestore(&uart->port.lock, flags); |
761 | } | 818 | } |
762 | 819 | ||
@@ -859,8 +916,9 @@ static void __init bfin_serial_init_ports(void) | |||
859 | return; | 916 | return; |
860 | first = 0; | 917 | first = 0; |
861 | 918 | ||
862 | for (i = 0; i < nr_ports; i++) { | 919 | for (i = 0; i < nr_active_ports; i++) { |
863 | bfin_serial_ports[i].port.uartclk = get_sclk(); | 920 | bfin_serial_ports[i].port.uartclk = get_sclk(); |
921 | bfin_serial_ports[i].port.fifosize = BFIN_UART_TX_FIFO_SIZE; | ||
864 | bfin_serial_ports[i].port.ops = &bfin_serial_pops; | 922 | bfin_serial_ports[i].port.ops = &bfin_serial_pops; |
865 | bfin_serial_ports[i].port.line = i; | 923 | bfin_serial_ports[i].port.line = i; |
866 | bfin_serial_ports[i].port.iotype = UPIO_MEM; | 924 | bfin_serial_ports[i].port.iotype = UPIO_MEM; |
@@ -961,7 +1019,7 @@ bfin_serial_console_setup(struct console *co, char *options) | |||
961 | * if so, search for the first available port that does have | 1019 | * if so, search for the first available port that does have |
962 | * console support. | 1020 | * console support. |
963 | */ | 1021 | */ |
964 | if (co->index == -1 || co->index >= nr_ports) | 1022 | if (co->index == -1 || co->index >= nr_active_ports) |
965 | co->index = 0; | 1023 | co->index = 0; |
966 | uart = &bfin_serial_ports[co->index]; | 1024 | uart = &bfin_serial_ports[co->index]; |
967 | 1025 | ||
@@ -1056,7 +1114,7 @@ static __init void early_serial_write(struct console *con, const char *s, | |||
1056 | } | 1114 | } |
1057 | } | 1115 | } |
1058 | 1116 | ||
1059 | static struct __init console bfin_early_serial_console = { | 1117 | static struct __initdata console bfin_early_serial_console = { |
1060 | .name = "early_BFuart", | 1118 | .name = "early_BFuart", |
1061 | .write = early_serial_write, | 1119 | .write = early_serial_write, |
1062 | .device = uart_console_device, | 1120 | .device = uart_console_device, |
@@ -1072,7 +1130,7 @@ struct console __init *bfin_earlyserial_init(unsigned int port, | |||
1072 | struct bfin_serial_port *uart; | 1130 | struct bfin_serial_port *uart; |
1073 | struct ktermios t; | 1131 | struct ktermios t; |
1074 | 1132 | ||
1075 | if (port == -1 || port >= nr_ports) | 1133 | if (port == -1 || port >= nr_active_ports) |
1076 | port = 0; | 1134 | port = 0; |
1077 | bfin_serial_init_ports(); | 1135 | bfin_serial_init_ports(); |
1078 | bfin_early_serial_console.index = port; | 1136 | bfin_early_serial_console.index = port; |
@@ -1100,20 +1158,26 @@ static struct uart_driver bfin_serial_reg = { | |||
1100 | 1158 | ||
1101 | static int bfin_serial_suspend(struct platform_device *dev, pm_message_t state) | 1159 | static int bfin_serial_suspend(struct platform_device *dev, pm_message_t state) |
1102 | { | 1160 | { |
1103 | struct bfin_serial_port *uart = platform_get_drvdata(dev); | 1161 | int i; |
1104 | 1162 | ||
1105 | if (uart) | 1163 | for (i = 0; i < nr_active_ports; i++) { |
1106 | uart_suspend_port(&bfin_serial_reg, &uart->port); | 1164 | if (bfin_serial_ports[i].port.dev != &dev->dev) |
1165 | continue; | ||
1166 | uart_suspend_port(&bfin_serial_reg, &bfin_serial_ports[i].port); | ||
1167 | } | ||
1107 | 1168 | ||
1108 | return 0; | 1169 | return 0; |
1109 | } | 1170 | } |
1110 | 1171 | ||
1111 | static int bfin_serial_resume(struct platform_device *dev) | 1172 | static int bfin_serial_resume(struct platform_device *dev) |
1112 | { | 1173 | { |
1113 | struct bfin_serial_port *uart = platform_get_drvdata(dev); | 1174 | int i; |
1114 | 1175 | ||
1115 | if (uart) | 1176 | for (i = 0; i < nr_active_ports; i++) { |
1116 | uart_resume_port(&bfin_serial_reg, &uart->port); | 1177 | if (bfin_serial_ports[i].port.dev != &dev->dev) |
1178 | continue; | ||
1179 | uart_resume_port(&bfin_serial_reg, &bfin_serial_ports[i].port); | ||
1180 | } | ||
1117 | 1181 | ||
1118 | return 0; | 1182 | return 0; |
1119 | } | 1183 | } |
@@ -1128,32 +1192,31 @@ static int bfin_serial_probe(struct platform_device *dev) | |||
1128 | break; | 1192 | break; |
1129 | 1193 | ||
1130 | if (i < dev->num_resources) { | 1194 | if (i < dev->num_resources) { |
1131 | for (i = 0; i < nr_ports; i++, res++) { | 1195 | for (i = 0; i < nr_active_ports; i++, res++) { |
1132 | if (bfin_serial_ports[i].port.mapbase != res->start) | 1196 | if (bfin_serial_ports[i].port.mapbase != res->start) |
1133 | continue; | 1197 | continue; |
1134 | bfin_serial_ports[i].port.dev = &dev->dev; | 1198 | bfin_serial_ports[i].port.dev = &dev->dev; |
1135 | uart_add_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port); | 1199 | uart_add_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port); |
1136 | platform_set_drvdata(dev, &bfin_serial_ports[i]); | ||
1137 | } | 1200 | } |
1138 | } | 1201 | } |
1139 | 1202 | ||
1140 | return 0; | 1203 | return 0; |
1141 | } | 1204 | } |
1142 | 1205 | ||
1143 | static int bfin_serial_remove(struct platform_device *pdev) | 1206 | static int bfin_serial_remove(struct platform_device *dev) |
1144 | { | 1207 | { |
1145 | struct bfin_serial_port *uart = platform_get_drvdata(pdev); | 1208 | int i; |
1146 | |||
1147 | 1209 | ||
1210 | for (i = 0; i < nr_active_ports; i++) { | ||
1211 | if (bfin_serial_ports[i].port.dev != &dev->dev) | ||
1212 | continue; | ||
1213 | uart_remove_one_port(&bfin_serial_reg, &bfin_serial_ports[i].port); | ||
1214 | bfin_serial_ports[i].port.dev = NULL; | ||
1148 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS | 1215 | #ifdef CONFIG_SERIAL_BFIN_CTSRTS |
1149 | gpio_free(uart->cts_pin); | 1216 | gpio_free(bfin_serial_ports[i].cts_pin); |
1150 | gpio_free(uart->rts_pin); | 1217 | gpio_free(bfin_serial_ports[i].rts_pin); |
1151 | #endif | 1218 | #endif |
1152 | 1219 | } | |
1153 | platform_set_drvdata(pdev, NULL); | ||
1154 | |||
1155 | if (uart) | ||
1156 | uart_remove_one_port(&bfin_serial_reg, &uart->port); | ||
1157 | 1220 | ||
1158 | return 0; | 1221 | return 0; |
1159 | } | 1222 | } |
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index bf94a770bb44..211c21797ce0 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c | |||
@@ -457,7 +457,6 @@ static struct e100_serial rs_table[] = { | |||
457 | #define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial)) | 457 | #define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial)) |
458 | 458 | ||
459 | static struct ktermios *serial_termios[NR_PORTS]; | 459 | static struct ktermios *serial_termios[NR_PORTS]; |
460 | static struct ktermios *serial_termios_locked[NR_PORTS]; | ||
461 | #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER | 460 | #ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER |
462 | static struct fast_timer fast_timers[NR_PORTS]; | 461 | static struct fast_timer fast_timers[NR_PORTS]; |
463 | #endif | 462 | #endif |
@@ -4419,6 +4418,7 @@ rs_init(void) | |||
4419 | rs485_pa_bit)) { | 4418 | rs485_pa_bit)) { |
4420 | printk(KERN_CRIT "ETRAX100LX serial: Could not allocate " | 4419 | printk(KERN_CRIT "ETRAX100LX serial: Could not allocate " |
4421 | "RS485 pin\n"); | 4420 | "RS485 pin\n"); |
4421 | put_tty_driver(driver); | ||
4422 | return -EBUSY; | 4422 | return -EBUSY; |
4423 | } | 4423 | } |
4424 | #endif | 4424 | #endif |
@@ -4427,6 +4427,7 @@ rs_init(void) | |||
4427 | rs485_port_g_bit)) { | 4427 | rs485_port_g_bit)) { |
4428 | printk(KERN_CRIT "ETRAX100LX serial: Could not allocate " | 4428 | printk(KERN_CRIT "ETRAX100LX serial: Could not allocate " |
4429 | "RS485 pin\n"); | 4429 | "RS485 pin\n"); |
4430 | put_tty_driver(driver); | ||
4430 | return -EBUSY; | 4431 | return -EBUSY; |
4431 | } | 4432 | } |
4432 | #endif | 4433 | #endif |
@@ -4446,8 +4447,6 @@ rs_init(void) | |||
4446 | driver->init_termios.c_ispeed = 115200; | 4447 | driver->init_termios.c_ispeed = 115200; |
4447 | driver->init_termios.c_ospeed = 115200; | 4448 | driver->init_termios.c_ospeed = 115200; |
4448 | driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | 4449 | driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; |
4449 | driver->termios = serial_termios; | ||
4450 | driver->termios_locked = serial_termios_locked; | ||
4451 | 4450 | ||
4452 | tty_set_operations(driver, &rs_ops); | 4451 | tty_set_operations(driver, &rs_ops); |
4453 | serial_driver = driver; | 4452 | serial_driver = driver; |
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c deleted file mode 100644 index fbe3835f6b77..000000000000 --- a/drivers/serial/mcfserial.c +++ /dev/null | |||
@@ -1,1965 +0,0 @@ | |||
1 | #warning This driver is deprecated. Check Kconfig for details. | ||
2 | /* | ||
3 | * mcfserial.c -- serial driver for ColdFire internal UARTS. | ||
4 | * | ||
5 | * Copyright (C) 1999-2003 Greg Ungerer <gerg@snapgear.com> | ||
6 | * Copyright (c) 2000-2001 Lineo, Inc. <www.lineo.com> | ||
7 | * Copyright (C) 2001-2002 SnapGear Inc. <www.snapgear.com> | ||
8 | * | ||
9 | * Based on code from 68332serial.c which was: | ||
10 | * | ||
11 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | ||
12 | * Copyright (C) 1998 TSHG | ||
13 | * Copyright (c) 1999 Rt-Control Inc. <jeff@uclinux.org> | ||
14 | * | ||
15 | * Changes: | ||
16 | * 08/07/2003 Daniele Bellucci <bellucda@tiscali.it> | ||
17 | * some cleanups in mcfrs_write. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/signal.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/timer.h> | ||
26 | #include <linux/wait.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/tty.h> | ||
29 | #include <linux/tty_flip.h> | ||
30 | #include <linux/string.h> | ||
31 | #include <linux/fcntl.h> | ||
32 | #include <linux/mm.h> | ||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/serial.h> | ||
35 | #include <linux/serialP.h> | ||
36 | #include <linux/console.h> | ||
37 | #include <linux/init.h> | ||
38 | #include <linux/bitops.h> | ||
39 | #include <linux/delay.h> | ||
40 | |||
41 | #include <asm/io.h> | ||
42 | #include <asm/irq.h> | ||
43 | #include <asm/system.h> | ||
44 | #include <asm/delay.h> | ||
45 | #include <asm/coldfire.h> | ||
46 | #include <asm/mcfsim.h> | ||
47 | #include <asm/mcfuart.h> | ||
48 | #include <asm/nettel.h> | ||
49 | #include <asm/uaccess.h> | ||
50 | #include "mcfserial.h" | ||
51 | |||
52 | struct timer_list mcfrs_timer_struct; | ||
53 | |||
54 | /* | ||
55 | * Default console baud rate, we use this as the default | ||
56 | * for all ports so init can just open /dev/console and | ||
57 | * keep going. Perhaps one day the cflag settings for the | ||
58 | * console can be used instead. | ||
59 | */ | ||
60 | #if defined(CONFIG_HW_FEITH) | ||
61 | #define CONSOLE_BAUD_RATE 38400 | ||
62 | #define DEFAULT_CBAUD B38400 | ||
63 | #elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || \ | ||
64 | defined(CONFIG_M5329EVB) || defined(CONFIG_GILBARCO) | ||
65 | #define CONSOLE_BAUD_RATE 115200 | ||
66 | #define DEFAULT_CBAUD B115200 | ||
67 | #elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \ | ||
68 | defined(CONFIG_senTec) || defined(CONFIG_SNEHA) || defined(CONFIG_AVNET) | ||
69 | #define CONSOLE_BAUD_RATE 19200 | ||
70 | #define DEFAULT_CBAUD B19200 | ||
71 | #endif | ||
72 | |||
73 | #ifndef CONSOLE_BAUD_RATE | ||
74 | #define CONSOLE_BAUD_RATE 9600 | ||
75 | #define DEFAULT_CBAUD B9600 | ||
76 | #endif | ||
77 | |||
78 | int mcfrs_console_inited = 0; | ||
79 | int mcfrs_console_port = -1; | ||
80 | int mcfrs_console_baud = CONSOLE_BAUD_RATE; | ||
81 | int mcfrs_console_cbaud = DEFAULT_CBAUD; | ||
82 | |||
83 | /* | ||
84 | * Driver data structures. | ||
85 | */ | ||
86 | static struct tty_driver *mcfrs_serial_driver; | ||
87 | |||
88 | /* number of characters left in xmit buffer before we ask for more */ | ||
89 | #define WAKEUP_CHARS 256 | ||
90 | |||
91 | /* Debugging... | ||
92 | */ | ||
93 | #undef SERIAL_DEBUG_OPEN | ||
94 | #undef SERIAL_DEBUG_FLOW | ||
95 | |||
96 | #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ | ||
97 | defined(CONFIG_M520x) || defined(CONFIG_M532x) | ||
98 | #define IRQBASE (MCFINT_VECBASE+MCFINT_UART0) | ||
99 | #else | ||
100 | #define IRQBASE 73 | ||
101 | #endif | ||
102 | |||
103 | /* | ||
104 | * Configuration table, UARTs to look for at startup. | ||
105 | */ | ||
106 | static struct mcf_serial mcfrs_table[] = { | ||
107 | { /* ttyS0 */ | ||
108 | .magic = 0, | ||
109 | .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE1), | ||
110 | .irq = IRQBASE, | ||
111 | .flags = ASYNC_BOOT_AUTOCONF, | ||
112 | }, | ||
113 | #ifdef MCFUART_BASE2 | ||
114 | { /* ttyS1 */ | ||
115 | .magic = 0, | ||
116 | .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE2), | ||
117 | .irq = IRQBASE+1, | ||
118 | .flags = ASYNC_BOOT_AUTOCONF, | ||
119 | }, | ||
120 | #endif | ||
121 | #ifdef MCFUART_BASE3 | ||
122 | { /* ttyS2 */ | ||
123 | .magic = 0, | ||
124 | .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE3), | ||
125 | .irq = IRQBASE+2, | ||
126 | .flags = ASYNC_BOOT_AUTOCONF, | ||
127 | }, | ||
128 | #endif | ||
129 | #ifdef MCFUART_BASE4 | ||
130 | { /* ttyS3 */ | ||
131 | .magic = 0, | ||
132 | .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE4), | ||
133 | .irq = IRQBASE+3, | ||
134 | .flags = ASYNC_BOOT_AUTOCONF, | ||
135 | }, | ||
136 | #endif | ||
137 | }; | ||
138 | |||
139 | |||
140 | #define NR_PORTS (sizeof(mcfrs_table) / sizeof(struct mcf_serial)) | ||
141 | |||
142 | /* | ||
143 | * This is used to figure out the divisor speeds and the timeouts. | ||
144 | */ | ||
145 | static int mcfrs_baud_table[] = { | ||
146 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, | ||
147 | 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 | ||
148 | }; | ||
149 | #define MCFRS_BAUD_TABLE_SIZE \ | ||
150 | (sizeof(mcfrs_baud_table)/sizeof(mcfrs_baud_table[0])) | ||
151 | |||
152 | |||
153 | #ifdef CONFIG_MAGIC_SYSRQ | ||
154 | /* | ||
155 | * Magic system request keys. Used for debugging... | ||
156 | */ | ||
157 | extern int magic_sysrq_key(int ch); | ||
158 | #endif | ||
159 | |||
160 | |||
161 | /* | ||
162 | * Forware declarations... | ||
163 | */ | ||
164 | static void mcfrs_change_speed(struct mcf_serial *info); | ||
165 | static void mcfrs_wait_until_sent(struct tty_struct *tty, int timeout); | ||
166 | |||
167 | |||
168 | static inline int serial_paranoia_check(struct mcf_serial *info, | ||
169 | char *name, const char *routine) | ||
170 | { | ||
171 | #ifdef SERIAL_PARANOIA_CHECK | ||
172 | static const char badmagic[] = | ||
173 | "MCFRS(warning): bad magic number for serial struct %s in %s\n"; | ||
174 | static const char badinfo[] = | ||
175 | "MCFRS(warning): null mcf_serial for %s in %s\n"; | ||
176 | |||
177 | if (!info) { | ||
178 | printk(badinfo, name, routine); | ||
179 | return 1; | ||
180 | } | ||
181 | if (info->magic != SERIAL_MAGIC) { | ||
182 | printk(badmagic, name, routine); | ||
183 | return 1; | ||
184 | } | ||
185 | #endif | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * Sets or clears DTR and RTS on the requested line. | ||
191 | */ | ||
192 | static void mcfrs_setsignals(struct mcf_serial *info, int dtr, int rts) | ||
193 | { | ||
194 | volatile unsigned char *uartp; | ||
195 | unsigned long flags; | ||
196 | |||
197 | #if 0 | ||
198 | printk("%s(%d): mcfrs_setsignals(info=%x,dtr=%d,rts=%d)\n", | ||
199 | __FILE__, __LINE__, info, dtr, rts); | ||
200 | #endif | ||
201 | |||
202 | local_irq_save(flags); | ||
203 | if (dtr >= 0) { | ||
204 | #ifdef MCFPP_DTR0 | ||
205 | if (info->line) | ||
206 | mcf_setppdata(MCFPP_DTR1, (dtr ? 0 : MCFPP_DTR1)); | ||
207 | else | ||
208 | mcf_setppdata(MCFPP_DTR0, (dtr ? 0 : MCFPP_DTR0)); | ||
209 | #endif | ||
210 | } | ||
211 | if (rts >= 0) { | ||
212 | uartp = info->addr; | ||
213 | if (rts) { | ||
214 | info->sigs |= TIOCM_RTS; | ||
215 | uartp[MCFUART_UOP1] = MCFUART_UOP_RTS; | ||
216 | } else { | ||
217 | info->sigs &= ~TIOCM_RTS; | ||
218 | uartp[MCFUART_UOP0] = MCFUART_UOP_RTS; | ||
219 | } | ||
220 | } | ||
221 | local_irq_restore(flags); | ||
222 | return; | ||
223 | } | ||
224 | |||
225 | /* | ||
226 | * Gets values of serial signals. | ||
227 | */ | ||
228 | static int mcfrs_getsignals(struct mcf_serial *info) | ||
229 | { | ||
230 | volatile unsigned char *uartp; | ||
231 | unsigned long flags; | ||
232 | int sigs; | ||
233 | #if defined(CONFIG_NETtel) && defined(CONFIG_M5307) | ||
234 | unsigned short ppdata; | ||
235 | #endif | ||
236 | |||
237 | #if 0 | ||
238 | printk("%s(%d): mcfrs_getsignals(info=%x)\n", __FILE__, __LINE__); | ||
239 | #endif | ||
240 | |||
241 | local_irq_save(flags); | ||
242 | uartp = info->addr; | ||
243 | sigs = (uartp[MCFUART_UIPR] & MCFUART_UIPR_CTS) ? 0 : TIOCM_CTS; | ||
244 | sigs |= (info->sigs & TIOCM_RTS); | ||
245 | |||
246 | #ifdef MCFPP_DCD0 | ||
247 | { | ||
248 | unsigned int ppdata; | ||
249 | ppdata = mcf_getppdata(); | ||
250 | if (info->line == 0) { | ||
251 | sigs |= (ppdata & MCFPP_DCD0) ? 0 : TIOCM_CD; | ||
252 | sigs |= (ppdata & MCFPP_DTR0) ? 0 : TIOCM_DTR; | ||
253 | } else if (info->line == 1) { | ||
254 | sigs |= (ppdata & MCFPP_DCD1) ? 0 : TIOCM_CD; | ||
255 | sigs |= (ppdata & MCFPP_DTR1) ? 0 : TIOCM_DTR; | ||
256 | } | ||
257 | } | ||
258 | #endif | ||
259 | |||
260 | local_irq_restore(flags); | ||
261 | return(sigs); | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * ------------------------------------------------------------ | ||
266 | * mcfrs_stop() and mcfrs_start() | ||
267 | * | ||
268 | * This routines are called before setting or resetting tty->stopped. | ||
269 | * They enable or disable transmitter interrupts, as necessary. | ||
270 | * ------------------------------------------------------------ | ||
271 | */ | ||
272 | static void mcfrs_stop(struct tty_struct *tty) | ||
273 | { | ||
274 | volatile unsigned char *uartp; | ||
275 | struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; | ||
276 | unsigned long flags; | ||
277 | |||
278 | if (serial_paranoia_check(info, tty->name, "mcfrs_stop")) | ||
279 | return; | ||
280 | |||
281 | local_irq_save(flags); | ||
282 | uartp = info->addr; | ||
283 | info->imr &= ~MCFUART_UIR_TXREADY; | ||
284 | uartp[MCFUART_UIMR] = info->imr; | ||
285 | local_irq_restore(flags); | ||
286 | } | ||
287 | |||
288 | static void mcfrs_start(struct tty_struct *tty) | ||
289 | { | ||
290 | volatile unsigned char *uartp; | ||
291 | struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; | ||
292 | unsigned long flags; | ||
293 | |||
294 | if (serial_paranoia_check(info, tty->name, "mcfrs_start")) | ||
295 | return; | ||
296 | |||
297 | local_irq_save(flags); | ||
298 | if (info->xmit_cnt && info->xmit_buf) { | ||
299 | uartp = info->addr; | ||
300 | info->imr |= MCFUART_UIR_TXREADY; | ||
301 | uartp[MCFUART_UIMR] = info->imr; | ||
302 | } | ||
303 | local_irq_restore(flags); | ||
304 | } | ||
305 | |||
306 | /* | ||
307 | * ---------------------------------------------------------------------- | ||
308 | * | ||
309 | * Here starts the interrupt handling routines. All of the following | ||
310 | * subroutines are declared as inline and are folded into | ||
311 | * mcfrs_interrupt(). They were separated out for readability's sake. | ||
312 | * | ||
313 | * Note: mcfrs_interrupt() is a "fast" interrupt, which means that it | ||
314 | * runs with interrupts turned off. People who may want to modify | ||
315 | * mcfrs_interrupt() should try to keep the interrupt handler as fast as | ||
316 | * possible. After you are done making modifications, it is not a bad | ||
317 | * idea to do: | ||
318 | * | ||
319 | * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c | ||
320 | * | ||
321 | * and look at the resulting assemble code in serial.s. | ||
322 | * | ||
323 | * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 | ||
324 | * ----------------------------------------------------------------------- | ||
325 | */ | ||
326 | |||
327 | static inline void receive_chars(struct mcf_serial *info) | ||
328 | { | ||
329 | volatile unsigned char *uartp; | ||
330 | struct tty_struct *tty = info->port.tty; | ||
331 | unsigned char status, ch, flag; | ||
332 | |||
333 | if (!tty) | ||
334 | return; | ||
335 | |||
336 | uartp = info->addr; | ||
337 | |||
338 | while ((status = uartp[MCFUART_USR]) & MCFUART_USR_RXREADY) { | ||
339 | ch = uartp[MCFUART_URB]; | ||
340 | info->stats.rx++; | ||
341 | |||
342 | #ifdef CONFIG_MAGIC_SYSRQ | ||
343 | if (mcfrs_console_inited && (info->line == mcfrs_console_port)) { | ||
344 | if (magic_sysrq_key(ch)) | ||
345 | continue; | ||
346 | } | ||
347 | #endif | ||
348 | |||
349 | flag = TTY_NORMAL; | ||
350 | if (status & MCFUART_USR_RXERR) { | ||
351 | uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR; | ||
352 | if (status & MCFUART_USR_RXBREAK) { | ||
353 | info->stats.rxbreak++; | ||
354 | flag = TTY_BREAK; | ||
355 | } else if (status & MCFUART_USR_RXPARITY) { | ||
356 | info->stats.rxparity++; | ||
357 | flag = TTY_PARITY; | ||
358 | } else if (status & MCFUART_USR_RXOVERRUN) { | ||
359 | info->stats.rxoverrun++; | ||
360 | flag = TTY_OVERRUN; | ||
361 | } else if (status & MCFUART_USR_RXFRAMING) { | ||
362 | info->stats.rxframing++; | ||
363 | flag = TTY_FRAME; | ||
364 | } | ||
365 | } | ||
366 | tty_insert_flip_char(tty, ch, flag); | ||
367 | } | ||
368 | tty_schedule_flip(tty); | ||
369 | return; | ||
370 | } | ||
371 | |||
372 | static inline void transmit_chars(struct mcf_serial *info) | ||
373 | { | ||
374 | volatile unsigned char *uartp; | ||
375 | |||
376 | uartp = info->addr; | ||
377 | |||
378 | if (info->x_char) { | ||
379 | /* Send special char - probably flow control */ | ||
380 | uartp[MCFUART_UTB] = info->x_char; | ||
381 | info->x_char = 0; | ||
382 | info->stats.tx++; | ||
383 | } | ||
384 | |||
385 | if ((info->xmit_cnt <= 0) || info->port.tty->stopped) { | ||
386 | info->imr &= ~MCFUART_UIR_TXREADY; | ||
387 | uartp[MCFUART_UIMR] = info->imr; | ||
388 | return; | ||
389 | } | ||
390 | |||
391 | while (uartp[MCFUART_USR] & MCFUART_USR_TXREADY) { | ||
392 | uartp[MCFUART_UTB] = info->xmit_buf[info->xmit_tail++]; | ||
393 | info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); | ||
394 | info->stats.tx++; | ||
395 | if (--info->xmit_cnt <= 0) | ||
396 | break; | ||
397 | } | ||
398 | |||
399 | if (info->xmit_cnt < WAKEUP_CHARS) | ||
400 | schedule_work(&info->tqueue); | ||
401 | return; | ||
402 | } | ||
403 | |||
404 | /* | ||
405 | * This is the serial driver's generic interrupt routine | ||
406 | */ | ||
407 | irqreturn_t mcfrs_interrupt(int irq, void *dev_id) | ||
408 | { | ||
409 | struct mcf_serial *info; | ||
410 | unsigned char isr; | ||
411 | |||
412 | info = &mcfrs_table[(irq - IRQBASE)]; | ||
413 | isr = info->addr[MCFUART_UISR] & info->imr; | ||
414 | |||
415 | if (isr & MCFUART_UIR_RXREADY) | ||
416 | receive_chars(info); | ||
417 | if (isr & MCFUART_UIR_TXREADY) | ||
418 | transmit_chars(info); | ||
419 | return IRQ_HANDLED; | ||
420 | } | ||
421 | |||
422 | /* | ||
423 | * ------------------------------------------------------------------- | ||
424 | * Here ends the serial interrupt routines. | ||
425 | * ------------------------------------------------------------------- | ||
426 | */ | ||
427 | |||
428 | static void mcfrs_offintr(struct work_struct *work) | ||
429 | { | ||
430 | struct mcf_serial *info = container_of(work, struct mcf_serial, tqueue); | ||
431 | struct tty_struct *tty = info->port.tty; | ||
432 | |||
433 | if (tty) | ||
434 | tty_wakeup(tty); | ||
435 | } | ||
436 | |||
437 | |||
438 | /* | ||
439 | * Change of state on a DCD line. | ||
440 | */ | ||
441 | void mcfrs_modem_change(struct mcf_serial *info, int dcd) | ||
442 | { | ||
443 | if (info->count == 0) | ||
444 | return; | ||
445 | |||
446 | if (info->flags & ASYNC_CHECK_CD) { | ||
447 | if (dcd) | ||
448 | wake_up_interruptible(&info->open_wait); | ||
449 | else | ||
450 | schedule_work(&info->tqueue_hangup); | ||
451 | } | ||
452 | } | ||
453 | |||
454 | |||
455 | #ifdef MCFPP_DCD0 | ||
456 | |||
457 | unsigned short mcfrs_ppstatus; | ||
458 | |||
459 | /* | ||
460 | * This subroutine is called when the RS_TIMER goes off. It is used | ||
461 | * to monitor the state of the DCD lines - since they have no edge | ||
462 | * sensors and interrupt generators. | ||
463 | */ | ||
464 | static void mcfrs_timer(void) | ||
465 | { | ||
466 | unsigned int ppstatus, dcdval, i; | ||
467 | |||
468 | ppstatus = mcf_getppdata() & (MCFPP_DCD0 | MCFPP_DCD1); | ||
469 | |||
470 | if (ppstatus != mcfrs_ppstatus) { | ||
471 | for (i = 0; (i < 2); i++) { | ||
472 | dcdval = (i ? MCFPP_DCD1 : MCFPP_DCD0); | ||
473 | if ((ppstatus & dcdval) != (mcfrs_ppstatus & dcdval)) { | ||
474 | mcfrs_modem_change(&mcfrs_table[i], | ||
475 | ((ppstatus & dcdval) ? 0 : 1)); | ||
476 | } | ||
477 | } | ||
478 | } | ||
479 | mcfrs_ppstatus = ppstatus; | ||
480 | |||
481 | /* Re-arm timer */ | ||
482 | mcfrs_timer_struct.expires = jiffies + HZ/25; | ||
483 | add_timer(&mcfrs_timer_struct); | ||
484 | } | ||
485 | |||
486 | #endif /* MCFPP_DCD0 */ | ||
487 | |||
488 | |||
489 | /* | ||
490 | * This routine is called from the scheduler tqueue when the interrupt | ||
491 | * routine has signalled that a hangup has occurred. The path of | ||
492 | * hangup processing is: | ||
493 | * | ||
494 | * serial interrupt routine -> (scheduler tqueue) -> | ||
495 | * do_serial_hangup() -> tty->hangup() -> mcfrs_hangup() | ||
496 | * | ||
497 | */ | ||
498 | static void do_serial_hangup(struct work_struct *work) | ||
499 | { | ||
500 | struct mcf_serial *info = container_of(work, struct mcf_serial, tqueue_hangup); | ||
501 | struct tty_struct *tty = info->port.tty; | ||
502 | |||
503 | if (tty) | ||
504 | tty_hangup(tty); | ||
505 | } | ||
506 | |||
507 | static int startup(struct mcf_serial * info) | ||
508 | { | ||
509 | volatile unsigned char *uartp; | ||
510 | unsigned long flags; | ||
511 | |||
512 | if (info->flags & ASYNC_INITIALIZED) | ||
513 | return 0; | ||
514 | |||
515 | if (!info->xmit_buf) { | ||
516 | info->xmit_buf = (unsigned char *) __get_free_page(GFP_KERNEL); | ||
517 | if (!info->xmit_buf) | ||
518 | return -ENOMEM; | ||
519 | } | ||
520 | |||
521 | local_irq_save(flags); | ||
522 | |||
523 | #ifdef SERIAL_DEBUG_OPEN | ||
524 | printk("starting up ttyS%d (irq %d)...\n", info->line, info->irq); | ||
525 | #endif | ||
526 | |||
527 | /* | ||
528 | * Reset UART, get it into known state... | ||
529 | */ | ||
530 | uartp = info->addr; | ||
531 | uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ | ||
532 | uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ | ||
533 | mcfrs_setsignals(info, 1, 1); | ||
534 | |||
535 | if (info->port.tty) | ||
536 | clear_bit(TTY_IO_ERROR, &info->port.tty->flags); | ||
537 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
538 | |||
539 | /* | ||
540 | * and set the speed of the serial port | ||
541 | */ | ||
542 | mcfrs_change_speed(info); | ||
543 | |||
544 | /* | ||
545 | * Lastly enable the UART transmitter and receiver, and | ||
546 | * interrupt enables. | ||
547 | */ | ||
548 | info->imr = MCFUART_UIR_RXREADY; | ||
549 | uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE; | ||
550 | uartp[MCFUART_UIMR] = info->imr; | ||
551 | |||
552 | info->flags |= ASYNC_INITIALIZED; | ||
553 | local_irq_restore(flags); | ||
554 | return 0; | ||
555 | } | ||
556 | |||
557 | /* | ||
558 | * This routine will shutdown a serial port; interrupts are disabled, and | ||
559 | * DTR is dropped if the hangup on close termio flag is on. | ||
560 | */ | ||
561 | static void shutdown(struct mcf_serial * info) | ||
562 | { | ||
563 | volatile unsigned char *uartp; | ||
564 | unsigned long flags; | ||
565 | |||
566 | if (!(info->flags & ASYNC_INITIALIZED)) | ||
567 | return; | ||
568 | |||
569 | #ifdef SERIAL_DEBUG_OPEN | ||
570 | printk("Shutting down serial port %d (irq %d)....\n", info->line, | ||
571 | info->irq); | ||
572 | #endif | ||
573 | |||
574 | local_irq_save(flags); | ||
575 | |||
576 | uartp = info->addr; | ||
577 | uartp[MCFUART_UIMR] = 0; /* mask all interrupts */ | ||
578 | uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ | ||
579 | uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ | ||
580 | |||
581 | if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) | ||
582 | mcfrs_setsignals(info, 0, 0); | ||
583 | |||
584 | if (info->xmit_buf) { | ||
585 | free_page((unsigned long) info->xmit_buf); | ||
586 | info->xmit_buf = 0; | ||
587 | } | ||
588 | |||
589 | if (info->port.tty) | ||
590 | set_bit(TTY_IO_ERROR, &info->port.tty->flags); | ||
591 | |||
592 | info->flags &= ~ASYNC_INITIALIZED; | ||
593 | local_irq_restore(flags); | ||
594 | } | ||
595 | |||
596 | |||
597 | /* | ||
598 | * This routine is called to set the UART divisor registers to match | ||
599 | * the specified baud rate for a serial port. | ||
600 | */ | ||
601 | static void mcfrs_change_speed(struct mcf_serial *info) | ||
602 | { | ||
603 | volatile unsigned char *uartp; | ||
604 | unsigned int baudclk, cflag; | ||
605 | unsigned long flags; | ||
606 | unsigned char mr1, mr2; | ||
607 | int i; | ||
608 | #ifdef CONFIG_M5272 | ||
609 | unsigned int fraction; | ||
610 | #endif | ||
611 | |||
612 | if (!info->port.tty || !info->port.tty->termios) | ||
613 | return; | ||
614 | cflag = info->port.tty->termios->c_cflag; | ||
615 | if (info->addr == 0) | ||
616 | return; | ||
617 | |||
618 | #if 0 | ||
619 | printk("%s(%d): mcfrs_change_speed()\n", __FILE__, __LINE__); | ||
620 | #endif | ||
621 | |||
622 | i = cflag & CBAUD; | ||
623 | if (i & CBAUDEX) { | ||
624 | i &= ~CBAUDEX; | ||
625 | if (i < 1 || i > 4) | ||
626 | info->port.tty->termios->c_cflag &= ~CBAUDEX; | ||
627 | else | ||
628 | i += 15; | ||
629 | } | ||
630 | if (i == 0) { | ||
631 | mcfrs_setsignals(info, 0, -1); | ||
632 | return; | ||
633 | } | ||
634 | |||
635 | /* compute the baudrate clock */ | ||
636 | #ifdef CONFIG_M5272 | ||
637 | /* | ||
638 | * For the MCF5272, also compute the baudrate fraction. | ||
639 | */ | ||
640 | baudclk = (MCF_BUSCLK / mcfrs_baud_table[i]) / 32; | ||
641 | fraction = MCF_BUSCLK - (baudclk * 32 * mcfrs_baud_table[i]); | ||
642 | fraction *= 16; | ||
643 | fraction /= (32 * mcfrs_baud_table[i]); | ||
644 | #else | ||
645 | baudclk = ((MCF_BUSCLK / mcfrs_baud_table[i]) + 16) / 32; | ||
646 | #endif | ||
647 | |||
648 | info->baud = mcfrs_baud_table[i]; | ||
649 | |||
650 | mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR; | ||
651 | mr2 = 0; | ||
652 | |||
653 | switch (cflag & CSIZE) { | ||
654 | case CS5: mr1 |= MCFUART_MR1_CS5; break; | ||
655 | case CS6: mr1 |= MCFUART_MR1_CS6; break; | ||
656 | case CS7: mr1 |= MCFUART_MR1_CS7; break; | ||
657 | case CS8: | ||
658 | default: mr1 |= MCFUART_MR1_CS8; break; | ||
659 | } | ||
660 | |||
661 | if (cflag & PARENB) { | ||
662 | if (cflag & CMSPAR) { | ||
663 | if (cflag & PARODD) | ||
664 | mr1 |= MCFUART_MR1_PARITYMARK; | ||
665 | else | ||
666 | mr1 |= MCFUART_MR1_PARITYSPACE; | ||
667 | } else { | ||
668 | if (cflag & PARODD) | ||
669 | mr1 |= MCFUART_MR1_PARITYODD; | ||
670 | else | ||
671 | mr1 |= MCFUART_MR1_PARITYEVEN; | ||
672 | } | ||
673 | } else { | ||
674 | mr1 |= MCFUART_MR1_PARITYNONE; | ||
675 | } | ||
676 | |||
677 | if (cflag & CSTOPB) | ||
678 | mr2 |= MCFUART_MR2_STOP2; | ||
679 | else | ||
680 | mr2 |= MCFUART_MR2_STOP1; | ||
681 | |||
682 | if (cflag & CRTSCTS) { | ||
683 | mr1 |= MCFUART_MR1_RXRTS; | ||
684 | mr2 |= MCFUART_MR2_TXCTS; | ||
685 | } | ||
686 | |||
687 | if (cflag & CLOCAL) | ||
688 | info->flags &= ~ASYNC_CHECK_CD; | ||
689 | else | ||
690 | info->flags |= ASYNC_CHECK_CD; | ||
691 | |||
692 | uartp = info->addr; | ||
693 | |||
694 | local_irq_save(flags); | ||
695 | #if 0 | ||
696 | printk("%s(%d): mr1=%x mr2=%x baudclk=%x\n", __FILE__, __LINE__, | ||
697 | mr1, mr2, baudclk); | ||
698 | #endif | ||
699 | /* | ||
700 | Note: pg 12-16 of MCF5206e User's Manual states that a | ||
701 | software reset should be performed prior to changing | ||
702 | UMR1,2, UCSR, UACR, bit 7 | ||
703 | */ | ||
704 | uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ | ||
705 | uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ | ||
706 | uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR; /* reset MR pointer */ | ||
707 | uartp[MCFUART_UMR] = mr1; | ||
708 | uartp[MCFUART_UMR] = mr2; | ||
709 | uartp[MCFUART_UBG1] = (baudclk & 0xff00) >> 8; /* set msb byte */ | ||
710 | uartp[MCFUART_UBG2] = (baudclk & 0xff); /* set lsb byte */ | ||
711 | #ifdef CONFIG_M5272 | ||
712 | uartp[MCFUART_UFPD] = (fraction & 0xf); /* set fraction */ | ||
713 | #endif | ||
714 | uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER; | ||
715 | uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE; | ||
716 | mcfrs_setsignals(info, 1, -1); | ||
717 | local_irq_restore(flags); | ||
718 | return; | ||
719 | } | ||
720 | |||
721 | static void mcfrs_flush_chars(struct tty_struct *tty) | ||
722 | { | ||
723 | volatile unsigned char *uartp; | ||
724 | struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; | ||
725 | unsigned long flags; | ||
726 | |||
727 | if (serial_paranoia_check(info, tty->name, "mcfrs_flush_chars")) | ||
728 | return; | ||
729 | |||
730 | uartp = (volatile unsigned char *) info->addr; | ||
731 | |||
732 | /* | ||
733 | * re-enable receiver interrupt | ||
734 | */ | ||
735 | local_irq_save(flags); | ||
736 | if ((!(info->imr & MCFUART_UIR_RXREADY)) && | ||
737 | (info->flags & ASYNC_INITIALIZED) ) { | ||
738 | info->imr |= MCFUART_UIR_RXREADY; | ||
739 | uartp[MCFUART_UIMR] = info->imr; | ||
740 | } | ||
741 | local_irq_restore(flags); | ||
742 | |||
743 | if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || | ||
744 | !info->xmit_buf) | ||
745 | return; | ||
746 | |||
747 | /* Enable transmitter */ | ||
748 | local_irq_save(flags); | ||
749 | info->imr |= MCFUART_UIR_TXREADY; | ||
750 | uartp[MCFUART_UIMR] = info->imr; | ||
751 | local_irq_restore(flags); | ||
752 | } | ||
753 | |||
754 | static int mcfrs_write(struct tty_struct * tty, | ||
755 | const unsigned char *buf, int count) | ||
756 | { | ||
757 | volatile unsigned char *uartp; | ||
758 | struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; | ||
759 | unsigned long flags; | ||
760 | int c, total = 0; | ||
761 | |||
762 | #if 0 | ||
763 | printk("%s(%d): mcfrs_write(tty=%x,buf=%x,count=%d)\n", | ||
764 | __FILE__, __LINE__, (int)tty, (int)buf, count); | ||
765 | #endif | ||
766 | |||
767 | if (serial_paranoia_check(info, tty->name, "mcfrs_write")) | ||
768 | return 0; | ||
769 | |||
770 | if (!tty || !info->xmit_buf) | ||
771 | return 0; | ||
772 | |||
773 | local_save_flags(flags); | ||
774 | while (1) { | ||
775 | local_irq_disable(); | ||
776 | c = min(count, (int) min(((int)SERIAL_XMIT_SIZE) - info->xmit_cnt - 1, | ||
777 | ((int)SERIAL_XMIT_SIZE) - info->xmit_head)); | ||
778 | local_irq_restore(flags); | ||
779 | |||
780 | if (c <= 0) | ||
781 | break; | ||
782 | |||
783 | memcpy(info->xmit_buf + info->xmit_head, buf, c); | ||
784 | |||
785 | local_irq_disable(); | ||
786 | info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); | ||
787 | info->xmit_cnt += c; | ||
788 | local_irq_restore(flags); | ||
789 | |||
790 | buf += c; | ||
791 | count -= c; | ||
792 | total += c; | ||
793 | } | ||
794 | |||
795 | local_irq_disable(); | ||
796 | uartp = info->addr; | ||
797 | info->imr |= MCFUART_UIR_TXREADY; | ||
798 | uartp[MCFUART_UIMR] = info->imr; | ||
799 | local_irq_restore(flags); | ||
800 | |||
801 | return total; | ||
802 | } | ||
803 | |||
804 | static int mcfrs_write_room(struct tty_struct *tty) | ||
805 | { | ||
806 | struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; | ||
807 | int ret; | ||
808 | |||
809 | if (serial_paranoia_check(info, tty->name, "mcfrs_write_room")) | ||
810 | return 0; | ||
811 | ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; | ||
812 | if (ret < 0) | ||
813 | ret = 0; | ||
814 | return ret; | ||
815 | } | ||
816 | |||
817 | static int mcfrs_chars_in_buffer(struct tty_struct *tty) | ||
818 | { | ||
819 | struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; | ||
820 | |||
821 | if (serial_paranoia_check(info, tty->name, "mcfrs_chars_in_buffer")) | ||
822 | return 0; | ||
823 | return info->xmit_cnt; | ||
824 | } | ||
825 | |||
826 | static void mcfrs_flush_buffer(struct tty_struct *tty) | ||
827 | { | ||
828 | struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; | ||
829 | unsigned long flags; | ||
830 | |||
831 | if (serial_paranoia_check(info, tty->name, "mcfrs_flush_buffer")) | ||
832 | return; | ||
833 | |||
834 | local_irq_save(flags); | ||
835 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
836 | local_irq_restore(flags); | ||
837 | |||
838 | tty_wakeup(tty); | ||
839 | } | ||
840 | |||
841 | /* | ||
842 | * ------------------------------------------------------------ | ||
843 | * mcfrs_throttle() | ||
844 | * | ||
845 | * This routine is called by the upper-layer tty layer to signal that | ||
846 | * incoming characters should be throttled. | ||
847 | * ------------------------------------------------------------ | ||
848 | */ | ||
849 | static void mcfrs_throttle(struct tty_struct * tty) | ||
850 | { | ||
851 | struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; | ||
852 | #ifdef SERIAL_DEBUG_THROTTLE | ||
853 | char buf[64]; | ||
854 | |||
855 | printk("throttle %s: %d....\n", tty_name(tty, buf), | ||
856 | tty->ldisc.chars_in_buffer(tty)); | ||
857 | #endif | ||
858 | |||
859 | if (serial_paranoia_check(info, tty->name, "mcfrs_throttle")) | ||
860 | return; | ||
861 | |||
862 | if (I_IXOFF(tty)) | ||
863 | info->x_char = STOP_CHAR(tty); | ||
864 | |||
865 | /* Turn off RTS line (do this atomic) */ | ||
866 | } | ||
867 | |||
868 | static void mcfrs_unthrottle(struct tty_struct * tty) | ||
869 | { | ||
870 | struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; | ||
871 | #ifdef SERIAL_DEBUG_THROTTLE | ||
872 | char buf[64]; | ||
873 | |||
874 | printk("unthrottle %s: %d....\n", tty_name(tty, buf), | ||
875 | tty->ldisc.chars_in_buffer(tty)); | ||
876 | #endif | ||
877 | |||
878 | if (serial_paranoia_check(info, tty->name, "mcfrs_unthrottle")) | ||
879 | return; | ||
880 | |||
881 | if (I_IXOFF(tty)) { | ||
882 | if (info->x_char) | ||
883 | info->x_char = 0; | ||
884 | else | ||
885 | info->x_char = START_CHAR(tty); | ||
886 | } | ||
887 | |||
888 | /* Assert RTS line (do this atomic) */ | ||
889 | } | ||
890 | |||
891 | /* | ||
892 | * ------------------------------------------------------------ | ||
893 | * mcfrs_ioctl() and friends | ||
894 | * ------------------------------------------------------------ | ||
895 | */ | ||
896 | |||
897 | static int get_serial_info(struct mcf_serial * info, | ||
898 | struct serial_struct * retinfo) | ||
899 | { | ||
900 | struct serial_struct tmp; | ||
901 | |||
902 | if (!retinfo) | ||
903 | return -EFAULT; | ||
904 | memset(&tmp, 0, sizeof(tmp)); | ||
905 | tmp.type = info->type; | ||
906 | tmp.line = info->line; | ||
907 | tmp.port = (unsigned int) info->addr; | ||
908 | tmp.irq = info->irq; | ||
909 | tmp.flags = info->flags; | ||
910 | tmp.baud_base = info->baud_base; | ||
911 | tmp.close_delay = info->close_delay; | ||
912 | tmp.closing_wait = info->closing_wait; | ||
913 | tmp.custom_divisor = info->custom_divisor; | ||
914 | return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0; | ||
915 | } | ||
916 | |||
917 | static int set_serial_info(struct mcf_serial * info, | ||
918 | struct serial_struct * new_info) | ||
919 | { | ||
920 | struct serial_struct new_serial; | ||
921 | struct mcf_serial old_info; | ||
922 | int retval = 0; | ||
923 | |||
924 | if (!new_info) | ||
925 | return -EFAULT; | ||
926 | if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) | ||
927 | return -EFAULT; | ||
928 | old_info = *info; | ||
929 | |||
930 | if (!capable(CAP_SYS_ADMIN)) { | ||
931 | if ((new_serial.baud_base != info->baud_base) || | ||
932 | (new_serial.type != info->type) || | ||
933 | (new_serial.close_delay != info->close_delay) || | ||
934 | ((new_serial.flags & ~ASYNC_USR_MASK) != | ||
935 | (info->flags & ~ASYNC_USR_MASK))) | ||
936 | return -EPERM; | ||
937 | info->flags = ((info->flags & ~ASYNC_USR_MASK) | | ||
938 | (new_serial.flags & ASYNC_USR_MASK)); | ||
939 | info->custom_divisor = new_serial.custom_divisor; | ||
940 | goto check_and_exit; | ||
941 | } | ||
942 | |||
943 | if (info->count > 1) | ||
944 | return -EBUSY; | ||
945 | |||
946 | /* | ||
947 | * OK, past this point, all the error checking has been done. | ||
948 | * At this point, we start making changes..... | ||
949 | */ | ||
950 | |||
951 | info->baud_base = new_serial.baud_base; | ||
952 | info->flags = ((info->flags & ~ASYNC_FLAGS) | | ||
953 | (new_serial.flags & ASYNC_FLAGS)); | ||
954 | info->type = new_serial.type; | ||
955 | info->close_delay = new_serial.close_delay; | ||
956 | info->closing_wait = new_serial.closing_wait; | ||
957 | |||
958 | check_and_exit: | ||
959 | retval = startup(info); | ||
960 | return retval; | ||
961 | } | ||
962 | |||
963 | /* | ||
964 | * get_lsr_info - get line status register info | ||
965 | * | ||
966 | * Purpose: Let user call ioctl() to get info when the UART physically | ||
967 | * is emptied. On bus types like RS485, the transmitter must | ||
968 | * release the bus after transmitting. This must be done when | ||
969 | * the transmit shift register is empty, not be done when the | ||
970 | * transmit holding register is empty. This functionality | ||
971 | * allows an RS485 driver to be written in user space. | ||
972 | */ | ||
973 | static int get_lsr_info(struct mcf_serial * info, unsigned int *value) | ||
974 | { | ||
975 | volatile unsigned char *uartp; | ||
976 | unsigned long flags; | ||
977 | unsigned char status; | ||
978 | |||
979 | local_irq_save(flags); | ||
980 | uartp = info->addr; | ||
981 | status = (uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY) ? TIOCSER_TEMT : 0; | ||
982 | local_irq_restore(flags); | ||
983 | |||
984 | return put_user(status,value); | ||
985 | } | ||
986 | |||
987 | /* | ||
988 | * This routine sends a break character out the serial port. | ||
989 | */ | ||
990 | static void send_break( struct mcf_serial * info, int duration) | ||
991 | { | ||
992 | volatile unsigned char *uartp; | ||
993 | unsigned long flags; | ||
994 | |||
995 | if (!info->addr) | ||
996 | return; | ||
997 | set_current_state(TASK_INTERRUPTIBLE); | ||
998 | uartp = info->addr; | ||
999 | |||
1000 | local_irq_save(flags); | ||
1001 | uartp[MCFUART_UCR] = MCFUART_UCR_CMDBREAKSTART; | ||
1002 | schedule_timeout(duration); | ||
1003 | uartp[MCFUART_UCR] = MCFUART_UCR_CMDBREAKSTOP; | ||
1004 | local_irq_restore(flags); | ||
1005 | } | ||
1006 | |||
1007 | static int mcfrs_tiocmget(struct tty_struct *tty, struct file *file) | ||
1008 | { | ||
1009 | struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; | ||
1010 | |||
1011 | if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl")) | ||
1012 | return -ENODEV; | ||
1013 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1014 | return -EIO; | ||
1015 | |||
1016 | return mcfrs_getsignals(info); | ||
1017 | } | ||
1018 | |||
1019 | static int mcfrs_tiocmset(struct tty_struct *tty, struct file *file, | ||
1020 | unsigned int set, unsigned int clear) | ||
1021 | { | ||
1022 | struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; | ||
1023 | int rts = -1, dtr = -1; | ||
1024 | |||
1025 | if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl")) | ||
1026 | return -ENODEV; | ||
1027 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1028 | return -EIO; | ||
1029 | |||
1030 | if (set & TIOCM_RTS) | ||
1031 | rts = 1; | ||
1032 | if (set & TIOCM_DTR) | ||
1033 | dtr = 1; | ||
1034 | if (clear & TIOCM_RTS) | ||
1035 | rts = 0; | ||
1036 | if (clear & TIOCM_DTR) | ||
1037 | dtr = 0; | ||
1038 | |||
1039 | mcfrs_setsignals(info, dtr, rts); | ||
1040 | |||
1041 | return 0; | ||
1042 | } | ||
1043 | |||
1044 | static int mcfrs_ioctl(struct tty_struct *tty, struct file * file, | ||
1045 | unsigned int cmd, unsigned long arg) | ||
1046 | { | ||
1047 | struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; | ||
1048 | int retval, error; | ||
1049 | |||
1050 | if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl")) | ||
1051 | return -ENODEV; | ||
1052 | |||
1053 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && | ||
1054 | (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && | ||
1055 | (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { | ||
1056 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1057 | return -EIO; | ||
1058 | } | ||
1059 | |||
1060 | switch (cmd) { | ||
1061 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | ||
1062 | retval = tty_check_change(tty); | ||
1063 | if (retval) | ||
1064 | return retval; | ||
1065 | tty_wait_until_sent(tty, 0); | ||
1066 | if (!arg) | ||
1067 | send_break(info, HZ/4); /* 1/4 second */ | ||
1068 | return 0; | ||
1069 | case TCSBRKP: /* support for POSIX tcsendbreak() */ | ||
1070 | retval = tty_check_change(tty); | ||
1071 | if (retval) | ||
1072 | return retval; | ||
1073 | tty_wait_until_sent(tty, 0); | ||
1074 | send_break(info, arg ? arg*(HZ/10) : HZ/4); | ||
1075 | return 0; | ||
1076 | case TIOCGSERIAL: | ||
1077 | if (access_ok(VERIFY_WRITE, (void *) arg, | ||
1078 | sizeof(struct serial_struct))) | ||
1079 | return get_serial_info(info, | ||
1080 | (struct serial_struct *) arg); | ||
1081 | return -EFAULT; | ||
1082 | case TIOCSSERIAL: | ||
1083 | return set_serial_info(info, | ||
1084 | (struct serial_struct *) arg); | ||
1085 | case TIOCSERGETLSR: /* Get line status register */ | ||
1086 | if (access_ok(VERIFY_WRITE, (void *) arg, | ||
1087 | sizeof(unsigned int))) | ||
1088 | return get_lsr_info(info, (unsigned int *) arg); | ||
1089 | return -EFAULT; | ||
1090 | case TIOCSERGSTRUCT: | ||
1091 | error = copy_to_user((struct mcf_serial *) arg, | ||
1092 | info, sizeof(struct mcf_serial)); | ||
1093 | if (error) | ||
1094 | return -EFAULT; | ||
1095 | return 0; | ||
1096 | |||
1097 | #ifdef TIOCSET422 | ||
1098 | case TIOCSET422: { | ||
1099 | unsigned int val; | ||
1100 | get_user(val, (unsigned int *) arg); | ||
1101 | mcf_setpa(MCFPP_PA11, (val ? 0 : MCFPP_PA11)); | ||
1102 | break; | ||
1103 | } | ||
1104 | case TIOCGET422: { | ||
1105 | unsigned int val; | ||
1106 | val = (mcf_getpa() & MCFPP_PA11) ? 0 : 1; | ||
1107 | put_user(val, (unsigned int *) arg); | ||
1108 | break; | ||
1109 | } | ||
1110 | #endif | ||
1111 | |||
1112 | default: | ||
1113 | return -ENOIOCTLCMD; | ||
1114 | } | ||
1115 | return 0; | ||
1116 | } | ||
1117 | |||
1118 | static void mcfrs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | ||
1119 | { | ||
1120 | struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; | ||
1121 | |||
1122 | if (tty->termios->c_cflag == old_termios->c_cflag) | ||
1123 | return; | ||
1124 | |||
1125 | mcfrs_change_speed(info); | ||
1126 | |||
1127 | if ((old_termios->c_cflag & CRTSCTS) && | ||
1128 | !(tty->termios->c_cflag & CRTSCTS)) { | ||
1129 | tty->hw_stopped = 0; | ||
1130 | mcfrs_setsignals(info, -1, 1); | ||
1131 | #if 0 | ||
1132 | mcfrs_start(tty); | ||
1133 | #endif | ||
1134 | } | ||
1135 | } | ||
1136 | |||
1137 | /* | ||
1138 | * ------------------------------------------------------------ | ||
1139 | * mcfrs_close() | ||
1140 | * | ||
1141 | * This routine is called when the serial port gets closed. First, we | ||
1142 | * wait for the last remaining data to be sent. Then, we unlink its | ||
1143 | * S structure from the interrupt chain if necessary, and we free | ||
1144 | * that IRQ if nothing is left in the chain. | ||
1145 | * ------------------------------------------------------------ | ||
1146 | */ | ||
1147 | static void mcfrs_close(struct tty_struct *tty, struct file * filp) | ||
1148 | { | ||
1149 | volatile unsigned char *uartp; | ||
1150 | struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; | ||
1151 | unsigned long flags; | ||
1152 | |||
1153 | if (!info || serial_paranoia_check(info, tty->name, "mcfrs_close")) | ||
1154 | return; | ||
1155 | |||
1156 | local_irq_save(flags); | ||
1157 | |||
1158 | if (tty_hung_up_p(filp)) { | ||
1159 | local_irq_restore(flags); | ||
1160 | return; | ||
1161 | } | ||
1162 | |||
1163 | #ifdef SERIAL_DEBUG_OPEN | ||
1164 | printk("mcfrs_close ttyS%d, count = %d\n", info->line, info->count); | ||
1165 | #endif | ||
1166 | if ((tty->count == 1) && (info->count != 1)) { | ||
1167 | /* | ||
1168 | * Uh, oh. tty->count is 1, which means that the tty | ||
1169 | * structure will be freed. Info->count should always | ||
1170 | * be one in these conditions. If it's greater than | ||
1171 | * one, we've got real problems, since it means the | ||
1172 | * serial port won't be shutdown. | ||
1173 | */ | ||
1174 | printk("MCFRS: bad serial port count; tty->count is 1, " | ||
1175 | "info->count is %d\n", info->count); | ||
1176 | info->count = 1; | ||
1177 | } | ||
1178 | if (--info->count < 0) { | ||
1179 | printk("MCFRS: bad serial port count for ttyS%d: %d\n", | ||
1180 | info->line, info->count); | ||
1181 | info->count = 0; | ||
1182 | } | ||
1183 | if (info->count) { | ||
1184 | local_irq_restore(flags); | ||
1185 | return; | ||
1186 | } | ||
1187 | info->flags |= ASYNC_CLOSING; | ||
1188 | |||
1189 | /* | ||
1190 | * Now we wait for the transmit buffer to clear; and we notify | ||
1191 | * the line discipline to only process XON/XOFF characters. | ||
1192 | */ | ||
1193 | tty->closing = 1; | ||
1194 | if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
1195 | tty_wait_until_sent(tty, info->closing_wait); | ||
1196 | |||
1197 | /* | ||
1198 | * At this point we stop accepting input. To do this, we | ||
1199 | * disable the receive line status interrupts, and tell the | ||
1200 | * interrupt driver to stop checking the data ready bit in the | ||
1201 | * line status register. | ||
1202 | */ | ||
1203 | info->imr &= ~MCFUART_UIR_RXREADY; | ||
1204 | uartp = info->addr; | ||
1205 | uartp[MCFUART_UIMR] = info->imr; | ||
1206 | |||
1207 | #if 0 | ||
1208 | /* FIXME: do we need to keep this enabled for console?? */ | ||
1209 | if (mcfrs_console_inited && (mcfrs_console_port == info->line)) { | ||
1210 | /* Do not disable the UART */ ; | ||
1211 | } else | ||
1212 | #endif | ||
1213 | shutdown(info); | ||
1214 | mcfrs_flush_buffer(tty); | ||
1215 | tty_ldisc_flush(tty); | ||
1216 | |||
1217 | tty->closing = 0; | ||
1218 | info->event = 0; | ||
1219 | info->port.tty = NULL; | ||
1220 | #if 0 | ||
1221 | if (tty->ldisc.num != ldiscs[N_TTY].num) { | ||
1222 | if (tty->ldisc.close) | ||
1223 | (tty->ldisc.close)(tty); | ||
1224 | tty->ldisc = ldiscs[N_TTY]; | ||
1225 | tty->termios->c_line = N_TTY; | ||
1226 | if (tty->ldisc.open) | ||
1227 | (tty->ldisc.open)(tty); | ||
1228 | } | ||
1229 | #endif | ||
1230 | if (info->blocked_open) { | ||
1231 | if (info->close_delay) { | ||
1232 | msleep_interruptible(jiffies_to_msecs(info->close_delay)); | ||
1233 | } | ||
1234 | wake_up_interruptible(&info->open_wait); | ||
1235 | } | ||
1236 | info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
1237 | wake_up_interruptible(&info->close_wait); | ||
1238 | local_irq_restore(flags); | ||
1239 | } | ||
1240 | |||
1241 | /* | ||
1242 | * mcfrs_wait_until_sent() --- wait until the transmitter is empty | ||
1243 | */ | ||
1244 | static void | ||
1245 | mcfrs_wait_until_sent(struct tty_struct *tty, int timeout) | ||
1246 | { | ||
1247 | #ifdef CONFIG_M5272 | ||
1248 | #define MCF5272_FIFO_SIZE 25 /* fifo size + shift reg */ | ||
1249 | |||
1250 | struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; | ||
1251 | volatile unsigned char *uartp; | ||
1252 | unsigned long orig_jiffies, fifo_time, char_time, fifo_cnt; | ||
1253 | |||
1254 | if (serial_paranoia_check(info, tty->name, "mcfrs_wait_until_sent")) | ||
1255 | return; | ||
1256 | |||
1257 | orig_jiffies = jiffies; | ||
1258 | |||
1259 | /* | ||
1260 | * Set the check interval to be 1/5 of the approximate time | ||
1261 | * to send the entire fifo, and make it at least 1. The check | ||
1262 | * interval should also be less than the timeout. | ||
1263 | * | ||
1264 | * Note: we have to use pretty tight timings here to satisfy | ||
1265 | * the NIST-PCTS. | ||
1266 | */ | ||
1267 | lock_kernel(); | ||
1268 | |||
1269 | fifo_time = (MCF5272_FIFO_SIZE * HZ * 10) / info->baud; | ||
1270 | char_time = fifo_time / 5; | ||
1271 | if (char_time == 0) | ||
1272 | char_time = 1; | ||
1273 | if (timeout && timeout < char_time) | ||
1274 | char_time = timeout; | ||
1275 | |||
1276 | /* | ||
1277 | * Clamp the timeout period at 2 * the time to empty the | ||
1278 | * fifo. Just to be safe, set the minimum at .5 seconds. | ||
1279 | */ | ||
1280 | fifo_time *= 2; | ||
1281 | if (fifo_time < (HZ/2)) | ||
1282 | fifo_time = HZ/2; | ||
1283 | if (!timeout || timeout > fifo_time) | ||
1284 | timeout = fifo_time; | ||
1285 | |||
1286 | /* | ||
1287 | * Account for the number of bytes in the UART | ||
1288 | * transmitter FIFO plus any byte being shifted out. | ||
1289 | */ | ||
1290 | uartp = (volatile unsigned char *) info->addr; | ||
1291 | for (;;) { | ||
1292 | fifo_cnt = (uartp[MCFUART_UTF] & MCFUART_UTF_TXB); | ||
1293 | if ((uartp[MCFUART_USR] & (MCFUART_USR_TXREADY| | ||
1294 | MCFUART_USR_TXEMPTY)) == | ||
1295 | MCFUART_USR_TXREADY) | ||
1296 | fifo_cnt++; | ||
1297 | if (fifo_cnt == 0) | ||
1298 | break; | ||
1299 | msleep_interruptible(jiffies_to_msecs(char_time)); | ||
1300 | if (signal_pending(current)) | ||
1301 | break; | ||
1302 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | ||
1303 | break; | ||
1304 | } | ||
1305 | unlock_kernel(); | ||
1306 | #else | ||
1307 | /* | ||
1308 | * For the other coldfire models, assume all data has been sent | ||
1309 | */ | ||
1310 | #endif | ||
1311 | } | ||
1312 | |||
1313 | /* | ||
1314 | * mcfrs_hangup() --- called by tty_hangup() when a hangup is signaled. | ||
1315 | */ | ||
1316 | void mcfrs_hangup(struct tty_struct *tty) | ||
1317 | { | ||
1318 | struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; | ||
1319 | |||
1320 | if (serial_paranoia_check(info, tty->name, "mcfrs_hangup")) | ||
1321 | return; | ||
1322 | |||
1323 | mcfrs_flush_buffer(tty); | ||
1324 | shutdown(info); | ||
1325 | info->event = 0; | ||
1326 | info->count = 0; | ||
1327 | info->flags &= ~ASYNC_NORMAL_ACTIVE; | ||
1328 | info->port.tty = NULL; | ||
1329 | wake_up_interruptible(&info->open_wait); | ||
1330 | } | ||
1331 | |||
1332 | /* | ||
1333 | * ------------------------------------------------------------ | ||
1334 | * mcfrs_open() and friends | ||
1335 | * ------------------------------------------------------------ | ||
1336 | */ | ||
1337 | static int block_til_ready(struct tty_struct *tty, struct file * filp, | ||
1338 | struct mcf_serial *info) | ||
1339 | { | ||
1340 | DECLARE_WAITQUEUE(wait, current); | ||
1341 | int retval; | ||
1342 | int do_clocal = 0; | ||
1343 | |||
1344 | /* | ||
1345 | * If the device is in the middle of being closed, then block | ||
1346 | * until it's done, and then try again. | ||
1347 | */ | ||
1348 | if (info->flags & ASYNC_CLOSING) { | ||
1349 | interruptible_sleep_on(&info->close_wait); | ||
1350 | #ifdef SERIAL_DO_RESTART | ||
1351 | if (info->flags & ASYNC_HUP_NOTIFY) | ||
1352 | return -EAGAIN; | ||
1353 | else | ||
1354 | return -ERESTARTSYS; | ||
1355 | #else | ||
1356 | return -EAGAIN; | ||
1357 | #endif | ||
1358 | } | ||
1359 | |||
1360 | /* | ||
1361 | * If non-blocking mode is set, or the port is not enabled, | ||
1362 | * then make the check up front and then exit. | ||
1363 | */ | ||
1364 | if ((filp->f_flags & O_NONBLOCK) || | ||
1365 | (tty->flags & (1 << TTY_IO_ERROR))) { | ||
1366 | info->flags |= ASYNC_NORMAL_ACTIVE; | ||
1367 | return 0; | ||
1368 | } | ||
1369 | |||
1370 | if (tty->termios->c_cflag & CLOCAL) | ||
1371 | do_clocal = 1; | ||
1372 | |||
1373 | /* | ||
1374 | * Block waiting for the carrier detect and the line to become | ||
1375 | * free (i.e., not in use by the callout). While we are in | ||
1376 | * this loop, info->count is dropped by one, so that | ||
1377 | * mcfrs_close() knows when to free things. We restore it upon | ||
1378 | * exit, either normal or abnormal. | ||
1379 | */ | ||
1380 | retval = 0; | ||
1381 | add_wait_queue(&info->open_wait, &wait); | ||
1382 | #ifdef SERIAL_DEBUG_OPEN | ||
1383 | printk("block_til_ready before block: ttyS%d, count = %d\n", | ||
1384 | info->line, info->count); | ||
1385 | #endif | ||
1386 | info->count--; | ||
1387 | info->blocked_open++; | ||
1388 | while (1) { | ||
1389 | local_irq_disable(); | ||
1390 | mcfrs_setsignals(info, 1, 1); | ||
1391 | local_irq_enable(); | ||
1392 | current->state = TASK_INTERRUPTIBLE; | ||
1393 | if (tty_hung_up_p(filp) || | ||
1394 | !(info->flags & ASYNC_INITIALIZED)) { | ||
1395 | #ifdef SERIAL_DO_RESTART | ||
1396 | if (info->flags & ASYNC_HUP_NOTIFY) | ||
1397 | retval = -EAGAIN; | ||
1398 | else | ||
1399 | retval = -ERESTARTSYS; | ||
1400 | #else | ||
1401 | retval = -EAGAIN; | ||
1402 | #endif | ||
1403 | break; | ||
1404 | } | ||
1405 | if (!(info->flags & ASYNC_CLOSING) && | ||
1406 | (do_clocal || (mcfrs_getsignals(info) & TIOCM_CD))) | ||
1407 | break; | ||
1408 | if (signal_pending(current)) { | ||
1409 | retval = -ERESTARTSYS; | ||
1410 | break; | ||
1411 | } | ||
1412 | #ifdef SERIAL_DEBUG_OPEN | ||
1413 | printk("block_til_ready blocking: ttyS%d, count = %d\n", | ||
1414 | info->line, info->count); | ||
1415 | #endif | ||
1416 | schedule(); | ||
1417 | } | ||
1418 | current->state = TASK_RUNNING; | ||
1419 | remove_wait_queue(&info->open_wait, &wait); | ||
1420 | if (!tty_hung_up_p(filp)) | ||
1421 | info->count++; | ||
1422 | info->blocked_open--; | ||
1423 | #ifdef SERIAL_DEBUG_OPEN | ||
1424 | printk("block_til_ready after blocking: ttyS%d, count = %d\n", | ||
1425 | info->line, info->count); | ||
1426 | #endif | ||
1427 | if (retval) | ||
1428 | return retval; | ||
1429 | info->flags |= ASYNC_NORMAL_ACTIVE; | ||
1430 | return 0; | ||
1431 | } | ||
1432 | |||
1433 | /* | ||
1434 | * This routine is called whenever a serial port is opened. It | ||
1435 | * enables interrupts for a serial port, linking in its structure into | ||
1436 | * the IRQ chain. It also performs the serial-specific | ||
1437 | * initialization for the tty structure. | ||
1438 | */ | ||
1439 | int mcfrs_open(struct tty_struct *tty, struct file * filp) | ||
1440 | { | ||
1441 | struct mcf_serial *info; | ||
1442 | int retval, line; | ||
1443 | |||
1444 | line = tty->index; | ||
1445 | if ((line < 0) || (line >= NR_PORTS)) | ||
1446 | return -ENODEV; | ||
1447 | info = mcfrs_table + line; | ||
1448 | if (serial_paranoia_check(info, tty->name, "mcfrs_open")) | ||
1449 | return -ENODEV; | ||
1450 | #ifdef SERIAL_DEBUG_OPEN | ||
1451 | printk("mcfrs_open %s, count = %d\n", tty->name, info->count); | ||
1452 | #endif | ||
1453 | info->count++; | ||
1454 | tty->driver_data = info; | ||
1455 | info->port.tty = tty; | ||
1456 | |||
1457 | /* | ||
1458 | * Start up serial port | ||
1459 | */ | ||
1460 | retval = startup(info); | ||
1461 | if (retval) | ||
1462 | return retval; | ||
1463 | |||
1464 | retval = block_til_ready(tty, filp, info); | ||
1465 | if (retval) { | ||
1466 | #ifdef SERIAL_DEBUG_OPEN | ||
1467 | printk("mcfrs_open returning after block_til_ready with %d\n", | ||
1468 | retval); | ||
1469 | #endif | ||
1470 | return retval; | ||
1471 | } | ||
1472 | |||
1473 | #ifdef SERIAL_DEBUG_OPEN | ||
1474 | printk("mcfrs_open %s successful...\n", tty->name); | ||
1475 | #endif | ||
1476 | return 0; | ||
1477 | } | ||
1478 | |||
1479 | /* | ||
1480 | * Based on the line number set up the internal interrupt stuff. | ||
1481 | */ | ||
1482 | static void mcfrs_irqinit(struct mcf_serial *info) | ||
1483 | { | ||
1484 | #if defined(CONFIG_M5272) | ||
1485 | volatile unsigned long *icrp; | ||
1486 | volatile unsigned long *portp; | ||
1487 | volatile unsigned char *uartp; | ||
1488 | |||
1489 | uartp = info->addr; | ||
1490 | icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR2); | ||
1491 | |||
1492 | switch (info->line) { | ||
1493 | case 0: | ||
1494 | *icrp = 0xe0000000; | ||
1495 | break; | ||
1496 | case 1: | ||
1497 | *icrp = 0x0e000000; | ||
1498 | break; | ||
1499 | default: | ||
1500 | printk("MCFRS: don't know how to handle UART %d interrupt?\n", | ||
1501 | info->line); | ||
1502 | return; | ||
1503 | } | ||
1504 | |||
1505 | /* Enable the output lines for the serial ports */ | ||
1506 | portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PBCNT); | ||
1507 | *portp = (*portp & ~0x000000ff) | 0x00000055; | ||
1508 | portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT); | ||
1509 | *portp = (*portp & ~0x000003fc) | 0x000002a8; | ||
1510 | #elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) | ||
1511 | volatile unsigned char *icrp, *uartp; | ||
1512 | volatile unsigned long *imrp; | ||
1513 | |||
1514 | uartp = info->addr; | ||
1515 | |||
1516 | icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 + | ||
1517 | MCFINTC_ICR0 + MCFINT_UART0 + info->line); | ||
1518 | *icrp = 0x30 + info->line; /* level 6, line based priority */ | ||
1519 | |||
1520 | imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 + | ||
1521 | MCFINTC_IMRL); | ||
1522 | *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1); | ||
1523 | #if defined(CONFIG_M527x) | ||
1524 | { | ||
1525 | /* | ||
1526 | * External Pin Mask Setting & Enable External Pin for Interface | ||
1527 | * mrcbis@aliceposta.it | ||
1528 | */ | ||
1529 | u16 *serpin_enable_mask; | ||
1530 | serpin_enable_mask = (u16 *) (MCF_IPSBAR + MCF_GPIO_PAR_UART); | ||
1531 | if (info->line == 0) | ||
1532 | *serpin_enable_mask |= UART0_ENABLE_MASK; | ||
1533 | else if (info->line == 1) | ||
1534 | *serpin_enable_mask |= UART1_ENABLE_MASK; | ||
1535 | else if (info->line == 2) | ||
1536 | *serpin_enable_mask |= UART2_ENABLE_MASK; | ||
1537 | } | ||
1538 | #endif | ||
1539 | #if defined(CONFIG_M528x) | ||
1540 | /* make sure PUAPAR is set for UART0 and UART1 */ | ||
1541 | if (info->line < 2) { | ||
1542 | volatile unsigned char *portp = (volatile unsigned char *) (MCF_MBAR + MCF5282_GPIO_PUAPAR); | ||
1543 | *portp |= (0x03 << (info->line * 2)); | ||
1544 | } | ||
1545 | #endif | ||
1546 | #elif defined(CONFIG_M520x) | ||
1547 | volatile unsigned char *icrp, *uartp; | ||
1548 | volatile unsigned long *imrp; | ||
1549 | |||
1550 | uartp = info->addr; | ||
1551 | |||
1552 | icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 + | ||
1553 | MCFINTC_ICR0 + MCFINT_UART0 + info->line); | ||
1554 | *icrp = 0x03; | ||
1555 | |||
1556 | imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 + | ||
1557 | MCFINTC_IMRL); | ||
1558 | *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1); | ||
1559 | if (info->line < 2) { | ||
1560 | unsigned short *uart_par; | ||
1561 | uart_par = (unsigned short *)(MCF_IPSBAR + MCF_GPIO_PAR_UART); | ||
1562 | if (info->line == 0) | ||
1563 | *uart_par |= MCF_GPIO_PAR_UART_PAR_UTXD0 | ||
1564 | | MCF_GPIO_PAR_UART_PAR_URXD0; | ||
1565 | else if (info->line == 1) | ||
1566 | *uart_par |= MCF_GPIO_PAR_UART_PAR_UTXD1 | ||
1567 | | MCF_GPIO_PAR_UART_PAR_URXD1; | ||
1568 | } else if (info->line == 2) { | ||
1569 | unsigned char *feci2c_par; | ||
1570 | feci2c_par = (unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C); | ||
1571 | *feci2c_par &= ~0x0F; | ||
1572 | *feci2c_par |= MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2 | ||
1573 | | MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2; | ||
1574 | } | ||
1575 | #elif defined(CONFIG_M532x) | ||
1576 | volatile unsigned char *uartp; | ||
1577 | uartp = info->addr; | ||
1578 | switch (info->line) { | ||
1579 | case 0: | ||
1580 | MCF_INTC0_ICR26 = 0x3; | ||
1581 | MCF_INTC0_CIMR = 26; | ||
1582 | /* GPIO initialization */ | ||
1583 | MCF_GPIO_PAR_UART |= 0x000F; | ||
1584 | break; | ||
1585 | case 1: | ||
1586 | MCF_INTC0_ICR27 = 0x3; | ||
1587 | MCF_INTC0_CIMR = 27; | ||
1588 | /* GPIO initialization */ | ||
1589 | MCF_GPIO_PAR_UART |= 0x0FF0; | ||
1590 | break; | ||
1591 | case 2: | ||
1592 | MCF_INTC0_ICR28 = 0x3; | ||
1593 | MCF_INTC0_CIMR = 28; | ||
1594 | /* GPIOs also must be initalized, depends on board */ | ||
1595 | break; | ||
1596 | } | ||
1597 | #else | ||
1598 | volatile unsigned char *icrp, *uartp; | ||
1599 | |||
1600 | switch (info->line) { | ||
1601 | case 0: | ||
1602 | icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_UART1ICR); | ||
1603 | *icrp = /*MCFSIM_ICR_AUTOVEC |*/ MCFSIM_ICR_LEVEL6 | | ||
1604 | MCFSIM_ICR_PRI1; | ||
1605 | mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART1); | ||
1606 | break; | ||
1607 | case 1: | ||
1608 | icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_UART2ICR); | ||
1609 | *icrp = /*MCFSIM_ICR_AUTOVEC |*/ MCFSIM_ICR_LEVEL6 | | ||
1610 | MCFSIM_ICR_PRI2; | ||
1611 | mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART2); | ||
1612 | break; | ||
1613 | default: | ||
1614 | printk("MCFRS: don't know how to handle UART %d interrupt?\n", | ||
1615 | info->line); | ||
1616 | return; | ||
1617 | } | ||
1618 | |||
1619 | uartp = info->addr; | ||
1620 | uartp[MCFUART_UIVR] = info->irq; | ||
1621 | #endif | ||
1622 | |||
1623 | /* Clear mask, so no surprise interrupts. */ | ||
1624 | uartp[MCFUART_UIMR] = 0; | ||
1625 | |||
1626 | if (request_irq(info->irq, mcfrs_interrupt, IRQF_DISABLED, | ||
1627 | "ColdFire UART", NULL)) { | ||
1628 | printk("MCFRS: Unable to attach ColdFire UART %d interrupt " | ||
1629 | "vector=%d\n", info->line, info->irq); | ||
1630 | } | ||
1631 | |||
1632 | return; | ||
1633 | } | ||
1634 | |||
1635 | |||
1636 | char *mcfrs_drivername = "ColdFire internal UART serial driver version 1.00\n"; | ||
1637 | |||
1638 | |||
1639 | /* | ||
1640 | * Serial stats reporting... | ||
1641 | */ | ||
1642 | int mcfrs_readproc(char *page, char **start, off_t off, int count, | ||
1643 | int *eof, void *data) | ||
1644 | { | ||
1645 | struct mcf_serial *info; | ||
1646 | char str[20]; | ||
1647 | int len, sigs, i; | ||
1648 | |||
1649 | len = sprintf(page, mcfrs_drivername); | ||
1650 | for (i = 0; (i < NR_PORTS); i++) { | ||
1651 | info = &mcfrs_table[i]; | ||
1652 | len += sprintf((page + len), "%d: port:%x irq=%d baud:%d ", | ||
1653 | i, (unsigned int) info->addr, info->irq, info->baud); | ||
1654 | if (info->stats.rx || info->stats.tx) | ||
1655 | len += sprintf((page + len), "tx:%d rx:%d ", | ||
1656 | info->stats.tx, info->stats.rx); | ||
1657 | if (info->stats.rxframing) | ||
1658 | len += sprintf((page + len), "fe:%d ", | ||
1659 | info->stats.rxframing); | ||
1660 | if (info->stats.rxparity) | ||
1661 | len += sprintf((page + len), "pe:%d ", | ||
1662 | info->stats.rxparity); | ||
1663 | if (info->stats.rxbreak) | ||
1664 | len += sprintf((page + len), "brk:%d ", | ||
1665 | info->stats.rxbreak); | ||
1666 | if (info->stats.rxoverrun) | ||
1667 | len += sprintf((page + len), "oe:%d ", | ||
1668 | info->stats.rxoverrun); | ||
1669 | |||
1670 | str[0] = str[1] = 0; | ||
1671 | if ((sigs = mcfrs_getsignals(info))) { | ||
1672 | if (sigs & TIOCM_RTS) | ||
1673 | strcat(str, "|RTS"); | ||
1674 | if (sigs & TIOCM_CTS) | ||
1675 | strcat(str, "|CTS"); | ||
1676 | if (sigs & TIOCM_DTR) | ||
1677 | strcat(str, "|DTR"); | ||
1678 | if (sigs & TIOCM_CD) | ||
1679 | strcat(str, "|CD"); | ||
1680 | } | ||
1681 | |||
1682 | len += sprintf((page + len), "%s\n", &str[1]); | ||
1683 | } | ||
1684 | |||
1685 | return(len); | ||
1686 | } | ||
1687 | |||
1688 | |||
1689 | /* Finally, routines used to initialize the serial driver. */ | ||
1690 | |||
1691 | static void show_serial_version(void) | ||
1692 | { | ||
1693 | printk(mcfrs_drivername); | ||
1694 | } | ||
1695 | |||
1696 | static const struct tty_operations mcfrs_ops = { | ||
1697 | .open = mcfrs_open, | ||
1698 | .close = mcfrs_close, | ||
1699 | .write = mcfrs_write, | ||
1700 | .flush_chars = mcfrs_flush_chars, | ||
1701 | .write_room = mcfrs_write_room, | ||
1702 | .chars_in_buffer = mcfrs_chars_in_buffer, | ||
1703 | .flush_buffer = mcfrs_flush_buffer, | ||
1704 | .ioctl = mcfrs_ioctl, | ||
1705 | .throttle = mcfrs_throttle, | ||
1706 | .unthrottle = mcfrs_unthrottle, | ||
1707 | .set_termios = mcfrs_set_termios, | ||
1708 | .stop = mcfrs_stop, | ||
1709 | .start = mcfrs_start, | ||
1710 | .hangup = mcfrs_hangup, | ||
1711 | .read_proc = mcfrs_readproc, | ||
1712 | .wait_until_sent = mcfrs_wait_until_sent, | ||
1713 | .tiocmget = mcfrs_tiocmget, | ||
1714 | .tiocmset = mcfrs_tiocmset, | ||
1715 | }; | ||
1716 | |||
1717 | /* mcfrs_init inits the driver */ | ||
1718 | static int __init | ||
1719 | mcfrs_init(void) | ||
1720 | { | ||
1721 | struct mcf_serial *info; | ||
1722 | unsigned long flags; | ||
1723 | int i; | ||
1724 | |||
1725 | /* Setup base handler, and timer table. */ | ||
1726 | #ifdef MCFPP_DCD0 | ||
1727 | init_timer(&mcfrs_timer_struct); | ||
1728 | mcfrs_timer_struct.function = mcfrs_timer; | ||
1729 | mcfrs_timer_struct.data = 0; | ||
1730 | mcfrs_timer_struct.expires = jiffies + HZ/25; | ||
1731 | add_timer(&mcfrs_timer_struct); | ||
1732 | mcfrs_ppstatus = mcf_getppdata() & (MCFPP_DCD0 | MCFPP_DCD1); | ||
1733 | #endif | ||
1734 | mcfrs_serial_driver = alloc_tty_driver(NR_PORTS); | ||
1735 | if (!mcfrs_serial_driver) | ||
1736 | return -ENOMEM; | ||
1737 | |||
1738 | show_serial_version(); | ||
1739 | |||
1740 | /* Initialize the tty_driver structure */ | ||
1741 | mcfrs_serial_driver->owner = THIS_MODULE; | ||
1742 | mcfrs_serial_driver->name = "ttyS"; | ||
1743 | mcfrs_serial_driver->driver_name = "mcfserial"; | ||
1744 | mcfrs_serial_driver->major = TTY_MAJOR; | ||
1745 | mcfrs_serial_driver->minor_start = 64; | ||
1746 | mcfrs_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
1747 | mcfrs_serial_driver->subtype = SERIAL_TYPE_NORMAL; | ||
1748 | mcfrs_serial_driver->init_termios = tty_std_termios; | ||
1749 | |||
1750 | mcfrs_serial_driver->init_termios.c_cflag = | ||
1751 | mcfrs_console_cbaud | CS8 | CREAD | HUPCL | CLOCAL; | ||
1752 | mcfrs_serial_driver->flags = TTY_DRIVER_REAL_RAW; | ||
1753 | |||
1754 | tty_set_operations(mcfrs_serial_driver, &mcfrs_ops); | ||
1755 | |||
1756 | if (tty_register_driver(mcfrs_serial_driver)) { | ||
1757 | printk("MCFRS: Couldn't register serial driver\n"); | ||
1758 | put_tty_driver(mcfrs_serial_driver); | ||
1759 | return(-EBUSY); | ||
1760 | } | ||
1761 | |||
1762 | local_irq_save(flags); | ||
1763 | |||
1764 | /* | ||
1765 | * Configure all the attached serial ports. | ||
1766 | */ | ||
1767 | for (i = 0, info = mcfrs_table; (i < NR_PORTS); i++, info++) { | ||
1768 | info->magic = SERIAL_MAGIC; | ||
1769 | info->line = i; | ||
1770 | info->port.tty = NULL; | ||
1771 | info->custom_divisor = 16; | ||
1772 | info->close_delay = 50; | ||
1773 | info->closing_wait = 3000; | ||
1774 | info->x_char = 0; | ||
1775 | info->event = 0; | ||
1776 | info->count = 0; | ||
1777 | info->blocked_open = 0; | ||
1778 | INIT_WORK(&info->tqueue, mcfrs_offintr); | ||
1779 | INIT_WORK(&info->tqueue_hangup, do_serial_hangup); | ||
1780 | init_waitqueue_head(&info->open_wait); | ||
1781 | init_waitqueue_head(&info->close_wait); | ||
1782 | |||
1783 | info->imr = 0; | ||
1784 | mcfrs_setsignals(info, 0, 0); | ||
1785 | mcfrs_irqinit(info); | ||
1786 | |||
1787 | printk("ttyS%d at 0x%04x (irq = %d)", info->line, | ||
1788 | (unsigned int) info->addr, info->irq); | ||
1789 | printk(" is a builtin ColdFire UART\n"); | ||
1790 | } | ||
1791 | |||
1792 | local_irq_restore(flags); | ||
1793 | return 0; | ||
1794 | } | ||
1795 | |||
1796 | module_init(mcfrs_init); | ||
1797 | |||
1798 | /****************************************************************************/ | ||
1799 | /* Serial Console */ | ||
1800 | /****************************************************************************/ | ||
1801 | |||
1802 | /* | ||
1803 | * Quick and dirty UART initialization, for console output. | ||
1804 | */ | ||
1805 | |||
1806 | void mcfrs_init_console(void) | ||
1807 | { | ||
1808 | volatile unsigned char *uartp; | ||
1809 | unsigned int clk; | ||
1810 | |||
1811 | /* | ||
1812 | * Reset UART, get it into known state... | ||
1813 | */ | ||
1814 | uartp = (volatile unsigned char *) (MCF_MBAR + | ||
1815 | (mcfrs_console_port ? MCFUART_BASE2 : MCFUART_BASE1)); | ||
1816 | |||
1817 | uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ | ||
1818 | uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ | ||
1819 | uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR; /* reset MR pointer */ | ||
1820 | |||
1821 | /* | ||
1822 | * Set port for defined baud , 8 data bits, 1 stop bit, no parity. | ||
1823 | */ | ||
1824 | uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8; | ||
1825 | uartp[MCFUART_UMR] = MCFUART_MR2_STOP1; | ||
1826 | |||
1827 | #ifdef CONFIG_M5272 | ||
1828 | { | ||
1829 | /* | ||
1830 | * For the MCF5272, also compute the baudrate fraction. | ||
1831 | */ | ||
1832 | int fraction = MCF_BUSCLK - (clk * 32 * mcfrs_console_baud); | ||
1833 | fraction *= 16; | ||
1834 | fraction /= (32 * mcfrs_console_baud); | ||
1835 | uartp[MCFUART_UFPD] = (fraction & 0xf); /* set fraction */ | ||
1836 | clk = (MCF_BUSCLK / mcfrs_console_baud) / 32; | ||
1837 | } | ||
1838 | #else | ||
1839 | clk = ((MCF_BUSCLK / mcfrs_console_baud) + 16) / 32; /* set baud */ | ||
1840 | #endif | ||
1841 | |||
1842 | uartp[MCFUART_UBG1] = (clk & 0xff00) >> 8; /* set msb baud */ | ||
1843 | uartp[MCFUART_UBG2] = (clk & 0xff); /* set lsb baud */ | ||
1844 | uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER; | ||
1845 | uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE; | ||
1846 | |||
1847 | mcfrs_console_inited++; | ||
1848 | return; | ||
1849 | } | ||
1850 | |||
1851 | |||
1852 | /* | ||
1853 | * Setup for console. Argument comes from the boot command line. | ||
1854 | */ | ||
1855 | |||
1856 | int mcfrs_console_setup(struct console *cp, char *arg) | ||
1857 | { | ||
1858 | int i, n = CONSOLE_BAUD_RATE; | ||
1859 | |||
1860 | if (!cp) | ||
1861 | return(-1); | ||
1862 | |||
1863 | if (!strncmp(cp->name, "ttyS", 4)) | ||
1864 | mcfrs_console_port = cp->index; | ||
1865 | else if (!strncmp(cp->name, "cua", 3)) | ||
1866 | mcfrs_console_port = cp->index; | ||
1867 | else | ||
1868 | return(-1); | ||
1869 | |||
1870 | if (arg) | ||
1871 | n = simple_strtoul(arg,NULL,0); | ||
1872 | for (i = 0; i < MCFRS_BAUD_TABLE_SIZE; i++) | ||
1873 | if (mcfrs_baud_table[i] == n) | ||
1874 | break; | ||
1875 | if (i < MCFRS_BAUD_TABLE_SIZE) { | ||
1876 | mcfrs_console_baud = n; | ||
1877 | mcfrs_console_cbaud = 0; | ||
1878 | if (i > 15) { | ||
1879 | mcfrs_console_cbaud |= CBAUDEX; | ||
1880 | i -= 15; | ||
1881 | } | ||
1882 | mcfrs_console_cbaud |= i; | ||
1883 | } | ||
1884 | mcfrs_init_console(); /* make sure baud rate changes */ | ||
1885 | return(0); | ||
1886 | } | ||
1887 | |||
1888 | |||
1889 | static struct tty_driver *mcfrs_console_device(struct console *c, int *index) | ||
1890 | { | ||
1891 | *index = c->index; | ||
1892 | return mcfrs_serial_driver; | ||
1893 | } | ||
1894 | |||
1895 | |||
1896 | /* | ||
1897 | * Output a single character, using UART polled mode. | ||
1898 | * This is used for console output. | ||
1899 | */ | ||
1900 | |||
1901 | int mcfrs_put_char(char ch) | ||
1902 | { | ||
1903 | volatile unsigned char *uartp; | ||
1904 | unsigned long flags; | ||
1905 | int i; | ||
1906 | |||
1907 | uartp = (volatile unsigned char *) (MCF_MBAR + | ||
1908 | (mcfrs_console_port ? MCFUART_BASE2 : MCFUART_BASE1)); | ||
1909 | |||
1910 | local_irq_save(flags); | ||
1911 | for (i = 0; (i < 0x10000); i++) { | ||
1912 | if (uartp[MCFUART_USR] & MCFUART_USR_TXREADY) | ||
1913 | break; | ||
1914 | } | ||
1915 | if (i < 0x10000) { | ||
1916 | uartp[MCFUART_UTB] = ch; | ||
1917 | for (i = 0; (i < 0x10000); i++) | ||
1918 | if (uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY) | ||
1919 | break; | ||
1920 | } | ||
1921 | if (i >= 0x10000) | ||
1922 | mcfrs_init_console(); /* try and get it back */ | ||
1923 | local_irq_restore(flags); | ||
1924 | |||
1925 | return 1; | ||
1926 | } | ||
1927 | |||
1928 | |||
1929 | /* | ||
1930 | * rs_console_write is registered for printk output. | ||
1931 | */ | ||
1932 | |||
1933 | void mcfrs_console_write(struct console *cp, const char *p, unsigned len) | ||
1934 | { | ||
1935 | if (!mcfrs_console_inited) | ||
1936 | mcfrs_init_console(); | ||
1937 | while (len-- > 0) { | ||
1938 | if (*p == '\n') | ||
1939 | mcfrs_put_char('\r'); | ||
1940 | mcfrs_put_char(*p++); | ||
1941 | } | ||
1942 | } | ||
1943 | |||
1944 | /* | ||
1945 | * declare our consoles | ||
1946 | */ | ||
1947 | |||
1948 | struct console mcfrs_console = { | ||
1949 | .name = "ttyS", | ||
1950 | .write = mcfrs_console_write, | ||
1951 | .device = mcfrs_console_device, | ||
1952 | .setup = mcfrs_console_setup, | ||
1953 | .flags = CON_PRINTBUFFER, | ||
1954 | .index = -1, | ||
1955 | }; | ||
1956 | |||
1957 | static int __init mcfrs_console_init(void) | ||
1958 | { | ||
1959 | register_console(&mcfrs_console); | ||
1960 | return 0; | ||
1961 | } | ||
1962 | |||
1963 | console_initcall(mcfrs_console_init); | ||
1964 | |||
1965 | /****************************************************************************/ | ||
diff --git a/drivers/serial/mcfserial.h b/drivers/serial/mcfserial.h deleted file mode 100644 index 56420e2cb110..000000000000 --- a/drivers/serial/mcfserial.h +++ /dev/null | |||
@@ -1,74 +0,0 @@ | |||
1 | /* | ||
2 | * mcfserial.c -- serial driver for ColdFire internal UARTS. | ||
3 | * | ||
4 | * Copyright (c) 1999 Greg Ungerer <gerg@snapgear.com> | ||
5 | * Copyright (c) 2000-2001 Lineo, Inc. <www.lineo.com> | ||
6 | * Copyright (c) 2002 SnapGear Inc., <www.snapgear.com> | ||
7 | * | ||
8 | * Based on code from 68332serial.c which was: | ||
9 | * | ||
10 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | ||
11 | * Copyright (C) 1998 TSHG | ||
12 | * Copyright (c) 1999 Rt-Control Inc. <jeff@uclinux.org> | ||
13 | */ | ||
14 | #ifndef _MCF_SERIAL_H | ||
15 | #define _MCF_SERIAL_H | ||
16 | |||
17 | #include <linux/serial.h> | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | |||
21 | /* | ||
22 | * Define a local serial stats structure. | ||
23 | */ | ||
24 | |||
25 | struct mcf_stats { | ||
26 | unsigned int rx; | ||
27 | unsigned int tx; | ||
28 | unsigned int rxbreak; | ||
29 | unsigned int rxframing; | ||
30 | unsigned int rxparity; | ||
31 | unsigned int rxoverrun; | ||
32 | }; | ||
33 | |||
34 | |||
35 | /* | ||
36 | * This is our internal structure for each serial port's state. | ||
37 | * Each serial port has one of these structures associated with it. | ||
38 | */ | ||
39 | |||
40 | struct mcf_serial { | ||
41 | int magic; | ||
42 | volatile unsigned char *addr; /* UART memory address */ | ||
43 | int irq; | ||
44 | int flags; /* defined in tty.h */ | ||
45 | int type; /* UART type */ | ||
46 | struct tty_struct *tty; | ||
47 | unsigned char imr; /* Software imr register */ | ||
48 | unsigned int baud; | ||
49 | int sigs; | ||
50 | int custom_divisor; | ||
51 | int x_char; /* xon/xoff character */ | ||
52 | int baud_base; | ||
53 | int close_delay; | ||
54 | unsigned short closing_wait; | ||
55 | unsigned short closing_wait2; | ||
56 | unsigned long event; | ||
57 | int line; | ||
58 | int count; /* # of fd on device */ | ||
59 | int blocked_open; /* # of blocked opens */ | ||
60 | unsigned char *xmit_buf; | ||
61 | int xmit_head; | ||
62 | int xmit_tail; | ||
63 | int xmit_cnt; | ||
64 | struct mcf_stats stats; | ||
65 | struct work_struct tqueue; | ||
66 | struct work_struct tqueue_hangup; | ||
67 | wait_queue_head_t open_wait; | ||
68 | wait_queue_head_t close_wait; | ||
69 | |||
70 | }; | ||
71 | |||
72 | #endif /* __KERNEL__ */ | ||
73 | |||
74 | #endif /* _MCF_SERIAL_H */ | ||
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index f977c98cfa95..6bdf3362e3b1 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -2051,7 +2051,8 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) | |||
2051 | "transmitter\n", | 2051 | "transmitter\n", |
2052 | port->dev ? port->dev->bus_id : "", | 2052 | port->dev ? port->dev->bus_id : "", |
2053 | port->dev ? ": " : "", | 2053 | port->dev ? ": " : "", |
2054 | drv->dev_name, port->line); | 2054 | drv->dev_name, |
2055 | drv->tty_driver->name_base + port->line); | ||
2055 | 2056 | ||
2056 | ops->shutdown(port); | 2057 | ops->shutdown(port); |
2057 | } | 2058 | } |
@@ -2154,12 +2155,11 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) | |||
2154 | 2155 | ||
2155 | switch (port->iotype) { | 2156 | switch (port->iotype) { |
2156 | case UPIO_PORT: | 2157 | case UPIO_PORT: |
2157 | snprintf(address, sizeof(address), | 2158 | snprintf(address, sizeof(address), "I/O 0x%lx", port->iobase); |
2158 | "I/O 0x%x", port->iobase); | ||
2159 | break; | 2159 | break; |
2160 | case UPIO_HUB6: | 2160 | case UPIO_HUB6: |
2161 | snprintf(address, sizeof(address), | 2161 | snprintf(address, sizeof(address), |
2162 | "I/O 0x%x offset 0x%x", port->iobase, port->hub6); | 2162 | "I/O 0x%lx offset 0x%x", port->iobase, port->hub6); |
2163 | break; | 2163 | break; |
2164 | case UPIO_MEM: | 2164 | case UPIO_MEM: |
2165 | case UPIO_MEM32: | 2165 | case UPIO_MEM32: |
@@ -2177,7 +2177,9 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) | |||
2177 | printk(KERN_INFO "%s%s%s%d at %s (irq = %d) is a %s\n", | 2177 | printk(KERN_INFO "%s%s%s%d at %s (irq = %d) is a %s\n", |
2178 | port->dev ? port->dev->bus_id : "", | 2178 | port->dev ? port->dev->bus_id : "", |
2179 | port->dev ? ": " : "", | 2179 | port->dev ? ": " : "", |
2180 | drv->dev_name, port->line, address, port->irq, uart_type(port)); | 2180 | drv->dev_name, |
2181 | drv->tty_driver->name_base + port->line, | ||
2182 | address, port->irq, uart_type(port)); | ||
2181 | } | 2183 | } |
2182 | 2184 | ||
2183 | static void | 2185 | static void |
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index 79ea98c66fa8..99fb7dc59c45 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c | |||
@@ -272,7 +272,7 @@ static void aircable_read(struct work_struct *work) | |||
272 | * 64 bytes, to ensure I do not get throttled. | 272 | * 64 bytes, to ensure I do not get throttled. |
273 | * Ask USB mailing list for better aproach. | 273 | * Ask USB mailing list for better aproach. |
274 | */ | 274 | */ |
275 | tty = port->port.tty; | 275 | tty = tty_port_tty_get(&port->port); |
276 | 276 | ||
277 | if (!tty) { | 277 | if (!tty) { |
278 | schedule_work(&priv->rx_work); | 278 | schedule_work(&priv->rx_work); |
@@ -283,12 +283,13 @@ static void aircable_read(struct work_struct *work) | |||
283 | count = min(64, serial_buf_data_avail(priv->rx_buf)); | 283 | count = min(64, serial_buf_data_avail(priv->rx_buf)); |
284 | 284 | ||
285 | if (count <= 0) | 285 | if (count <= 0) |
286 | return; /* We have finished sending everything. */ | 286 | goto out; /* We have finished sending everything. */ |
287 | 287 | ||
288 | tty_prepare_flip_string(tty, &data, count); | 288 | tty_prepare_flip_string(tty, &data, count); |
289 | if (!data) { | 289 | if (!data) { |
290 | err("%s- kzalloc(%d) failed.", __func__, count); | 290 | dev_err(&port->dev, "%s- kzalloc(%d) failed.", |
291 | return; | 291 | __func__, count); |
292 | goto out; | ||
292 | } | 293 | } |
293 | 294 | ||
294 | serial_buf_get(priv->rx_buf, data, count); | 295 | serial_buf_get(priv->rx_buf, data, count); |
@@ -297,7 +298,8 @@ static void aircable_read(struct work_struct *work) | |||
297 | 298 | ||
298 | if (serial_buf_data_avail(priv->rx_buf)) | 299 | if (serial_buf_data_avail(priv->rx_buf)) |
299 | schedule_work(&priv->rx_work); | 300 | schedule_work(&priv->rx_work); |
300 | 301 | out: | |
302 | tty_kref_put(tty); | ||
301 | return; | 303 | return; |
302 | } | 304 | } |
303 | /* End of private methods */ | 305 | /* End of private methods */ |
@@ -495,7 +497,7 @@ static void aircable_read_bulk_callback(struct urb *urb) | |||
495 | usb_serial_debug_data(debug, &port->dev, __func__, | 497 | usb_serial_debug_data(debug, &port->dev, __func__, |
496 | urb->actual_length, urb->transfer_buffer); | 498 | urb->actual_length, urb->transfer_buffer); |
497 | 499 | ||
498 | tty = port->port.tty; | 500 | tty = tty_port_tty_get(&port->port); |
499 | if (tty && urb->actual_length) { | 501 | if (tty && urb->actual_length) { |
500 | if (urb->actual_length <= 2) { | 502 | if (urb->actual_length <= 2) { |
501 | /* This is an incomplete package */ | 503 | /* This is an incomplete package */ |
@@ -527,6 +529,7 @@ static void aircable_read_bulk_callback(struct urb *urb) | |||
527 | } | 529 | } |
528 | aircable_read(&priv->rx_work); | 530 | aircable_read(&priv->rx_work); |
529 | } | 531 | } |
532 | tty_kref_put(tty); | ||
530 | 533 | ||
531 | /* Schedule the next read _if_ we are still open */ | 534 | /* Schedule the next read _if_ we are still open */ |
532 | if (port->port.count) { | 535 | if (port->port.count) { |
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 2ebe06c3405a..1913bc7c5f0b 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c | |||
@@ -322,7 +322,7 @@ static void belkin_sa_read_int_callback(struct urb *urb) | |||
322 | * to look in to this before committing any code. | 322 | * to look in to this before committing any code. |
323 | */ | 323 | */ |
324 | if (priv->last_lsr & BELKIN_SA_LSR_ERR) { | 324 | if (priv->last_lsr & BELKIN_SA_LSR_ERR) { |
325 | tty = port->port.tty; | 325 | tty = tty_port_tty_get(&port->port); |
326 | /* Overrun Error */ | 326 | /* Overrun Error */ |
327 | if (priv->last_lsr & BELKIN_SA_LSR_OE) { | 327 | if (priv->last_lsr & BELKIN_SA_LSR_OE) { |
328 | } | 328 | } |
@@ -335,6 +335,7 @@ static void belkin_sa_read_int_callback(struct urb *urb) | |||
335 | /* Break Indicator */ | 335 | /* Break Indicator */ |
336 | if (priv->last_lsr & BELKIN_SA_LSR_BI) { | 336 | if (priv->last_lsr & BELKIN_SA_LSR_BI) { |
337 | } | 337 | } |
338 | tty_kref_put(tty); | ||
338 | } | 339 | } |
339 | #endif | 340 | #endif |
340 | spin_unlock_irqrestore(&priv->lock, flags); | 341 | spin_unlock_irqrestore(&priv->lock, flags); |
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index e980766bb84b..5b20de130e08 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c | |||
@@ -117,7 +117,7 @@ static int usb_console_setup(struct console *co, char *options) | |||
117 | } | 117 | } |
118 | 118 | ||
119 | port = serial->port[0]; | 119 | port = serial->port[0]; |
120 | port->port.tty = NULL; | 120 | tty_port_tty_set(&port->port, NULL); |
121 | 121 | ||
122 | info->port = port; | 122 | info->port = port; |
123 | 123 | ||
@@ -143,7 +143,7 @@ static int usb_console_setup(struct console *co, char *options) | |||
143 | } | 143 | } |
144 | memset(&dummy, 0, sizeof(struct ktermios)); | 144 | memset(&dummy, 0, sizeof(struct ktermios)); |
145 | tty->termios = termios; | 145 | tty->termios = termios; |
146 | port->port.tty = tty; | 146 | tty_port_tty_set(&port->port, tty); |
147 | } | 147 | } |
148 | 148 | ||
149 | /* only call the device specific open if this | 149 | /* only call the device specific open if this |
@@ -163,7 +163,7 @@ static int usb_console_setup(struct console *co, char *options) | |||
163 | tty_termios_encode_baud_rate(termios, baud, baud); | 163 | tty_termios_encode_baud_rate(termios, baud, baud); |
164 | serial->type->set_termios(tty, port, &dummy); | 164 | serial->type->set_termios(tty, port, &dummy); |
165 | 165 | ||
166 | port->port.tty = NULL; | 166 | tty_port_tty_set(&port->port, NULL); |
167 | kfree(termios); | 167 | kfree(termios); |
168 | kfree(tty); | 168 | kfree(tty); |
169 | } | 169 | } |
@@ -176,7 +176,7 @@ out: | |||
176 | return retval; | 176 | return retval; |
177 | free_termios: | 177 | free_termios: |
178 | kfree(termios); | 178 | kfree(termios); |
179 | port->port.tty = NULL; | 179 | tty_port_tty_set(&port->port, NULL); |
180 | free_tty: | 180 | free_tty: |
181 | kfree(tty); | 181 | kfree(tty); |
182 | reset_open_count: | 182 | reset_open_count: |
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index b4d72351cb96..94ef36c4764b 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c | |||
@@ -384,7 +384,7 @@ static void cyberjack_read_bulk_callback(struct urb *urb) | |||
384 | return; | 384 | return; |
385 | } | 385 | } |
386 | 386 | ||
387 | tty = port->port.tty; | 387 | tty = tty_port_tty_get(&port->port); |
388 | if (!tty) { | 388 | if (!tty) { |
389 | dbg("%s - ignoring since device not open\n", __func__); | 389 | dbg("%s - ignoring since device not open\n", __func__); |
390 | return; | 390 | return; |
@@ -394,6 +394,7 @@ static void cyberjack_read_bulk_callback(struct urb *urb) | |||
394 | tty_insert_flip_string(tty, data, urb->actual_length); | 394 | tty_insert_flip_string(tty, data, urb->actual_length); |
395 | tty_flip_buffer_push(tty); | 395 | tty_flip_buffer_push(tty); |
396 | } | 396 | } |
397 | tty_kref_put(tty); | ||
397 | 398 | ||
398 | spin_lock(&priv->lock); | 399 | spin_lock(&priv->lock); |
399 | 400 | ||
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 22837a3f2f89..f3514a91f915 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
@@ -1286,7 +1286,7 @@ static void cypress_read_int_callback(struct urb *urb) | |||
1286 | } | 1286 | } |
1287 | spin_unlock_irqrestore(&priv->lock, flags); | 1287 | spin_unlock_irqrestore(&priv->lock, flags); |
1288 | 1288 | ||
1289 | tty = port->port.tty; | 1289 | tty = tty_port_tty_get(&port->port); |
1290 | if (!tty) { | 1290 | if (!tty) { |
1291 | dbg("%s - bad tty pointer - exiting", __func__); | 1291 | dbg("%s - bad tty pointer - exiting", __func__); |
1292 | return; | 1292 | return; |
@@ -1362,7 +1362,7 @@ static void cypress_read_int_callback(struct urb *urb) | |||
1362 | data[i]); | 1362 | data[i]); |
1363 | tty_insert_flip_char(tty, data[i], tty_flag); | 1363 | tty_insert_flip_char(tty, data[i], tty_flag); |
1364 | } | 1364 | } |
1365 | tty_flip_buffer_push(port->port.tty); | 1365 | tty_flip_buffer_push(tty); |
1366 | } | 1366 | } |
1367 | 1367 | ||
1368 | spin_lock_irqsave(&priv->lock, flags); | 1368 | spin_lock_irqsave(&priv->lock, flags); |
@@ -1371,6 +1371,7 @@ static void cypress_read_int_callback(struct urb *urb) | |||
1371 | spin_unlock_irqrestore(&priv->lock, flags); | 1371 | spin_unlock_irqrestore(&priv->lock, flags); |
1372 | 1372 | ||
1373 | continue_read: | 1373 | continue_read: |
1374 | tty_kref_put(tty); | ||
1374 | 1375 | ||
1375 | /* Continue trying to always read... unless the port has closed. */ | 1376 | /* Continue trying to always read... unless the port has closed. */ |
1376 | 1377 | ||
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 240aad1acaab..5756ac6d6c92 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c | |||
@@ -604,7 +604,9 @@ static void digi_wakeup_write_lock(struct work_struct *work) | |||
604 | 604 | ||
605 | static void digi_wakeup_write(struct usb_serial_port *port) | 605 | static void digi_wakeup_write(struct usb_serial_port *port) |
606 | { | 606 | { |
607 | tty_wakeup(port->port.tty); | 607 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
608 | tty_wakeup(tty); | ||
609 | tty_kref_put(tty); | ||
608 | } | 610 | } |
609 | 611 | ||
610 | 612 | ||
@@ -1668,7 +1670,7 @@ static int digi_read_inb_callback(struct urb *urb) | |||
1668 | { | 1670 | { |
1669 | 1671 | ||
1670 | struct usb_serial_port *port = urb->context; | 1672 | struct usb_serial_port *port = urb->context; |
1671 | struct tty_struct *tty = port->port.tty; | 1673 | struct tty_struct *tty; |
1672 | struct digi_port *priv = usb_get_serial_port_data(port); | 1674 | struct digi_port *priv = usb_get_serial_port_data(port); |
1673 | int opcode = ((unsigned char *)urb->transfer_buffer)[0]; | 1675 | int opcode = ((unsigned char *)urb->transfer_buffer)[0]; |
1674 | int len = ((unsigned char *)urb->transfer_buffer)[1]; | 1676 | int len = ((unsigned char *)urb->transfer_buffer)[1]; |
@@ -1692,6 +1694,7 @@ static int digi_read_inb_callback(struct urb *urb) | |||
1692 | return -1; | 1694 | return -1; |
1693 | } | 1695 | } |
1694 | 1696 | ||
1697 | tty = tty_port_tty_get(&port->port); | ||
1695 | spin_lock(&priv->dp_port_lock); | 1698 | spin_lock(&priv->dp_port_lock); |
1696 | 1699 | ||
1697 | /* check for throttle; if set, do not resubmit read urb */ | 1700 | /* check for throttle; if set, do not resubmit read urb */ |
@@ -1735,6 +1738,7 @@ static int digi_read_inb_callback(struct urb *urb) | |||
1735 | } | 1738 | } |
1736 | } | 1739 | } |
1737 | spin_unlock(&priv->dp_port_lock); | 1740 | spin_unlock(&priv->dp_port_lock); |
1741 | tty_kref_put(tty); | ||
1738 | 1742 | ||
1739 | if (opcode == DIGI_CMD_RECEIVE_DISABLE) | 1743 | if (opcode == DIGI_CMD_RECEIVE_DISABLE) |
1740 | dbg("%s: got RECEIVE_DISABLE", __func__); | 1744 | dbg("%s: got RECEIVE_DISABLE", __func__); |
@@ -1760,6 +1764,7 @@ static int digi_read_oob_callback(struct urb *urb) | |||
1760 | 1764 | ||
1761 | struct usb_serial_port *port = urb->context; | 1765 | struct usb_serial_port *port = urb->context; |
1762 | struct usb_serial *serial = port->serial; | 1766 | struct usb_serial *serial = port->serial; |
1767 | struct tty_struct *tty; | ||
1763 | struct digi_port *priv = usb_get_serial_port_data(port); | 1768 | struct digi_port *priv = usb_get_serial_port_data(port); |
1764 | int opcode, line, status, val; | 1769 | int opcode, line, status, val; |
1765 | int i; | 1770 | int i; |
@@ -1787,10 +1792,11 @@ static int digi_read_oob_callback(struct urb *urb) | |||
1787 | if (priv == NULL) | 1792 | if (priv == NULL) |
1788 | return -1; | 1793 | return -1; |
1789 | 1794 | ||
1795 | tty = tty_port_tty_get(&port->port); | ||
1790 | rts = 0; | 1796 | rts = 0; |
1791 | if (port->port.count) | 1797 | if (port->port.count) |
1792 | rts = port->port.tty->termios->c_cflag & CRTSCTS; | 1798 | rts = tty->termios->c_cflag & CRTSCTS; |
1793 | 1799 | ||
1794 | if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) { | 1800 | if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) { |
1795 | spin_lock(&priv->dp_port_lock); | 1801 | spin_lock(&priv->dp_port_lock); |
1796 | /* convert from digi flags to termiox flags */ | 1802 | /* convert from digi flags to termiox flags */ |
@@ -1798,14 +1804,14 @@ static int digi_read_oob_callback(struct urb *urb) | |||
1798 | priv->dp_modem_signals |= TIOCM_CTS; | 1804 | priv->dp_modem_signals |= TIOCM_CTS; |
1799 | /* port must be open to use tty struct */ | 1805 | /* port must be open to use tty struct */ |
1800 | if (rts) { | 1806 | if (rts) { |
1801 | port->port.tty->hw_stopped = 0; | 1807 | tty->hw_stopped = 0; |
1802 | digi_wakeup_write(port); | 1808 | digi_wakeup_write(port); |
1803 | } | 1809 | } |
1804 | } else { | 1810 | } else { |
1805 | priv->dp_modem_signals &= ~TIOCM_CTS; | 1811 | priv->dp_modem_signals &= ~TIOCM_CTS; |
1806 | /* port must be open to use tty struct */ | 1812 | /* port must be open to use tty struct */ |
1807 | if (rts) | 1813 | if (rts) |
1808 | port->port.tty->hw_stopped = 1; | 1814 | tty->hw_stopped = 1; |
1809 | } | 1815 | } |
1810 | if (val & DIGI_READ_INPUT_SIGNALS_DSR) | 1816 | if (val & DIGI_READ_INPUT_SIGNALS_DSR) |
1811 | priv->dp_modem_signals |= TIOCM_DSR; | 1817 | priv->dp_modem_signals |= TIOCM_DSR; |
@@ -1830,6 +1836,7 @@ static int digi_read_oob_callback(struct urb *urb) | |||
1830 | } else if (opcode == DIGI_CMD_IFLUSH_FIFO) { | 1836 | } else if (opcode == DIGI_CMD_IFLUSH_FIFO) { |
1831 | wake_up_interruptible(&priv->dp_flush_wait); | 1837 | wake_up_interruptible(&priv->dp_flush_wait); |
1832 | } | 1838 | } |
1839 | tty_kref_put(tty); | ||
1833 | } | 1840 | } |
1834 | return 0; | 1841 | return 0; |
1835 | 1842 | ||
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index a6ab5b58d9ca..1072e847280f 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c | |||
@@ -33,9 +33,8 @@ | |||
33 | * Moved MOD_DEC_USE_COUNT to end of empeg_close(). | 33 | * Moved MOD_DEC_USE_COUNT to end of empeg_close(). |
34 | * | 34 | * |
35 | * (12/03/2000) gb | 35 | * (12/03/2000) gb |
36 | * Added port->port.tty->ldisc.set_termios(port->port.tty, NULL) to | 36 | * Added tty->ldisc.set_termios(port, tty, NULL) to empeg_open(). |
37 | * empeg_open(). This notifies the tty driver that the termios have | 37 | * This notifies the tty driver that the termios have changed. |
38 | * changed. | ||
39 | * | 38 | * |
40 | * (11/13/2000) gb | 39 | * (11/13/2000) gb |
41 | * Moved tty->low_latency = 1 from empeg_read_bulk_callback() to | 40 | * Moved tty->low_latency = 1 from empeg_read_bulk_callback() to |
@@ -354,7 +353,7 @@ static void empeg_read_bulk_callback(struct urb *urb) | |||
354 | 353 | ||
355 | usb_serial_debug_data(debug, &port->dev, __func__, | 354 | usb_serial_debug_data(debug, &port->dev, __func__, |
356 | urb->actual_length, data); | 355 | urb->actual_length, data); |
357 | tty = port->port.tty; | 356 | tty = tty_port_tty_get(&port->port); |
358 | 357 | ||
359 | if (urb->actual_length) { | 358 | if (urb->actual_length) { |
360 | tty_buffer_request_room(tty, urb->actual_length); | 359 | tty_buffer_request_room(tty, urb->actual_length); |
@@ -362,6 +361,7 @@ static void empeg_read_bulk_callback(struct urb *urb) | |||
362 | tty_flip_buffer_push(tty); | 361 | tty_flip_buffer_push(tty); |
363 | bytes_in += urb->actual_length; | 362 | bytes_in += urb->actual_length; |
364 | } | 363 | } |
364 | tty_kref_put(tty); | ||
365 | 365 | ||
366 | /* Continue trying to always read */ | 366 | /* Continue trying to always read */ |
367 | usb_fill_bulk_urb( | 367 | usb_fill_bulk_urb( |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 3dc93b542b30..c2ac129557aa 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -860,7 +860,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, | |||
860 | 860 | ||
861 | kfree(buf); | 861 | kfree(buf); |
862 | if (rv < 0) { | 862 | if (rv < 0) { |
863 | err("%s Error from MODEM_CTRL urb: DTR %s, RTS %s", | 863 | dbg("%s Error from MODEM_CTRL urb: DTR %s, RTS %s", |
864 | __func__, | 864 | __func__, |
865 | (set & TIOCM_DTR) ? "HIGH" : | 865 | (set & TIOCM_DTR) ? "HIGH" : |
866 | (clear & TIOCM_DTR) ? "LOW" : "unchanged", | 866 | (clear & TIOCM_DTR) ? "LOW" : "unchanged", |
@@ -1808,7 +1808,7 @@ static void ftdi_read_bulk_callback(struct urb *urb) | |||
1808 | if (port->port.count <= 0) | 1808 | if (port->port.count <= 0) |
1809 | return; | 1809 | return; |
1810 | 1810 | ||
1811 | tty = port->port.tty; | 1811 | tty = tty_port_tty_get(&port->port); |
1812 | if (!tty) { | 1812 | if (!tty) { |
1813 | dbg("%s - bad tty pointer - exiting", __func__); | 1813 | dbg("%s - bad tty pointer - exiting", __func__); |
1814 | return; | 1814 | return; |
@@ -1817,7 +1817,7 @@ static void ftdi_read_bulk_callback(struct urb *urb) | |||
1817 | priv = usb_get_serial_port_data(port); | 1817 | priv = usb_get_serial_port_data(port); |
1818 | if (!priv) { | 1818 | if (!priv) { |
1819 | dbg("%s - bad port private data pointer - exiting", __func__); | 1819 | dbg("%s - bad port private data pointer - exiting", __func__); |
1820 | return; | 1820 | goto out; |
1821 | } | 1821 | } |
1822 | 1822 | ||
1823 | if (urb != port->read_urb) | 1823 | if (urb != port->read_urb) |
@@ -1827,7 +1827,7 @@ static void ftdi_read_bulk_callback(struct urb *urb) | |||
1827 | /* This will happen at close every time so it is a dbg not an | 1827 | /* This will happen at close every time so it is a dbg not an |
1828 | err */ | 1828 | err */ |
1829 | dbg("(this is ok on close) nonzero read bulk status received: %d", status); | 1829 | dbg("(this is ok on close) nonzero read bulk status received: %d", status); |
1830 | return; | 1830 | goto out; |
1831 | } | 1831 | } |
1832 | 1832 | ||
1833 | /* count data bytes, but not status bytes */ | 1833 | /* count data bytes, but not status bytes */ |
@@ -1838,7 +1838,8 @@ static void ftdi_read_bulk_callback(struct urb *urb) | |||
1838 | spin_unlock_irqrestore(&priv->rx_lock, flags); | 1838 | spin_unlock_irqrestore(&priv->rx_lock, flags); |
1839 | 1839 | ||
1840 | ftdi_process_read(&priv->rx_work.work); | 1840 | ftdi_process_read(&priv->rx_work.work); |
1841 | 1841 | out: | |
1842 | tty_kref_put(tty); | ||
1842 | } /* ftdi_read_bulk_callback */ | 1843 | } /* ftdi_read_bulk_callback */ |
1843 | 1844 | ||
1844 | 1845 | ||
@@ -1863,7 +1864,7 @@ static void ftdi_process_read(struct work_struct *work) | |||
1863 | if (port->port.count <= 0) | 1864 | if (port->port.count <= 0) |
1864 | return; | 1865 | return; |
1865 | 1866 | ||
1866 | tty = port->port.tty; | 1867 | tty = tty_port_tty_get(&port->port); |
1867 | if (!tty) { | 1868 | if (!tty) { |
1868 | dbg("%s - bad tty pointer - exiting", __func__); | 1869 | dbg("%s - bad tty pointer - exiting", __func__); |
1869 | return; | 1870 | return; |
@@ -1872,13 +1873,13 @@ static void ftdi_process_read(struct work_struct *work) | |||
1872 | priv = usb_get_serial_port_data(port); | 1873 | priv = usb_get_serial_port_data(port); |
1873 | if (!priv) { | 1874 | if (!priv) { |
1874 | dbg("%s - bad port private data pointer - exiting", __func__); | 1875 | dbg("%s - bad port private data pointer - exiting", __func__); |
1875 | return; | 1876 | goto out; |
1876 | } | 1877 | } |
1877 | 1878 | ||
1878 | urb = port->read_urb; | 1879 | urb = port->read_urb; |
1879 | if (!urb) { | 1880 | if (!urb) { |
1880 | dbg("%s - bad read_urb pointer - exiting", __func__); | 1881 | dbg("%s - bad read_urb pointer - exiting", __func__); |
1881 | return; | 1882 | goto out; |
1882 | } | 1883 | } |
1883 | 1884 | ||
1884 | data = urb->transfer_buffer; | 1885 | data = urb->transfer_buffer; |
@@ -2020,7 +2021,7 @@ static void ftdi_process_read(struct work_struct *work) | |||
2020 | schedule_delayed_work(&priv->rx_work, 1); | 2021 | schedule_delayed_work(&priv->rx_work, 1); |
2021 | else | 2022 | else |
2022 | dbg("%s - port is closed", __func__); | 2023 | dbg("%s - port is closed", __func__); |
2023 | return; | 2024 | goto out; |
2024 | } | 2025 | } |
2025 | 2026 | ||
2026 | /* urb is completely processed */ | 2027 | /* urb is completely processed */ |
@@ -2041,6 +2042,8 @@ static void ftdi_process_read(struct work_struct *work) | |||
2041 | err("%s - failed resubmitting read urb, error %d", | 2042 | err("%s - failed resubmitting read urb, error %d", |
2042 | __func__, result); | 2043 | __func__, result); |
2043 | } | 2044 | } |
2045 | out: | ||
2046 | tty_kref_put(tty); | ||
2044 | } /* ftdi_process_read */ | 2047 | } /* ftdi_process_read */ |
2045 | 2048 | ||
2046 | 2049 | ||
@@ -2256,7 +2259,7 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) | |||
2256 | 0, 0, | 2259 | 0, 0, |
2257 | buf, 1, WDR_TIMEOUT); | 2260 | buf, 1, WDR_TIMEOUT); |
2258 | if (ret < 0) { | 2261 | if (ret < 0) { |
2259 | err("%s Could not get modem status of device - err: %d", __func__, | 2262 | dbg("%s Could not get modem status of device - err: %d", __func__, |
2260 | ret); | 2263 | ret); |
2261 | return ret; | 2264 | return ret; |
2262 | } | 2265 | } |
@@ -2275,7 +2278,7 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) | |||
2275 | 0, priv->interface, | 2278 | 0, priv->interface, |
2276 | buf, 2, WDR_TIMEOUT); | 2279 | buf, 2, WDR_TIMEOUT); |
2277 | if (ret < 0) { | 2280 | if (ret < 0) { |
2278 | err("%s Could not get modem status of device - err: %d", __func__, | 2281 | dbg("%s Could not get modem status of device - err: %d", __func__, |
2279 | ret); | 2282 | ret); |
2280 | return ret; | 2283 | return ret; |
2281 | } | 2284 | } |
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index d95382088075..2ad0569bcf19 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c | |||
@@ -276,7 +276,7 @@ static inline int isAbortTrfCmnd(const unsigned char *buf) | |||
276 | static void send_to_tty(struct usb_serial_port *port, | 276 | static void send_to_tty(struct usb_serial_port *port, |
277 | char *data, unsigned int actual_length) | 277 | char *data, unsigned int actual_length) |
278 | { | 278 | { |
279 | struct tty_struct *tty = port->port.tty; | 279 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
280 | 280 | ||
281 | if (tty && actual_length) { | 281 | if (tty && actual_length) { |
282 | 282 | ||
@@ -287,6 +287,7 @@ static void send_to_tty(struct usb_serial_port *port, | |||
287 | tty_insert_flip_string(tty, data, actual_length); | 287 | tty_insert_flip_string(tty, data, actual_length); |
288 | tty_flip_buffer_push(tty); | 288 | tty_flip_buffer_push(tty); |
289 | } | 289 | } |
290 | tty_kref_put(tty); | ||
290 | } | 291 | } |
291 | 292 | ||
292 | 293 | ||
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index fe84c88ec20c..814909f1ee63 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -330,7 +330,7 @@ static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags) | |||
330 | static void flush_and_resubmit_read_urb(struct usb_serial_port *port) | 330 | static void flush_and_resubmit_read_urb(struct usb_serial_port *port) |
331 | { | 331 | { |
332 | struct urb *urb = port->read_urb; | 332 | struct urb *urb = port->read_urb; |
333 | struct tty_struct *tty = port->port.tty; | 333 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
334 | int room; | 334 | int room; |
335 | 335 | ||
336 | /* Push data to tty */ | 336 | /* Push data to tty */ |
@@ -341,6 +341,7 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port) | |||
341 | tty_flip_buffer_push(tty); | 341 | tty_flip_buffer_push(tty); |
342 | } | 342 | } |
343 | } | 343 | } |
344 | tty_kref_put(tty); | ||
344 | 345 | ||
345 | resubmit_read_urb(port, GFP_ATOMIC); | 346 | resubmit_read_urb(port, GFP_ATOMIC); |
346 | } | 347 | } |
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index bfa508ddb0fe..611f97fd62f1 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c | |||
@@ -600,6 +600,7 @@ static void edge_interrupt_callback(struct urb *urb) | |||
600 | struct edgeport_serial *edge_serial = urb->context; | 600 | struct edgeport_serial *edge_serial = urb->context; |
601 | struct edgeport_port *edge_port; | 601 | struct edgeport_port *edge_port; |
602 | struct usb_serial_port *port; | 602 | struct usb_serial_port *port; |
603 | struct tty_struct *tty; | ||
603 | unsigned char *data = urb->transfer_buffer; | 604 | unsigned char *data = urb->transfer_buffer; |
604 | int length = urb->actual_length; | 605 | int length = urb->actual_length; |
605 | int bytes_avail; | 606 | int bytes_avail; |
@@ -675,9 +676,12 @@ static void edge_interrupt_callback(struct urb *urb) | |||
675 | 676 | ||
676 | /* tell the tty driver that something | 677 | /* tell the tty driver that something |
677 | has changed */ | 678 | has changed */ |
678 | if (edge_port->port->port.tty) | 679 | tty = tty_port_tty_get( |
679 | tty_wakeup(edge_port->port->port.tty); | 680 | &edge_port->port->port); |
680 | 681 | if (tty) { | |
682 | tty_wakeup(tty); | ||
683 | tty_kref_put(tty); | ||
684 | } | ||
681 | /* Since we have more credit, check | 685 | /* Since we have more credit, check |
682 | if more data can be sent */ | 686 | if more data can be sent */ |
683 | send_more_port_data(edge_serial, | 687 | send_more_port_data(edge_serial, |
@@ -778,13 +782,14 @@ static void edge_bulk_out_data_callback(struct urb *urb) | |||
778 | __func__, status); | 782 | __func__, status); |
779 | } | 783 | } |
780 | 784 | ||
781 | tty = edge_port->port->port.tty; | 785 | tty = tty_port_tty_get(&edge_port->port->port); |
782 | 786 | ||
783 | if (tty && edge_port->open) { | 787 | if (tty && edge_port->open) { |
784 | /* let the tty driver wakeup if it has a special | 788 | /* let the tty driver wakeup if it has a special |
785 | write_wakeup function */ | 789 | write_wakeup function */ |
786 | tty_wakeup(tty); | 790 | tty_wakeup(tty); |
787 | } | 791 | } |
792 | tty_kref_put(tty); | ||
788 | 793 | ||
789 | /* Release the Write URB */ | 794 | /* Release the Write URB */ |
790 | edge_port->write_in_progress = false; | 795 | edge_port->write_in_progress = false; |
@@ -826,11 +831,12 @@ static void edge_bulk_out_cmd_callback(struct urb *urb) | |||
826 | } | 831 | } |
827 | 832 | ||
828 | /* Get pointer to tty */ | 833 | /* Get pointer to tty */ |
829 | tty = edge_port->port->port.tty; | 834 | tty = tty_port_tty_get(&edge_port->port->port); |
830 | 835 | ||
831 | /* tell the tty driver that something has changed */ | 836 | /* tell the tty driver that something has changed */ |
832 | if (tty && edge_port->open) | 837 | if (tty && edge_port->open) |
833 | tty_wakeup(tty); | 838 | tty_wakeup(tty); |
839 | tty_kref_put(tty); | ||
834 | 840 | ||
835 | /* we have completed the command */ | 841 | /* we have completed the command */ |
836 | edge_port->commandPending = false; | 842 | edge_port->commandPending = false; |
@@ -1932,11 +1938,13 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, | |||
1932 | edge_serial->rxPort]; | 1938 | edge_serial->rxPort]; |
1933 | edge_port = usb_get_serial_port_data(port); | 1939 | edge_port = usb_get_serial_port_data(port); |
1934 | if (edge_port->open) { | 1940 | if (edge_port->open) { |
1935 | tty = edge_port->port->port.tty; | 1941 | tty = tty_port_tty_get( |
1942 | &edge_port->port->port); | ||
1936 | if (tty) { | 1943 | if (tty) { |
1937 | dbg("%s - Sending %d bytes to TTY for port %d", | 1944 | dbg("%s - Sending %d bytes to TTY for port %d", |
1938 | __func__, rxLen, edge_serial->rxPort); | 1945 | __func__, rxLen, edge_serial->rxPort); |
1939 | edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen); | 1946 | edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen); |
1947 | tty_kref_put(tty); | ||
1940 | } | 1948 | } |
1941 | edge_port->icount.rx += rxLen; | 1949 | edge_port->icount.rx += rxLen; |
1942 | } | 1950 | } |
@@ -1971,6 +1979,7 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, | |||
1971 | { | 1979 | { |
1972 | struct usb_serial_port *port; | 1980 | struct usb_serial_port *port; |
1973 | struct edgeport_port *edge_port; | 1981 | struct edgeport_port *edge_port; |
1982 | struct tty_struct *tty; | ||
1974 | __u8 code = edge_serial->rxStatusCode; | 1983 | __u8 code = edge_serial->rxStatusCode; |
1975 | 1984 | ||
1976 | /* switch the port pointer to the one being currently talked about */ | 1985 | /* switch the port pointer to the one being currently talked about */ |
@@ -2020,10 +2029,12 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, | |||
2020 | 2029 | ||
2021 | /* send the current line settings to the port so we are | 2030 | /* send the current line settings to the port so we are |
2022 | in sync with any further termios calls */ | 2031 | in sync with any further termios calls */ |
2023 | /* FIXME: locking on tty */ | 2032 | tty = tty_port_tty_get(&edge_port->port->port); |
2024 | if (edge_port->port->port.tty) | 2033 | if (tty) { |
2025 | change_port_settings(edge_port->port->port.tty, | 2034 | change_port_settings(tty, |
2026 | edge_port, edge_port->port->port.tty->termios); | 2035 | edge_port, tty->termios); |
2036 | tty_kref_put(tty); | ||
2037 | } | ||
2027 | 2038 | ||
2028 | /* we have completed the open */ | 2039 | /* we have completed the open */ |
2029 | edge_port->openPending = false; | 2040 | edge_port->openPending = false; |
@@ -2163,10 +2174,14 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, | |||
2163 | } | 2174 | } |
2164 | 2175 | ||
2165 | /* Place LSR data byte into Rx buffer */ | 2176 | /* Place LSR data byte into Rx buffer */ |
2166 | if (lsrData && edge_port->port->port.tty) | 2177 | if (lsrData) { |
2167 | edge_tty_recv(&edge_port->port->dev, | 2178 | struct tty_struct *tty = |
2168 | edge_port->port->port.tty, &data, 1); | 2179 | tty_port_tty_get(&edge_port->port->port); |
2169 | 2180 | if (tty) { | |
2181 | edge_tty_recv(&edge_port->port->dev, tty, &data, 1); | ||
2182 | tty_kref_put(tty); | ||
2183 | } | ||
2184 | } | ||
2170 | /* update input line counters */ | 2185 | /* update input line counters */ |
2171 | icount = &edge_port->icount; | 2186 | icount = &edge_port->icount; |
2172 | if (newLsr & LSR_BREAK) | 2187 | if (newLsr & LSR_BREAK) |
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index cb4c54316cf5..541dd8e6e7a2 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c | |||
@@ -572,7 +572,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, | |||
572 | int flush) | 572 | int flush) |
573 | { | 573 | { |
574 | int baud_rate; | 574 | int baud_rate; |
575 | struct tty_struct *tty = port->port->port.tty; | 575 | struct tty_struct *tty = tty_port_tty_get(&port->port->port); |
576 | wait_queue_t wait; | 576 | wait_queue_t wait; |
577 | unsigned long flags; | 577 | unsigned long flags; |
578 | 578 | ||
@@ -599,6 +599,7 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, | |||
599 | if (flush) | 599 | if (flush) |
600 | edge_buf_clear(port->ep_out_buf); | 600 | edge_buf_clear(port->ep_out_buf); |
601 | spin_unlock_irqrestore(&port->ep_lock, flags); | 601 | spin_unlock_irqrestore(&port->ep_lock, flags); |
602 | tty_kref_put(tty); | ||
602 | 603 | ||
603 | /* wait for data to drain from the device */ | 604 | /* wait for data to drain from the device */ |
604 | timeout += jiffies; | 605 | timeout += jiffies; |
@@ -1554,7 +1555,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr) | |||
1554 | /* Save the new modem status */ | 1555 | /* Save the new modem status */ |
1555 | edge_port->shadow_msr = msr & 0xf0; | 1556 | edge_port->shadow_msr = msr & 0xf0; |
1556 | 1557 | ||
1557 | tty = edge_port->port->port.tty; | 1558 | tty = tty_port_tty_get(&edge_port->port->port); |
1558 | /* handle CTS flow control */ | 1559 | /* handle CTS flow control */ |
1559 | if (tty && C_CRTSCTS(tty)) { | 1560 | if (tty && C_CRTSCTS(tty)) { |
1560 | if (msr & EDGEPORT_MSR_CTS) { | 1561 | if (msr & EDGEPORT_MSR_CTS) { |
@@ -1564,6 +1565,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr) | |||
1564 | tty->hw_stopped = 1; | 1565 | tty->hw_stopped = 1; |
1565 | } | 1566 | } |
1566 | } | 1567 | } |
1568 | tty_kref_put(tty); | ||
1567 | 1569 | ||
1568 | return; | 1570 | return; |
1569 | } | 1571 | } |
@@ -1574,6 +1576,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data, | |||
1574 | struct async_icount *icount; | 1576 | struct async_icount *icount; |
1575 | __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | | 1577 | __u8 new_lsr = (__u8)(lsr & (__u8)(LSR_OVER_ERR | LSR_PAR_ERR | |
1576 | LSR_FRM_ERR | LSR_BREAK)); | 1578 | LSR_FRM_ERR | LSR_BREAK)); |
1579 | struct tty_struct *tty; | ||
1577 | 1580 | ||
1578 | dbg("%s - %02x", __func__, new_lsr); | 1581 | dbg("%s - %02x", __func__, new_lsr); |
1579 | 1582 | ||
@@ -1587,8 +1590,13 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data, | |||
1587 | new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK); | 1590 | new_lsr &= (__u8)(LSR_OVER_ERR | LSR_BREAK); |
1588 | 1591 | ||
1589 | /* Place LSR data byte into Rx buffer */ | 1592 | /* Place LSR data byte into Rx buffer */ |
1590 | if (lsr_data && edge_port->port->port.tty) | 1593 | if (lsr_data) { |
1591 | edge_tty_recv(&edge_port->port->dev, edge_port->port->port.tty, &data, 1); | 1594 | tty = tty_port_tty_get(&edge_port->port->port); |
1595 | if (tty) { | ||
1596 | edge_tty_recv(&edge_port->port->dev, tty, &data, 1); | ||
1597 | tty_kref_put(tty); | ||
1598 | } | ||
1599 | } | ||
1592 | 1600 | ||
1593 | /* update input line counters */ | 1601 | /* update input line counters */ |
1594 | icount = &edge_port->icount; | 1602 | icount = &edge_port->icount; |
@@ -1749,7 +1757,7 @@ static void edge_bulk_in_callback(struct urb *urb) | |||
1749 | ++data; | 1757 | ++data; |
1750 | } | 1758 | } |
1751 | 1759 | ||
1752 | tty = edge_port->port->port.tty; | 1760 | tty = tty_port_tty_get(&edge_port->port->port); |
1753 | if (tty && urb->actual_length) { | 1761 | if (tty && urb->actual_length) { |
1754 | usb_serial_debug_data(debug, &edge_port->port->dev, | 1762 | usb_serial_debug_data(debug, &edge_port->port->dev, |
1755 | __func__, urb->actual_length, data); | 1763 | __func__, urb->actual_length, data); |
@@ -1761,6 +1769,7 @@ static void edge_bulk_in_callback(struct urb *urb) | |||
1761 | urb->actual_length); | 1769 | urb->actual_length); |
1762 | edge_port->icount.rx += urb->actual_length; | 1770 | edge_port->icount.rx += urb->actual_length; |
1763 | } | 1771 | } |
1772 | tty_kref_put(tty); | ||
1764 | 1773 | ||
1765 | exit: | 1774 | exit: |
1766 | /* continue read unless stopped */ | 1775 | /* continue read unless stopped */ |
@@ -1796,6 +1805,7 @@ static void edge_bulk_out_callback(struct urb *urb) | |||
1796 | struct usb_serial_port *port = urb->context; | 1805 | struct usb_serial_port *port = urb->context; |
1797 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | 1806 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); |
1798 | int status = urb->status; | 1807 | int status = urb->status; |
1808 | struct tty_struct *tty; | ||
1799 | 1809 | ||
1800 | dbg("%s - port %d", __func__, port->number); | 1810 | dbg("%s - port %d", __func__, port->number); |
1801 | 1811 | ||
@@ -1818,7 +1828,9 @@ static void edge_bulk_out_callback(struct urb *urb) | |||
1818 | } | 1828 | } |
1819 | 1829 | ||
1820 | /* send any buffered data */ | 1830 | /* send any buffered data */ |
1821 | edge_send(port->port.tty); | 1831 | tty = tty_port_tty_get(&port->port); |
1832 | edge_send(tty); | ||
1833 | tty_kref_put(tty); | ||
1822 | } | 1834 | } |
1823 | 1835 | ||
1824 | static int edge_open(struct tty_struct *tty, | 1836 | static int edge_open(struct tty_struct *tty, |
@@ -1876,7 +1888,7 @@ static int edge_open(struct tty_struct *tty, | |||
1876 | 1888 | ||
1877 | /* set up the port settings */ | 1889 | /* set up the port settings */ |
1878 | if (tty) | 1890 | if (tty) |
1879 | edge_set_termios(tty, port, port->port.tty->termios); | 1891 | edge_set_termios(tty, port, tty->termios); |
1880 | 1892 | ||
1881 | /* open up the port */ | 1893 | /* open up the port */ |
1882 | 1894 | ||
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index cd9a2e138c8b..2affa9c118b2 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -764,13 +764,14 @@ static void ipaq_read_bulk_callback(struct urb *urb) | |||
764 | usb_serial_debug_data(debug, &port->dev, __func__, | 764 | usb_serial_debug_data(debug, &port->dev, __func__, |
765 | urb->actual_length, data); | 765 | urb->actual_length, data); |
766 | 766 | ||
767 | tty = port->port.tty; | 767 | tty = tty_port_tty_get(&port->port); |
768 | if (tty && urb->actual_length) { | 768 | if (tty && urb->actual_length) { |
769 | tty_buffer_request_room(tty, urb->actual_length); | 769 | tty_buffer_request_room(tty, urb->actual_length); |
770 | tty_insert_flip_string(tty, data, urb->actual_length); | 770 | tty_insert_flip_string(tty, data, urb->actual_length); |
771 | tty_flip_buffer_push(tty); | 771 | tty_flip_buffer_push(tty); |
772 | bytes_in += urb->actual_length; | 772 | bytes_in += urb->actual_length; |
773 | } | 773 | } |
774 | tty_kref_put(tty); | ||
774 | 775 | ||
775 | /* Continue trying to always read */ | 776 | /* Continue trying to always read */ |
776 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | 777 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, |
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index a842025b9b57..480cac27d646 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c | |||
@@ -170,12 +170,13 @@ static void ipw_read_bulk_callback(struct urb *urb) | |||
170 | usb_serial_debug_data(debug, &port->dev, __func__, | 170 | usb_serial_debug_data(debug, &port->dev, __func__, |
171 | urb->actual_length, data); | 171 | urb->actual_length, data); |
172 | 172 | ||
173 | tty = port->port.tty; | 173 | tty = tty_port_tty_get(&port->port); |
174 | if (tty && urb->actual_length) { | 174 | if (tty && urb->actual_length) { |
175 | tty_buffer_request_room(tty, urb->actual_length); | 175 | tty_buffer_request_room(tty, urb->actual_length); |
176 | tty_insert_flip_string(tty, data, urb->actual_length); | 176 | tty_insert_flip_string(tty, data, urb->actual_length); |
177 | tty_flip_buffer_push(tty); | 177 | tty_flip_buffer_push(tty); |
178 | } | 178 | } |
179 | tty_kref_put(tty); | ||
179 | 180 | ||
180 | /* Continue trying to always read */ | 181 | /* Continue trying to always read */ |
181 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | 182 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, |
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index e59155c6607d..45d4043e04ab 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c | |||
@@ -465,11 +465,12 @@ static void ir_read_bulk_callback(struct urb *urb) | |||
465 | ir_baud = *data & 0x0f; | 465 | ir_baud = *data & 0x0f; |
466 | usb_serial_debug_data(debug, &port->dev, __func__, | 466 | usb_serial_debug_data(debug, &port->dev, __func__, |
467 | urb->actual_length, data); | 467 | urb->actual_length, data); |
468 | tty = port->port.tty; | 468 | tty = tty_port_tty_get(&port->port); |
469 | if (tty_buffer_request_room(tty, urb->actual_length - 1)) { | 469 | if (tty_buffer_request_room(tty, urb->actual_length - 1)) { |
470 | tty_insert_flip_string(tty, data+1, urb->actual_length - 1); | 470 | tty_insert_flip_string(tty, data+1, urb->actual_length - 1); |
471 | tty_flip_buffer_push(tty); | 471 | tty_flip_buffer_push(tty); |
472 | } | 472 | } |
473 | tty_kref_put(tty); | ||
473 | 474 | ||
474 | /* | 475 | /* |
475 | * No break here. | 476 | * No break here. |
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index ddff37fa6339..53710aa7eadd 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c | |||
@@ -629,13 +629,14 @@ static void read_buf_callback(struct urb *urb) | |||
629 | } | 629 | } |
630 | 630 | ||
631 | dbg("%s - %i chars to write", __func__, urb->actual_length); | 631 | dbg("%s - %i chars to write", __func__, urb->actual_length); |
632 | tty = port->port.tty; | 632 | tty = tty_port_tty_get(&port->port); |
633 | if (data == NULL) | 633 | if (data == NULL) |
634 | dbg("%s - data is NULL !!!", __func__); | 634 | dbg("%s - data is NULL !!!", __func__); |
635 | if (tty && urb->actual_length && data) { | 635 | if (tty && urb->actual_length && data) { |
636 | tty_insert_flip_string(tty, data, urb->actual_length); | 636 | tty_insert_flip_string(tty, data, urb->actual_length); |
637 | tty_flip_buffer_push(tty); | 637 | tty_flip_buffer_push(tty); |
638 | } | 638 | } |
639 | tty_kref_put(tty); | ||
639 | iuu_led_activity_on(urb); | 640 | iuu_led_activity_on(urb); |
640 | } | 641 | } |
641 | 642 | ||
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 704716f6f6d3..15447af48691 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c | |||
@@ -430,7 +430,7 @@ static void usa26_indat_callback(struct urb *urb) | |||
430 | } | 430 | } |
431 | 431 | ||
432 | port = urb->context; | 432 | port = urb->context; |
433 | tty = port->port.tty; | 433 | tty = tty_port_tty_get(&port->port); |
434 | if (tty && urb->actual_length) { | 434 | if (tty && urb->actual_length) { |
435 | /* 0x80 bit is error flag */ | 435 | /* 0x80 bit is error flag */ |
436 | if ((data[0] & 0x80) == 0) { | 436 | if ((data[0] & 0x80) == 0) { |
@@ -459,6 +459,7 @@ static void usa26_indat_callback(struct urb *urb) | |||
459 | } | 459 | } |
460 | tty_flip_buffer_push(tty); | 460 | tty_flip_buffer_push(tty); |
461 | } | 461 | } |
462 | tty_kref_put(tty); | ||
462 | 463 | ||
463 | /* Resubmit urb so we continue receiving */ | 464 | /* Resubmit urb so we continue receiving */ |
464 | urb->dev = port->serial->dev; | 465 | urb->dev = port->serial->dev; |
@@ -513,6 +514,7 @@ static void usa26_instat_callback(struct urb *urb) | |||
513 | struct usb_serial *serial; | 514 | struct usb_serial *serial; |
514 | struct usb_serial_port *port; | 515 | struct usb_serial_port *port; |
515 | struct keyspan_port_private *p_priv; | 516 | struct keyspan_port_private *p_priv; |
517 | struct tty_struct *tty; | ||
516 | int old_dcd_state, err; | 518 | int old_dcd_state, err; |
517 | int status = urb->status; | 519 | int status = urb->status; |
518 | 520 | ||
@@ -553,12 +555,11 @@ static void usa26_instat_callback(struct urb *urb) | |||
553 | p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); | 555 | p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); |
554 | p_priv->ri_state = ((msg->ri) ? 1 : 0); | 556 | p_priv->ri_state = ((msg->ri) ? 1 : 0); |
555 | 557 | ||
556 | if (port->port.tty && !C_CLOCAL(port->port.tty) | 558 | if (old_dcd_state != p_priv->dcd_state) { |
557 | && old_dcd_state != p_priv->dcd_state) { | 559 | tty = tty_port_tty_get(&port->port); |
558 | if (old_dcd_state) | 560 | if (tty && !C_CLOCAL(tty)) |
559 | tty_hangup(port->port.tty); | 561 | tty_hangup(tty); |
560 | /* else */ | 562 | tty_kref_put(tty); |
561 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
562 | } | 563 | } |
563 | 564 | ||
564 | /* Resubmit urb so we continue receiving */ | 565 | /* Resubmit urb so we continue receiving */ |
@@ -604,11 +605,12 @@ static void usa28_indat_callback(struct urb *urb) | |||
604 | p_priv = usb_get_serial_port_data(port); | 605 | p_priv = usb_get_serial_port_data(port); |
605 | data = urb->transfer_buffer; | 606 | data = urb->transfer_buffer; |
606 | 607 | ||
607 | tty = port->port.tty; | 608 | tty =tty_port_tty_get(&port->port); |
608 | if (urb->actual_length) { | 609 | if (tty && urb->actual_length) { |
609 | tty_insert_flip_string(tty, data, urb->actual_length); | 610 | tty_insert_flip_string(tty, data, urb->actual_length); |
610 | tty_flip_buffer_push(tty); | 611 | tty_flip_buffer_push(tty); |
611 | } | 612 | } |
613 | tty_kref_put(tty); | ||
612 | 614 | ||
613 | /* Resubmit urb so we continue receiving */ | 615 | /* Resubmit urb so we continue receiving */ |
614 | urb->dev = port->serial->dev; | 616 | urb->dev = port->serial->dev; |
@@ -652,6 +654,7 @@ static void usa28_instat_callback(struct urb *urb) | |||
652 | struct usb_serial *serial; | 654 | struct usb_serial *serial; |
653 | struct usb_serial_port *port; | 655 | struct usb_serial_port *port; |
654 | struct keyspan_port_private *p_priv; | 656 | struct keyspan_port_private *p_priv; |
657 | struct tty_struct *tty; | ||
655 | int old_dcd_state; | 658 | int old_dcd_state; |
656 | int status = urb->status; | 659 | int status = urb->status; |
657 | 660 | ||
@@ -689,12 +692,11 @@ static void usa28_instat_callback(struct urb *urb) | |||
689 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); | 692 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); |
690 | p_priv->ri_state = ((msg->ri) ? 1 : 0); | 693 | p_priv->ri_state = ((msg->ri) ? 1 : 0); |
691 | 694 | ||
692 | if (port->port.tty && !C_CLOCAL(port->port.tty) | 695 | if( old_dcd_state != p_priv->dcd_state && old_dcd_state) { |
693 | && old_dcd_state != p_priv->dcd_state) { | 696 | tty = tty_port_tty_get(&port->port); |
694 | if (old_dcd_state) | 697 | if (tty && !C_CLOCAL(tty)) |
695 | tty_hangup(port->port.tty); | 698 | tty_hangup(tty); |
696 | /* else */ | 699 | tty_kref_put(tty); |
697 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
698 | } | 700 | } |
699 | 701 | ||
700 | /* Resubmit urb so we continue receiving */ | 702 | /* Resubmit urb so we continue receiving */ |
@@ -785,12 +787,11 @@ static void usa49_instat_callback(struct urb *urb) | |||
785 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); | 787 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); |
786 | p_priv->ri_state = ((msg->ri) ? 1 : 0); | 788 | p_priv->ri_state = ((msg->ri) ? 1 : 0); |
787 | 789 | ||
788 | if (port->port.tty && !C_CLOCAL(port->port.tty) | 790 | if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { |
789 | && old_dcd_state != p_priv->dcd_state) { | 791 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
790 | if (old_dcd_state) | 792 | if (tty && !C_CLOCAL(tty)) |
791 | tty_hangup(port->port.tty); | 793 | tty_hangup(tty); |
792 | /* else */ | 794 | tty_kref_put(tty); |
793 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
794 | } | 795 | } |
795 | 796 | ||
796 | /* Resubmit urb so we continue receiving */ | 797 | /* Resubmit urb so we continue receiving */ |
@@ -827,7 +828,7 @@ static void usa49_indat_callback(struct urb *urb) | |||
827 | } | 828 | } |
828 | 829 | ||
829 | port = urb->context; | 830 | port = urb->context; |
830 | tty = port->port.tty; | 831 | tty = tty_port_tty_get(&port->port); |
831 | if (tty && urb->actual_length) { | 832 | if (tty && urb->actual_length) { |
832 | /* 0x80 bit is error flag */ | 833 | /* 0x80 bit is error flag */ |
833 | if ((data[0] & 0x80) == 0) { | 834 | if ((data[0] & 0x80) == 0) { |
@@ -850,6 +851,7 @@ static void usa49_indat_callback(struct urb *urb) | |||
850 | } | 851 | } |
851 | tty_flip_buffer_push(tty); | 852 | tty_flip_buffer_push(tty); |
852 | } | 853 | } |
854 | tty_kref_put(tty); | ||
853 | 855 | ||
854 | /* Resubmit urb so we continue receiving */ | 856 | /* Resubmit urb so we continue receiving */ |
855 | urb->dev = port->serial->dev; | 857 | urb->dev = port->serial->dev; |
@@ -893,7 +895,7 @@ static void usa49wg_indat_callback(struct urb *urb) | |||
893 | return; | 895 | return; |
894 | } | 896 | } |
895 | port = serial->port[data[i++]]; | 897 | port = serial->port[data[i++]]; |
896 | tty = port->port.tty; | 898 | tty = tty_port_tty_get(&port->port); |
897 | len = data[i++]; | 899 | len = data[i++]; |
898 | 900 | ||
899 | /* 0x80 bit is error flag */ | 901 | /* 0x80 bit is error flag */ |
@@ -927,6 +929,7 @@ static void usa49wg_indat_callback(struct urb *urb) | |||
927 | } | 929 | } |
928 | if (port->port.count) | 930 | if (port->port.count) |
929 | tty_flip_buffer_push(tty); | 931 | tty_flip_buffer_push(tty); |
932 | tty_kref_put(tty); | ||
930 | } | 933 | } |
931 | } | 934 | } |
932 | 935 | ||
@@ -967,8 +970,8 @@ static void usa90_indat_callback(struct urb *urb) | |||
967 | port = urb->context; | 970 | port = urb->context; |
968 | p_priv = usb_get_serial_port_data(port); | 971 | p_priv = usb_get_serial_port_data(port); |
969 | 972 | ||
970 | tty = port->port.tty; | ||
971 | if (urb->actual_length) { | 973 | if (urb->actual_length) { |
974 | tty = tty_port_tty_get(&port->port); | ||
972 | /* if current mode is DMA, looks like usa28 format | 975 | /* if current mode is DMA, looks like usa28 format |
973 | otherwise looks like usa26 data format */ | 976 | otherwise looks like usa26 data format */ |
974 | 977 | ||
@@ -1004,6 +1007,7 @@ static void usa90_indat_callback(struct urb *urb) | |||
1004 | } | 1007 | } |
1005 | } | 1008 | } |
1006 | tty_flip_buffer_push(tty); | 1009 | tty_flip_buffer_push(tty); |
1010 | tty_kref_put(tty); | ||
1007 | } | 1011 | } |
1008 | 1012 | ||
1009 | /* Resubmit urb so we continue receiving */ | 1013 | /* Resubmit urb so we continue receiving */ |
@@ -1025,6 +1029,7 @@ static void usa90_instat_callback(struct urb *urb) | |||
1025 | struct usb_serial *serial; | 1029 | struct usb_serial *serial; |
1026 | struct usb_serial_port *port; | 1030 | struct usb_serial_port *port; |
1027 | struct keyspan_port_private *p_priv; | 1031 | struct keyspan_port_private *p_priv; |
1032 | struct tty_struct *tty; | ||
1028 | int old_dcd_state, err; | 1033 | int old_dcd_state, err; |
1029 | int status = urb->status; | 1034 | int status = urb->status; |
1030 | 1035 | ||
@@ -1053,12 +1058,11 @@ static void usa90_instat_callback(struct urb *urb) | |||
1053 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); | 1058 | p_priv->dcd_state = ((msg->dcd) ? 1 : 0); |
1054 | p_priv->ri_state = ((msg->ri) ? 1 : 0); | 1059 | p_priv->ri_state = ((msg->ri) ? 1 : 0); |
1055 | 1060 | ||
1056 | if (port->port.tty && !C_CLOCAL(port->port.tty) | 1061 | if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { |
1057 | && old_dcd_state != p_priv->dcd_state) { | 1062 | tty = tty_port_tty_get(&port->port); |
1058 | if (old_dcd_state) | 1063 | if (tty && !C_CLOCAL(tty)) |
1059 | tty_hangup(port->port.tty); | 1064 | tty_hangup(tty); |
1060 | /* else */ | 1065 | tty_kref_put(tty); |
1061 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
1062 | } | 1066 | } |
1063 | 1067 | ||
1064 | /* Resubmit urb so we continue receiving */ | 1068 | /* Resubmit urb so we continue receiving */ |
@@ -1130,12 +1134,11 @@ static void usa67_instat_callback(struct urb *urb) | |||
1130 | p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0); | 1134 | p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0); |
1131 | p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); | 1135 | p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); |
1132 | 1136 | ||
1133 | if (port->port.tty && !C_CLOCAL(port->port.tty) | 1137 | if (old_dcd_state != p_priv->dcd_state && old_dcd_state) { |
1134 | && old_dcd_state != p_priv->dcd_state) { | 1138 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
1135 | if (old_dcd_state) | 1139 | if (tty && !C_CLOCAL(tty)) |
1136 | tty_hangup(port->port.tty); | 1140 | tty_hangup(tty); |
1137 | /* else */ | 1141 | tty_kref_put(tty); |
1138 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
1139 | } | 1142 | } |
1140 | 1143 | ||
1141 | /* Resubmit urb so we continue receiving */ | 1144 | /* Resubmit urb so we continue receiving */ |
@@ -1332,7 +1335,7 @@ static void keyspan_close(struct tty_struct *tty, | |||
1332 | stop_urb(p_priv->out_urbs[i]); | 1335 | stop_urb(p_priv->out_urbs[i]); |
1333 | } | 1336 | } |
1334 | } | 1337 | } |
1335 | port->port.tty = NULL; | 1338 | tty_port_tty_set(&port->port, NULL); |
1336 | } | 1339 | } |
1337 | 1340 | ||
1338 | /* download the firmware to a pre-renumeration device */ | 1341 | /* download the firmware to a pre-renumeration device */ |
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 040040a267d9..99e9a14c5bf6 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c | |||
@@ -172,8 +172,9 @@ static void keyspan_pda_wakeup_write(struct work_struct *work) | |||
172 | struct keyspan_pda_private *priv = | 172 | struct keyspan_pda_private *priv = |
173 | container_of(work, struct keyspan_pda_private, wakeup_work); | 173 | container_of(work, struct keyspan_pda_private, wakeup_work); |
174 | struct usb_serial_port *port = priv->port; | 174 | struct usb_serial_port *port = priv->port; |
175 | 175 | struct tty_struct *tty = tty_port_tty_get(&port->port); | |
176 | tty_wakeup(port->port.tty); | 176 | tty_wakeup(tty); |
177 | tty_kref_put(tty); | ||
177 | } | 178 | } |
178 | 179 | ||
179 | static void keyspan_pda_request_unthrottle(struct work_struct *work) | 180 | static void keyspan_pda_request_unthrottle(struct work_struct *work) |
@@ -205,7 +206,7 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work) | |||
205 | static void keyspan_pda_rx_interrupt(struct urb *urb) | 206 | static void keyspan_pda_rx_interrupt(struct urb *urb) |
206 | { | 207 | { |
207 | struct usb_serial_port *port = urb->context; | 208 | struct usb_serial_port *port = urb->context; |
208 | struct tty_struct *tty = port->port.tty; | 209 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
209 | unsigned char *data = urb->transfer_buffer; | 210 | unsigned char *data = urb->transfer_buffer; |
210 | int retval; | 211 | int retval; |
211 | int status = urb->status; | 212 | int status = urb->status; |
@@ -222,7 +223,7 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) | |||
222 | /* this urb is terminated, clean up */ | 223 | /* this urb is terminated, clean up */ |
223 | dbg("%s - urb shutting down with status: %d", | 224 | dbg("%s - urb shutting down with status: %d", |
224 | __func__, status); | 225 | __func__, status); |
225 | return; | 226 | goto out; |
226 | default: | 227 | default: |
227 | dbg("%s - nonzero urb status received: %d", | 228 | dbg("%s - nonzero urb status received: %d", |
228 | __func__, status); | 229 | __func__, status); |
@@ -261,8 +262,11 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) | |||
261 | exit: | 262 | exit: |
262 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 263 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
263 | if (retval) | 264 | if (retval) |
264 | err("%s - usb_submit_urb failed with result %d", | 265 | dev_err(&port->dev, |
265 | __func__, retval); | 266 | "%s - usb_submit_urb failed with result %d", |
267 | __func__, retval); | ||
268 | out: | ||
269 | tty_kref_put(tty); | ||
266 | } | 270 | } |
267 | 271 | ||
268 | 272 | ||
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index b84dddc71124..ff3a07f5102f 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c | |||
@@ -658,7 +658,7 @@ static void klsi_105_read_bulk_callback(struct urb *urb) | |||
658 | } else { | 658 | } else { |
659 | int bytes_sent = ((__u8 *) data)[0] + | 659 | int bytes_sent = ((__u8 *) data)[0] + |
660 | ((unsigned int) ((__u8 *) data)[1] << 8); | 660 | ((unsigned int) ((__u8 *) data)[1] << 8); |
661 | tty = port->port.tty; | 661 | tty = tty_port_tty_get(&port->port); |
662 | /* we should immediately resubmit the URB, before attempting | 662 | /* we should immediately resubmit the URB, before attempting |
663 | * to pass the data on to the tty layer. But that needs locking | 663 | * to pass the data on to the tty layer. But that needs locking |
664 | * against re-entry an then mixed-up data because of | 664 | * against re-entry an then mixed-up data because of |
@@ -679,6 +679,7 @@ static void klsi_105_read_bulk_callback(struct urb *urb) | |||
679 | tty_buffer_request_room(tty, bytes_sent); | 679 | tty_buffer_request_room(tty, bytes_sent); |
680 | tty_insert_flip_string(tty, data + 2, bytes_sent); | 680 | tty_insert_flip_string(tty, data + 2, bytes_sent); |
681 | tty_flip_buffer_push(tty); | 681 | tty_flip_buffer_push(tty); |
682 | tty_kref_put(tty); | ||
682 | 683 | ||
683 | /* again lockless, but debug info only */ | 684 | /* again lockless, but debug info only */ |
684 | priv->bytes_in += bytes_sent; | 685 | priv->bytes_in += bytes_sent; |
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index deba28ec77e8..cfcf37c2b957 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c | |||
@@ -383,7 +383,7 @@ static void kobil_read_int_callback(struct urb *urb) | |||
383 | return; | 383 | return; |
384 | } | 384 | } |
385 | 385 | ||
386 | tty = port->port.tty; | 386 | tty = tty_port_tty_get(&port->port); |
387 | if (urb->actual_length) { | 387 | if (urb->actual_length) { |
388 | 388 | ||
389 | /* BEGIN DEBUG */ | 389 | /* BEGIN DEBUG */ |
@@ -405,6 +405,7 @@ static void kobil_read_int_callback(struct urb *urb) | |||
405 | tty_insert_flip_string(tty, data, urb->actual_length); | 405 | tty_insert_flip_string(tty, data, urb->actual_length); |
406 | tty_flip_buffer_push(tty); | 406 | tty_flip_buffer_push(tty); |
407 | } | 407 | } |
408 | tty_kref_put(tty); | ||
408 | /* someone sets the dev to 0 if the close method has been called */ | 409 | /* someone sets the dev to 0 if the close method has been called */ |
409 | port->interrupt_in_urb->dev = port->serial->dev; | 410 | port->interrupt_in_urb->dev = port->serial->dev; |
410 | 411 | ||
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 0ded8bd6ec85..9b2cef81cde0 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c | |||
@@ -563,10 +563,11 @@ static void mct_u232_read_int_callback(struct urb *urb) | |||
563 | * Work-a-round: handle the 'usual' bulk-in pipe here | 563 | * Work-a-round: handle the 'usual' bulk-in pipe here |
564 | */ | 564 | */ |
565 | if (urb->transfer_buffer_length > 2) { | 565 | if (urb->transfer_buffer_length > 2) { |
566 | tty = port->port.tty; | 566 | tty = tty_port_tty_get(&port->port); |
567 | if (urb->actual_length) { | 567 | if (urb->actual_length) { |
568 | tty_insert_flip_string(tty, data, urb->actual_length); | 568 | tty_insert_flip_string(tty, data, urb->actual_length); |
569 | tty_flip_buffer_push(tty); | 569 | tty_flip_buffer_push(tty); |
570 | tty_kref_put(tty); | ||
570 | } | 571 | } |
571 | goto exit; | 572 | goto exit; |
572 | } | 573 | } |
@@ -591,7 +592,7 @@ static void mct_u232_read_int_callback(struct urb *urb) | |||
591 | * to look in to this before committing any code. | 592 | * to look in to this before committing any code. |
592 | */ | 593 | */ |
593 | if (priv->last_lsr & MCT_U232_LSR_ERR) { | 594 | if (priv->last_lsr & MCT_U232_LSR_ERR) { |
594 | tty = port->port.tty; | 595 | tty = tty_port_tty_get(&port->port); |
595 | /* Overrun Error */ | 596 | /* Overrun Error */ |
596 | if (priv->last_lsr & MCT_U232_LSR_OE) { | 597 | if (priv->last_lsr & MCT_U232_LSR_OE) { |
597 | } | 598 | } |
@@ -604,6 +605,7 @@ static void mct_u232_read_int_callback(struct urb *urb) | |||
604 | /* Break Indicator */ | 605 | /* Break Indicator */ |
605 | if (priv->last_lsr & MCT_U232_LSR_BI) { | 606 | if (priv->last_lsr & MCT_U232_LSR_BI) { |
606 | } | 607 | } |
608 | tty_kref_put(tty); | ||
607 | } | 609 | } |
608 | #endif | 610 | #endif |
609 | spin_unlock_irqrestore(&priv->lock, flags); | 611 | spin_unlock_irqrestore(&priv->lock, flags); |
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 7c4917d77c0a..7b538caec37f 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c | |||
@@ -216,12 +216,13 @@ static void mos7720_bulk_in_callback(struct urb *urb) | |||
216 | 216 | ||
217 | data = urb->transfer_buffer; | 217 | data = urb->transfer_buffer; |
218 | 218 | ||
219 | tty = port->port.tty; | 219 | tty = tty_port_tty_get(&port->port); |
220 | if (tty && urb->actual_length) { | 220 | if (tty && urb->actual_length) { |
221 | tty_buffer_request_room(tty, urb->actual_length); | 221 | tty_buffer_request_room(tty, urb->actual_length); |
222 | tty_insert_flip_string(tty, data, urb->actual_length); | 222 | tty_insert_flip_string(tty, data, urb->actual_length); |
223 | tty_flip_buffer_push(tty); | 223 | tty_flip_buffer_push(tty); |
224 | } | 224 | } |
225 | tty_kref_put(tty); | ||
225 | 226 | ||
226 | if (!port->read_urb) { | 227 | if (!port->read_urb) { |
227 | dbg("URB KILLED !!!"); | 228 | dbg("URB KILLED !!!"); |
@@ -262,10 +263,11 @@ static void mos7720_bulk_out_data_callback(struct urb *urb) | |||
262 | 263 | ||
263 | dbg("Entering ........."); | 264 | dbg("Entering ........."); |
264 | 265 | ||
265 | tty = mos7720_port->port->port.tty; | 266 | tty = tty_port_tty_get(&mos7720_port->port->port); |
266 | 267 | ||
267 | if (tty && mos7720_port->open) | 268 | if (tty && mos7720_port->open) |
268 | tty_wakeup(tty); | 269 | tty_wakeup(tty); |
270 | tty_kref_put(tty); | ||
269 | } | 271 | } |
270 | 272 | ||
271 | /* | 273 | /* |
@@ -1267,29 +1269,6 @@ static int get_lsr_info(struct tty_struct *tty, | |||
1267 | return 0; | 1269 | return 0; |
1268 | } | 1270 | } |
1269 | 1271 | ||
1270 | /* | ||
1271 | * get_number_bytes_avail - get number of bytes available | ||
1272 | * | ||
1273 | * Purpose: Let user call ioctl to get the count of number of bytes available. | ||
1274 | */ | ||
1275 | static int get_number_bytes_avail(struct moschip_port *mos7720_port, | ||
1276 | unsigned int __user *value) | ||
1277 | { | ||
1278 | unsigned int result = 0; | ||
1279 | struct tty_struct *tty = mos7720_port->port->port.tty; | ||
1280 | |||
1281 | if (!tty) | ||
1282 | return -ENOIOCTLCMD; | ||
1283 | |||
1284 | result = tty->read_cnt; | ||
1285 | |||
1286 | dbg("%s(%d) = %d", __func__, mos7720_port->port->number, result); | ||
1287 | if (copy_to_user(value, &result, sizeof(int))) | ||
1288 | return -EFAULT; | ||
1289 | |||
1290 | return -ENOIOCTLCMD; | ||
1291 | } | ||
1292 | |||
1293 | static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd, | 1272 | static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd, |
1294 | unsigned int __user *value) | 1273 | unsigned int __user *value) |
1295 | { | 1274 | { |
@@ -1409,13 +1388,6 @@ static int mos7720_ioctl(struct tty_struct *tty, struct file *file, | |||
1409 | dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); | 1388 | dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); |
1410 | 1389 | ||
1411 | switch (cmd) { | 1390 | switch (cmd) { |
1412 | case TIOCINQ: | ||
1413 | /* return number of bytes available */ | ||
1414 | dbg("%s (%d) TIOCINQ", __func__, port->number); | ||
1415 | return get_number_bytes_avail(mos7720_port, | ||
1416 | (unsigned int __user *)arg); | ||
1417 | break; | ||
1418 | |||
1419 | case TIOCSERGETLSR: | 1391 | case TIOCSERGETLSR: |
1420 | dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); | 1392 | dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); |
1421 | return get_lsr_info(tty, mos7720_port, | 1393 | return get_lsr_info(tty, mos7720_port, |
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 09d82062b973..60543d79ef56 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
@@ -709,12 +709,13 @@ static void mos7840_bulk_in_callback(struct urb *urb) | |||
709 | dbg("%s", "Entering ........... \n"); | 709 | dbg("%s", "Entering ........... \n"); |
710 | 710 | ||
711 | if (urb->actual_length) { | 711 | if (urb->actual_length) { |
712 | tty = mos7840_port->port->port.tty; | 712 | tty = tty_port_tty_get(&mos7840_port->port->port); |
713 | if (tty) { | 713 | if (tty) { |
714 | tty_buffer_request_room(tty, urb->actual_length); | 714 | tty_buffer_request_room(tty, urb->actual_length); |
715 | tty_insert_flip_string(tty, data, urb->actual_length); | 715 | tty_insert_flip_string(tty, data, urb->actual_length); |
716 | dbg(" %s \n", data); | 716 | dbg(" %s \n", data); |
717 | tty_flip_buffer_push(tty); | 717 | tty_flip_buffer_push(tty); |
718 | tty_kref_put(tty); | ||
718 | } | 719 | } |
719 | mos7840_port->icount.rx += urb->actual_length; | 720 | mos7840_port->icount.rx += urb->actual_length; |
720 | smp_wmb(); | 721 | smp_wmb(); |
@@ -773,10 +774,10 @@ static void mos7840_bulk_out_data_callback(struct urb *urb) | |||
773 | 774 | ||
774 | dbg("%s \n", "Entering ........."); | 775 | dbg("%s \n", "Entering ........."); |
775 | 776 | ||
776 | tty = mos7840_port->port->port.tty; | 777 | tty = tty_port_tty_get(&mos7840_port->port->port); |
777 | |||
778 | if (tty && mos7840_port->open) | 778 | if (tty && mos7840_port->open) |
779 | tty_wakeup(tty); | 779 | tty_wakeup(tty); |
780 | tty_kref_put(tty); | ||
780 | 781 | ||
781 | } | 782 | } |
782 | 783 | ||
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index d6736531a0fa..bcdcbb822705 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c | |||
@@ -64,12 +64,13 @@ static void navman_read_int_callback(struct urb *urb) | |||
64 | usb_serial_debug_data(debug, &port->dev, __func__, | 64 | usb_serial_debug_data(debug, &port->dev, __func__, |
65 | urb->actual_length, data); | 65 | urb->actual_length, data); |
66 | 66 | ||
67 | tty = port->port.tty; | 67 | tty = tty_port_tty_get(&port->port); |
68 | if (tty && urb->actual_length) { | 68 | if (tty && urb->actual_length) { |
69 | tty_buffer_request_room(tty, urb->actual_length); | 69 | tty_buffer_request_room(tty, urb->actual_length); |
70 | tty_insert_flip_string(tty, data, urb->actual_length); | 70 | tty_insert_flip_string(tty, data, urb->actual_length); |
71 | tty_flip_buffer_push(tty); | 71 | tty_flip_buffer_push(tty); |
72 | } | 72 | } |
73 | tty_kref_put(tty); | ||
73 | 74 | ||
74 | exit: | 75 | exit: |
75 | result = usb_submit_urb(urb, GFP_ATOMIC); | 76 | result = usb_submit_urb(urb, GFP_ATOMIC); |
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index ae8e227f3db2..c4d70b0f1e48 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c | |||
@@ -172,7 +172,7 @@ static int omninet_open(struct tty_struct *tty, | |||
172 | dbg("%s - port %d", __func__, port->number); | 172 | dbg("%s - port %d", __func__, port->number); |
173 | 173 | ||
174 | wport = serial->port[1]; | 174 | wport = serial->port[1]; |
175 | wport->port.tty = tty; /* FIXME */ | 175 | tty_port_tty_set(&wport->port, tty); |
176 | 176 | ||
177 | /* Start reading from the device */ | 177 | /* Start reading from the device */ |
178 | usb_fill_bulk_urb(port->read_urb, serial->dev, | 178 | usb_fill_bulk_urb(port->read_urb, serial->dev, |
@@ -229,9 +229,11 @@ static void omninet_read_bulk_callback(struct urb *urb) | |||
229 | } | 229 | } |
230 | 230 | ||
231 | if (urb->actual_length && header->oh_len) { | 231 | if (urb->actual_length && header->oh_len) { |
232 | tty_insert_flip_string(port->port.tty, | 232 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
233 | data + OMNINET_DATAOFFSET, header->oh_len); | 233 | tty_insert_flip_string(tty, data + OMNINET_DATAOFFSET, |
234 | tty_flip_buffer_push(port->port.tty); | 234 | header->oh_len); |
235 | tty_flip_buffer_push(tty); | ||
236 | tty_kref_put(tty); | ||
235 | } | 237 | } |
236 | 238 | ||
237 | /* Continue trying to always read */ | 239 | /* Continue trying to always read */ |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 73f8277f88f2..6b1727e751e3 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -571,14 +571,14 @@ static void option_indat_callback(struct urb *urb) | |||
571 | dbg("%s: nonzero status: %d on endpoint %02x.", | 571 | dbg("%s: nonzero status: %d on endpoint %02x.", |
572 | __func__, status, endpoint); | 572 | __func__, status, endpoint); |
573 | } else { | 573 | } else { |
574 | tty = port->port.tty; | 574 | tty = tty_port_tty_get(&port->port); |
575 | if (urb->actual_length) { | 575 | if (urb->actual_length) { |
576 | tty_buffer_request_room(tty, urb->actual_length); | 576 | tty_buffer_request_room(tty, urb->actual_length); |
577 | tty_insert_flip_string(tty, data, urb->actual_length); | 577 | tty_insert_flip_string(tty, data, urb->actual_length); |
578 | tty_flip_buffer_push(tty); | 578 | tty_flip_buffer_push(tty); |
579 | } else { | 579 | } else |
580 | dbg("%s: empty read urb received", __func__); | 580 | dbg("%s: empty read urb received", __func__); |
581 | } | 581 | tty_kref_put(tty); |
582 | 582 | ||
583 | /* Resubmit urb so we continue receiving */ | 583 | /* Resubmit urb so we continue receiving */ |
584 | if (port->port.count && status != -ESHUTDOWN) { | 584 | if (port->port.count && status != -ESHUTDOWN) { |
@@ -647,9 +647,13 @@ static void option_instat_callback(struct urb *urb) | |||
647 | portdata->dsr_state = ((signals & 0x02) ? 1 : 0); | 647 | portdata->dsr_state = ((signals & 0x02) ? 1 : 0); |
648 | portdata->ri_state = ((signals & 0x08) ? 1 : 0); | 648 | portdata->ri_state = ((signals & 0x08) ? 1 : 0); |
649 | 649 | ||
650 | if (port->port.tty && !C_CLOCAL(port->port.tty) && | 650 | if (old_dcd_state && !portdata->dcd_state) { |
651 | old_dcd_state && !portdata->dcd_state) | 651 | struct tty_struct *tty = |
652 | tty_hangup(port->port.tty); | 652 | tty_port_tty_get(&port->port); |
653 | if (tty && !C_CLOCAL(tty)) | ||
654 | tty_hangup(tty); | ||
655 | tty_kref_put(tty); | ||
656 | } | ||
653 | } else { | 657 | } else { |
654 | dbg("%s: type %x req %x", __func__, | 658 | dbg("%s: type %x req %x", __func__, |
655 | req_pkt->bRequestType, req_pkt->bRequest); | 659 | req_pkt->bRequestType, req_pkt->bRequest); |
@@ -793,7 +797,7 @@ static void option_close(struct tty_struct *tty, | |||
793 | for (i = 0; i < N_OUT_URB; i++) | 797 | for (i = 0; i < N_OUT_URB; i++) |
794 | usb_kill_urb(portdata->out_urbs[i]); | 798 | usb_kill_urb(portdata->out_urbs[i]); |
795 | } | 799 | } |
796 | port->port.tty = NULL; /* FIXME */ | 800 | tty_port_tty_set(&port->port, NULL); |
797 | } | 801 | } |
798 | 802 | ||
799 | /* Helper functions used by option_setup_urbs */ | 803 | /* Helper functions used by option_setup_urbs */ |
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 81db5715ee25..ba551f00f16f 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c | |||
@@ -224,10 +224,6 @@ struct oti6858_private { | |||
224 | struct usb_serial_port *port; /* USB port with which associated */ | 224 | struct usb_serial_port *port; /* USB port with which associated */ |
225 | }; | 225 | }; |
226 | 226 | ||
227 | #undef dbg | ||
228 | /* #define dbg(format, arg...) printk(KERN_INFO "%s: " format "\n", __FILE__, ## arg) */ | ||
229 | #define dbg(format, arg...) printk(KERN_INFO "" format "\n", ## arg) | ||
230 | |||
231 | static void setup_line(struct work_struct *work) | 227 | static void setup_line(struct work_struct *work) |
232 | { | 228 | { |
233 | struct oti6858_private *priv = container_of(work, | 229 | struct oti6858_private *priv = container_of(work, |
@@ -1002,11 +998,12 @@ static void oti6858_read_bulk_callback(struct urb *urb) | |||
1002 | return; | 998 | return; |
1003 | } | 999 | } |
1004 | 1000 | ||
1005 | tty = port->port.tty; | 1001 | tty = tty_port_tty_get(&port->port); |
1006 | if (tty != NULL && urb->actual_length > 0) { | 1002 | if (tty != NULL && urb->actual_length > 0) { |
1007 | tty_insert_flip_string(tty, data, urb->actual_length); | 1003 | tty_insert_flip_string(tty, data, urb->actual_length); |
1008 | tty_flip_buffer_push(tty); | 1004 | tty_flip_buffer_push(tty); |
1009 | } | 1005 | } |
1006 | tty_kref_put(tty); | ||
1010 | 1007 | ||
1011 | /* schedule the interrupt urb if we are still open */ | 1008 | /* schedule the interrupt urb if we are still open */ |
1012 | if (port->port.count != 0) { | 1009 | if (port->port.count != 0) { |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 1ede1441cb1b..908437847165 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -154,7 +154,6 @@ struct pl2303_private { | |||
154 | wait_queue_head_t delta_msr_wait; | 154 | wait_queue_head_t delta_msr_wait; |
155 | u8 line_control; | 155 | u8 line_control; |
156 | u8 line_status; | 156 | u8 line_status; |
157 | u8 termios_initialized; | ||
158 | enum pl2303_type type; | 157 | enum pl2303_type type; |
159 | }; | 158 | }; |
160 | 159 | ||
@@ -526,16 +525,6 @@ static void pl2303_set_termios(struct tty_struct *tty, | |||
526 | 525 | ||
527 | dbg("%s - port %d", __func__, port->number); | 526 | dbg("%s - port %d", __func__, port->number); |
528 | 527 | ||
529 | spin_lock_irqsave(&priv->lock, flags); | ||
530 | if (!priv->termios_initialized) { | ||
531 | *(tty->termios) = tty_std_termios; | ||
532 | tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; | ||
533 | tty->termios->c_ispeed = 9600; | ||
534 | tty->termios->c_ospeed = 9600; | ||
535 | priv->termios_initialized = 1; | ||
536 | } | ||
537 | spin_unlock_irqrestore(&priv->lock, flags); | ||
538 | |||
539 | /* The PL2303 is reported to lose bytes if you change | 528 | /* The PL2303 is reported to lose bytes if you change |
540 | serial settings even to the same values as before. Thus | 529 | serial settings even to the same values as before. Thus |
541 | we actually need to filter in this specific case */ | 530 | we actually need to filter in this specific case */ |
@@ -1057,7 +1046,7 @@ static void pl2303_read_bulk_callback(struct urb *urb) | |||
1057 | tty_flag = TTY_FRAME; | 1046 | tty_flag = TTY_FRAME; |
1058 | dbg("%s - tty_flag = %d", __func__, tty_flag); | 1047 | dbg("%s - tty_flag = %d", __func__, tty_flag); |
1059 | 1048 | ||
1060 | tty = port->port.tty; | 1049 | tty = tty_port_tty_get(&port->port); |
1061 | if (tty && urb->actual_length) { | 1050 | if (tty && urb->actual_length) { |
1062 | tty_buffer_request_room(tty, urb->actual_length + 1); | 1051 | tty_buffer_request_room(tty, urb->actual_length + 1); |
1063 | /* overrun is special, not associated with a char */ | 1052 | /* overrun is special, not associated with a char */ |
@@ -1067,7 +1056,7 @@ static void pl2303_read_bulk_callback(struct urb *urb) | |||
1067 | tty_insert_flip_char(tty, data[i], tty_flag); | 1056 | tty_insert_flip_char(tty, data[i], tty_flag); |
1068 | tty_flip_buffer_push(tty); | 1057 | tty_flip_buffer_push(tty); |
1069 | } | 1058 | } |
1070 | 1059 | tty_kref_put(tty); | |
1071 | /* Schedule the next read _if_ we are still open */ | 1060 | /* Schedule the next read _if_ we are still open */ |
1072 | if (port->port.count) { | 1061 | if (port->port.count) { |
1073 | urb->dev = port->serial->dev; | 1062 | urb->dev = port->serial->dev; |
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index def52d07a4ea..72903ac9f5c0 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c | |||
@@ -217,6 +217,7 @@ static void safe_read_bulk_callback(struct urb *urb) | |||
217 | struct usb_serial_port *port = urb->context; | 217 | struct usb_serial_port *port = urb->context; |
218 | unsigned char *data = urb->transfer_buffer; | 218 | unsigned char *data = urb->transfer_buffer; |
219 | unsigned char length = urb->actual_length; | 219 | unsigned char length = urb->actual_length; |
220 | struct tty_struct *tty; | ||
220 | int result; | 221 | int result; |
221 | int status = urb->status; | 222 | int status = urb->status; |
222 | 223 | ||
@@ -242,6 +243,7 @@ static void safe_read_bulk_callback(struct urb *urb) | |||
242 | printk("\n"); | 243 | printk("\n"); |
243 | } | 244 | } |
244 | #endif | 245 | #endif |
246 | tty = tty_port_tty_get(&port->port); | ||
245 | if (safe) { | 247 | if (safe) { |
246 | __u16 fcs; | 248 | __u16 fcs; |
247 | fcs = fcs_compute10(data, length, CRC10_INITFCS); | 249 | fcs = fcs_compute10(data, length, CRC10_INITFCS); |
@@ -250,9 +252,9 @@ static void safe_read_bulk_callback(struct urb *urb) | |||
250 | if (actual_length <= (length - 2)) { | 252 | if (actual_length <= (length - 2)) { |
251 | info("%s - actual: %d", __func__, | 253 | info("%s - actual: %d", __func__, |
252 | actual_length); | 254 | actual_length); |
253 | tty_insert_flip_string(port->port.tty, | 255 | tty_insert_flip_string(tty, |
254 | data, actual_length); | 256 | data, actual_length); |
255 | tty_flip_buffer_push(port->port.tty); | 257 | tty_flip_buffer_push(tty); |
256 | } else { | 258 | } else { |
257 | err("%s - inconsistent lengths %d:%d", | 259 | err("%s - inconsistent lengths %d:%d", |
258 | __func__, actual_length, length); | 260 | __func__, actual_length, length); |
@@ -261,9 +263,10 @@ static void safe_read_bulk_callback(struct urb *urb) | |||
261 | err("%s - bad CRC %x", __func__, fcs); | 263 | err("%s - bad CRC %x", __func__, fcs); |
262 | } | 264 | } |
263 | } else { | 265 | } else { |
264 | tty_insert_flip_string(port->port.tty, data, length); | 266 | tty_insert_flip_string(tty, data, length); |
265 | tty_flip_buffer_push(port->port.tty); | 267 | tty_flip_buffer_push(tty); |
266 | } | 268 | } |
269 | tty_kref_put(tty); | ||
267 | 270 | ||
268 | /* Continue trying to always read */ | 271 | /* Continue trying to always read */ |
269 | usb_fill_bulk_urb(urb, port->serial->dev, | 272 | usb_fill_bulk_urb(urb, port->serial->dev, |
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index ea1a103c99be..8b9eaf383679 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -440,14 +440,14 @@ static void sierra_indat_callback(struct urb *urb) | |||
440 | dbg("%s: nonzero status: %d on endpoint %02x.", | 440 | dbg("%s: nonzero status: %d on endpoint %02x.", |
441 | __func__, status, endpoint); | 441 | __func__, status, endpoint); |
442 | } else { | 442 | } else { |
443 | tty = port->port.tty; | ||
444 | if (urb->actual_length) { | 443 | if (urb->actual_length) { |
444 | tty = tty_port_tty_get(&port->port); | ||
445 | tty_buffer_request_room(tty, urb->actual_length); | 445 | tty_buffer_request_room(tty, urb->actual_length); |
446 | tty_insert_flip_string(tty, data, urb->actual_length); | 446 | tty_insert_flip_string(tty, data, urb->actual_length); |
447 | tty_flip_buffer_push(tty); | 447 | tty_flip_buffer_push(tty); |
448 | } else { | 448 | tty_kref_put(tty); |
449 | } else | ||
449 | dbg("%s: empty read urb received", __func__); | 450 | dbg("%s: empty read urb received", __func__); |
450 | } | ||
451 | 451 | ||
452 | /* Resubmit urb so we continue receiving */ | 452 | /* Resubmit urb so we continue receiving */ |
453 | if (port->port.count && status != -ESHUTDOWN) { | 453 | if (port->port.count && status != -ESHUTDOWN) { |
@@ -485,6 +485,7 @@ static void sierra_instat_callback(struct urb *urb) | |||
485 | unsigned char signals = *((unsigned char *) | 485 | unsigned char signals = *((unsigned char *) |
486 | urb->transfer_buffer + | 486 | urb->transfer_buffer + |
487 | sizeof(struct usb_ctrlrequest)); | 487 | sizeof(struct usb_ctrlrequest)); |
488 | struct tty_struct *tty; | ||
488 | 489 | ||
489 | dbg("%s: signal x%x", __func__, signals); | 490 | dbg("%s: signal x%x", __func__, signals); |
490 | 491 | ||
@@ -494,9 +495,11 @@ static void sierra_instat_callback(struct urb *urb) | |||
494 | portdata->dsr_state = ((signals & 0x02) ? 1 : 0); | 495 | portdata->dsr_state = ((signals & 0x02) ? 1 : 0); |
495 | portdata->ri_state = ((signals & 0x08) ? 1 : 0); | 496 | portdata->ri_state = ((signals & 0x08) ? 1 : 0); |
496 | 497 | ||
497 | if (port->port.tty && !C_CLOCAL(port->port.tty) && | 498 | tty = tty_port_tty_get(&port->port); |
499 | if (tty && !C_CLOCAL(tty) && | ||
498 | old_dcd_state && !portdata->dcd_state) | 500 | old_dcd_state && !portdata->dcd_state) |
499 | tty_hangup(port->port.tty); | 501 | tty_hangup(tty); |
502 | tty_kref_put(tty); | ||
500 | } else { | 503 | } else { |
501 | dbg("%s: type %x req %x", __func__, | 504 | dbg("%s: type %x req %x", __func__, |
502 | req_pkt->bRequestType, req_pkt->bRequest); | 505 | req_pkt->bRequestType, req_pkt->bRequest); |
@@ -616,8 +619,7 @@ static void sierra_close(struct tty_struct *tty, | |||
616 | } | 619 | } |
617 | 620 | ||
618 | usb_kill_urb(port->interrupt_in_urb); | 621 | usb_kill_urb(port->interrupt_in_urb); |
619 | 622 | tty_port_tty_set(&port->port, NULL); | |
620 | port->port.tty = NULL; /* FIXME */ | ||
621 | } | 623 | } |
622 | 624 | ||
623 | static int sierra_startup(struct usb_serial *serial) | 625 | static int sierra_startup(struct usb_serial *serial) |
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 283cf6b36b2c..1533d6e12238 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c | |||
@@ -755,7 +755,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb) | |||
755 | tty_flag = TTY_FRAME; | 755 | tty_flag = TTY_FRAME; |
756 | dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag); | 756 | dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag); |
757 | 757 | ||
758 | tty = port->port.tty; | 758 | tty = tty_port_tty_get(&port->port); |
759 | if (tty && urb->actual_length) { | 759 | if (tty && urb->actual_length) { |
760 | tty_buffer_request_room(tty, urb->actual_length + 1); | 760 | tty_buffer_request_room(tty, urb->actual_length + 1); |
761 | /* overrun is special, not associated with a char */ | 761 | /* overrun is special, not associated with a char */ |
@@ -765,6 +765,7 @@ static void spcp8x5_read_bulk_callback(struct urb *urb) | |||
765 | tty_insert_flip_char(tty, data[i], tty_flag); | 765 | tty_insert_flip_char(tty, data[i], tty_flag); |
766 | tty_flip_buffer_push(tty); | 766 | tty_flip_buffer_push(tty); |
767 | } | 767 | } |
768 | tty_kref_put(tty); | ||
768 | 769 | ||
769 | /* Schedule the next read _if_ we are still open */ | 770 | /* Schedule the next read _if_ we are still open */ |
770 | if (port->port.count) { | 771 | if (port->port.count) { |
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 9a3e495c769c..c90237d48b0e 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c | |||
@@ -179,7 +179,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr); | |||
179 | static int ti_get_lsr(struct ti_port *tport); | 179 | static int ti_get_lsr(struct ti_port *tport); |
180 | static int ti_get_serial_info(struct ti_port *tport, | 180 | static int ti_get_serial_info(struct ti_port *tport, |
181 | struct serial_struct __user *ret_arg); | 181 | struct serial_struct __user *ret_arg); |
182 | static int ti_set_serial_info(struct ti_port *tport, | 182 | static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport, |
183 | struct serial_struct __user *new_arg); | 183 | struct serial_struct __user *new_arg); |
184 | static void ti_handle_new_msr(struct ti_port *tport, __u8 msr); | 184 | static void ti_handle_new_msr(struct ti_port *tport, __u8 msr); |
185 | 185 | ||
@@ -857,8 +857,8 @@ static int ti_ioctl(struct tty_struct *tty, struct file *file, | |||
857 | (struct serial_struct __user *)arg); | 857 | (struct serial_struct __user *)arg); |
858 | case TIOCSSERIAL: | 858 | case TIOCSSERIAL: |
859 | dbg("%s - (%d) TIOCSSERIAL", __func__, port->number); | 859 | dbg("%s - (%d) TIOCSSERIAL", __func__, port->number); |
860 | return ti_set_serial_info(tport, | 860 | return ti_set_serial_info(tty, tport, |
861 | (struct serial_struct __user *)arg); | 861 | (struct serial_struct __user *)arg); |
862 | case TIOCMIWAIT: | 862 | case TIOCMIWAIT: |
863 | dbg("%s - (%d) TIOCMIWAIT", __func__, port->number); | 863 | dbg("%s - (%d) TIOCMIWAIT", __func__, port->number); |
864 | cprev = tport->tp_icount; | 864 | cprev = tport->tp_icount; |
@@ -1211,6 +1211,7 @@ static void ti_bulk_in_callback(struct urb *urb) | |||
1211 | struct device *dev = &urb->dev->dev; | 1211 | struct device *dev = &urb->dev->dev; |
1212 | int status = urb->status; | 1212 | int status = urb->status; |
1213 | int retval = 0; | 1213 | int retval = 0; |
1214 | struct tty_struct *tty; | ||
1214 | 1215 | ||
1215 | dbg("%s", __func__); | 1216 | dbg("%s", __func__); |
1216 | 1217 | ||
@@ -1239,20 +1240,22 @@ static void ti_bulk_in_callback(struct urb *urb) | |||
1239 | return; | 1240 | return; |
1240 | } | 1241 | } |
1241 | 1242 | ||
1242 | if (port->port.tty && urb->actual_length) { | 1243 | tty = tty_port_tty_get(&port->port); |
1244 | if (tty && urb->actual_length) { | ||
1243 | usb_serial_debug_data(debug, dev, __func__, | 1245 | usb_serial_debug_data(debug, dev, __func__, |
1244 | urb->actual_length, urb->transfer_buffer); | 1246 | urb->actual_length, urb->transfer_buffer); |
1245 | 1247 | ||
1246 | if (!tport->tp_is_open) | 1248 | if (!tport->tp_is_open) |
1247 | dbg("%s - port closed, dropping data", __func__); | 1249 | dbg("%s - port closed, dropping data", __func__); |
1248 | else | 1250 | else |
1249 | ti_recv(&urb->dev->dev, port->port.tty, | 1251 | ti_recv(&urb->dev->dev, tty, |
1250 | urb->transfer_buffer, | 1252 | urb->transfer_buffer, |
1251 | urb->actual_length); | 1253 | urb->actual_length); |
1252 | 1254 | ||
1253 | spin_lock(&tport->tp_lock); | 1255 | spin_lock(&tport->tp_lock); |
1254 | tport->tp_icount.rx += urb->actual_length; | 1256 | tport->tp_icount.rx += urb->actual_length; |
1255 | spin_unlock(&tport->tp_lock); | 1257 | spin_unlock(&tport->tp_lock); |
1258 | tty_kref_put(tty); | ||
1256 | } | 1259 | } |
1257 | 1260 | ||
1258 | exit: | 1261 | exit: |
@@ -1330,7 +1333,7 @@ static void ti_send(struct ti_port *tport) | |||
1330 | { | 1333 | { |
1331 | int count, result; | 1334 | int count, result; |
1332 | struct usb_serial_port *port = tport->tp_port; | 1335 | struct usb_serial_port *port = tport->tp_port; |
1333 | struct tty_struct *tty = port->port.tty; /* FIXME */ | 1336 | struct tty_struct *tty = tty_port_tty_get(&port->port); /* FIXME */ |
1334 | unsigned long flags; | 1337 | unsigned long flags; |
1335 | 1338 | ||
1336 | 1339 | ||
@@ -1338,19 +1341,15 @@ static void ti_send(struct ti_port *tport) | |||
1338 | 1341 | ||
1339 | spin_lock_irqsave(&tport->tp_lock, flags); | 1342 | spin_lock_irqsave(&tport->tp_lock, flags); |
1340 | 1343 | ||
1341 | if (tport->tp_write_urb_in_use) { | 1344 | if (tport->tp_write_urb_in_use) |
1342 | spin_unlock_irqrestore(&tport->tp_lock, flags); | 1345 | goto unlock; |
1343 | return; | ||
1344 | } | ||
1345 | 1346 | ||
1346 | count = ti_buf_get(tport->tp_write_buf, | 1347 | count = ti_buf_get(tport->tp_write_buf, |
1347 | port->write_urb->transfer_buffer, | 1348 | port->write_urb->transfer_buffer, |
1348 | port->bulk_out_size); | 1349 | port->bulk_out_size); |
1349 | 1350 | ||
1350 | if (count == 0) { | 1351 | if (count == 0) |
1351 | spin_unlock_irqrestore(&tport->tp_lock, flags); | 1352 | goto unlock; |
1352 | return; | ||
1353 | } | ||
1354 | 1353 | ||
1355 | tport->tp_write_urb_in_use = 1; | 1354 | tport->tp_write_urb_in_use = 1; |
1356 | 1355 | ||
@@ -1380,7 +1379,13 @@ static void ti_send(struct ti_port *tport) | |||
1380 | /* more room in the buffer for new writes, wakeup */ | 1379 | /* more room in the buffer for new writes, wakeup */ |
1381 | if (tty) | 1380 | if (tty) |
1382 | tty_wakeup(tty); | 1381 | tty_wakeup(tty); |
1382 | tty_kref_put(tty); | ||
1383 | wake_up_interruptible(&tport->tp_write_wait); | 1383 | wake_up_interruptible(&tport->tp_write_wait); |
1384 | return; | ||
1385 | unlock: | ||
1386 | spin_unlock_irqrestore(&tport->tp_lock, flags); | ||
1387 | tty_kref_put(tty); | ||
1388 | return; | ||
1384 | } | 1389 | } |
1385 | 1390 | ||
1386 | 1391 | ||
@@ -1464,20 +1469,16 @@ static int ti_get_serial_info(struct ti_port *tport, | |||
1464 | } | 1469 | } |
1465 | 1470 | ||
1466 | 1471 | ||
1467 | static int ti_set_serial_info(struct ti_port *tport, | 1472 | static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport, |
1468 | struct serial_struct __user *new_arg) | 1473 | struct serial_struct __user *new_arg) |
1469 | { | 1474 | { |
1470 | struct usb_serial_port *port = tport->tp_port; | ||
1471 | struct serial_struct new_serial; | 1475 | struct serial_struct new_serial; |
1472 | 1476 | ||
1473 | if (copy_from_user(&new_serial, new_arg, sizeof(new_serial))) | 1477 | if (copy_from_user(&new_serial, new_arg, sizeof(new_serial))) |
1474 | return -EFAULT; | 1478 | return -EFAULT; |
1475 | 1479 | ||
1476 | tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS; | 1480 | tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS; |
1477 | /* FIXME */ | 1481 | tty->low_latency = (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
1478 | if (port->port.tty) | ||
1479 | port->port.tty->low_latency = | ||
1480 | (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0; | ||
1481 | tport->tp_closing_wait = new_serial.closing_wait; | 1482 | tport->tp_closing_wait = new_serial.closing_wait; |
1482 | 1483 | ||
1483 | return 0; | 1484 | return 0; |
@@ -1510,7 +1511,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) | |||
1510 | tport->tp_msr = msr & TI_MSR_MASK; | 1511 | tport->tp_msr = msr & TI_MSR_MASK; |
1511 | 1512 | ||
1512 | /* handle CTS flow control */ | 1513 | /* handle CTS flow control */ |
1513 | tty = tport->tp_port->port.tty; | 1514 | tty = tty_port_tty_get(&tport->tp_port->port); |
1514 | if (tty && C_CRTSCTS(tty)) { | 1515 | if (tty && C_CRTSCTS(tty)) { |
1515 | if (msr & TI_MSR_CTS) { | 1516 | if (msr & TI_MSR_CTS) { |
1516 | tty->hw_stopped = 0; | 1517 | tty->hw_stopped = 0; |
@@ -1519,6 +1520,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) | |||
1519 | tty->hw_stopped = 1; | 1520 | tty->hw_stopped = 1; |
1520 | } | 1521 | } |
1521 | } | 1522 | } |
1523 | tty_kref_put(tty); | ||
1522 | } | 1524 | } |
1523 | 1525 | ||
1524 | 1526 | ||
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 4f7f9e3ae0a4..e7d4246027b2 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -214,7 +214,7 @@ static int serial_open (struct tty_struct *tty, struct file *filp) | |||
214 | /* set up our port structure making the tty driver | 214 | /* set up our port structure making the tty driver |
215 | * remember our port object, and us it */ | 215 | * remember our port object, and us it */ |
216 | tty->driver_data = port; | 216 | tty->driver_data = port; |
217 | port->port.tty = tty; | 217 | tty_port_tty_set(&port->port, tty); |
218 | 218 | ||
219 | if (port->port.count == 1) { | 219 | if (port->port.count == 1) { |
220 | 220 | ||
@@ -246,7 +246,7 @@ bailout_module_put: | |||
246 | bailout_mutex_unlock: | 246 | bailout_mutex_unlock: |
247 | port->port.count = 0; | 247 | port->port.count = 0; |
248 | tty->driver_data = NULL; | 248 | tty->driver_data = NULL; |
249 | port->port.tty = NULL; | 249 | tty_port_tty_set(&port->port, NULL); |
250 | mutex_unlock(&port->mutex); | 250 | mutex_unlock(&port->mutex); |
251 | bailout_kref_put: | 251 | bailout_kref_put: |
252 | usb_serial_put(serial); | 252 | usb_serial_put(serial); |
@@ -276,10 +276,11 @@ static void serial_close(struct tty_struct *tty, struct file *filp) | |||
276 | port->serial->type->close(tty, port, filp); | 276 | port->serial->type->close(tty, port, filp); |
277 | 277 | ||
278 | if (port->port.count == (port->console? 1 : 0)) { | 278 | if (port->port.count == (port->console? 1 : 0)) { |
279 | if (port->port.tty) { | 279 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
280 | if (port->port.tty->driver_data) | 280 | if (tty) { |
281 | port->port.tty->driver_data = NULL; | 281 | if (tty->driver_data) |
282 | port->port.tty = NULL; | 282 | tty->driver_data = NULL; |
283 | tty_port_tty_set(&port->port, NULL); | ||
283 | } | 284 | } |
284 | } | 285 | } |
285 | 286 | ||
@@ -508,11 +509,12 @@ static void usb_serial_port_work(struct work_struct *work) | |||
508 | if (!port) | 509 | if (!port) |
509 | return; | 510 | return; |
510 | 511 | ||
511 | tty = port->port.tty; | 512 | tty = tty_port_tty_get(&port->port); |
512 | if (!tty) | 513 | if (!tty) |
513 | return; | 514 | return; |
514 | 515 | ||
515 | tty_wakeup(tty); | 516 | tty_wakeup(tty); |
517 | tty_kref_put(tty); | ||
516 | } | 518 | } |
517 | 519 | ||
518 | static void port_release(struct device *dev) | 520 | static void port_release(struct device *dev) |
@@ -819,6 +821,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
819 | port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); | 821 | port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); |
820 | if (!port) | 822 | if (!port) |
821 | goto probe_error; | 823 | goto probe_error; |
824 | tty_port_init(&port->port); | ||
822 | port->serial = serial; | 825 | port->serial = serial; |
823 | spin_lock_init(&port->lock); | 826 | spin_lock_init(&port->lock); |
824 | mutex_init(&port->mutex); | 827 | mutex_init(&port->mutex); |
@@ -1040,8 +1043,11 @@ void usb_serial_disconnect(struct usb_interface *interface) | |||
1040 | for (i = 0; i < serial->num_ports; ++i) { | 1043 | for (i = 0; i < serial->num_ports; ++i) { |
1041 | port = serial->port[i]; | 1044 | port = serial->port[i]; |
1042 | if (port) { | 1045 | if (port) { |
1043 | if (port->port.tty) | 1046 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
1044 | tty_hangup(port->port.tty); | 1047 | if (tty) { |
1048 | tty_hangup(tty); | ||
1049 | tty_kref_put(tty); | ||
1050 | } | ||
1045 | kill_traffic(port); | 1051 | kill_traffic(port); |
1046 | } | 1052 | } |
1047 | } | 1053 | } |
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index cf8924f9a2cc..a6d1c75a1c89 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c | |||
@@ -499,7 +499,7 @@ static void visor_read_bulk_callback(struct urb *urb) | |||
499 | int status = urb->status; | 499 | int status = urb->status; |
500 | struct tty_struct *tty; | 500 | struct tty_struct *tty; |
501 | int result; | 501 | int result; |
502 | int available_room; | 502 | int available_room = 0; |
503 | 503 | ||
504 | dbg("%s - port %d", __func__, port->number); | 504 | dbg("%s - port %d", __func__, port->number); |
505 | 505 | ||
@@ -512,13 +512,17 @@ static void visor_read_bulk_callback(struct urb *urb) | |||
512 | usb_serial_debug_data(debug, &port->dev, __func__, | 512 | usb_serial_debug_data(debug, &port->dev, __func__, |
513 | urb->actual_length, data); | 513 | urb->actual_length, data); |
514 | 514 | ||
515 | tty = port->port.tty; | 515 | if (urb->actual_length) { |
516 | if (tty && urb->actual_length) { | 516 | tty = tty_port_tty_get(&port->port); |
517 | available_room = tty_buffer_request_room(tty, | 517 | if (tty) { |
518 | available_room = tty_buffer_request_room(tty, | ||
518 | urb->actual_length); | 519 | urb->actual_length); |
519 | if (available_room) { | 520 | if (available_room) { |
520 | tty_insert_flip_string(tty, data, available_room); | 521 | tty_insert_flip_string(tty, data, |
521 | tty_flip_buffer_push(tty); | 522 | available_room); |
523 | tty_flip_buffer_push(tty); | ||
524 | } | ||
525 | tty_kref_put(tty); | ||
522 | } | 526 | } |
523 | spin_lock(&priv->lock); | 527 | spin_lock(&priv->lock); |
524 | priv->bytes_in += available_room; | 528 | priv->bytes_in += available_room; |
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 3a9d14384a43..11c8b97a5177 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c | |||
@@ -1481,7 +1481,7 @@ static void rx_data_softint(struct work_struct *work) | |||
1481 | struct whiteheat_private *info = | 1481 | struct whiteheat_private *info = |
1482 | container_of(work, struct whiteheat_private, rx_work); | 1482 | container_of(work, struct whiteheat_private, rx_work); |
1483 | struct usb_serial_port *port = info->port; | 1483 | struct usb_serial_port *port = info->port; |
1484 | struct tty_struct *tty = port->port.tty; | 1484 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
1485 | struct whiteheat_urb_wrap *wrap; | 1485 | struct whiteheat_urb_wrap *wrap; |
1486 | struct urb *urb; | 1486 | struct urb *urb; |
1487 | unsigned long flags; | 1487 | unsigned long flags; |
@@ -1493,7 +1493,7 @@ static void rx_data_softint(struct work_struct *work) | |||
1493 | spin_lock_irqsave(&info->lock, flags); | 1493 | spin_lock_irqsave(&info->lock, flags); |
1494 | if (info->flags & THROTTLED) { | 1494 | if (info->flags & THROTTLED) { |
1495 | spin_unlock_irqrestore(&info->lock, flags); | 1495 | spin_unlock_irqrestore(&info->lock, flags); |
1496 | return; | 1496 | goto out; |
1497 | } | 1497 | } |
1498 | 1498 | ||
1499 | list_for_each_safe(tmp, tmp2, &info->rx_urb_q) { | 1499 | list_for_each_safe(tmp, tmp2, &info->rx_urb_q) { |
@@ -1513,7 +1513,7 @@ static void rx_data_softint(struct work_struct *work) | |||
1513 | spin_unlock_irqrestore(&info->lock, flags); | 1513 | spin_unlock_irqrestore(&info->lock, flags); |
1514 | tty_flip_buffer_push(tty); | 1514 | tty_flip_buffer_push(tty); |
1515 | schedule_work(&info->rx_work); | 1515 | schedule_work(&info->rx_work); |
1516 | return; | 1516 | goto out; |
1517 | } | 1517 | } |
1518 | tty_insert_flip_string(tty, urb->transfer_buffer, len); | 1518 | tty_insert_flip_string(tty, urb->transfer_buffer, len); |
1519 | sent += len; | 1519 | sent += len; |
@@ -1536,6 +1536,8 @@ static void rx_data_softint(struct work_struct *work) | |||
1536 | 1536 | ||
1537 | if (sent) | 1537 | if (sent) |
1538 | tty_flip_buffer_push(tty); | 1538 | tty_flip_buffer_push(tty); |
1539 | out: | ||
1540 | tty_kref_put(tty); | ||
1539 | } | 1541 | } |
1540 | 1542 | ||
1541 | 1543 | ||
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c index 385cba40ea87..06964af761c6 100644 --- a/drivers/video/backlight/mbp_nvidia_bl.c +++ b/drivers/video/backlight/mbp_nvidia_bl.c | |||
@@ -111,6 +111,4 @@ module_exit(mbp_exit); | |||
111 | MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); | 111 | MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); |
112 | MODULE_DESCRIPTION("Nvidia-based Macbook Pro Backlight Driver"); | 112 | MODULE_DESCRIPTION("Nvidia-based Macbook Pro Backlight Driver"); |
113 | MODULE_LICENSE("GPL"); | 113 | MODULE_LICENSE("GPL"); |
114 | MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,1"); | 114 | MODULE_DEVICE_TABLE(dmi, mbp_device_table); |
115 | MODULE_ALIAS("svnAppleInc.:pnMacBookPro3,2"); | ||
116 | MODULE_ALIAS("svnAppleInc.:pnMacBookPro4,1"); | ||
diff --git a/fs/Kconfig b/fs/Kconfig index 40183d94b683..f54a157a0296 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -170,8 +170,8 @@ config EXT4DEV_COMPAT | |||
170 | help | 170 | help |
171 | Starting with 2.6.28, the name of the ext4 filesystem was | 171 | Starting with 2.6.28, the name of the ext4 filesystem was |
172 | renamed from ext4dev to ext4. Unfortunately there are some | 172 | renamed from ext4dev to ext4. Unfortunately there are some |
173 | lagecy userspace programs (such as klibc's fstype) have | 173 | legacy userspace programs (such as klibc's fstype) have |
174 | "ext4dev" hardcoded. | 174 | "ext4dev" hardcoded. |
175 | 175 | ||
176 | To enable backwards compatibility so that systems that are | 176 | To enable backwards compatibility so that systems that are |
177 | still expecting to mount ext4 filesystems using ext4dev, | 177 | still expecting to mount ext4 filesystems using ext4dev, |
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index 4a551af6f3fc..17c9c5ec14c5 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt | |||
@@ -59,10 +59,12 @@ config BINFMT_SHARED_FLAT | |||
59 | help | 59 | help |
60 | Support FLAT shared libraries | 60 | Support FLAT shared libraries |
61 | 61 | ||
62 | config HAVE_AOUT | ||
63 | def_bool n | ||
64 | |||
62 | config BINFMT_AOUT | 65 | config BINFMT_AOUT |
63 | tristate "Kernel support for a.out and ECOFF binaries" | 66 | tristate "Kernel support for a.out and ECOFF binaries" |
64 | depends on ARCH_SUPPORTS_AOUT && \ | 67 | depends on HAVE_AOUT |
65 | (X86_32 || ALPHA || ARM || M68K) | ||
66 | ---help--- | 68 | ---help--- |
67 | A.out (Assembler.OUTput) is a set of formats for libraries and | 69 | A.out (Assembler.OUTput) is a set of formats for libraries and |
68 | executables used in the earliest versions of UNIX. Linux used | 70 | executables used in the earliest versions of UNIX. Linux used |
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 488eb424f662..a70d5d0890c7 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #define DEVPTS_SUPER_MAGIC 0x1cd1 | 27 | #define DEVPTS_SUPER_MAGIC 0x1cd1 |
28 | 28 | ||
29 | #define DEVPTS_DEFAULT_MODE 0600 | 29 | #define DEVPTS_DEFAULT_MODE 0600 |
30 | #define PTMX_MINOR 2 | ||
30 | 31 | ||
31 | extern int pty_limit; /* Config limit on Unix98 ptys */ | 32 | extern int pty_limit; /* Config limit on Unix98 ptys */ |
32 | static DEFINE_IDA(allocated_ptys); | 33 | static DEFINE_IDA(allocated_ptys); |
@@ -169,15 +170,7 @@ static struct file_system_type devpts_fs_type = { | |||
169 | * to the System V naming convention | 170 | * to the System V naming convention |
170 | */ | 171 | */ |
171 | 172 | ||
172 | static struct dentry *get_node(int num) | 173 | int devpts_new_index(struct inode *ptmx_inode) |
173 | { | ||
174 | char s[12]; | ||
175 | struct dentry *root = devpts_root; | ||
176 | mutex_lock(&root->d_inode->i_mutex); | ||
177 | return lookup_one_len(s, root, sprintf(s, "%d", num)); | ||
178 | } | ||
179 | |||
180 | int devpts_new_index(void) | ||
181 | { | 174 | { |
182 | int index; | 175 | int index; |
183 | int ida_ret; | 176 | int ida_ret; |
@@ -205,20 +198,21 @@ retry: | |||
205 | return index; | 198 | return index; |
206 | } | 199 | } |
207 | 200 | ||
208 | void devpts_kill_index(int idx) | 201 | void devpts_kill_index(struct inode *ptmx_inode, int idx) |
209 | { | 202 | { |
210 | mutex_lock(&allocated_ptys_lock); | 203 | mutex_lock(&allocated_ptys_lock); |
211 | ida_remove(&allocated_ptys, idx); | 204 | ida_remove(&allocated_ptys, idx); |
212 | mutex_unlock(&allocated_ptys_lock); | 205 | mutex_unlock(&allocated_ptys_lock); |
213 | } | 206 | } |
214 | 207 | ||
215 | int devpts_pty_new(struct tty_struct *tty) | 208 | int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty) |
216 | { | 209 | { |
217 | int number = tty->index; /* tty layer puts index from devpts_new_index() in here */ | 210 | int number = tty->index; /* tty layer puts index from devpts_new_index() in here */ |
218 | struct tty_driver *driver = tty->driver; | 211 | struct tty_driver *driver = tty->driver; |
219 | dev_t device = MKDEV(driver->major, driver->minor_start+number); | 212 | dev_t device = MKDEV(driver->major, driver->minor_start+number); |
220 | struct dentry *dentry; | 213 | struct dentry *dentry; |
221 | struct inode *inode = new_inode(devpts_mnt->mnt_sb); | 214 | struct inode *inode = new_inode(devpts_mnt->mnt_sb); |
215 | char s[12]; | ||
222 | 216 | ||
223 | /* We're supposed to be given the slave end of a pty */ | 217 | /* We're supposed to be given the slave end of a pty */ |
224 | BUG_ON(driver->type != TTY_DRIVER_TYPE_PTY); | 218 | BUG_ON(driver->type != TTY_DRIVER_TYPE_PTY); |
@@ -233,10 +227,15 @@ int devpts_pty_new(struct tty_struct *tty) | |||
233 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | 227 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; |
234 | init_special_inode(inode, S_IFCHR|config.mode, device); | 228 | init_special_inode(inode, S_IFCHR|config.mode, device); |
235 | inode->i_private = tty; | 229 | inode->i_private = tty; |
230 | tty->driver_data = inode; | ||
236 | 231 | ||
237 | dentry = get_node(number); | 232 | sprintf(s, "%d", number); |
238 | if (!IS_ERR(dentry) && !dentry->d_inode) { | 233 | |
239 | d_instantiate(dentry, inode); | 234 | mutex_lock(&devpts_root->d_inode->i_mutex); |
235 | |||
236 | dentry = d_alloc_name(devpts_root, s); | ||
237 | if (!IS_ERR(dentry)) { | ||
238 | d_add(dentry, inode); | ||
240 | fsnotify_create(devpts_root->d_inode, dentry); | 239 | fsnotify_create(devpts_root->d_inode, dentry); |
241 | } | 240 | } |
242 | 241 | ||
@@ -245,36 +244,31 @@ int devpts_pty_new(struct tty_struct *tty) | |||
245 | return 0; | 244 | return 0; |
246 | } | 245 | } |
247 | 246 | ||
248 | struct tty_struct *devpts_get_tty(int number) | 247 | struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number) |
249 | { | 248 | { |
250 | struct dentry *dentry = get_node(number); | 249 | BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); |
251 | struct tty_struct *tty; | ||
252 | |||
253 | tty = NULL; | ||
254 | if (!IS_ERR(dentry)) { | ||
255 | if (dentry->d_inode) | ||
256 | tty = dentry->d_inode->i_private; | ||
257 | dput(dentry); | ||
258 | } | ||
259 | 250 | ||
260 | mutex_unlock(&devpts_root->d_inode->i_mutex); | 251 | if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) |
261 | 252 | return (struct tty_struct *)pts_inode->i_private; | |
262 | return tty; | 253 | return NULL; |
263 | } | 254 | } |
264 | 255 | ||
265 | void devpts_pty_kill(int number) | 256 | void devpts_pty_kill(struct tty_struct *tty) |
266 | { | 257 | { |
267 | struct dentry *dentry = get_node(number); | 258 | struct inode *inode = tty->driver_data; |
259 | struct dentry *dentry; | ||
268 | 260 | ||
269 | if (!IS_ERR(dentry)) { | 261 | BUG_ON(inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR)); |
270 | struct inode *inode = dentry->d_inode; | 262 | |
271 | if (inode) { | 263 | mutex_lock(&devpts_root->d_inode->i_mutex); |
272 | inode->i_nlink--; | 264 | |
273 | d_delete(dentry); | 265 | dentry = d_find_alias(inode); |
274 | dput(dentry); | 266 | if (dentry && !IS_ERR(dentry)) { |
275 | } | 267 | inode->i_nlink--; |
268 | d_delete(dentry); | ||
276 | dput(dentry); | 269 | dput(dentry); |
277 | } | 270 | } |
271 | |||
278 | mutex_unlock(&devpts_root->d_inode->i_mutex); | 272 | mutex_unlock(&devpts_root->d_inode->i_mutex); |
279 | } | 273 | } |
280 | 274 | ||
diff --git a/fs/dquot.c b/fs/dquot.c index 8ec4d6cc7633..ad7e59003e04 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
@@ -895,10 +895,9 @@ static void print_warning(struct dquot *dquot, const int warntype) | |||
895 | warntype == QUOTA_NL_BSOFTBELOW || !need_print_warning(dquot)) | 895 | warntype == QUOTA_NL_BSOFTBELOW || !need_print_warning(dquot)) |
896 | return; | 896 | return; |
897 | 897 | ||
898 | mutex_lock(&tty_mutex); | ||
899 | tty = get_current_tty(); | 898 | tty = get_current_tty(); |
900 | if (!tty) | 899 | if (!tty) |
901 | goto out_lock; | 900 | return; |
902 | tty_write_message(tty, dquot->dq_sb->s_id); | 901 | tty_write_message(tty, dquot->dq_sb->s_id); |
903 | if (warntype == QUOTA_NL_ISOFTWARN || warntype == QUOTA_NL_BSOFTWARN) | 902 | if (warntype == QUOTA_NL_ISOFTWARN || warntype == QUOTA_NL_BSOFTWARN) |
904 | tty_write_message(tty, ": warning, "); | 903 | tty_write_message(tty, ": warning, "); |
@@ -926,8 +925,7 @@ static void print_warning(struct dquot *dquot, const int warntype) | |||
926 | break; | 925 | break; |
927 | } | 926 | } |
928 | tty_write_message(tty, msg); | 927 | tty_write_message(tty, msg); |
929 | out_lock: | 928 | tty_kref_put(tty); |
930 | mutex_unlock(&tty_mutex); | ||
931 | } | 929 | } |
932 | #endif | 930 | #endif |
933 | 931 | ||
diff --git a/fs/efs/super.c b/fs/efs/super.c index 567b134fa1f1..73b19cfc91fc 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c | |||
@@ -341,8 +341,6 @@ static int efs_statfs(struct dentry *dentry, struct kstatfs *buf) { | |||
341 | sb->inode_blocks * | 341 | sb->inode_blocks * |
342 | (EFS_BLOCKSIZE / sizeof(struct efs_dinode)); | 342 | (EFS_BLOCKSIZE / sizeof(struct efs_dinode)); |
343 | buf->f_ffree = sb->inode_free; /* free inodes */ | 343 | buf->f_ffree = sb->inode_free; /* free inodes */ |
344 | buf->f_fsid.val[0] = (sb->fs_magic >> 16) & 0xffff; /* fs ID */ | ||
345 | buf->f_fsid.val[1] = sb->fs_magic & 0xffff; /* fs ID */ | ||
346 | buf->f_namelen = EFS_MAXNAMELEN; /* max filename length */ | 344 | buf->f_namelen = EFS_MAXNAMELEN; /* max filename length */ |
347 | 345 | ||
348 | return 0; | 346 | return 0; |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index f46a513a5157..6690a41cdd9f 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -540,6 +540,8 @@ do { \ | |||
540 | #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */ | 540 | #define EXT4_MOUNT_JOURNAL_ASYNC_COMMIT 0x1000000 /* Journal Async Commit */ |
541 | #define EXT4_MOUNT_I_VERSION 0x2000000 /* i_version support */ | 541 | #define EXT4_MOUNT_I_VERSION 0x2000000 /* i_version support */ |
542 | #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */ | 542 | #define EXT4_MOUNT_DELALLOC 0x8000000 /* Delalloc support */ |
543 | #define EXT4_MOUNT_DATA_ERR_ABORT 0x10000000 /* Abort on file data write */ | ||
544 | |||
543 | /* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */ | 545 | /* Compatibility, for having both ext2_fs.h and ext4_fs.h included at once */ |
544 | #ifndef _LINUX_EXT2_FS_H | 546 | #ifndef _LINUX_EXT2_FS_H |
545 | #define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt | 547 | #define clear_opt(o, opt) o &= ~EXT4_MOUNT_##opt |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index ea27eaa0cfe5..dc99b4776d58 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
@@ -192,7 +192,7 @@ setversion_out: | |||
192 | case EXT4_IOC_GROUP_EXTEND: { | 192 | case EXT4_IOC_GROUP_EXTEND: { |
193 | ext4_fsblk_t n_blocks_count; | 193 | ext4_fsblk_t n_blocks_count; |
194 | struct super_block *sb = inode->i_sb; | 194 | struct super_block *sb = inode->i_sb; |
195 | int err; | 195 | int err, err2; |
196 | 196 | ||
197 | if (!capable(CAP_SYS_RESOURCE)) | 197 | if (!capable(CAP_SYS_RESOURCE)) |
198 | return -EPERM; | 198 | return -EPERM; |
@@ -206,8 +206,10 @@ setversion_out: | |||
206 | 206 | ||
207 | err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); | 207 | err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count); |
208 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); | 208 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); |
209 | jbd2_journal_flush(EXT4_SB(sb)->s_journal); | 209 | err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); |
210 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | 210 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); |
211 | if (err == 0) | ||
212 | err = err2; | ||
211 | mnt_drop_write(filp->f_path.mnt); | 213 | mnt_drop_write(filp->f_path.mnt); |
212 | 214 | ||
213 | return err; | 215 | return err; |
@@ -215,7 +217,7 @@ setversion_out: | |||
215 | case EXT4_IOC_GROUP_ADD: { | 217 | case EXT4_IOC_GROUP_ADD: { |
216 | struct ext4_new_group_data input; | 218 | struct ext4_new_group_data input; |
217 | struct super_block *sb = inode->i_sb; | 219 | struct super_block *sb = inode->i_sb; |
218 | int err; | 220 | int err, err2; |
219 | 221 | ||
220 | if (!capable(CAP_SYS_RESOURCE)) | 222 | if (!capable(CAP_SYS_RESOURCE)) |
221 | return -EPERM; | 223 | return -EPERM; |
@@ -230,8 +232,10 @@ setversion_out: | |||
230 | 232 | ||
231 | err = ext4_group_add(sb, &input); | 233 | err = ext4_group_add(sb, &input); |
232 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); | 234 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); |
233 | jbd2_journal_flush(EXT4_SB(sb)->s_journal); | 235 | err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); |
234 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | 236 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); |
237 | if (err == 0) | ||
238 | err = err2; | ||
235 | mnt_drop_write(filp->f_path.mnt); | 239 | mnt_drop_write(filp->f_path.mnt); |
236 | 240 | ||
237 | return err; | 241 | return err; |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0e661c569660..fb940c22ab0d 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -507,7 +507,8 @@ static void ext4_put_super(struct super_block *sb) | |||
507 | ext4_mb_release(sb); | 507 | ext4_mb_release(sb); |
508 | ext4_ext_release(sb); | 508 | ext4_ext_release(sb); |
509 | ext4_xattr_put_super(sb); | 509 | ext4_xattr_put_super(sb); |
510 | jbd2_journal_destroy(sbi->s_journal); | 510 | if (jbd2_journal_destroy(sbi->s_journal) < 0) |
511 | ext4_abort(sb, __func__, "Couldn't clean up the journal"); | ||
511 | sbi->s_journal = NULL; | 512 | sbi->s_journal = NULL; |
512 | if (!(sb->s_flags & MS_RDONLY)) { | 513 | if (!(sb->s_flags & MS_RDONLY)) { |
513 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 514 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
@@ -777,6 +778,9 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
777 | seq_printf(seq, ",inode_readahead_blks=%u", | 778 | seq_printf(seq, ",inode_readahead_blks=%u", |
778 | sbi->s_inode_readahead_blks); | 779 | sbi->s_inode_readahead_blks); |
779 | 780 | ||
781 | if (test_opt(sb, DATA_ERR_ABORT)) | ||
782 | seq_puts(seq, ",data_err=abort"); | ||
783 | |||
780 | ext4_show_quota_options(seq, sb); | 784 | ext4_show_quota_options(seq, sb); |
781 | return 0; | 785 | return 0; |
782 | } | 786 | } |
@@ -906,6 +910,7 @@ enum { | |||
906 | Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, | 910 | Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev, |
907 | Opt_journal_checksum, Opt_journal_async_commit, | 911 | Opt_journal_checksum, Opt_journal_async_commit, |
908 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, | 912 | Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback, |
913 | Opt_data_err_abort, Opt_data_err_ignore, | ||
909 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, | 914 | Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota, |
910 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, | 915 | Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota, |
911 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, | 916 | Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota, |
@@ -952,6 +957,8 @@ static match_table_t tokens = { | |||
952 | {Opt_data_journal, "data=journal"}, | 957 | {Opt_data_journal, "data=journal"}, |
953 | {Opt_data_ordered, "data=ordered"}, | 958 | {Opt_data_ordered, "data=ordered"}, |
954 | {Opt_data_writeback, "data=writeback"}, | 959 | {Opt_data_writeback, "data=writeback"}, |
960 | {Opt_data_err_abort, "data_err=abort"}, | ||
961 | {Opt_data_err_ignore, "data_err=ignore"}, | ||
955 | {Opt_offusrjquota, "usrjquota="}, | 962 | {Opt_offusrjquota, "usrjquota="}, |
956 | {Opt_usrjquota, "usrjquota=%s"}, | 963 | {Opt_usrjquota, "usrjquota=%s"}, |
957 | {Opt_offgrpjquota, "grpjquota="}, | 964 | {Opt_offgrpjquota, "grpjquota="}, |
@@ -1186,6 +1193,12 @@ static int parse_options(char *options, struct super_block *sb, | |||
1186 | sbi->s_mount_opt |= data_opt; | 1193 | sbi->s_mount_opt |= data_opt; |
1187 | } | 1194 | } |
1188 | break; | 1195 | break; |
1196 | case Opt_data_err_abort: | ||
1197 | set_opt(sbi->s_mount_opt, DATA_ERR_ABORT); | ||
1198 | break; | ||
1199 | case Opt_data_err_ignore: | ||
1200 | clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT); | ||
1201 | break; | ||
1189 | #ifdef CONFIG_QUOTA | 1202 | #ifdef CONFIG_QUOTA |
1190 | case Opt_usrjquota: | 1203 | case Opt_usrjquota: |
1191 | qtype = USRQUOTA; | 1204 | qtype = USRQUOTA; |
@@ -2218,6 +2231,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2218 | goto failed_mount; | 2231 | goto failed_mount; |
2219 | } | 2232 | } |
2220 | 2233 | ||
2234 | #ifdef CONFIG_PROC_FS | ||
2221 | if (ext4_proc_root) | 2235 | if (ext4_proc_root) |
2222 | sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root); | 2236 | sbi->s_proc = proc_mkdir(sb->s_id, ext4_proc_root); |
2223 | 2237 | ||
@@ -2225,6 +2239,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2225 | proc_create_data("inode_readahead_blks", 0644, sbi->s_proc, | 2239 | proc_create_data("inode_readahead_blks", 0644, sbi->s_proc, |
2226 | &ext4_ui_proc_fops, | 2240 | &ext4_ui_proc_fops, |
2227 | &sbi->s_inode_readahead_blks); | 2241 | &sbi->s_inode_readahead_blks); |
2242 | #endif | ||
2228 | 2243 | ||
2229 | bgl_lock_init(&sbi->s_blockgroup_lock); | 2244 | bgl_lock_init(&sbi->s_blockgroup_lock); |
2230 | 2245 | ||
@@ -2534,6 +2549,10 @@ static void ext4_init_journal_params(struct super_block *sb, journal_t *journal) | |||
2534 | journal->j_flags |= JBD2_BARRIER; | 2549 | journal->j_flags |= JBD2_BARRIER; |
2535 | else | 2550 | else |
2536 | journal->j_flags &= ~JBD2_BARRIER; | 2551 | journal->j_flags &= ~JBD2_BARRIER; |
2552 | if (test_opt(sb, DATA_ERR_ABORT)) | ||
2553 | journal->j_flags |= JBD2_ABORT_ON_SYNCDATA_ERR; | ||
2554 | else | ||
2555 | journal->j_flags &= ~JBD2_ABORT_ON_SYNCDATA_ERR; | ||
2537 | spin_unlock(&journal->j_state_lock); | 2556 | spin_unlock(&journal->j_state_lock); |
2538 | } | 2557 | } |
2539 | 2558 | ||
@@ -2853,7 +2872,9 @@ static void ext4_mark_recovery_complete(struct super_block *sb, | |||
2853 | journal_t *journal = EXT4_SB(sb)->s_journal; | 2872 | journal_t *journal = EXT4_SB(sb)->s_journal; |
2854 | 2873 | ||
2855 | jbd2_journal_lock_updates(journal); | 2874 | jbd2_journal_lock_updates(journal); |
2856 | jbd2_journal_flush(journal); | 2875 | if (jbd2_journal_flush(journal) < 0) |
2876 | goto out; | ||
2877 | |||
2857 | lock_super(sb); | 2878 | lock_super(sb); |
2858 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) && | 2879 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) && |
2859 | sb->s_flags & MS_RDONLY) { | 2880 | sb->s_flags & MS_RDONLY) { |
@@ -2862,6 +2883,8 @@ static void ext4_mark_recovery_complete(struct super_block *sb, | |||
2862 | ext4_commit_super(sb, es, 1); | 2883 | ext4_commit_super(sb, es, 1); |
2863 | } | 2884 | } |
2864 | unlock_super(sb); | 2885 | unlock_super(sb); |
2886 | |||
2887 | out: | ||
2865 | jbd2_journal_unlock_updates(journal); | 2888 | jbd2_journal_unlock_updates(journal); |
2866 | } | 2889 | } |
2867 | 2890 | ||
@@ -2962,7 +2985,13 @@ static void ext4_write_super_lockfs(struct super_block *sb) | |||
2962 | 2985 | ||
2963 | /* Now we set up the journal barrier. */ | 2986 | /* Now we set up the journal barrier. */ |
2964 | jbd2_journal_lock_updates(journal); | 2987 | jbd2_journal_lock_updates(journal); |
2965 | jbd2_journal_flush(journal); | 2988 | |
2989 | /* | ||
2990 | * We don't want to clear needs_recovery flag when we failed | ||
2991 | * to flush the journal. | ||
2992 | */ | ||
2993 | if (jbd2_journal_flush(journal) < 0) | ||
2994 | return; | ||
2966 | 2995 | ||
2967 | /* Journal blocked and flushed, clear needs_recovery flag. */ | 2996 | /* Journal blocked and flushed, clear needs_recovery flag. */ |
2968 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 2997 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
@@ -3402,8 +3431,12 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, | |||
3402 | * otherwise be livelocked... | 3431 | * otherwise be livelocked... |
3403 | */ | 3432 | */ |
3404 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); | 3433 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); |
3405 | jbd2_journal_flush(EXT4_SB(sb)->s_journal); | 3434 | err = jbd2_journal_flush(EXT4_SB(sb)->s_journal); |
3406 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | 3435 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); |
3436 | if (err) { | ||
3437 | path_put(&nd.path); | ||
3438 | return err; | ||
3439 | } | ||
3407 | } | 3440 | } |
3408 | 3441 | ||
3409 | err = vfs_quota_on_path(sb, type, format_id, &nd.path); | 3442 | err = vfs_quota_on_path(sb, type, format_id, &nd.path); |
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 42895d369458..9203c3332f17 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
@@ -94,7 +94,8 @@ static int __try_to_free_cp_buf(struct journal_head *jh) | |||
94 | int ret = 0; | 94 | int ret = 0; |
95 | struct buffer_head *bh = jh2bh(jh); | 95 | struct buffer_head *bh = jh2bh(jh); |
96 | 96 | ||
97 | if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) { | 97 | if (jh->b_jlist == BJ_None && !buffer_locked(bh) && |
98 | !buffer_dirty(bh) && !buffer_write_io_error(bh)) { | ||
98 | JBUFFER_TRACE(jh, "remove from checkpoint list"); | 99 | JBUFFER_TRACE(jh, "remove from checkpoint list"); |
99 | ret = __jbd2_journal_remove_checkpoint(jh) + 1; | 100 | ret = __jbd2_journal_remove_checkpoint(jh) + 1; |
100 | jbd_unlock_bh_state(bh); | 101 | jbd_unlock_bh_state(bh); |
@@ -176,21 +177,25 @@ static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh) | |||
176 | * buffers. Note that we take the buffers in the opposite ordering | 177 | * buffers. Note that we take the buffers in the opposite ordering |
177 | * from the one in which they were submitted for IO. | 178 | * from the one in which they were submitted for IO. |
178 | * | 179 | * |
180 | * Return 0 on success, and return <0 if some buffers have failed | ||
181 | * to be written out. | ||
182 | * | ||
179 | * Called with j_list_lock held. | 183 | * Called with j_list_lock held. |
180 | */ | 184 | */ |
181 | static void __wait_cp_io(journal_t *journal, transaction_t *transaction) | 185 | static int __wait_cp_io(journal_t *journal, transaction_t *transaction) |
182 | { | 186 | { |
183 | struct journal_head *jh; | 187 | struct journal_head *jh; |
184 | struct buffer_head *bh; | 188 | struct buffer_head *bh; |
185 | tid_t this_tid; | 189 | tid_t this_tid; |
186 | int released = 0; | 190 | int released = 0; |
191 | int ret = 0; | ||
187 | 192 | ||
188 | this_tid = transaction->t_tid; | 193 | this_tid = transaction->t_tid; |
189 | restart: | 194 | restart: |
190 | /* Did somebody clean up the transaction in the meanwhile? */ | 195 | /* Did somebody clean up the transaction in the meanwhile? */ |
191 | if (journal->j_checkpoint_transactions != transaction || | 196 | if (journal->j_checkpoint_transactions != transaction || |
192 | transaction->t_tid != this_tid) | 197 | transaction->t_tid != this_tid) |
193 | return; | 198 | return ret; |
194 | while (!released && transaction->t_checkpoint_io_list) { | 199 | while (!released && transaction->t_checkpoint_io_list) { |
195 | jh = transaction->t_checkpoint_io_list; | 200 | jh = transaction->t_checkpoint_io_list; |
196 | bh = jh2bh(jh); | 201 | bh = jh2bh(jh); |
@@ -210,6 +215,9 @@ restart: | |||
210 | spin_lock(&journal->j_list_lock); | 215 | spin_lock(&journal->j_list_lock); |
211 | goto restart; | 216 | goto restart; |
212 | } | 217 | } |
218 | if (unlikely(buffer_write_io_error(bh))) | ||
219 | ret = -EIO; | ||
220 | |||
213 | /* | 221 | /* |
214 | * Now in whatever state the buffer currently is, we know that | 222 | * Now in whatever state the buffer currently is, we know that |
215 | * it has been written out and so we can drop it from the list | 223 | * it has been written out and so we can drop it from the list |
@@ -219,6 +227,8 @@ restart: | |||
219 | jbd2_journal_remove_journal_head(bh); | 227 | jbd2_journal_remove_journal_head(bh); |
220 | __brelse(bh); | 228 | __brelse(bh); |
221 | } | 229 | } |
230 | |||
231 | return ret; | ||
222 | } | 232 | } |
223 | 233 | ||
224 | #define NR_BATCH 64 | 234 | #define NR_BATCH 64 |
@@ -242,7 +252,8 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) | |||
242 | * Try to flush one buffer from the checkpoint list to disk. | 252 | * Try to flush one buffer from the checkpoint list to disk. |
243 | * | 253 | * |
244 | * Return 1 if something happened which requires us to abort the current | 254 | * Return 1 if something happened which requires us to abort the current |
245 | * scan of the checkpoint list. | 255 | * scan of the checkpoint list. Return <0 if the buffer has failed to |
256 | * be written out. | ||
246 | * | 257 | * |
247 | * Called with j_list_lock held and drops it if 1 is returned | 258 | * Called with j_list_lock held and drops it if 1 is returned |
248 | * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it | 259 | * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it |
@@ -274,6 +285,9 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, | |||
274 | jbd2_log_wait_commit(journal, tid); | 285 | jbd2_log_wait_commit(journal, tid); |
275 | ret = 1; | 286 | ret = 1; |
276 | } else if (!buffer_dirty(bh)) { | 287 | } else if (!buffer_dirty(bh)) { |
288 | ret = 1; | ||
289 | if (unlikely(buffer_write_io_error(bh))) | ||
290 | ret = -EIO; | ||
277 | J_ASSERT_JH(jh, !buffer_jbddirty(bh)); | 291 | J_ASSERT_JH(jh, !buffer_jbddirty(bh)); |
278 | BUFFER_TRACE(bh, "remove from checkpoint"); | 292 | BUFFER_TRACE(bh, "remove from checkpoint"); |
279 | __jbd2_journal_remove_checkpoint(jh); | 293 | __jbd2_journal_remove_checkpoint(jh); |
@@ -281,7 +295,6 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, | |||
281 | jbd_unlock_bh_state(bh); | 295 | jbd_unlock_bh_state(bh); |
282 | jbd2_journal_remove_journal_head(bh); | 296 | jbd2_journal_remove_journal_head(bh); |
283 | __brelse(bh); | 297 | __brelse(bh); |
284 | ret = 1; | ||
285 | } else { | 298 | } else { |
286 | /* | 299 | /* |
287 | * Important: we are about to write the buffer, and | 300 | * Important: we are about to write the buffer, and |
@@ -314,6 +327,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, | |||
314 | * to disk. We submit larger chunks of data at once. | 327 | * to disk. We submit larger chunks of data at once. |
315 | * | 328 | * |
316 | * The journal should be locked before calling this function. | 329 | * The journal should be locked before calling this function. |
330 | * Called with j_checkpoint_mutex held. | ||
317 | */ | 331 | */ |
318 | int jbd2_log_do_checkpoint(journal_t *journal) | 332 | int jbd2_log_do_checkpoint(journal_t *journal) |
319 | { | 333 | { |
@@ -339,6 +353,7 @@ int jbd2_log_do_checkpoint(journal_t *journal) | |||
339 | * OK, we need to start writing disk blocks. Take one transaction | 353 | * OK, we need to start writing disk blocks. Take one transaction |
340 | * and write it. | 354 | * and write it. |
341 | */ | 355 | */ |
356 | result = 0; | ||
342 | spin_lock(&journal->j_list_lock); | 357 | spin_lock(&journal->j_list_lock); |
343 | if (!journal->j_checkpoint_transactions) | 358 | if (!journal->j_checkpoint_transactions) |
344 | goto out; | 359 | goto out; |
@@ -357,7 +372,7 @@ restart: | |||
357 | int batch_count = 0; | 372 | int batch_count = 0; |
358 | struct buffer_head *bhs[NR_BATCH]; | 373 | struct buffer_head *bhs[NR_BATCH]; |
359 | struct journal_head *jh; | 374 | struct journal_head *jh; |
360 | int retry = 0; | 375 | int retry = 0, err; |
361 | 376 | ||
362 | while (!retry && transaction->t_checkpoint_list) { | 377 | while (!retry && transaction->t_checkpoint_list) { |
363 | struct buffer_head *bh; | 378 | struct buffer_head *bh; |
@@ -371,6 +386,8 @@ restart: | |||
371 | } | 386 | } |
372 | retry = __process_buffer(journal, jh, bhs, &batch_count, | 387 | retry = __process_buffer(journal, jh, bhs, &batch_count, |
373 | transaction); | 388 | transaction); |
389 | if (retry < 0 && !result) | ||
390 | result = retry; | ||
374 | if (!retry && (need_resched() || | 391 | if (!retry && (need_resched() || |
375 | spin_needbreak(&journal->j_list_lock))) { | 392 | spin_needbreak(&journal->j_list_lock))) { |
376 | spin_unlock(&journal->j_list_lock); | 393 | spin_unlock(&journal->j_list_lock); |
@@ -395,14 +412,18 @@ restart: | |||
395 | * Now we have cleaned up the first transaction's checkpoint | 412 | * Now we have cleaned up the first transaction's checkpoint |
396 | * list. Let's clean up the second one | 413 | * list. Let's clean up the second one |
397 | */ | 414 | */ |
398 | __wait_cp_io(journal, transaction); | 415 | err = __wait_cp_io(journal, transaction); |
416 | if (!result) | ||
417 | result = err; | ||
399 | } | 418 | } |
400 | out: | 419 | out: |
401 | spin_unlock(&journal->j_list_lock); | 420 | spin_unlock(&journal->j_list_lock); |
402 | result = jbd2_cleanup_journal_tail(journal); | ||
403 | if (result < 0) | 421 | if (result < 0) |
404 | return result; | 422 | jbd2_journal_abort(journal, result); |
405 | return 0; | 423 | else |
424 | result = jbd2_cleanup_journal_tail(journal); | ||
425 | |||
426 | return (result < 0) ? result : 0; | ||
406 | } | 427 | } |
407 | 428 | ||
408 | /* | 429 | /* |
@@ -418,8 +439,9 @@ out: | |||
418 | * This is the only part of the journaling code which really needs to be | 439 | * This is the only part of the journaling code which really needs to be |
419 | * aware of transaction aborts. Checkpointing involves writing to the | 440 | * aware of transaction aborts. Checkpointing involves writing to the |
420 | * main filesystem area rather than to the journal, so it can proceed | 441 | * main filesystem area rather than to the journal, so it can proceed |
421 | * even in abort state, but we must not update the journal superblock if | 442 | * even in abort state, but we must not update the super block if |
422 | * we have an abort error outstanding. | 443 | * checkpointing may have failed. Otherwise, we would lose some metadata |
444 | * buffers which should be written-back to the filesystem. | ||
423 | */ | 445 | */ |
424 | 446 | ||
425 | int jbd2_cleanup_journal_tail(journal_t *journal) | 447 | int jbd2_cleanup_journal_tail(journal_t *journal) |
@@ -428,6 +450,9 @@ int jbd2_cleanup_journal_tail(journal_t *journal) | |||
428 | tid_t first_tid; | 450 | tid_t first_tid; |
429 | unsigned long blocknr, freed; | 451 | unsigned long blocknr, freed; |
430 | 452 | ||
453 | if (is_journal_aborted(journal)) | ||
454 | return 1; | ||
455 | |||
431 | /* OK, work out the oldest transaction remaining in the log, and | 456 | /* OK, work out the oldest transaction remaining in the log, and |
432 | * the log block it starts at. | 457 | * the log block it starts at. |
433 | * | 458 | * |
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 0d3814a35ed1..0abe02c4242a 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -504,9 +504,10 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
504 | jh = commit_transaction->t_buffers; | 504 | jh = commit_transaction->t_buffers; |
505 | 505 | ||
506 | /* If we're in abort mode, we just un-journal the buffer and | 506 | /* If we're in abort mode, we just un-journal the buffer and |
507 | release it for background writing. */ | 507 | release it. */ |
508 | 508 | ||
509 | if (is_journal_aborted(journal)) { | 509 | if (is_journal_aborted(journal)) { |
510 | clear_buffer_jbddirty(jh2bh(jh)); | ||
510 | JBUFFER_TRACE(jh, "journal is aborting: refile"); | 511 | JBUFFER_TRACE(jh, "journal is aborting: refile"); |
511 | jbd2_journal_refile_buffer(journal, jh); | 512 | jbd2_journal_refile_buffer(journal, jh); |
512 | /* If that was the last one, we need to clean up | 513 | /* If that was the last one, we need to clean up |
@@ -683,6 +684,8 @@ start_journal_io: | |||
683 | printk(KERN_WARNING | 684 | printk(KERN_WARNING |
684 | "JBD2: Detected IO errors while flushing file data " | 685 | "JBD2: Detected IO errors while flushing file data " |
685 | "on %s\n", journal->j_devname); | 686 | "on %s\n", journal->j_devname); |
687 | if (journal->j_flags & JBD2_ABORT_ON_SYNCDATA_ERR) | ||
688 | jbd2_journal_abort(journal, err); | ||
686 | err = 0; | 689 | err = 0; |
687 | } | 690 | } |
688 | 691 | ||
@@ -783,6 +786,9 @@ wait_for_iobuf: | |||
783 | /* AKPM: bforget here */ | 786 | /* AKPM: bforget here */ |
784 | } | 787 | } |
785 | 788 | ||
789 | if (err) | ||
790 | jbd2_journal_abort(journal, err); | ||
791 | |||
786 | jbd_debug(3, "JBD: commit phase 5\n"); | 792 | jbd_debug(3, "JBD: commit phase 5\n"); |
787 | 793 | ||
788 | if (!JBD2_HAS_INCOMPAT_FEATURE(journal, | 794 | if (!JBD2_HAS_INCOMPAT_FEATURE(journal, |
@@ -881,6 +887,8 @@ restart_loop: | |||
881 | if (buffer_jbddirty(bh)) { | 887 | if (buffer_jbddirty(bh)) { |
882 | JBUFFER_TRACE(jh, "add to new checkpointing trans"); | 888 | JBUFFER_TRACE(jh, "add to new checkpointing trans"); |
883 | __jbd2_journal_insert_checkpoint(jh, commit_transaction); | 889 | __jbd2_journal_insert_checkpoint(jh, commit_transaction); |
890 | if (is_journal_aborted(journal)) | ||
891 | clear_buffer_jbddirty(bh); | ||
884 | JBUFFER_TRACE(jh, "refile for checkpoint writeback"); | 892 | JBUFFER_TRACE(jh, "refile for checkpoint writeback"); |
885 | __jbd2_journal_refile_buffer(jh); | 893 | __jbd2_journal_refile_buffer(jh); |
886 | jbd_unlock_bh_state(bh); | 894 | jbd_unlock_bh_state(bh); |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 01c3901c3a07..783de118de92 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -1451,9 +1451,12 @@ recovery_error: | |||
1451 | * | 1451 | * |
1452 | * Release a journal_t structure once it is no longer in use by the | 1452 | * Release a journal_t structure once it is no longer in use by the |
1453 | * journaled object. | 1453 | * journaled object. |
1454 | * Return <0 if we couldn't clean up the journal. | ||
1454 | */ | 1455 | */ |
1455 | void jbd2_journal_destroy(journal_t *journal) | 1456 | int jbd2_journal_destroy(journal_t *journal) |
1456 | { | 1457 | { |
1458 | int err = 0; | ||
1459 | |||
1457 | /* Wait for the commit thread to wake up and die. */ | 1460 | /* Wait for the commit thread to wake up and die. */ |
1458 | journal_kill_thread(journal); | 1461 | journal_kill_thread(journal); |
1459 | 1462 | ||
@@ -1476,11 +1479,16 @@ void jbd2_journal_destroy(journal_t *journal) | |||
1476 | J_ASSERT(journal->j_checkpoint_transactions == NULL); | 1479 | J_ASSERT(journal->j_checkpoint_transactions == NULL); |
1477 | spin_unlock(&journal->j_list_lock); | 1480 | spin_unlock(&journal->j_list_lock); |
1478 | 1481 | ||
1479 | /* We can now mark the journal as empty. */ | ||
1480 | journal->j_tail = 0; | ||
1481 | journal->j_tail_sequence = ++journal->j_transaction_sequence; | ||
1482 | if (journal->j_sb_buffer) { | 1482 | if (journal->j_sb_buffer) { |
1483 | jbd2_journal_update_superblock(journal, 1); | 1483 | if (!is_journal_aborted(journal)) { |
1484 | /* We can now mark the journal as empty. */ | ||
1485 | journal->j_tail = 0; | ||
1486 | journal->j_tail_sequence = | ||
1487 | ++journal->j_transaction_sequence; | ||
1488 | jbd2_journal_update_superblock(journal, 1); | ||
1489 | } else { | ||
1490 | err = -EIO; | ||
1491 | } | ||
1484 | brelse(journal->j_sb_buffer); | 1492 | brelse(journal->j_sb_buffer); |
1485 | } | 1493 | } |
1486 | 1494 | ||
@@ -1492,6 +1500,8 @@ void jbd2_journal_destroy(journal_t *journal) | |||
1492 | jbd2_journal_destroy_revoke(journal); | 1500 | jbd2_journal_destroy_revoke(journal); |
1493 | kfree(journal->j_wbuf); | 1501 | kfree(journal->j_wbuf); |
1494 | kfree(journal); | 1502 | kfree(journal); |
1503 | |||
1504 | return err; | ||
1495 | } | 1505 | } |
1496 | 1506 | ||
1497 | 1507 | ||
@@ -1717,10 +1727,16 @@ int jbd2_journal_flush(journal_t *journal) | |||
1717 | spin_lock(&journal->j_list_lock); | 1727 | spin_lock(&journal->j_list_lock); |
1718 | while (!err && journal->j_checkpoint_transactions != NULL) { | 1728 | while (!err && journal->j_checkpoint_transactions != NULL) { |
1719 | spin_unlock(&journal->j_list_lock); | 1729 | spin_unlock(&journal->j_list_lock); |
1730 | mutex_lock(&journal->j_checkpoint_mutex); | ||
1720 | err = jbd2_log_do_checkpoint(journal); | 1731 | err = jbd2_log_do_checkpoint(journal); |
1732 | mutex_unlock(&journal->j_checkpoint_mutex); | ||
1721 | spin_lock(&journal->j_list_lock); | 1733 | spin_lock(&journal->j_list_lock); |
1722 | } | 1734 | } |
1723 | spin_unlock(&journal->j_list_lock); | 1735 | spin_unlock(&journal->j_list_lock); |
1736 | |||
1737 | if (is_journal_aborted(journal)) | ||
1738 | return -EIO; | ||
1739 | |||
1724 | jbd2_cleanup_journal_tail(journal); | 1740 | jbd2_cleanup_journal_tail(journal); |
1725 | 1741 | ||
1726 | /* Finally, mark the journal as really needing no recovery. | 1742 | /* Finally, mark the journal as really needing no recovery. |
@@ -1742,7 +1758,7 @@ int jbd2_journal_flush(journal_t *journal) | |||
1742 | J_ASSERT(journal->j_head == journal->j_tail); | 1758 | J_ASSERT(journal->j_head == journal->j_tail); |
1743 | J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); | 1759 | J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); |
1744 | spin_unlock(&journal->j_state_lock); | 1760 | spin_unlock(&journal->j_state_lock); |
1745 | return err; | 1761 | return 0; |
1746 | } | 1762 | } |
1747 | 1763 | ||
1748 | /** | 1764 | /** |
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c index 058f50f65b76..73063285b13f 100644 --- a/fs/jbd2/recovery.c +++ b/fs/jbd2/recovery.c | |||
@@ -225,7 +225,7 @@ do { \ | |||
225 | */ | 225 | */ |
226 | int jbd2_journal_recover(journal_t *journal) | 226 | int jbd2_journal_recover(journal_t *journal) |
227 | { | 227 | { |
228 | int err; | 228 | int err, err2; |
229 | journal_superblock_t * sb; | 229 | journal_superblock_t * sb; |
230 | 230 | ||
231 | struct recovery_info info; | 231 | struct recovery_info info; |
@@ -263,7 +263,10 @@ int jbd2_journal_recover(journal_t *journal) | |||
263 | journal->j_transaction_sequence = ++info.end_transaction; | 263 | journal->j_transaction_sequence = ++info.end_transaction; |
264 | 264 | ||
265 | jbd2_journal_clear_revoke(journal); | 265 | jbd2_journal_clear_revoke(journal); |
266 | sync_blockdev(journal->j_fs_dev); | 266 | err2 = sync_blockdev(journal->j_fs_dev); |
267 | if (!err) | ||
268 | err = err2; | ||
269 | |||
267 | return err; | 270 | return err; |
268 | } | 271 | } |
269 | 272 | ||
@@ -1141,8 +1141,7 @@ EXPORT_SYMBOL(sys_close); | |||
1141 | asmlinkage long sys_vhangup(void) | 1141 | asmlinkage long sys_vhangup(void) |
1142 | { | 1142 | { |
1143 | if (capable(CAP_SYS_TTY_CONFIG)) { | 1143 | if (capable(CAP_SYS_TTY_CONFIG)) { |
1144 | /* XXX: this needs locking */ | 1144 | tty_vhangup_self(); |
1145 | tty_vhangup(current->signal->tty); | ||
1146 | return 0; | 1145 | return 0; |
1147 | } | 1146 | } |
1148 | return -EPERM; | 1147 | return -EPERM; |
diff --git a/include/asm-cris/a.out.h b/include/asm-cris/a.out.h deleted file mode 100644 index c82e9f9b75f6..000000000000 --- a/include/asm-cris/a.out.h +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | #ifndef __CRIS_A_OUT_H__ | ||
2 | #define __CRIS_A_OUT_H__ | ||
3 | |||
4 | /* we don't support a.out binaries on Linux/CRIS anyway, so this is | ||
5 | * not really used but still needed because binfmt_elf.c for some reason | ||
6 | * wants to know about a.out even if there is no interpreter available... | ||
7 | */ | ||
8 | |||
9 | struct exec | ||
10 | { | ||
11 | unsigned long a_info; /* Use macros N_MAGIC, etc for access */ | ||
12 | unsigned a_text; /* length of text, in bytes */ | ||
13 | unsigned a_data; /* length of data, in bytes */ | ||
14 | unsigned a_bss; /* length of uninitialized data area for file, in bytes */ | ||
15 | unsigned a_syms; /* length of symbol table data in file, in bytes */ | ||
16 | unsigned a_entry; /* start address */ | ||
17 | unsigned a_trsize; /* length of relocation info for text, in bytes */ | ||
18 | unsigned a_drsize; /* length of relocation info for data, in bytes */ | ||
19 | }; | ||
20 | |||
21 | |||
22 | #define N_TRSIZE(a) ((a).a_trsize) | ||
23 | #define N_DRSIZE(a) ((a).a_drsize) | ||
24 | #define N_SYMSIZE(a) ((a).a_syms) | ||
25 | |||
26 | #endif | ||
diff --git a/include/asm-generic/statfs.h b/include/asm-generic/statfs.h index 1d01043e797d..6129d6802149 100644 --- a/include/asm-generic/statfs.h +++ b/include/asm-generic/statfs.h | |||
@@ -6,33 +6,64 @@ | |||
6 | typedef __kernel_fsid_t fsid_t; | 6 | typedef __kernel_fsid_t fsid_t; |
7 | #endif | 7 | #endif |
8 | 8 | ||
9 | /* | ||
10 | * Most 64-bit platforms use 'long', while most 32-bit platforms use '__u32'. | ||
11 | * Yes, they differ in signedness as well as size. | ||
12 | * Special cases can override it for themselves -- except for S390x, which | ||
13 | * is just a little too special for us. And MIPS, which I'm not touching | ||
14 | * with a 10' pole. | ||
15 | */ | ||
16 | #ifndef __statfs_word | ||
17 | #if BITS_PER_LONG == 64 | ||
18 | #define __statfs_word long | ||
19 | #else | ||
20 | #define __statfs_word __u32 | ||
21 | #endif | ||
22 | #endif | ||
23 | |||
9 | struct statfs { | 24 | struct statfs { |
10 | __u32 f_type; | 25 | __statfs_word f_type; |
11 | __u32 f_bsize; | 26 | __statfs_word f_bsize; |
12 | __u32 f_blocks; | 27 | __statfs_word f_blocks; |
13 | __u32 f_bfree; | 28 | __statfs_word f_bfree; |
14 | __u32 f_bavail; | 29 | __statfs_word f_bavail; |
15 | __u32 f_files; | 30 | __statfs_word f_files; |
16 | __u32 f_ffree; | 31 | __statfs_word f_ffree; |
17 | __kernel_fsid_t f_fsid; | 32 | __kernel_fsid_t f_fsid; |
18 | __u32 f_namelen; | 33 | __statfs_word f_namelen; |
19 | __u32 f_frsize; | 34 | __statfs_word f_frsize; |
20 | __u32 f_spare[5]; | 35 | __statfs_word f_spare[5]; |
21 | }; | 36 | }; |
22 | 37 | ||
38 | /* | ||
39 | * ARM needs to avoid the 32-bit padding at the end, for consistency | ||
40 | * between EABI and OABI | ||
41 | */ | ||
42 | #ifndef ARCH_PACK_STATFS64 | ||
43 | #define ARCH_PACK_STATFS64 | ||
44 | #endif | ||
45 | |||
23 | struct statfs64 { | 46 | struct statfs64 { |
24 | __u32 f_type; | 47 | __statfs_word f_type; |
25 | __u32 f_bsize; | 48 | __statfs_word f_bsize; |
26 | __u64 f_blocks; | 49 | __u64 f_blocks; |
27 | __u64 f_bfree; | 50 | __u64 f_bfree; |
28 | __u64 f_bavail; | 51 | __u64 f_bavail; |
29 | __u64 f_files; | 52 | __u64 f_files; |
30 | __u64 f_ffree; | 53 | __u64 f_ffree; |
31 | __kernel_fsid_t f_fsid; | 54 | __kernel_fsid_t f_fsid; |
32 | __u32 f_namelen; | 55 | __statfs_word f_namelen; |
33 | __u32 f_frsize; | 56 | __statfs_word f_frsize; |
34 | __u32 f_spare[5]; | 57 | __statfs_word f_spare[5]; |
35 | }; | 58 | } ARCH_PACK_STATFS64; |
59 | |||
60 | /* | ||
61 | * IA64 and x86_64 need to avoid the 32-bit padding at the end, | ||
62 | * to be compatible with the i386 ABI | ||
63 | */ | ||
64 | #ifndef ARCH_PACK_COMPAT_STATFS64 | ||
65 | #define ARCH_PACK_COMPAT_STATFS64 | ||
66 | #endif | ||
36 | 67 | ||
37 | struct compat_statfs64 { | 68 | struct compat_statfs64 { |
38 | __u32 f_type; | 69 | __u32 f_type; |
@@ -46,6 +77,6 @@ struct compat_statfs64 { | |||
46 | __u32 f_namelen; | 77 | __u32 f_namelen; |
47 | __u32 f_frsize; | 78 | __u32 f_frsize; |
48 | __u32 f_spare[5]; | 79 | __u32 f_spare[5]; |
49 | }; | 80 | } ARCH_PACK_COMPAT_STATFS64; |
50 | 81 | ||
51 | #endif | 82 | #endif |
diff --git a/include/asm-m32r/a.out.h b/include/asm-m32r/a.out.h deleted file mode 100644 index ab150f5c1666..000000000000 --- a/include/asm-m32r/a.out.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | #ifndef _ASM_M32R_A_OUT_H | ||
2 | #define _ASM_M32R_A_OUT_H | ||
3 | |||
4 | struct exec | ||
5 | { | ||
6 | unsigned long a_info; /* Use macros N_MAGIC, etc for access */ | ||
7 | unsigned a_text; /* length of text, in bytes */ | ||
8 | unsigned a_data; /* length of data, in bytes */ | ||
9 | unsigned a_bss; /* length of uninitialized data area for file, in bytes */ | ||
10 | unsigned a_syms; /* length of symbol table data in file, in bytes */ | ||
11 | unsigned a_entry; /* start address */ | ||
12 | unsigned a_trsize; /* length of relocation info for text, in bytes */ | ||
13 | unsigned a_drsize; /* length of relocation info for data, in bytes */ | ||
14 | }; | ||
15 | |||
16 | #define N_TRSIZE(a) ((a).a_trsize) | ||
17 | #define N_DRSIZE(a) ((a).a_drsize) | ||
18 | #define N_SYMSIZE(a) ((a).a_syms) | ||
19 | |||
20 | #endif /* _ASM_M32R_A_OUT_H */ | ||
diff --git a/include/asm-parisc/a.out.h b/include/asm-parisc/a.out.h deleted file mode 100644 index eb04e34c5bb1..000000000000 --- a/include/asm-parisc/a.out.h +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | #ifndef __PARISC_A_OUT_H__ | ||
2 | #define __PARISC_A_OUT_H__ | ||
3 | |||
4 | struct exec | ||
5 | { | ||
6 | unsigned int a_info; /* Use macros N_MAGIC, etc for access */ | ||
7 | unsigned a_text; /* length of text, in bytes */ | ||
8 | unsigned a_data; /* length of data, in bytes */ | ||
9 | unsigned a_bss; /* length of uninitialized data area for file, in bytes */ | ||
10 | unsigned a_syms; /* length of symbol table data in file, in bytes */ | ||
11 | unsigned a_entry; /* start address */ | ||
12 | unsigned a_trsize; /* length of relocation info for text, in bytes */ | ||
13 | unsigned a_drsize; /* length of relocation info for data, in bytes */ | ||
14 | }; | ||
15 | |||
16 | #define N_TRSIZE(a) ((a).a_trsize) | ||
17 | #define N_DRSIZE(a) ((a).a_drsize) | ||
18 | #define N_SYMSIZE(a) ((a).a_syms) | ||
19 | |||
20 | #endif /* __A_OUT_GNU_H__ */ | ||
diff --git a/include/asm-parisc/statfs.h b/include/asm-parisc/statfs.h index 1d2b8130b23d..324bea905dc6 100644 --- a/include/asm-parisc/statfs.h +++ b/include/asm-parisc/statfs.h | |||
@@ -1,58 +1,7 @@ | |||
1 | #ifndef _PARISC_STATFS_H | 1 | #ifndef _PARISC_STATFS_H |
2 | #define _PARISC_STATFS_H | 2 | #define _PARISC_STATFS_H |
3 | 3 | ||
4 | #ifndef __KERNEL_STRICT_NAMES | 4 | #define __statfs_word long |
5 | 5 | #include <asm-generic/statfs.h> | |
6 | #include <linux/types.h> | ||
7 | |||
8 | typedef __kernel_fsid_t fsid_t; | ||
9 | |||
10 | #endif | ||
11 | |||
12 | /* | ||
13 | * It appears that PARISC could be 64 _or_ 32 bit. | ||
14 | * 64-bit fields must be explicitly 64-bit in statfs64. | ||
15 | */ | ||
16 | struct statfs { | ||
17 | long f_type; | ||
18 | long f_bsize; | ||
19 | long f_blocks; | ||
20 | long f_bfree; | ||
21 | long f_bavail; | ||
22 | long f_files; | ||
23 | long f_ffree; | ||
24 | __kernel_fsid_t f_fsid; | ||
25 | long f_namelen; | ||
26 | long f_frsize; | ||
27 | long f_spare[5]; | ||
28 | }; | ||
29 | |||
30 | struct statfs64 { | ||
31 | long f_type; | ||
32 | long f_bsize; | ||
33 | __u64 f_blocks; | ||
34 | __u64 f_bfree; | ||
35 | __u64 f_bavail; | ||
36 | __u64 f_files; | ||
37 | __u64 f_ffree; | ||
38 | __kernel_fsid_t f_fsid; | ||
39 | long f_namelen; | ||
40 | long f_frsize; | ||
41 | long f_spare[5]; | ||
42 | }; | ||
43 | |||
44 | struct compat_statfs64 { | ||
45 | __u32 f_type; | ||
46 | __u32 f_bsize; | ||
47 | __u64 f_blocks; | ||
48 | __u64 f_bfree; | ||
49 | __u64 f_bavail; | ||
50 | __u64 f_files; | ||
51 | __u64 f_ffree; | ||
52 | __kernel_fsid_t f_fsid; | ||
53 | __u32 f_namelen; | ||
54 | __u32 f_frsize; | ||
55 | __u32 f_spare[5]; | ||
56 | }; | ||
57 | 6 | ||
58 | #endif | 7 | #endif |
diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h index ebc307817e98..f06adac7938c 100644 --- a/include/asm-x86/desc.h +++ b/include/asm-x86/desc.h | |||
@@ -351,20 +351,16 @@ static inline void set_system_intr_gate(unsigned int n, void *addr) | |||
351 | _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS); | 351 | _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS); |
352 | } | 352 | } |
353 | 353 | ||
354 | static inline void set_trap_gate(unsigned int n, void *addr) | 354 | static inline void set_system_trap_gate(unsigned int n, void *addr) |
355 | { | 355 | { |
356 | BUG_ON((unsigned)n > 0xFF); | 356 | BUG_ON((unsigned)n > 0xFF); |
357 | _set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS); | 357 | _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS); |
358 | } | 358 | } |
359 | 359 | ||
360 | static inline void set_system_gate(unsigned int n, void *addr) | 360 | static inline void set_trap_gate(unsigned int n, void *addr) |
361 | { | 361 | { |
362 | BUG_ON((unsigned)n > 0xFF); | 362 | BUG_ON((unsigned)n > 0xFF); |
363 | #ifdef CONFIG_X86_32 | 363 | _set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS); |
364 | _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS); | ||
365 | #else | ||
366 | _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS); | ||
367 | #endif | ||
368 | } | 364 | } |
369 | 365 | ||
370 | static inline void set_task_gate(unsigned int n, unsigned int gdt_entry) | 366 | static inline void set_task_gate(unsigned int n, unsigned int gdt_entry) |
@@ -379,7 +375,7 @@ static inline void set_intr_gate_ist(int n, void *addr, unsigned ist) | |||
379 | _set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS); | 375 | _set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS); |
380 | } | 376 | } |
381 | 377 | ||
382 | static inline void set_system_gate_ist(int n, void *addr, unsigned ist) | 378 | static inline void set_system_intr_gate_ist(int n, void *addr, unsigned ist) |
383 | { | 379 | { |
384 | BUG_ON((unsigned)n > 0xFF); | 380 | BUG_ON((unsigned)n > 0xFF); |
385 | _set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS); | 381 | _set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS); |
diff --git a/include/asm-x86/es7000/mpparse.h b/include/asm-x86/es7000/mpparse.h index 7b5c889d8e7d..ed5a3caae141 100644 --- a/include/asm-x86/es7000/mpparse.h +++ b/include/asm-x86/es7000/mpparse.h | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | extern int parse_unisys_oem (char *oemptr); | 6 | extern int parse_unisys_oem (char *oemptr); |
7 | extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); | 7 | extern int find_unisys_acpi_oem_table(unsigned long *oem_addr); |
8 | extern void unmap_unisys_acpi_oem_table(unsigned long oem_addr); | ||
8 | extern void setup_unisys(void); | 9 | extern void setup_unisys(void); |
9 | 10 | ||
10 | #ifndef CONFIG_X86_GENERICARCH | 11 | #ifndef CONFIG_X86_GENERICARCH |
diff --git a/include/asm-x86/fixmap_32.h b/include/asm-x86/fixmap_32.h index 784e3e759866..8844002da0e0 100644 --- a/include/asm-x86/fixmap_32.h +++ b/include/asm-x86/fixmap_32.h | |||
@@ -94,10 +94,10 @@ enum fixed_addresses { | |||
94 | * can have a single pgd entry and a single pte table: | 94 | * can have a single pgd entry and a single pte table: |
95 | */ | 95 | */ |
96 | #define NR_FIX_BTMAPS 64 | 96 | #define NR_FIX_BTMAPS 64 |
97 | #define FIX_BTMAPS_NESTING 4 | 97 | #define FIX_BTMAPS_SLOTS 4 |
98 | FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 - | 98 | FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 - |
99 | (__end_of_permanent_fixed_addresses & 255), | 99 | (__end_of_permanent_fixed_addresses & 255), |
100 | FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1, | 100 | FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1, |
101 | FIX_WP_TEST, | 101 | FIX_WP_TEST, |
102 | #ifdef CONFIG_ACPI | 102 | #ifdef CONFIG_ACPI |
103 | FIX_ACPI_BEGIN, | 103 | FIX_ACPI_BEGIN, |
diff --git a/include/asm-x86/fixmap_64.h b/include/asm-x86/fixmap_64.h index dafb24bc0424..dab4751d1307 100644 --- a/include/asm-x86/fixmap_64.h +++ b/include/asm-x86/fixmap_64.h | |||
@@ -49,6 +49,7 @@ enum fixed_addresses { | |||
49 | #ifdef CONFIG_PARAVIRT | 49 | #ifdef CONFIG_PARAVIRT |
50 | FIX_PARAVIRT_BOOTMAP, | 50 | FIX_PARAVIRT_BOOTMAP, |
51 | #endif | 51 | #endif |
52 | __end_of_permanent_fixed_addresses, | ||
52 | #ifdef CONFIG_ACPI | 53 | #ifdef CONFIG_ACPI |
53 | FIX_ACPI_BEGIN, | 54 | FIX_ACPI_BEGIN, |
54 | FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1, | 55 | FIX_ACPI_END = FIX_ACPI_BEGIN + FIX_ACPI_PAGES - 1, |
@@ -56,19 +57,18 @@ enum fixed_addresses { | |||
56 | #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT | 57 | #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT |
57 | FIX_OHCI1394_BASE, | 58 | FIX_OHCI1394_BASE, |
58 | #endif | 59 | #endif |
59 | __end_of_permanent_fixed_addresses, | ||
60 | /* | 60 | /* |
61 | * 256 temporary boot-time mappings, used by early_ioremap(), | 61 | * 256 temporary boot-time mappings, used by early_ioremap(), |
62 | * before ioremap() is functional. | 62 | * before ioremap() is functional. |
63 | * | 63 | * |
64 | * We round it up to the next 512 pages boundary so that we | 64 | * We round it up to the next 256 pages boundary so that we |
65 | * can have a single pgd entry and a single pte table: | 65 | * can have a single pgd entry and a single pte table: |
66 | */ | 66 | */ |
67 | #define NR_FIX_BTMAPS 64 | 67 | #define NR_FIX_BTMAPS 64 |
68 | #define FIX_BTMAPS_NESTING 4 | 68 | #define FIX_BTMAPS_SLOTS 4 |
69 | FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 512 - | 69 | FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 - |
70 | (__end_of_permanent_fixed_addresses & 511), | 70 | (__end_of_permanent_fixed_addresses & 255), |
71 | FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1, | 71 | FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_SLOTS - 1, |
72 | __end_of_fixed_addresses | 72 | __end_of_fixed_addresses |
73 | }; | 73 | }; |
74 | 74 | ||
diff --git a/include/asm-x86/io.h b/include/asm-x86/io.h index 72b7719523bf..a233f835e0b5 100644 --- a/include/asm-x86/io.h +++ b/include/asm-x86/io.h | |||
@@ -5,20 +5,6 @@ | |||
5 | 5 | ||
6 | #include <linux/compiler.h> | 6 | #include <linux/compiler.h> |
7 | 7 | ||
8 | /* | ||
9 | * early_ioremap() and early_iounmap() are for temporary early boot-time | ||
10 | * mappings, before the real ioremap() is functional. | ||
11 | * A boot-time mapping is currently limited to at most 16 pages. | ||
12 | */ | ||
13 | #ifndef __ASSEMBLY__ | ||
14 | extern void early_ioremap_init(void); | ||
15 | extern void early_ioremap_clear(void); | ||
16 | extern void early_ioremap_reset(void); | ||
17 | extern void *early_ioremap(unsigned long offset, unsigned long size); | ||
18 | extern void early_iounmap(void *addr, unsigned long size); | ||
19 | extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys); | ||
20 | #endif | ||
21 | |||
22 | #define build_mmio_read(name, size, type, reg, barrier) \ | 8 | #define build_mmio_read(name, size, type, reg, barrier) \ |
23 | static inline type name(const volatile void __iomem *addr) \ | 9 | static inline type name(const volatile void __iomem *addr) \ |
24 | { type ret; asm volatile("mov" size " %1,%0":reg (ret) \ | 10 | { type ret; asm volatile("mov" size " %1,%0":reg (ret) \ |
@@ -97,6 +83,7 @@ extern void early_ioremap_init(void); | |||
97 | extern void early_ioremap_clear(void); | 83 | extern void early_ioremap_clear(void); |
98 | extern void early_ioremap_reset(void); | 84 | extern void early_ioremap_reset(void); |
99 | extern void *early_ioremap(unsigned long offset, unsigned long size); | 85 | extern void *early_ioremap(unsigned long offset, unsigned long size); |
86 | extern void *early_memremap(unsigned long offset, unsigned long size); | ||
100 | extern void early_iounmap(void *addr, unsigned long size); | 87 | extern void early_iounmap(void *addr, unsigned long size); |
101 | extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys); | 88 | extern void __iomem *fix_ioremap(unsigned idx, unsigned long phys); |
102 | 89 | ||
diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h index 64429e9431a8..ee6e086b7dfe 100644 --- a/include/asm-x86/io_64.h +++ b/include/asm-x86/io_64.h | |||
@@ -165,9 +165,6 @@ static inline void *phys_to_virt(unsigned long address) | |||
165 | 165 | ||
166 | #include <asm-generic/iomap.h> | 166 | #include <asm-generic/iomap.h> |
167 | 167 | ||
168 | extern void *early_ioremap(unsigned long addr, unsigned long size); | ||
169 | extern void early_iounmap(void *addr, unsigned long size); | ||
170 | |||
171 | /* | 168 | /* |
172 | * This one maps high address device memory and turns off caching for that area. | 169 | * This one maps high address device memory and turns off caching for that area. |
173 | * it's useful if some control registers are in such an area and write combining | 170 | * it's useful if some control registers are in such an area and write combining |
diff --git a/include/asm-x86/ioctls.h b/include/asm-x86/ioctls.h index 336603512399..06752a649044 100644 --- a/include/asm-x86/ioctls.h +++ b/include/asm-x86/ioctls.h | |||
@@ -51,9 +51,15 @@ | |||
51 | #define TCSETS2 _IOW('T', 0x2B, struct termios2) | 51 | #define TCSETS2 _IOW('T', 0x2B, struct termios2) |
52 | #define TCSETSW2 _IOW('T', 0x2C, struct termios2) | 52 | #define TCSETSW2 _IOW('T', 0x2C, struct termios2) |
53 | #define TCSETSF2 _IOW('T', 0x2D, struct termios2) | 53 | #define TCSETSF2 _IOW('T', 0x2D, struct termios2) |
54 | #define TIOCGRS485 0x542E | ||
55 | #define TIOCSRS485 0x542F | ||
54 | #define TIOCGPTN _IOR('T', 0x30, unsigned int) | 56 | #define TIOCGPTN _IOR('T', 0x30, unsigned int) |
55 | /* Get Pty Number (of pty-mux device) */ | 57 | /* Get Pty Number (of pty-mux device) */ |
56 | #define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */ | 58 | #define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */ |
59 | #define TCGETX 0x5432 /* SYS5 TCGETX compatibility */ | ||
60 | #define TCSETX 0x5433 | ||
61 | #define TCSETXF 0x5434 | ||
62 | #define TCSETXW 0x5435 | ||
57 | 63 | ||
58 | #define FIONCLEX 0x5450 | 64 | #define FIONCLEX 0x5450 |
59 | #define FIOCLEX 0x5451 | 65 | #define FIOCLEX 0x5451 |
diff --git a/include/asm-x86/irqflags.h b/include/asm-x86/irqflags.h index 424acb48cd61..2bdab21f0898 100644 --- a/include/asm-x86/irqflags.h +++ b/include/asm-x86/irqflags.h | |||
@@ -166,27 +166,6 @@ static inline int raw_irqs_disabled(void) | |||
166 | return raw_irqs_disabled_flags(flags); | 166 | return raw_irqs_disabled_flags(flags); |
167 | } | 167 | } |
168 | 168 | ||
169 | /* | ||
170 | * makes the traced hardirq state match with the machine state | ||
171 | * | ||
172 | * should be a rarely used function, only in places where its | ||
173 | * otherwise impossible to know the irq state, like in traps. | ||
174 | */ | ||
175 | static inline void trace_hardirqs_fixup_flags(unsigned long flags) | ||
176 | { | ||
177 | if (raw_irqs_disabled_flags(flags)) | ||
178 | trace_hardirqs_off(); | ||
179 | else | ||
180 | trace_hardirqs_on(); | ||
181 | } | ||
182 | |||
183 | static inline void trace_hardirqs_fixup(void) | ||
184 | { | ||
185 | unsigned long flags = __raw_local_save_flags(); | ||
186 | |||
187 | trace_hardirqs_fixup_flags(flags); | ||
188 | } | ||
189 | |||
190 | #else | 169 | #else |
191 | 170 | ||
192 | #ifdef CONFIG_X86_64 | 171 | #ifdef CONFIG_X86_64 |
diff --git a/include/asm-x86/kdebug.h b/include/asm-x86/kdebug.h index 5ec3ad3e825c..fbbab66ee9df 100644 --- a/include/asm-x86/kdebug.h +++ b/include/asm-x86/kdebug.h | |||
@@ -27,10 +27,9 @@ extern void printk_address(unsigned long address, int reliable); | |||
27 | extern void die(const char *, struct pt_regs *,long); | 27 | extern void die(const char *, struct pt_regs *,long); |
28 | extern int __must_check __die(const char *, struct pt_regs *, long); | 28 | extern int __must_check __die(const char *, struct pt_regs *, long); |
29 | extern void show_registers(struct pt_regs *regs); | 29 | extern void show_registers(struct pt_regs *regs); |
30 | extern void __show_registers(struct pt_regs *, int all); | ||
31 | extern void show_trace(struct task_struct *t, struct pt_regs *regs, | 30 | extern void show_trace(struct task_struct *t, struct pt_regs *regs, |
32 | unsigned long *sp, unsigned long bp); | 31 | unsigned long *sp, unsigned long bp); |
33 | extern void __show_regs(struct pt_regs *regs); | 32 | extern void __show_regs(struct pt_regs *regs, int all); |
34 | extern void show_regs(struct pt_regs *regs); | 33 | extern void show_regs(struct pt_regs *regs); |
35 | extern unsigned long oops_begin(void); | 34 | extern unsigned long oops_begin(void); |
36 | extern void oops_end(unsigned long, struct pt_regs *, int signr); | 35 | extern void oops_end(unsigned long, struct pt_regs *, int signr); |
diff --git a/include/asm-x86/kprobes.h b/include/asm-x86/kprobes.h index bd8407863c13..8a0748d01036 100644 --- a/include/asm-x86/kprobes.h +++ b/include/asm-x86/kprobes.h | |||
@@ -82,15 +82,6 @@ struct kprobe_ctlblk { | |||
82 | struct prev_kprobe prev_kprobe; | 82 | struct prev_kprobe prev_kprobe; |
83 | }; | 83 | }; |
84 | 84 | ||
85 | /* trap3/1 are intr gates for kprobes. So, restore the status of IF, | ||
86 | * if necessary, before executing the original int3/1 (trap) handler. | ||
87 | */ | ||
88 | static inline void restore_interrupts(struct pt_regs *regs) | ||
89 | { | ||
90 | if (regs->flags & X86_EFLAGS_IF) | ||
91 | local_irq_enable(); | ||
92 | } | ||
93 | |||
94 | extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr); | 85 | extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr); |
95 | extern int kprobe_exceptions_notify(struct notifier_block *self, | 86 | extern int kprobe_exceptions_notify(struct notifier_block *self, |
96 | unsigned long val, void *data); | 87 | unsigned long val, void *data); |
diff --git a/include/asm-x86/mach-default/mach_traps.h b/include/asm-x86/mach-default/mach_traps.h index de9ac3f5c4ce..ff8778f26b84 100644 --- a/include/asm-x86/mach-default/mach_traps.h +++ b/include/asm-x86/mach-default/mach_traps.h | |||
@@ -7,12 +7,6 @@ | |||
7 | 7 | ||
8 | #include <asm/mc146818rtc.h> | 8 | #include <asm/mc146818rtc.h> |
9 | 9 | ||
10 | static inline void clear_mem_error(unsigned char reason) | ||
11 | { | ||
12 | reason = (reason & 0xf) | 4; | ||
13 | outb(reason, 0x61); | ||
14 | } | ||
15 | |||
16 | static inline unsigned char get_nmi_reason(void) | 10 | static inline unsigned char get_nmi_reason(void) |
17 | { | 11 | { |
18 | return inb(0x61); | 12 | return inb(0x61); |
diff --git a/include/asm-x86/module.h b/include/asm-x86/module.h index 48dc3e0c07d9..864f2005fc1d 100644 --- a/include/asm-x86/module.h +++ b/include/asm-x86/module.h | |||
@@ -52,8 +52,6 @@ struct mod_arch_specific {}; | |||
52 | #define MODULE_PROC_FAMILY "EFFICEON " | 52 | #define MODULE_PROC_FAMILY "EFFICEON " |
53 | #elif defined CONFIG_MWINCHIPC6 | 53 | #elif defined CONFIG_MWINCHIPC6 |
54 | #define MODULE_PROC_FAMILY "WINCHIPC6 " | 54 | #define MODULE_PROC_FAMILY "WINCHIPC6 " |
55 | #elif defined CONFIG_MWINCHIP2 | ||
56 | #define MODULE_PROC_FAMILY "WINCHIP2 " | ||
57 | #elif defined CONFIG_MWINCHIP3D | 55 | #elif defined CONFIG_MWINCHIP3D |
58 | #define MODULE_PROC_FAMILY "WINCHIP3D " | 56 | #define MODULE_PROC_FAMILY "WINCHIP3D " |
59 | #elif defined CONFIG_MCYRIXIII | 57 | #elif defined CONFIG_MCYRIXIII |
diff --git a/include/asm-x86/nmi.h b/include/asm-x86/nmi.h index d5e715f024dc..a53f829a97c5 100644 --- a/include/asm-x86/nmi.h +++ b/include/asm-x86/nmi.h | |||
@@ -15,10 +15,6 @@ | |||
15 | */ | 15 | */ |
16 | int do_nmi_callback(struct pt_regs *regs, int cpu); | 16 | int do_nmi_callback(struct pt_regs *regs, int cpu); |
17 | 17 | ||
18 | #ifdef CONFIG_X86_64 | ||
19 | extern void default_do_nmi(struct pt_regs *); | ||
20 | #endif | ||
21 | |||
22 | extern void die_nmi(char *str, struct pt_regs *regs, int do_panic); | 18 | extern void die_nmi(char *str, struct pt_regs *regs, int do_panic); |
23 | extern int check_nmi_watchdog(void); | 19 | extern int check_nmi_watchdog(void); |
24 | extern int nmi_watchdog_enabled; | 20 | extern int nmi_watchdog_enabled; |
diff --git a/include/asm-x86/page.h b/include/asm-x86/page.h index c91574776751..d4f1d5791fc1 100644 --- a/include/asm-x86/page.h +++ b/include/asm-x86/page.h | |||
@@ -179,6 +179,7 @@ static inline pteval_t native_pte_flags(pte_t pte) | |||
179 | #endif /* CONFIG_PARAVIRT */ | 179 | #endif /* CONFIG_PARAVIRT */ |
180 | 180 | ||
181 | #define __pa(x) __phys_addr((unsigned long)(x)) | 181 | #define __pa(x) __phys_addr((unsigned long)(x)) |
182 | #define __pa_nodebug(x) __phys_addr_nodebug((unsigned long)(x)) | ||
182 | /* __pa_symbol should be used for C visible symbols. | 183 | /* __pa_symbol should be used for C visible symbols. |
183 | This seems to be the official gcc blessed way to do such arithmetic. */ | 184 | This seems to be the official gcc blessed way to do such arithmetic. */ |
184 | #define __pa_symbol(x) __pa(__phys_reloc_hide((unsigned long)(x))) | 185 | #define __pa_symbol(x) __pa(__phys_reloc_hide((unsigned long)(x))) |
@@ -188,9 +189,14 @@ static inline pteval_t native_pte_flags(pte_t pte) | |||
188 | #define __boot_va(x) __va(x) | 189 | #define __boot_va(x) __va(x) |
189 | #define __boot_pa(x) __pa(x) | 190 | #define __boot_pa(x) __pa(x) |
190 | 191 | ||
192 | /* | ||
193 | * virt_to_page(kaddr) returns a valid pointer if and only if | ||
194 | * virt_addr_valid(kaddr) returns true. | ||
195 | */ | ||
191 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | 196 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) |
192 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) | 197 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) |
193 | #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) | 198 | extern bool __virt_addr_valid(unsigned long kaddr); |
199 | #define virt_addr_valid(kaddr) __virt_addr_valid((unsigned long) (kaddr)) | ||
194 | 200 | ||
195 | #endif /* __ASSEMBLY__ */ | 201 | #endif /* __ASSEMBLY__ */ |
196 | 202 | ||
diff --git a/include/asm-x86/page_32.h b/include/asm-x86/page_32.h index 9c5a737a9af9..e8d80d1de237 100644 --- a/include/asm-x86/page_32.h +++ b/include/asm-x86/page_32.h | |||
@@ -20,6 +20,12 @@ | |||
20 | #endif | 20 | #endif |
21 | #define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER) | 21 | #define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER) |
22 | 22 | ||
23 | #define STACKFAULT_STACK 0 | ||
24 | #define DOUBLEFAULT_STACK 1 | ||
25 | #define NMI_STACK 0 | ||
26 | #define DEBUG_STACK 0 | ||
27 | #define MCE_STACK 0 | ||
28 | #define N_EXCEPTION_STACKS 1 | ||
23 | 29 | ||
24 | #ifdef CONFIG_X86_PAE | 30 | #ifdef CONFIG_X86_PAE |
25 | /* 44=32+12, the limit we can fit into an unsigned long pfn */ | 31 | /* 44=32+12, the limit we can fit into an unsigned long pfn */ |
@@ -73,11 +79,11 @@ typedef struct page *pgtable_t; | |||
73 | #endif | 79 | #endif |
74 | 80 | ||
75 | #ifndef __ASSEMBLY__ | 81 | #ifndef __ASSEMBLY__ |
76 | #define __phys_addr_const(x) ((x) - PAGE_OFFSET) | 82 | #define __phys_addr_nodebug(x) ((x) - PAGE_OFFSET) |
77 | #ifdef CONFIG_DEBUG_VIRTUAL | 83 | #ifdef CONFIG_DEBUG_VIRTUAL |
78 | extern unsigned long __phys_addr(unsigned long); | 84 | extern unsigned long __phys_addr(unsigned long); |
79 | #else | 85 | #else |
80 | #define __phys_addr(x) ((x) - PAGE_OFFSET) | 86 | #define __phys_addr(x) __phys_addr_nodebug(x) |
81 | #endif | 87 | #endif |
82 | #define __phys_reloc_hide(x) RELOC_HIDE((x), 0) | 88 | #define __phys_reloc_hide(x) RELOC_HIDE((x), 0) |
83 | 89 | ||
diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h index ed932453ef26..182f9d4c570f 100644 --- a/include/asm-x86/pgtable.h +++ b/include/asm-x86/pgtable.h | |||
@@ -15,7 +15,7 @@ | |||
15 | #define _PAGE_BIT_PAT 7 /* on 4KB pages */ | 15 | #define _PAGE_BIT_PAT 7 /* on 4KB pages */ |
16 | #define _PAGE_BIT_GLOBAL 8 /* Global TLB entry PPro+ */ | 16 | #define _PAGE_BIT_GLOBAL 8 /* Global TLB entry PPro+ */ |
17 | #define _PAGE_BIT_UNUSED1 9 /* available for programmer */ | 17 | #define _PAGE_BIT_UNUSED1 9 /* available for programmer */ |
18 | #define _PAGE_BIT_UNUSED2 10 | 18 | #define _PAGE_BIT_IOMAP 10 /* flag used to indicate IO mapping */ |
19 | #define _PAGE_BIT_UNUSED3 11 | 19 | #define _PAGE_BIT_UNUSED3 11 |
20 | #define _PAGE_BIT_PAT_LARGE 12 /* On 2MB or 1GB pages */ | 20 | #define _PAGE_BIT_PAT_LARGE 12 /* On 2MB or 1GB pages */ |
21 | #define _PAGE_BIT_SPECIAL _PAGE_BIT_UNUSED1 | 21 | #define _PAGE_BIT_SPECIAL _PAGE_BIT_UNUSED1 |
@@ -32,7 +32,7 @@ | |||
32 | #define _PAGE_PSE (_AT(pteval_t, 1) << _PAGE_BIT_PSE) | 32 | #define _PAGE_PSE (_AT(pteval_t, 1) << _PAGE_BIT_PSE) |
33 | #define _PAGE_GLOBAL (_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL) | 33 | #define _PAGE_GLOBAL (_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL) |
34 | #define _PAGE_UNUSED1 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1) | 34 | #define _PAGE_UNUSED1 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1) |
35 | #define _PAGE_UNUSED2 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED2) | 35 | #define _PAGE_IOMAP (_AT(pteval_t, 1) << _PAGE_BIT_IOMAP) |
36 | #define _PAGE_UNUSED3 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3) | 36 | #define _PAGE_UNUSED3 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3) |
37 | #define _PAGE_PAT (_AT(pteval_t, 1) << _PAGE_BIT_PAT) | 37 | #define _PAGE_PAT (_AT(pteval_t, 1) << _PAGE_BIT_PAT) |
38 | #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE) | 38 | #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE) |
@@ -99,6 +99,11 @@ | |||
99 | #define __PAGE_KERNEL_LARGE_NOCACHE (__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE) | 99 | #define __PAGE_KERNEL_LARGE_NOCACHE (__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE) |
100 | #define __PAGE_KERNEL_LARGE_EXEC (__PAGE_KERNEL_EXEC | _PAGE_PSE) | 100 | #define __PAGE_KERNEL_LARGE_EXEC (__PAGE_KERNEL_EXEC | _PAGE_PSE) |
101 | 101 | ||
102 | #define __PAGE_KERNEL_IO (__PAGE_KERNEL | _PAGE_IOMAP) | ||
103 | #define __PAGE_KERNEL_IO_NOCACHE (__PAGE_KERNEL_NOCACHE | _PAGE_IOMAP) | ||
104 | #define __PAGE_KERNEL_IO_UC_MINUS (__PAGE_KERNEL_UC_MINUS | _PAGE_IOMAP) | ||
105 | #define __PAGE_KERNEL_IO_WC (__PAGE_KERNEL_WC | _PAGE_IOMAP) | ||
106 | |||
102 | #define PAGE_KERNEL __pgprot(__PAGE_KERNEL) | 107 | #define PAGE_KERNEL __pgprot(__PAGE_KERNEL) |
103 | #define PAGE_KERNEL_RO __pgprot(__PAGE_KERNEL_RO) | 108 | #define PAGE_KERNEL_RO __pgprot(__PAGE_KERNEL_RO) |
104 | #define PAGE_KERNEL_EXEC __pgprot(__PAGE_KERNEL_EXEC) | 109 | #define PAGE_KERNEL_EXEC __pgprot(__PAGE_KERNEL_EXEC) |
@@ -113,6 +118,11 @@ | |||
113 | #define PAGE_KERNEL_VSYSCALL __pgprot(__PAGE_KERNEL_VSYSCALL) | 118 | #define PAGE_KERNEL_VSYSCALL __pgprot(__PAGE_KERNEL_VSYSCALL) |
114 | #define PAGE_KERNEL_VSYSCALL_NOCACHE __pgprot(__PAGE_KERNEL_VSYSCALL_NOCACHE) | 119 | #define PAGE_KERNEL_VSYSCALL_NOCACHE __pgprot(__PAGE_KERNEL_VSYSCALL_NOCACHE) |
115 | 120 | ||
121 | #define PAGE_KERNEL_IO __pgprot(__PAGE_KERNEL_IO) | ||
122 | #define PAGE_KERNEL_IO_NOCACHE __pgprot(__PAGE_KERNEL_IO_NOCACHE) | ||
123 | #define PAGE_KERNEL_IO_UC_MINUS __pgprot(__PAGE_KERNEL_IO_UC_MINUS) | ||
124 | #define PAGE_KERNEL_IO_WC __pgprot(__PAGE_KERNEL_IO_WC) | ||
125 | |||
116 | /* xwr */ | 126 | /* xwr */ |
117 | #define __P000 PAGE_NONE | 127 | #define __P000 PAGE_NONE |
118 | #define __P001 PAGE_READONLY | 128 | #define __P001 PAGE_READONLY |
@@ -196,7 +206,7 @@ static inline int pte_exec(pte_t pte) | |||
196 | 206 | ||
197 | static inline int pte_special(pte_t pte) | 207 | static inline int pte_special(pte_t pte) |
198 | { | 208 | { |
199 | return pte_val(pte) & _PAGE_SPECIAL; | 209 | return pte_flags(pte) & _PAGE_SPECIAL; |
200 | } | 210 | } |
201 | 211 | ||
202 | static inline unsigned long pte_pfn(pte_t pte) | 212 | static inline unsigned long pte_pfn(pte_t pte) |
diff --git a/include/asm-x86/ptrace.h b/include/asm-x86/ptrace.h index ac578f11c1c5..a2025525a15a 100644 --- a/include/asm-x86/ptrace.h +++ b/include/asm-x86/ptrace.h | |||
@@ -174,12 +174,8 @@ extern unsigned long profile_pc(struct pt_regs *regs); | |||
174 | 174 | ||
175 | extern unsigned long | 175 | extern unsigned long |
176 | convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs); | 176 | convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs); |
177 | |||
178 | #ifdef CONFIG_X86_32 | ||
179 | extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, | 177 | extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, |
180 | int error_code, int si_code); | 178 | int error_code, int si_code); |
181 | #endif | ||
182 | |||
183 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where); | 179 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where); |
184 | 180 | ||
185 | extern long syscall_trace_enter(struct pt_regs *); | 181 | extern long syscall_trace_enter(struct pt_regs *); |
diff --git a/include/asm-x86/segment.h b/include/asm-x86/segment.h index ea5f0a8686f7..5d6e69454891 100644 --- a/include/asm-x86/segment.h +++ b/include/asm-x86/segment.h | |||
@@ -131,12 +131,6 @@ | |||
131 | * Matching rules for certain types of segments. | 131 | * Matching rules for certain types of segments. |
132 | */ | 132 | */ |
133 | 133 | ||
134 | /* Matches only __KERNEL_CS, ignoring PnP / USER / APM segments */ | ||
135 | #define SEGMENT_IS_KERNEL_CODE(x) (((x) & 0xfc) == GDT_ENTRY_KERNEL_CS * 8) | ||
136 | |||
137 | /* Matches __KERNEL_CS and __USER_CS (they must be 2 entries apart) */ | ||
138 | #define SEGMENT_IS_FLAT_CODE(x) (((x) & 0xec) == GDT_ENTRY_KERNEL_CS * 8) | ||
139 | |||
140 | /* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */ | 134 | /* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */ |
141 | #define SEGMENT_IS_PNP_CODE(x) (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8) | 135 | #define SEGMENT_IS_PNP_CODE(x) (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8) |
142 | 136 | ||
diff --git a/include/asm-x86/smp.h b/include/asm-x86/smp.h index 6df2615f9138..a6afc29f2dd9 100644 --- a/include/asm-x86/smp.h +++ b/include/asm-x86/smp.h | |||
@@ -141,6 +141,8 @@ void play_dead_common(void); | |||
141 | void native_send_call_func_ipi(cpumask_t mask); | 141 | void native_send_call_func_ipi(cpumask_t mask); |
142 | void native_send_call_func_single_ipi(int cpu); | 142 | void native_send_call_func_single_ipi(int cpu); |
143 | 143 | ||
144 | extern void prefill_possible_map(void); | ||
145 | |||
144 | void smp_store_cpu_info(int id); | 146 | void smp_store_cpu_info(int id); |
145 | #define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu) | 147 | #define cpu_physical_id(cpu) per_cpu(x86_cpu_to_apicid, cpu) |
146 | 148 | ||
@@ -149,15 +151,11 @@ static inline int num_booting_cpus(void) | |||
149 | { | 151 | { |
150 | return cpus_weight(cpu_callout_map); | 152 | return cpus_weight(cpu_callout_map); |
151 | } | 153 | } |
152 | #endif /* CONFIG_SMP */ | ||
153 | |||
154 | #if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_CPU) | ||
155 | extern void prefill_possible_map(void); | ||
156 | #else | 154 | #else |
157 | static inline void prefill_possible_map(void) | 155 | static inline void prefill_possible_map(void) |
158 | { | 156 | { |
159 | } | 157 | } |
160 | #endif | 158 | #endif /* CONFIG_SMP */ |
161 | 159 | ||
162 | extern unsigned disabled_cpus __cpuinitdata; | 160 | extern unsigned disabled_cpus __cpuinitdata; |
163 | 161 | ||
diff --git a/include/asm-x86/statfs.h b/include/asm-x86/statfs.h index 3f005bc3aa5b..ca5dc19dd461 100644 --- a/include/asm-x86/statfs.h +++ b/include/asm-x86/statfs.h | |||
@@ -1,63 +1,12 @@ | |||
1 | #ifndef ASM_X86__STATFS_H | 1 | #ifndef ASM_X86__STATFS_H |
2 | #define ASM_X86__STATFS_H | 2 | #define ASM_X86__STATFS_H |
3 | 3 | ||
4 | #ifdef __i386__ | ||
5 | #include <asm-generic/statfs.h> | ||
6 | #else | ||
7 | |||
8 | #ifndef __KERNEL_STRICT_NAMES | ||
9 | |||
10 | #include <linux/types.h> | ||
11 | |||
12 | typedef __kernel_fsid_t fsid_t; | ||
13 | |||
14 | #endif | ||
15 | |||
16 | /* | 4 | /* |
17 | * This is ugly -- we're already 64-bit clean, so just duplicate the | 5 | * We need compat_statfs64 to be packed, because the i386 ABI won't |
18 | * definitions. | 6 | * add padding at the end to bring it to a multiple of 8 bytes, but |
7 | * the x86_64 ABI will. | ||
19 | */ | 8 | */ |
20 | struct statfs { | 9 | #define ARCH_PACK_COMPAT_STATFS64 __attribute__((packed,aligned(4))) |
21 | long f_type; | ||
22 | long f_bsize; | ||
23 | long f_blocks; | ||
24 | long f_bfree; | ||
25 | long f_bavail; | ||
26 | long f_files; | ||
27 | long f_ffree; | ||
28 | __kernel_fsid_t f_fsid; | ||
29 | long f_namelen; | ||
30 | long f_frsize; | ||
31 | long f_spare[5]; | ||
32 | }; | ||
33 | |||
34 | struct statfs64 { | ||
35 | long f_type; | ||
36 | long f_bsize; | ||
37 | long f_blocks; | ||
38 | long f_bfree; | ||
39 | long f_bavail; | ||
40 | long f_files; | ||
41 | long f_ffree; | ||
42 | __kernel_fsid_t f_fsid; | ||
43 | long f_namelen; | ||
44 | long f_frsize; | ||
45 | long f_spare[5]; | ||
46 | }; | ||
47 | 10 | ||
48 | struct compat_statfs64 { | 11 | #include <asm-generic/statfs.h> |
49 | __u32 f_type; | ||
50 | __u32 f_bsize; | ||
51 | __u64 f_blocks; | ||
52 | __u64 f_bfree; | ||
53 | __u64 f_bavail; | ||
54 | __u64 f_files; | ||
55 | __u64 f_ffree; | ||
56 | __kernel_fsid_t f_fsid; | ||
57 | __u32 f_namelen; | ||
58 | __u32 f_frsize; | ||
59 | __u32 f_spare[5]; | ||
60 | } __attribute__((packed)); | ||
61 | |||
62 | #endif /* !__i386__ */ | ||
63 | #endif /* ASM_X86__STATFS_H */ | 12 | #endif /* ASM_X86__STATFS_H */ |
diff --git a/include/asm-x86/system.h b/include/asm-x86/system.h index 34505dd7b24d..b20c894660f9 100644 --- a/include/asm-x86/system.h +++ b/include/asm-x86/system.h | |||
@@ -64,7 +64,10 @@ do { \ | |||
64 | \ | 64 | \ |
65 | /* regparm parameters for __switch_to(): */ \ | 65 | /* regparm parameters for __switch_to(): */ \ |
66 | [prev] "a" (prev), \ | 66 | [prev] "a" (prev), \ |
67 | [next] "d" (next)); \ | 67 | [next] "d" (next) \ |
68 | \ | ||
69 | : /* reloaded segment registers */ \ | ||
70 | "memory"); \ | ||
68 | } while (0) | 71 | } while (0) |
69 | 72 | ||
70 | /* | 73 | /* |
diff --git a/include/asm-x86/traps.h b/include/asm-x86/traps.h index 7a692baa51ae..6c3dc2c65751 100644 --- a/include/asm-x86/traps.h +++ b/include/asm-x86/traps.h | |||
@@ -3,7 +3,12 @@ | |||
3 | 3 | ||
4 | #include <asm/debugreg.h> | 4 | #include <asm/debugreg.h> |
5 | 5 | ||
6 | /* Common in X86_32 and X86_64 */ | 6 | #ifdef CONFIG_X86_32 |
7 | #define dotraplinkage | ||
8 | #else | ||
9 | #define dotraplinkage asmlinkage | ||
10 | #endif | ||
11 | |||
7 | asmlinkage void divide_error(void); | 12 | asmlinkage void divide_error(void); |
8 | asmlinkage void debug(void); | 13 | asmlinkage void debug(void); |
9 | asmlinkage void nmi(void); | 14 | asmlinkage void nmi(void); |
@@ -12,31 +17,47 @@ asmlinkage void overflow(void); | |||
12 | asmlinkage void bounds(void); | 17 | asmlinkage void bounds(void); |
13 | asmlinkage void invalid_op(void); | 18 | asmlinkage void invalid_op(void); |
14 | asmlinkage void device_not_available(void); | 19 | asmlinkage void device_not_available(void); |
20 | #ifdef CONFIG_X86_64 | ||
21 | asmlinkage void double_fault(void); | ||
22 | #endif | ||
15 | asmlinkage void coprocessor_segment_overrun(void); | 23 | asmlinkage void coprocessor_segment_overrun(void); |
16 | asmlinkage void invalid_TSS(void); | 24 | asmlinkage void invalid_TSS(void); |
17 | asmlinkage void segment_not_present(void); | 25 | asmlinkage void segment_not_present(void); |
18 | asmlinkage void stack_segment(void); | 26 | asmlinkage void stack_segment(void); |
19 | asmlinkage void general_protection(void); | 27 | asmlinkage void general_protection(void); |
20 | asmlinkage void page_fault(void); | 28 | asmlinkage void page_fault(void); |
29 | asmlinkage void spurious_interrupt_bug(void); | ||
21 | asmlinkage void coprocessor_error(void); | 30 | asmlinkage void coprocessor_error(void); |
22 | asmlinkage void simd_coprocessor_error(void); | ||
23 | asmlinkage void alignment_check(void); | 31 | asmlinkage void alignment_check(void); |
24 | asmlinkage void spurious_interrupt_bug(void); | ||
25 | #ifdef CONFIG_X86_MCE | 32 | #ifdef CONFIG_X86_MCE |
26 | asmlinkage void machine_check(void); | 33 | asmlinkage void machine_check(void); |
27 | #endif /* CONFIG_X86_MCE */ | 34 | #endif /* CONFIG_X86_MCE */ |
35 | asmlinkage void simd_coprocessor_error(void); | ||
28 | 36 | ||
29 | void do_divide_error(struct pt_regs *, long); | 37 | dotraplinkage void do_divide_error(struct pt_regs *, long); |
30 | void do_overflow(struct pt_regs *, long); | 38 | dotraplinkage void do_debug(struct pt_regs *, long); |
31 | void do_bounds(struct pt_regs *, long); | 39 | dotraplinkage void do_nmi(struct pt_regs *, long); |
32 | void do_coprocessor_segment_overrun(struct pt_regs *, long); | 40 | dotraplinkage void do_int3(struct pt_regs *, long); |
33 | void do_invalid_TSS(struct pt_regs *, long); | 41 | dotraplinkage void do_overflow(struct pt_regs *, long); |
34 | void do_segment_not_present(struct pt_regs *, long); | 42 | dotraplinkage void do_bounds(struct pt_regs *, long); |
35 | void do_stack_segment(struct pt_regs *, long); | 43 | dotraplinkage void do_invalid_op(struct pt_regs *, long); |
36 | void do_alignment_check(struct pt_regs *, long); | 44 | dotraplinkage void do_device_not_available(struct pt_regs *, long); |
37 | void do_invalid_op(struct pt_regs *, long); | 45 | dotraplinkage void do_coprocessor_segment_overrun(struct pt_regs *, long); |
38 | void do_general_protection(struct pt_regs *, long); | 46 | dotraplinkage void do_invalid_TSS(struct pt_regs *, long); |
39 | void do_nmi(struct pt_regs *, long); | 47 | dotraplinkage void do_segment_not_present(struct pt_regs *, long); |
48 | dotraplinkage void do_stack_segment(struct pt_regs *, long); | ||
49 | dotraplinkage void do_general_protection(struct pt_regs *, long); | ||
50 | dotraplinkage void do_page_fault(struct pt_regs *, unsigned long); | ||
51 | dotraplinkage void do_spurious_interrupt_bug(struct pt_regs *, long); | ||
52 | dotraplinkage void do_coprocessor_error(struct pt_regs *, long); | ||
53 | dotraplinkage void do_alignment_check(struct pt_regs *, long); | ||
54 | #ifdef CONFIG_X86_MCE | ||
55 | dotraplinkage void do_machine_check(struct pt_regs *, long); | ||
56 | #endif | ||
57 | dotraplinkage void do_simd_coprocessor_error(struct pt_regs *, long); | ||
58 | #ifdef CONFIG_X86_32 | ||
59 | dotraplinkage void do_iret_error(struct pt_regs *, long); | ||
60 | #endif | ||
40 | 61 | ||
41 | static inline int get_si_code(unsigned long condition) | 62 | static inline int get_si_code(unsigned long condition) |
42 | { | 63 | { |
@@ -52,31 +73,9 @@ extern int panic_on_unrecovered_nmi; | |||
52 | extern int kstack_depth_to_print; | 73 | extern int kstack_depth_to_print; |
53 | 74 | ||
54 | #ifdef CONFIG_X86_32 | 75 | #ifdef CONFIG_X86_32 |
55 | |||
56 | void do_iret_error(struct pt_regs *, long); | ||
57 | void do_int3(struct pt_regs *, long); | ||
58 | void do_debug(struct pt_regs *, long); | ||
59 | void math_error(void __user *); | 76 | void math_error(void __user *); |
60 | void do_coprocessor_error(struct pt_regs *, long); | ||
61 | void do_simd_coprocessor_error(struct pt_regs *, long); | ||
62 | void do_spurious_interrupt_bug(struct pt_regs *, long); | ||
63 | unsigned long patch_espfix_desc(unsigned long, unsigned long); | 77 | unsigned long patch_espfix_desc(unsigned long, unsigned long); |
64 | asmlinkage void math_emulate(long); | 78 | asmlinkage void math_emulate(long); |
79 | #endif | ||
65 | 80 | ||
66 | void do_page_fault(struct pt_regs *regs, unsigned long error_code); | ||
67 | |||
68 | #else /* CONFIG_X86_32 */ | ||
69 | |||
70 | asmlinkage void double_fault(void); | ||
71 | |||
72 | asmlinkage void do_int3(struct pt_regs *, long); | ||
73 | asmlinkage void do_stack_segment(struct pt_regs *, long); | ||
74 | asmlinkage void do_debug(struct pt_regs *, unsigned long); | ||
75 | asmlinkage void do_coprocessor_error(struct pt_regs *); | ||
76 | asmlinkage void do_simd_coprocessor_error(struct pt_regs *); | ||
77 | asmlinkage void do_spurious_interrupt_bug(struct pt_regs *); | ||
78 | |||
79 | asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code); | ||
80 | |||
81 | #endif /* CONFIG_X86_32 */ | ||
82 | #endif /* ASM_X86__TRAPS_H */ | 81 | #endif /* ASM_X86__TRAPS_H */ |
diff --git a/include/asm-xtensa/a.out.h b/include/asm-xtensa/a.out.h deleted file mode 100644 index fdf13702924a..000000000000 --- a/include/asm-xtensa/a.out.h +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * include/asm-xtensa/a.out.h | ||
3 | * | ||
4 | * Dummy a.out file. Xtensa does not support the a.out format, but the kernel | ||
5 | * seems to depend on it. | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file "COPYING" in the main directory of this archive | ||
9 | * for more details. | ||
10 | * | ||
11 | * Copyright (C) 2001 - 2005 Tensilica Inc. | ||
12 | */ | ||
13 | |||
14 | #ifndef _XTENSA_A_OUT_H | ||
15 | #define _XTENSA_A_OUT_H | ||
16 | |||
17 | struct exec | ||
18 | { | ||
19 | unsigned long a_info; | ||
20 | unsigned a_text; | ||
21 | unsigned a_data; | ||
22 | unsigned a_bss; | ||
23 | unsigned a_syms; | ||
24 | unsigned a_entry; | ||
25 | unsigned a_trsize; | ||
26 | unsigned a_drsize; | ||
27 | }; | ||
28 | |||
29 | #endif /* _XTENSA_A_OUT_H */ | ||
diff --git a/include/linux/devpts_fs.h b/include/linux/devpts_fs.h index 154769cad3f3..5ce0e5fd712e 100644 --- a/include/linux/devpts_fs.h +++ b/include/linux/devpts_fs.h | |||
@@ -17,20 +17,31 @@ | |||
17 | 17 | ||
18 | #ifdef CONFIG_UNIX98_PTYS | 18 | #ifdef CONFIG_UNIX98_PTYS |
19 | 19 | ||
20 | int devpts_new_index(void); | 20 | int devpts_new_index(struct inode *ptmx_inode); |
21 | void devpts_kill_index(int idx); | 21 | void devpts_kill_index(struct inode *ptmx_inode, int idx); |
22 | int devpts_pty_new(struct tty_struct *tty); /* mknod in devpts */ | 22 | /* mknod in devpts */ |
23 | struct tty_struct *devpts_get_tty(int number); /* get tty structure */ | 23 | int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty); |
24 | void devpts_pty_kill(int number); /* unlink */ | 24 | /* get tty structure */ |
25 | struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number); | ||
26 | /* unlink */ | ||
27 | void devpts_pty_kill(struct tty_struct *tty); | ||
25 | 28 | ||
26 | #else | 29 | #else |
27 | 30 | ||
28 | /* Dummy stubs in the no-pty case */ | 31 | /* Dummy stubs in the no-pty case */ |
29 | static inline int devpts_new_index(void) { return -EINVAL; } | 32 | static inline int devpts_new_index(struct inode *ptmx_inode) { return -EINVAL; } |
30 | static inline void devpts_kill_index(int idx) { } | 33 | static inline void devpts_kill_index(struct inode *ptmx_inode, int idx) { } |
31 | static inline int devpts_pty_new(struct tty_struct *tty) { return -EINVAL; } | 34 | static inline int devpts_pty_new(struct inode *ptmx_inode, |
32 | static inline struct tty_struct *devpts_get_tty(int number) { return NULL; } | 35 | struct tty_struct *tty) |
33 | static inline void devpts_pty_kill(int number) { } | 36 | { |
37 | return -EINVAL; | ||
38 | } | ||
39 | static inline struct tty_struct *devpts_get_tty(struct inode *pts_inode, | ||
40 | int number) | ||
41 | { | ||
42 | return NULL; | ||
43 | } | ||
44 | static inline void devpts_pty_kill(struct tty_struct *tty) { } | ||
34 | 45 | ||
35 | #endif | 46 | #endif |
36 | 47 | ||
diff --git a/include/linux/dmi.h b/include/linux/dmi.h index 2a063b64133f..e5084eb5943a 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h | |||
@@ -2,29 +2,9 @@ | |||
2 | #define __DMI_H__ | 2 | #define __DMI_H__ |
3 | 3 | ||
4 | #include <linux/list.h> | 4 | #include <linux/list.h> |
5 | #include <linux/mod_devicetable.h> | ||
5 | 6 | ||
6 | enum dmi_field { | 7 | /* enum dmi_field is in mod_devicetable.h */ |
7 | DMI_NONE, | ||
8 | DMI_BIOS_VENDOR, | ||
9 | DMI_BIOS_VERSION, | ||
10 | DMI_BIOS_DATE, | ||
11 | DMI_SYS_VENDOR, | ||
12 | DMI_PRODUCT_NAME, | ||
13 | DMI_PRODUCT_VERSION, | ||
14 | DMI_PRODUCT_SERIAL, | ||
15 | DMI_PRODUCT_UUID, | ||
16 | DMI_BOARD_VENDOR, | ||
17 | DMI_BOARD_NAME, | ||
18 | DMI_BOARD_VERSION, | ||
19 | DMI_BOARD_SERIAL, | ||
20 | DMI_BOARD_ASSET_TAG, | ||
21 | DMI_CHASSIS_VENDOR, | ||
22 | DMI_CHASSIS_TYPE, | ||
23 | DMI_CHASSIS_VERSION, | ||
24 | DMI_CHASSIS_SERIAL, | ||
25 | DMI_CHASSIS_ASSET_TAG, | ||
26 | DMI_STRING_MAX, | ||
27 | }; | ||
28 | 8 | ||
29 | enum dmi_device_type { | 9 | enum dmi_device_type { |
30 | DMI_DEV_TYPE_ANY = 0, | 10 | DMI_DEV_TYPE_ANY = 0, |
@@ -48,23 +28,6 @@ struct dmi_header { | |||
48 | u16 handle; | 28 | u16 handle; |
49 | }; | 29 | }; |
50 | 30 | ||
51 | /* | ||
52 | * DMI callbacks for problem boards | ||
53 | */ | ||
54 | struct dmi_strmatch { | ||
55 | u8 slot; | ||
56 | char *substr; | ||
57 | }; | ||
58 | |||
59 | struct dmi_system_id { | ||
60 | int (*callback)(const struct dmi_system_id *); | ||
61 | const char *ident; | ||
62 | struct dmi_strmatch matches[4]; | ||
63 | void *driver_data; | ||
64 | }; | ||
65 | |||
66 | #define DMI_MATCH(a, b) { a, b } | ||
67 | |||
68 | struct dmi_device { | 31 | struct dmi_device { |
69 | struct list_head list; | 32 | struct list_head list; |
70 | int type; | 33 | int type; |
diff --git a/include/linux/hpet.h b/include/linux/hpet.h index 2dc29ce6c8e4..79f63a27bcef 100644 --- a/include/linux/hpet.h +++ b/include/linux/hpet.h | |||
@@ -37,6 +37,7 @@ struct hpet { | |||
37 | #define hpet_compare _u1._hpet_compare | 37 | #define hpet_compare _u1._hpet_compare |
38 | 38 | ||
39 | #define HPET_MAX_TIMERS (32) | 39 | #define HPET_MAX_TIMERS (32) |
40 | #define HPET_MAX_IRQ (32) | ||
40 | 41 | ||
41 | /* | 42 | /* |
42 | * HPET general capabilities register | 43 | * HPET general capabilities register |
@@ -64,7 +65,7 @@ struct hpet { | |||
64 | */ | 65 | */ |
65 | 66 | ||
66 | #define Tn_INT_ROUTE_CAP_MASK (0xffffffff00000000ULL) | 67 | #define Tn_INT_ROUTE_CAP_MASK (0xffffffff00000000ULL) |
67 | #define Tn_INI_ROUTE_CAP_SHIFT (32UL) | 68 | #define Tn_INT_ROUTE_CAP_SHIFT (32UL) |
68 | #define Tn_FSB_INT_DELCAP_MASK (0x8000UL) | 69 | #define Tn_FSB_INT_DELCAP_MASK (0x8000UL) |
69 | #define Tn_FSB_INT_DELCAP_SHIFT (15) | 70 | #define Tn_FSB_INT_DELCAP_SHIFT (15) |
70 | #define Tn_FSB_EN_CNF_MASK (0x4000UL) | 71 | #define Tn_FSB_EN_CNF_MASK (0x4000UL) |
@@ -91,23 +92,14 @@ struct hpet { | |||
91 | * exported interfaces | 92 | * exported interfaces |
92 | */ | 93 | */ |
93 | 94 | ||
94 | struct hpet_task { | ||
95 | void (*ht_func) (void *); | ||
96 | void *ht_data; | ||
97 | void *ht_opaque; | ||
98 | }; | ||
99 | |||
100 | struct hpet_data { | 95 | struct hpet_data { |
101 | unsigned long hd_phys_address; | 96 | unsigned long hd_phys_address; |
102 | void __iomem *hd_address; | 97 | void __iomem *hd_address; |
103 | unsigned short hd_nirqs; | 98 | unsigned short hd_nirqs; |
104 | unsigned short hd_flags; | ||
105 | unsigned int hd_state; /* timer allocated */ | 99 | unsigned int hd_state; /* timer allocated */ |
106 | unsigned int hd_irq[HPET_MAX_TIMERS]; | 100 | unsigned int hd_irq[HPET_MAX_TIMERS]; |
107 | }; | 101 | }; |
108 | 102 | ||
109 | #define HPET_DATA_PLATFORM 0x0001 /* platform call to hpet_alloc */ | ||
110 | |||
111 | static inline void hpet_reserve_timer(struct hpet_data *hd, int timer) | 103 | static inline void hpet_reserve_timer(struct hpet_data *hd, int timer) |
112 | { | 104 | { |
113 | hd->hd_state |= (1 << timer); | 105 | hd->hd_state |= (1 << timer); |
@@ -125,7 +117,7 @@ struct hpet_info { | |||
125 | unsigned short hi_timer; | 117 | unsigned short hi_timer; |
126 | }; | 118 | }; |
127 | 119 | ||
128 | #define HPET_INFO_PERIODIC 0x0001 /* timer is periodic */ | 120 | #define HPET_INFO_PERIODIC 0x0010 /* periodic-capable comparator */ |
129 | 121 | ||
130 | #define HPET_IE_ON _IO('h', 0x01) /* interrupt on */ | 122 | #define HPET_IE_ON _IO('h', 0x01) /* interrupt on */ |
131 | #define HPET_IE_OFF _IO('h', 0x02) /* interrupt off */ | 123 | #define HPET_IE_OFF _IO('h', 0x02) /* interrupt off */ |
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 66c3499478b5..d2e91ea998fd 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h | |||
@@ -967,6 +967,9 @@ struct journal_s | |||
967 | #define JBD2_FLUSHED 0x008 /* The journal superblock has been flushed */ | 967 | #define JBD2_FLUSHED 0x008 /* The journal superblock has been flushed */ |
968 | #define JBD2_LOADED 0x010 /* The journal superblock has been loaded */ | 968 | #define JBD2_LOADED 0x010 /* The journal superblock has been loaded */ |
969 | #define JBD2_BARRIER 0x020 /* Use IDE barriers */ | 969 | #define JBD2_BARRIER 0x020 /* Use IDE barriers */ |
970 | #define JBD2_ABORT_ON_SYNCDATA_ERR 0x040 /* Abort the journal on file | ||
971 | * data write error in ordered | ||
972 | * mode */ | ||
970 | 973 | ||
971 | /* | 974 | /* |
972 | * Function declarations for the journaling transaction and buffer | 975 | * Function declarations for the journaling transaction and buffer |
@@ -1060,7 +1063,7 @@ extern void jbd2_journal_clear_features | |||
1060 | (journal_t *, unsigned long, unsigned long, unsigned long); | 1063 | (journal_t *, unsigned long, unsigned long, unsigned long); |
1061 | extern int jbd2_journal_create (journal_t *); | 1064 | extern int jbd2_journal_create (journal_t *); |
1062 | extern int jbd2_journal_load (journal_t *journal); | 1065 | extern int jbd2_journal_load (journal_t *journal); |
1063 | extern void jbd2_journal_destroy (journal_t *); | 1066 | extern int jbd2_journal_destroy (journal_t *); |
1064 | extern int jbd2_journal_recover (journal_t *journal); | 1067 | extern int jbd2_journal_recover (journal_t *journal); |
1065 | extern int jbd2_journal_wipe (journal_t *, int); | 1068 | extern int jbd2_journal_wipe (journal_t *, int); |
1066 | extern int jbd2_journal_skip_recovery (journal_t *); | 1069 | extern int jbd2_journal_skip_recovery (journal_t *); |
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index c4db5827963d..3481a7d5bc0a 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h | |||
@@ -388,5 +388,52 @@ struct i2c_device_id { | |||
388 | __attribute__((aligned(sizeof(kernel_ulong_t)))); | 388 | __attribute__((aligned(sizeof(kernel_ulong_t)))); |
389 | }; | 389 | }; |
390 | 390 | ||
391 | /* dmi */ | ||
392 | enum dmi_field { | ||
393 | DMI_NONE, | ||
394 | DMI_BIOS_VENDOR, | ||
395 | DMI_BIOS_VERSION, | ||
396 | DMI_BIOS_DATE, | ||
397 | DMI_SYS_VENDOR, | ||
398 | DMI_PRODUCT_NAME, | ||
399 | DMI_PRODUCT_VERSION, | ||
400 | DMI_PRODUCT_SERIAL, | ||
401 | DMI_PRODUCT_UUID, | ||
402 | DMI_BOARD_VENDOR, | ||
403 | DMI_BOARD_NAME, | ||
404 | DMI_BOARD_VERSION, | ||
405 | DMI_BOARD_SERIAL, | ||
406 | DMI_BOARD_ASSET_TAG, | ||
407 | DMI_CHASSIS_VENDOR, | ||
408 | DMI_CHASSIS_TYPE, | ||
409 | DMI_CHASSIS_VERSION, | ||
410 | DMI_CHASSIS_SERIAL, | ||
411 | DMI_CHASSIS_ASSET_TAG, | ||
412 | DMI_STRING_MAX, | ||
413 | }; | ||
414 | |||
415 | struct dmi_strmatch { | ||
416 | unsigned char slot; | ||
417 | char substr[79]; | ||
418 | }; | ||
419 | |||
420 | #ifndef __KERNEL__ | ||
421 | struct dmi_system_id { | ||
422 | kernel_ulong_t callback; | ||
423 | kernel_ulong_t ident; | ||
424 | struct dmi_strmatch matches[4]; | ||
425 | kernel_ulong_t driver_data | ||
426 | __attribute__((aligned(sizeof(kernel_ulong_t)))); | ||
427 | }; | ||
428 | #else | ||
429 | struct dmi_system_id { | ||
430 | int (*callback)(const struct dmi_system_id *); | ||
431 | const char *ident; | ||
432 | struct dmi_strmatch matches[4]; | ||
433 | void *driver_data; | ||
434 | }; | ||
435 | #endif | ||
436 | |||
437 | #define DMI_MATCH(a, b) { a, b } | ||
391 | 438 | ||
392 | #endif /* LINUX_MOD_DEVICETABLE_H */ | 439 | #endif /* LINUX_MOD_DEVICETABLE_H */ |
diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h index 041bb31100f4..bcb8f725427c 100644 --- a/include/linux/oprofile.h +++ b/include/linux/oprofile.h | |||
@@ -36,6 +36,8 @@ | |||
36 | #define XEN_ENTER_SWITCH_CODE 10 | 36 | #define XEN_ENTER_SWITCH_CODE 10 |
37 | #define SPU_PROFILING_CODE 11 | 37 | #define SPU_PROFILING_CODE 11 |
38 | #define SPU_CTX_SWITCH_CODE 12 | 38 | #define SPU_CTX_SWITCH_CODE 12 |
39 | #define IBS_FETCH_CODE 13 | ||
40 | #define IBS_OP_CODE 14 | ||
39 | 41 | ||
40 | struct super_block; | 42 | struct super_block; |
41 | struct dentry; | 43 | struct dentry; |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f63b5455801c..1176f1f177e2 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
@@ -1533,7 +1533,9 @@ | |||
1533 | #define PCI_DEVICE_ID_MARVELL_GT64260 0x6430 | 1533 | #define PCI_DEVICE_ID_MARVELL_GT64260 0x6430 |
1534 | #define PCI_DEVICE_ID_MARVELL_MV64360 0x6460 | 1534 | #define PCI_DEVICE_ID_MARVELL_MV64360 0x6460 |
1535 | #define PCI_DEVICE_ID_MARVELL_MV64460 0x6480 | 1535 | #define PCI_DEVICE_ID_MARVELL_MV64460 0x6480 |
1536 | #define PCI_DEVICE_ID_MARVELL_CAFE_SD 0x4101 | 1536 | #define PCI_DEVICE_ID_MARVELL_88ALP01_NAND 0x4100 |
1537 | #define PCI_DEVICE_ID_MARVELL_88ALP01_SD 0x4101 | ||
1538 | #define PCI_DEVICE_ID_MARVELL_88ALP01_CCIC 0x4102 | ||
1537 | 1539 | ||
1538 | #define PCI_VENDOR_ID_V3 0x11b0 | 1540 | #define PCI_VENDOR_ID_V3 0x11b0 |
1539 | #define PCI_DEVICE_ID_V3_V960 0x0001 | 1541 | #define PCI_DEVICE_ID_V3_V960 0x0001 |
diff --git a/include/linux/serial.h b/include/linux/serial.h index deb714314fb1..1ea8d9265bf6 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h | |||
@@ -173,6 +173,22 @@ struct serial_icounter_struct { | |||
173 | int reserved[9]; | 173 | int reserved[9]; |
174 | }; | 174 | }; |
175 | 175 | ||
176 | /* | ||
177 | * Serial interface for controlling RS485 settings on chips with suitable | ||
178 | * support. Set with TIOCSRS485 and get with TIOCGRS485 if supported by your | ||
179 | * platform. The set function returns the new state, with any unsupported bits | ||
180 | * reverted appropriately. | ||
181 | */ | ||
182 | |||
183 | struct serial_rs485 { | ||
184 | __u32 flags; /* RS485 feature flags */ | ||
185 | #define SER_RS485_ENABLED (1 << 0) | ||
186 | #define SER_RS485_RTS_ON_SEND (1 << 1) | ||
187 | #define SER_RS485_RTS_AFTER_SEND (1 << 2) | ||
188 | __u32 delay_rts_before_send; /* Milliseconds */ | ||
189 | __u32 padding[6]; /* Memory is cheap, new structs | ||
190 | are a royal PITA .. */ | ||
191 | }; | ||
176 | 192 | ||
177 | #ifdef __KERNEL__ | 193 | #ifdef __KERNEL__ |
178 | #include <linux/compiler.h> | 194 | #include <linux/compiler.h> |
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 3b2f6c04855e..e27f216361fc 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h | |||
@@ -241,7 +241,7 @@ typedef unsigned int __bitwise__ upf_t; | |||
241 | 241 | ||
242 | struct uart_port { | 242 | struct uart_port { |
243 | spinlock_t lock; /* port lock */ | 243 | spinlock_t lock; /* port lock */ |
244 | unsigned int iobase; /* in/out[bwl] */ | 244 | unsigned long iobase; /* in/out[bwl] */ |
245 | unsigned char __iomem *membase; /* read/write[bwl] */ | 245 | unsigned char __iomem *membase; /* read/write[bwl] */ |
246 | unsigned int irq; /* irq number */ | 246 | unsigned int irq; /* irq number */ |
247 | unsigned int uartclk; /* base uart clock */ | 247 | unsigned int uartclk; /* base uart clock */ |
diff --git a/include/linux/termios.h b/include/linux/termios.h index 478662889f48..2acd0c1f8a2a 100644 --- a/include/linux/termios.h +++ b/include/linux/termios.h | |||
@@ -4,4 +4,19 @@ | |||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | #include <asm/termios.h> | 5 | #include <asm/termios.h> |
6 | 6 | ||
7 | #define NFF 5 | ||
8 | |||
9 | struct termiox | ||
10 | { | ||
11 | __u16 x_hflag; | ||
12 | __u16 x_cflag; | ||
13 | __u16 x_rflag[NFF]; | ||
14 | __u16 x_sflag; | ||
15 | }; | ||
16 | |||
17 | #define RTSXOFF 0x0001 /* RTS flow control on input */ | ||
18 | #define CTSXON 0x0002 /* CTS flow control on output */ | ||
19 | #define DTRXOFF 0x0004 /* DTR flow control on input */ | ||
20 | #define DSRXON 0x0008 /* DCD flow control on output */ | ||
21 | |||
7 | #endif | 22 | #endif |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 0cbec74ec086..3b8121d4e36f 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | #define NR_UNIX98_PTY_DEFAULT 4096 /* Default maximum for Unix98 ptys */ | 24 | #define NR_UNIX98_PTY_DEFAULT 4096 /* Default maximum for Unix98 ptys */ |
25 | #define NR_UNIX98_PTY_MAX (1 << MINORBITS) /* Absolute limit */ | 25 | #define NR_UNIX98_PTY_MAX (1 << MINORBITS) /* Absolute limit */ |
26 | #define NR_LDISCS 18 | 26 | #define NR_LDISCS 19 |
27 | 27 | ||
28 | /* line disciplines */ | 28 | /* line disciplines */ |
29 | #define N_TTY 0 | 29 | #define N_TTY 0 |
@@ -45,6 +45,7 @@ | |||
45 | #define N_HCI 15 /* Bluetooth HCI UART */ | 45 | #define N_HCI 15 /* Bluetooth HCI UART */ |
46 | #define N_GIGASET_M101 16 /* Siemens Gigaset M101 serial DECT adapter */ | 46 | #define N_GIGASET_M101 16 /* Siemens Gigaset M101 serial DECT adapter */ |
47 | #define N_SLCAN 17 /* Serial / USB serial CAN Adaptors */ | 47 | #define N_SLCAN 17 /* Serial / USB serial CAN Adaptors */ |
48 | #define N_PPS 18 /* Pulse per Second */ | ||
48 | 49 | ||
49 | /* | 50 | /* |
50 | * This character is the same as _POSIX_VDISABLE: it cannot be used as | 51 | * This character is the same as _POSIX_VDISABLE: it cannot be used as |
@@ -181,6 +182,7 @@ struct signal_struct; | |||
181 | 182 | ||
182 | struct tty_port { | 183 | struct tty_port { |
183 | struct tty_struct *tty; /* Back pointer */ | 184 | struct tty_struct *tty; /* Back pointer */ |
185 | spinlock_t lock; /* Lock protecting tty field */ | ||
184 | int blocked_open; /* Waiting to open */ | 186 | int blocked_open; /* Waiting to open */ |
185 | int count; /* Usage count */ | 187 | int count; /* Usage count */ |
186 | wait_queue_head_t open_wait; /* Open waiters */ | 188 | wait_queue_head_t open_wait; /* Open waiters */ |
@@ -208,6 +210,7 @@ struct tty_operations; | |||
208 | 210 | ||
209 | struct tty_struct { | 211 | struct tty_struct { |
210 | int magic; | 212 | int magic; |
213 | struct kref kref; | ||
211 | struct tty_driver *driver; | 214 | struct tty_driver *driver; |
212 | const struct tty_operations *ops; | 215 | const struct tty_operations *ops; |
213 | int index; | 216 | int index; |
@@ -217,6 +220,7 @@ struct tty_struct { | |||
217 | spinlock_t ctrl_lock; | 220 | spinlock_t ctrl_lock; |
218 | /* Termios values are protected by the termios mutex */ | 221 | /* Termios values are protected by the termios mutex */ |
219 | struct ktermios *termios, *termios_locked; | 222 | struct ktermios *termios, *termios_locked; |
223 | struct termiox *termiox; /* May be NULL for unsupported */ | ||
220 | char name[64]; | 224 | char name[64]; |
221 | struct pid *pgrp; /* Protected by ctrl lock */ | 225 | struct pid *pgrp; /* Protected by ctrl lock */ |
222 | struct pid *session; | 226 | struct pid *session; |
@@ -310,6 +314,25 @@ extern int kmsg_redirect; | |||
310 | extern void console_init(void); | 314 | extern void console_init(void); |
311 | extern int vcs_init(void); | 315 | extern int vcs_init(void); |
312 | 316 | ||
317 | extern struct class *tty_class; | ||
318 | |||
319 | /** | ||
320 | * tty_kref_get - get a tty reference | ||
321 | * @tty: tty device | ||
322 | * | ||
323 | * Return a new reference to a tty object. The caller must hold | ||
324 | * sufficient locks/counts to ensure that their existing reference cannot | ||
325 | * go away | ||
326 | */ | ||
327 | |||
328 | extern inline struct tty_struct *tty_kref_get(struct tty_struct *tty) | ||
329 | { | ||
330 | if (tty) | ||
331 | kref_get(&tty->kref); | ||
332 | return tty; | ||
333 | } | ||
334 | extern void tty_kref_put(struct tty_struct *tty); | ||
335 | |||
313 | extern int tty_paranoia_check(struct tty_struct *tty, struct inode *inode, | 336 | extern int tty_paranoia_check(struct tty_struct *tty, struct inode *inode, |
314 | const char *routine); | 337 | const char *routine); |
315 | extern char *tty_name(struct tty_struct *tty, char *buf); | 338 | extern char *tty_name(struct tty_struct *tty, char *buf); |
@@ -333,13 +356,15 @@ extern void tty_throttle(struct tty_struct *tty); | |||
333 | extern void tty_unthrottle(struct tty_struct *tty); | 356 | extern void tty_unthrottle(struct tty_struct *tty); |
334 | extern int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, | 357 | extern int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, |
335 | struct winsize *ws); | 358 | struct winsize *ws); |
336 | 359 | extern void tty_shutdown(struct tty_struct *tty); | |
360 | extern void tty_free_termios(struct tty_struct *tty); | ||
337 | extern int is_current_pgrp_orphaned(void); | 361 | extern int is_current_pgrp_orphaned(void); |
338 | extern struct pid *tty_get_pgrp(struct tty_struct *tty); | 362 | extern struct pid *tty_get_pgrp(struct tty_struct *tty); |
339 | extern int is_ignored(int sig); | 363 | extern int is_ignored(int sig); |
340 | extern int tty_signal(int sig, struct tty_struct *tty); | 364 | extern int tty_signal(int sig, struct tty_struct *tty); |
341 | extern void tty_hangup(struct tty_struct *tty); | 365 | extern void tty_hangup(struct tty_struct *tty); |
342 | extern void tty_vhangup(struct tty_struct *tty); | 366 | extern void tty_vhangup(struct tty_struct *tty); |
367 | extern void tty_vhangup_self(void); | ||
343 | extern void tty_unhangup(struct file *filp); | 368 | extern void tty_unhangup(struct file *filp); |
344 | extern int tty_hung_up_p(struct file *filp); | 369 | extern int tty_hung_up_p(struct file *filp); |
345 | extern void do_SAK(struct tty_struct *tty); | 370 | extern void do_SAK(struct tty_struct *tty); |
@@ -347,6 +372,9 @@ extern void __do_SAK(struct tty_struct *tty); | |||
347 | extern void disassociate_ctty(int priv); | 372 | extern void disassociate_ctty(int priv); |
348 | extern void no_tty(void); | 373 | extern void no_tty(void); |
349 | extern void tty_flip_buffer_push(struct tty_struct *tty); | 374 | extern void tty_flip_buffer_push(struct tty_struct *tty); |
375 | extern void tty_buffer_free_all(struct tty_struct *tty); | ||
376 | extern void tty_buffer_flush(struct tty_struct *tty); | ||
377 | extern void tty_buffer_init(struct tty_struct *tty); | ||
350 | extern speed_t tty_get_baud_rate(struct tty_struct *tty); | 378 | extern speed_t tty_get_baud_rate(struct tty_struct *tty); |
351 | extern speed_t tty_termios_baud_rate(struct ktermios *termios); | 379 | extern speed_t tty_termios_baud_rate(struct ktermios *termios); |
352 | extern speed_t tty_termios_input_baud_rate(struct ktermios *termios); | 380 | extern speed_t tty_termios_input_baud_rate(struct ktermios *termios); |
@@ -372,6 +400,15 @@ extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg); | |||
372 | extern dev_t tty_devnum(struct tty_struct *tty); | 400 | extern dev_t tty_devnum(struct tty_struct *tty); |
373 | extern void proc_clear_tty(struct task_struct *p); | 401 | extern void proc_clear_tty(struct task_struct *p); |
374 | extern struct tty_struct *get_current_tty(void); | 402 | extern struct tty_struct *get_current_tty(void); |
403 | extern void tty_default_fops(struct file_operations *fops); | ||
404 | extern struct tty_struct *alloc_tty_struct(void); | ||
405 | extern void free_tty_struct(struct tty_struct *tty); | ||
406 | extern void initialize_tty_struct(struct tty_struct *tty, | ||
407 | struct tty_driver *driver, int idx); | ||
408 | extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, | ||
409 | int first_ok); | ||
410 | extern void tty_release_dev(struct file *filp); | ||
411 | extern int tty_init_termios(struct tty_struct *tty); | ||
375 | 412 | ||
376 | extern struct mutex tty_mutex; | 413 | extern struct mutex tty_mutex; |
377 | 414 | ||
@@ -382,6 +419,8 @@ extern int tty_write_lock(struct tty_struct *tty, int ndelay); | |||
382 | extern void tty_port_init(struct tty_port *port); | 419 | extern void tty_port_init(struct tty_port *port); |
383 | extern int tty_port_alloc_xmit_buf(struct tty_port *port); | 420 | extern int tty_port_alloc_xmit_buf(struct tty_port *port); |
384 | extern void tty_port_free_xmit_buf(struct tty_port *port); | 421 | extern void tty_port_free_xmit_buf(struct tty_port *port); |
422 | extern struct tty_struct *tty_port_tty_get(struct tty_port *port); | ||
423 | extern void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty); | ||
385 | 424 | ||
386 | extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc); | 425 | extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc); |
387 | extern int tty_unregister_ldisc(int disc); | 426 | extern int tty_unregister_ldisc(int disc); |
@@ -427,7 +466,7 @@ static inline void tty_audit_push_task(struct task_struct *tsk, | |||
427 | #endif | 466 | #endif |
428 | 467 | ||
429 | /* tty_ioctl.c */ | 468 | /* tty_ioctl.c */ |
430 | extern int n_tty_ioctl(struct tty_struct *tty, struct file *file, | 469 | extern int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file, |
431 | unsigned int cmd, unsigned long arg); | 470 | unsigned int cmd, unsigned long arg); |
432 | 471 | ||
433 | /* serial.c */ | 472 | /* serial.c */ |
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 16d27944c321..78416b901589 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h | |||
@@ -7,6 +7,28 @@ | |||
7 | * defined; unless noted otherwise, they are optional, and can be | 7 | * defined; unless noted otherwise, they are optional, and can be |
8 | * filled in with a null pointer. | 8 | * filled in with a null pointer. |
9 | * | 9 | * |
10 | * struct tty_struct * (*lookup)(struct tty_driver *self, int idx) | ||
11 | * | ||
12 | * Return the tty device corresponding to idx, NULL if there is not | ||
13 | * one currently in use and an ERR_PTR value on error. Called under | ||
14 | * tty_mutex (for now!) | ||
15 | * | ||
16 | * Optional method. Default behaviour is to use the ttys array | ||
17 | * | ||
18 | * int (*install)(struct tty_driver *self, struct tty_struct *tty) | ||
19 | * | ||
20 | * Install a new tty into the tty driver internal tables. Used in | ||
21 | * conjunction with lookup and remove methods. | ||
22 | * | ||
23 | * Optional method. Default behaviour is to use the ttys array | ||
24 | * | ||
25 | * void (*remove)(struct tty_driver *self, struct tty_struct *tty) | ||
26 | * | ||
27 | * Remove a closed tty from the tty driver internal tables. Used in | ||
28 | * conjunction with lookup and remove methods. | ||
29 | * | ||
30 | * Optional method. Default behaviour is to use the ttys array | ||
31 | * | ||
10 | * int (*open)(struct tty_struct * tty, struct file * filp); | 32 | * int (*open)(struct tty_struct * tty, struct file * filp); |
11 | * | 33 | * |
12 | * This routine is called when a particular tty device is opened. | 34 | * This routine is called when a particular tty device is opened. |
@@ -21,6 +43,11 @@ | |||
21 | * | 43 | * |
22 | * Required method. | 44 | * Required method. |
23 | * | 45 | * |
46 | * void (*shutdown)(struct tty_struct * tty); | ||
47 | * | ||
48 | * This routine is called when a particular tty device is closed for | ||
49 | * the last time freeing up the resources. | ||
50 | * | ||
24 | * int (*write)(struct tty_struct * tty, | 51 | * int (*write)(struct tty_struct * tty, |
25 | * const unsigned char *buf, int count); | 52 | * const unsigned char *buf, int count); |
26 | * | 53 | * |
@@ -180,6 +207,14 @@ | |||
180 | * not force errors here if they are not resizable objects (eg a serial | 207 | * not force errors here if they are not resizable objects (eg a serial |
181 | * line). See tty_do_resize() if you need to wrap the standard method | 208 | * line). See tty_do_resize() if you need to wrap the standard method |
182 | * in your own logic - the usual case. | 209 | * in your own logic - the usual case. |
210 | * | ||
211 | * void (*set_termiox)(struct tty_struct *tty, struct termiox *new); | ||
212 | * | ||
213 | * Called when the device receives a termiox based ioctl. Passes down | ||
214 | * the requested data from user space. This method will not be invoked | ||
215 | * unless the tty also has a valid tty->termiox pointer. | ||
216 | * | ||
217 | * Optional: Called under the termios lock | ||
183 | */ | 218 | */ |
184 | 219 | ||
185 | #include <linux/fs.h> | 220 | #include <linux/fs.h> |
@@ -190,8 +225,13 @@ struct tty_struct; | |||
190 | struct tty_driver; | 225 | struct tty_driver; |
191 | 226 | ||
192 | struct tty_operations { | 227 | struct tty_operations { |
228 | struct tty_struct * (*lookup)(struct tty_driver *driver, | ||
229 | struct inode *inode, int idx); | ||
230 | int (*install)(struct tty_driver *driver, struct tty_struct *tty); | ||
231 | void (*remove)(struct tty_driver *driver, struct tty_struct *tty); | ||
193 | int (*open)(struct tty_struct * tty, struct file * filp); | 232 | int (*open)(struct tty_struct * tty, struct file * filp); |
194 | void (*close)(struct tty_struct * tty, struct file * filp); | 233 | void (*close)(struct tty_struct * tty, struct file * filp); |
234 | void (*shutdown)(struct tty_struct *tty); | ||
195 | int (*write)(struct tty_struct * tty, | 235 | int (*write)(struct tty_struct * tty, |
196 | const unsigned char *buf, int count); | 236 | const unsigned char *buf, int count); |
197 | int (*put_char)(struct tty_struct *tty, unsigned char ch); | 237 | int (*put_char)(struct tty_struct *tty, unsigned char ch); |
@@ -220,6 +260,7 @@ struct tty_operations { | |||
220 | unsigned int set, unsigned int clear); | 260 | unsigned int set, unsigned int clear); |
221 | int (*resize)(struct tty_struct *tty, struct tty_struct *real_tty, | 261 | int (*resize)(struct tty_struct *tty, struct tty_struct *real_tty, |
222 | struct winsize *ws); | 262 | struct winsize *ws); |
263 | int (*set_termiox)(struct tty_struct *tty, struct termiox *tnew); | ||
223 | #ifdef CONFIG_CONSOLE_POLL | 264 | #ifdef CONFIG_CONSOLE_POLL |
224 | int (*poll_init)(struct tty_driver *driver, int line, char *options); | 265 | int (*poll_init)(struct tty_driver *driver, int line, char *options); |
225 | int (*poll_get_char)(struct tty_driver *driver, int line); | 266 | int (*poll_get_char)(struct tty_driver *driver, int line); |
@@ -229,6 +270,7 @@ struct tty_operations { | |||
229 | 270 | ||
230 | struct tty_driver { | 271 | struct tty_driver { |
231 | int magic; /* magic number for this structure */ | 272 | int magic; /* magic number for this structure */ |
273 | struct kref kref; /* Reference management */ | ||
232 | struct cdev cdev; | 274 | struct cdev cdev; |
233 | struct module *owner; | 275 | struct module *owner; |
234 | const char *driver_name; | 276 | const char *driver_name; |
@@ -242,7 +284,6 @@ struct tty_driver { | |||
242 | short subtype; /* subtype of tty driver */ | 284 | short subtype; /* subtype of tty driver */ |
243 | struct ktermios init_termios; /* Initial termios */ | 285 | struct ktermios init_termios; /* Initial termios */ |
244 | int flags; /* tty driver flags */ | 286 | int flags; /* tty driver flags */ |
245 | int refcount; /* for loadable tty drivers */ | ||
246 | struct proc_dir_entry *proc_entry; /* /proc fs entry */ | 287 | struct proc_dir_entry *proc_entry; /* /proc fs entry */ |
247 | struct tty_driver *other; /* only used for the PTY driver */ | 288 | struct tty_driver *other; /* only used for the PTY driver */ |
248 | 289 | ||
@@ -264,12 +305,19 @@ struct tty_driver { | |||
264 | 305 | ||
265 | extern struct list_head tty_drivers; | 306 | extern struct list_head tty_drivers; |
266 | 307 | ||
267 | struct tty_driver *alloc_tty_driver(int lines); | 308 | extern struct tty_driver *alloc_tty_driver(int lines); |
268 | void put_tty_driver(struct tty_driver *driver); | 309 | extern void put_tty_driver(struct tty_driver *driver); |
269 | void tty_set_operations(struct tty_driver *driver, | 310 | extern void tty_set_operations(struct tty_driver *driver, |
270 | const struct tty_operations *op); | 311 | const struct tty_operations *op); |
271 | extern struct tty_driver *tty_find_polling_driver(char *name, int *line); | 312 | extern struct tty_driver *tty_find_polling_driver(char *name, int *line); |
272 | 313 | ||
314 | extern void tty_driver_kref_put(struct tty_driver *driver); | ||
315 | extern inline struct tty_driver *tty_driver_kref_get(struct tty_driver *d) | ||
316 | { | ||
317 | kref_get(&d->kref); | ||
318 | return d; | ||
319 | } | ||
320 | |||
273 | /* tty driver magic number */ | 321 | /* tty driver magic number */ |
274 | #define TTY_DRIVER_MAGIC 0x5402 | 322 | #define TTY_DRIVER_MAGIC 0x5402 |
275 | 323 | ||
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index 1cbd0a7db4e6..2f1113467f70 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h | |||
@@ -96,7 +96,7 @@ void change_console(struct vc_data *new_vc); | |||
96 | void reset_vc(struct vc_data *vc); | 96 | void reset_vc(struct vc_data *vc); |
97 | extern int unbind_con_driver(const struct consw *csw, int first, int last, | 97 | extern int unbind_con_driver(const struct consw *csw, int first, int last, |
98 | int deflt); | 98 | int deflt); |
99 | int vty_init(void); | 99 | int vty_init(const struct file_operations *console_fops); |
100 | 100 | ||
101 | /* | 101 | /* |
102 | * vc_screen.c shares this temporary buffer with the console write code so that | 102 | * vc_screen.c shares this temporary buffer with the console write code so that |
diff --git a/kernel/acct.c b/kernel/acct.c index dd68b9059418..f6006a60df5d 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
@@ -548,7 +548,7 @@ static void do_acct_process(struct bsd_acct_struct *acct, | |||
548 | #endif | 548 | #endif |
549 | 549 | ||
550 | spin_lock_irq(¤t->sighand->siglock); | 550 | spin_lock_irq(¤t->sighand->siglock); |
551 | tty = current->signal->tty; | 551 | tty = current->signal->tty; /* Safe as we hold the siglock */ |
552 | ac.ac_tty = tty ? old_encode_dev(tty_devnum(tty)) : 0; | 552 | ac.ac_tty = tty ? old_encode_dev(tty_devnum(tty)) : 0; |
553 | ac.ac_utime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_utime))); | 553 | ac.ac_utime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_utime))); |
554 | ac.ac_stime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_stime))); | 554 | ac.ac_stime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_stime))); |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 59cedfb040e7..cf5bc2f5f9c3 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -246,8 +246,8 @@ static int audit_match_perm(struct audit_context *ctx, int mask) | |||
246 | unsigned n; | 246 | unsigned n; |
247 | if (unlikely(!ctx)) | 247 | if (unlikely(!ctx)) |
248 | return 0; | 248 | return 0; |
249 | |||
250 | n = ctx->major; | 249 | n = ctx->major; |
250 | |||
251 | switch (audit_classify_syscall(ctx->arch, n)) { | 251 | switch (audit_classify_syscall(ctx->arch, n)) { |
252 | case 0: /* native */ | 252 | case 0: /* native */ |
253 | if ((mask & AUDIT_PERM_WRITE) && | 253 | if ((mask & AUDIT_PERM_WRITE) && |
@@ -1204,13 +1204,13 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
1204 | (context->return_valid==AUDITSC_SUCCESS)?"yes":"no", | 1204 | (context->return_valid==AUDITSC_SUCCESS)?"yes":"no", |
1205 | context->return_code); | 1205 | context->return_code); |
1206 | 1206 | ||
1207 | mutex_lock(&tty_mutex); | 1207 | spin_lock_irq(&tsk->sighand->siglock); |
1208 | read_lock(&tasklist_lock); | ||
1209 | if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) | 1208 | if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) |
1210 | tty = tsk->signal->tty->name; | 1209 | tty = tsk->signal->tty->name; |
1211 | else | 1210 | else |
1212 | tty = "(none)"; | 1211 | tty = "(none)"; |
1213 | read_unlock(&tasklist_lock); | 1212 | spin_unlock_irq(&tsk->sighand->siglock); |
1213 | |||
1214 | audit_log_format(ab, | 1214 | audit_log_format(ab, |
1215 | " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" | 1215 | " a0=%lx a1=%lx a2=%lx a3=%lx items=%d" |
1216 | " ppid=%d pid=%d auid=%u uid=%u gid=%u" | 1216 | " ppid=%d pid=%d auid=%u uid=%u gid=%u" |
@@ -1230,7 +1230,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
1230 | context->egid, context->sgid, context->fsgid, tty, | 1230 | context->egid, context->sgid, context->fsgid, tty, |
1231 | tsk->sessionid); | 1231 | tsk->sessionid); |
1232 | 1232 | ||
1233 | mutex_unlock(&tty_mutex); | ||
1234 | 1233 | ||
1235 | audit_log_task_info(ab, tsk); | 1234 | audit_log_task_info(ab, tsk); |
1236 | if (context->filterkey) { | 1235 | if (context->filterkey) { |
diff --git a/kernel/fork.c b/kernel/fork.c index 7ce2ebe84796..30de644a40c4 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -802,6 +802,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
802 | 802 | ||
803 | sig->leader = 0; /* session leadership doesn't inherit */ | 803 | sig->leader = 0; /* session leadership doesn't inherit */ |
804 | sig->tty_old_pgrp = NULL; | 804 | sig->tty_old_pgrp = NULL; |
805 | sig->tty = NULL; | ||
805 | 806 | ||
806 | sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero; | 807 | sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero; |
807 | sig->gtime = cputime_zero; | 808 | sig->gtime = cputime_zero; |
@@ -838,6 +839,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) | |||
838 | void __cleanup_signal(struct signal_struct *sig) | 839 | void __cleanup_signal(struct signal_struct *sig) |
839 | { | 840 | { |
840 | exit_thread_group_keys(sig); | 841 | exit_thread_group_keys(sig); |
842 | tty_kref_put(sig->tty); | ||
841 | kmem_cache_free(signal_cachep, sig); | 843 | kmem_cache_free(signal_cachep, sig); |
842 | } | 844 | } |
843 | 845 | ||
@@ -1227,7 +1229,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1227 | p->nsproxy->pid_ns->child_reaper = p; | 1229 | p->nsproxy->pid_ns->child_reaper = p; |
1228 | 1230 | ||
1229 | p->signal->leader_pid = pid; | 1231 | p->signal->leader_pid = pid; |
1230 | p->signal->tty = current->signal->tty; | 1232 | tty_kref_put(p->signal->tty); |
1233 | p->signal->tty = tty_kref_get(current->signal->tty); | ||
1231 | set_task_pgrp(p, task_pgrp_nr(current)); | 1234 | set_task_pgrp(p, task_pgrp_nr(current)); |
1232 | set_task_session(p, task_session_nr(current)); | 1235 | set_task_session(p, task_session_nr(current)); |
1233 | attach_pid(p, PIDTYPE_PGID, task_pgrp(current)); | 1236 | attach_pid(p, PIDTYPE_PGID, task_pgrp(current)); |
diff --git a/kernel/printk.c b/kernel/printk.c index b51b1567bb55..a430fd04008b 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -1291,22 +1291,6 @@ static int __init disable_boot_consoles(void) | |||
1291 | } | 1291 | } |
1292 | late_initcall(disable_boot_consoles); | 1292 | late_initcall(disable_boot_consoles); |
1293 | 1293 | ||
1294 | /** | ||
1295 | * tty_write_message - write a message to a certain tty, not just the console. | ||
1296 | * @tty: the destination tty_struct | ||
1297 | * @msg: the message to write | ||
1298 | * | ||
1299 | * This is used for messages that need to be redirected to a specific tty. | ||
1300 | * We don't put it into the syslog queue right now maybe in the future if | ||
1301 | * really needed. | ||
1302 | */ | ||
1303 | void tty_write_message(struct tty_struct *tty, char *msg) | ||
1304 | { | ||
1305 | if (tty && tty->ops->write) | ||
1306 | tty->ops->write(tty, msg, strlen(msg)); | ||
1307 | return; | ||
1308 | } | ||
1309 | |||
1310 | #if defined CONFIG_PRINTK | 1294 | #if defined CONFIG_PRINTK |
1311 | 1295 | ||
1312 | /* | 1296 | /* |
diff --git a/kernel/sys.c b/kernel/sys.c index 038a7bc0901d..234d9454294e 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -1060,9 +1060,7 @@ asmlinkage long sys_setsid(void) | |||
1060 | group_leader->signal->leader = 1; | 1060 | group_leader->signal->leader = 1; |
1061 | __set_special_pids(sid); | 1061 | __set_special_pids(sid); |
1062 | 1062 | ||
1063 | spin_lock(&group_leader->sighand->siglock); | 1063 | proc_clear_tty(group_leader); |
1064 | group_leader->signal->tty = NULL; | ||
1065 | spin_unlock(&group_leader->sighand->siglock); | ||
1066 | 1064 | ||
1067 | err = session; | 1065 | err = session; |
1068 | out: | 1066 | out: |
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 4c9890ec2528..473f94e56ead 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
@@ -629,6 +629,59 @@ static int do_i2c_entry(const char *filename, struct i2c_device_id *id, | |||
629 | return 1; | 629 | return 1; |
630 | } | 630 | } |
631 | 631 | ||
632 | static const struct dmifield { | ||
633 | const char *prefix; | ||
634 | int field; | ||
635 | } dmi_fields[] = { | ||
636 | { "bvn", DMI_BIOS_VENDOR }, | ||
637 | { "bvr", DMI_BIOS_VERSION }, | ||
638 | { "bd", DMI_BIOS_DATE }, | ||
639 | { "svn", DMI_SYS_VENDOR }, | ||
640 | { "pn", DMI_PRODUCT_NAME }, | ||
641 | { "pvr", DMI_PRODUCT_VERSION }, | ||
642 | { "rvn", DMI_BOARD_VENDOR }, | ||
643 | { "rn", DMI_BOARD_NAME }, | ||
644 | { "rvr", DMI_BOARD_VERSION }, | ||
645 | { "cvn", DMI_CHASSIS_VENDOR }, | ||
646 | { "ct", DMI_CHASSIS_TYPE }, | ||
647 | { "cvr", DMI_CHASSIS_VERSION }, | ||
648 | { NULL, DMI_NONE } | ||
649 | }; | ||
650 | |||
651 | static void dmi_ascii_filter(char *d, const char *s) | ||
652 | { | ||
653 | /* Filter out characters we don't want to see in the modalias string */ | ||
654 | for (; *s; s++) | ||
655 | if (*s > ' ' && *s < 127 && *s != ':') | ||
656 | *(d++) = *s; | ||
657 | |||
658 | *d = 0; | ||
659 | } | ||
660 | |||
661 | |||
662 | static int do_dmi_entry(const char *filename, struct dmi_system_id *id, | ||
663 | char *alias) | ||
664 | { | ||
665 | int i, j; | ||
666 | |||
667 | sprintf(alias, "dmi*"); | ||
668 | |||
669 | for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) { | ||
670 | for (j = 0; j < 4; j++) { | ||
671 | if (id->matches[j].slot && | ||
672 | id->matches[j].slot == dmi_fields[i].field) { | ||
673 | sprintf(alias + strlen(alias), ":%s*", | ||
674 | dmi_fields[i].prefix); | ||
675 | dmi_ascii_filter(alias + strlen(alias), | ||
676 | id->matches[j].substr); | ||
677 | strcat(alias, "*"); | ||
678 | } | ||
679 | } | ||
680 | } | ||
681 | |||
682 | strcat(alias, ":"); | ||
683 | return 1; | ||
684 | } | ||
632 | /* Ignore any prefix, eg. some architectures prepend _ */ | 685 | /* Ignore any prefix, eg. some architectures prepend _ */ |
633 | static inline int sym_is(const char *symbol, const char *name) | 686 | static inline int sym_is(const char *symbol, const char *name) |
634 | { | 687 | { |
@@ -760,6 +813,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
760 | do_table(symval, sym->st_size, | 813 | do_table(symval, sym->st_size, |
761 | sizeof(struct i2c_device_id), "i2c", | 814 | sizeof(struct i2c_device_id), "i2c", |
762 | do_i2c_entry, mod); | 815 | do_i2c_entry, mod); |
816 | else if (sym_is(symname, "__mod_dmi_device_table")) | ||
817 | do_table(symval, sym->st_size, | ||
818 | sizeof(struct dmi_system_id), "dmi", | ||
819 | do_dmi_entry, mod); | ||
763 | free(zeros); | 820 | free(zeros); |
764 | } | 821 | } |
765 | 822 | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c679ba653e1d..88f19536efad 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -2122,7 +2122,6 @@ static inline void flush_unauthorized_files(struct files_struct *files) | |||
2122 | long j = -1; | 2122 | long j = -1; |
2123 | int drop_tty = 0; | 2123 | int drop_tty = 0; |
2124 | 2124 | ||
2125 | mutex_lock(&tty_mutex); | ||
2126 | tty = get_current_tty(); | 2125 | tty = get_current_tty(); |
2127 | if (tty) { | 2126 | if (tty) { |
2128 | file_list_lock(); | 2127 | file_list_lock(); |
@@ -2140,8 +2139,8 @@ static inline void flush_unauthorized_files(struct files_struct *files) | |||
2140 | } | 2139 | } |
2141 | } | 2140 | } |
2142 | file_list_unlock(); | 2141 | file_list_unlock(); |
2142 | tty_kref_put(tty); | ||
2143 | } | 2143 | } |
2144 | mutex_unlock(&tty_mutex); | ||
2145 | /* Reset controlling tty. */ | 2144 | /* Reset controlling tty. */ |
2146 | if (drop_tty) | 2145 | if (drop_tty) |
2147 | no_tty(); | 2146 | no_tty(); |