diff options
Diffstat (limited to 'drivers')
122 files changed, 3410 insertions, 1780 deletions
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 879250d3d069..ff8c4beaace4 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig | |||
@@ -51,6 +51,8 @@ config CRYPTO_DEV_PADLOCK_SHA | |||
51 | If unsure say M. The compiled module will be | 51 | If unsure say M. The compiled module will be |
52 | called padlock-sha.ko | 52 | called padlock-sha.ko |
53 | 53 | ||
54 | source "arch/s390/crypto/Kconfig" | ||
55 | |||
54 | config CRYPTO_DEV_GEODE | 56 | config CRYPTO_DEV_GEODE |
55 | tristate "Support for the Geode LX AES engine" | 57 | tristate "Support for the Geode LX AES engine" |
56 | depends on CRYPTO && X86_32 && PCI | 58 | depends on CRYPTO && X86_32 && PCI |
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index ec796ad087df..850788f4dd2e 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -22,5 +22,19 @@ config HID | |||
22 | 22 | ||
23 | If unsure, say Y | 23 | If unsure, say Y |
24 | 24 | ||
25 | config HID_DEBUG | ||
26 | bool "HID debugging support" | ||
27 | depends on HID | ||
28 | ---help--- | ||
29 | This option lets the HID layer output diagnostics about its internal | ||
30 | state, resolve HID usages, dump HID fields, etc. Individual HID drivers | ||
31 | use this debugging facility to output information about individual HID | ||
32 | devices, etc. | ||
33 | |||
34 | This feature is useful for those who are either debugging the HID parser | ||
35 | or any HID hardware device. | ||
36 | |||
37 | If unsure, say N | ||
38 | |||
25 | endmenu | 39 | endmenu |
26 | 40 | ||
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 6432392110bf..52e97d8f3c95 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -1,15 +1,8 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the HID driver | 2 | # Makefile for the HID driver |
3 | # | 3 | # |
4 | 4 | hid-objs := hid-core.o hid-input.o | |
5 | # Multipart objects. | ||
6 | hid-objs := hid-core.o hid-input.o | ||
7 | |||
8 | # Optional parts of multipart objects. | ||
9 | 5 | ||
10 | obj-$(CONFIG_HID) += hid.o | 6 | obj-$(CONFIG_HID) += hid.o |
11 | 7 | hid-$(CONFIG_HID_DEBUG) += hid-debug.o | |
12 | ifeq ($(CONFIG_INPUT_DEBUG),y) | ||
13 | EXTRA_CFLAGS += -DDEBUG | ||
14 | endif | ||
15 | 8 | ||
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 49f18f5b2514..8c7d48eff7b7 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -28,11 +28,9 @@ | |||
28 | #include <linux/input.h> | 28 | #include <linux/input.h> |
29 | #include <linux/wait.h> | 29 | #include <linux/wait.h> |
30 | 30 | ||
31 | #undef DEBUG | ||
32 | #undef DEBUG_DATA | ||
33 | |||
34 | #include <linux/hid.h> | 31 | #include <linux/hid.h> |
35 | #include <linux/hiddev.h> | 32 | #include <linux/hiddev.h> |
33 | #include <linux/hid-debug.h> | ||
36 | 34 | ||
37 | /* | 35 | /* |
38 | * Version Information | 36 | * Version Information |
@@ -951,7 +949,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i | |||
951 | return -1; | 949 | return -1; |
952 | } | 950 | } |
953 | 951 | ||
954 | #ifdef DEBUG_DATA | 952 | #ifdef CONFIG_HID_DEBUG |
955 | printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un"); | 953 | printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un"); |
956 | #endif | 954 | #endif |
957 | 955 | ||
@@ -961,7 +959,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i | |||
961 | size--; | 959 | size--; |
962 | } | 960 | } |
963 | 961 | ||
964 | #ifdef DEBUG_DATA | 962 | #ifdef CONFIG_HID_DEBUG |
965 | { | 963 | { |
966 | int i; | 964 | int i; |
967 | printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size); | 965 | printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size); |
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c new file mode 100644 index 000000000000..89241be4ec9b --- /dev/null +++ b/drivers/hid/hid-debug.c | |||
@@ -0,0 +1,764 @@ | |||
1 | /* | ||
2 | * $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $ | ||
3 | * | ||
4 | * (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de> | ||
5 | * (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz> | ||
6 | * (c) 2007 Jiri Kosina | ||
7 | * | ||
8 | * Some debug stuff for the HID parser. | ||
9 | */ | ||
10 | |||
11 | /* | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | * Should you need to contact me, the author, you can do so either by | ||
27 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
28 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
29 | */ | ||
30 | |||
31 | #include <linux/hid.h> | ||
32 | |||
33 | struct hid_usage_entry { | ||
34 | unsigned page; | ||
35 | unsigned usage; | ||
36 | char *description; | ||
37 | }; | ||
38 | |||
39 | static const struct hid_usage_entry hid_usage_table[] = { | ||
40 | { 0, 0, "Undefined" }, | ||
41 | { 1, 0, "GenericDesktop" }, | ||
42 | {0, 0x01, "Pointer"}, | ||
43 | {0, 0x02, "Mouse"}, | ||
44 | {0, 0x04, "Joystick"}, | ||
45 | {0, 0x05, "GamePad"}, | ||
46 | {0, 0x06, "Keyboard"}, | ||
47 | {0, 0x07, "Keypad"}, | ||
48 | {0, 0x08, "MultiAxis"}, | ||
49 | {0, 0x30, "X"}, | ||
50 | {0, 0x31, "Y"}, | ||
51 | {0, 0x32, "Z"}, | ||
52 | {0, 0x33, "Rx"}, | ||
53 | {0, 0x34, "Ry"}, | ||
54 | {0, 0x35, "Rz"}, | ||
55 | {0, 0x36, "Slider"}, | ||
56 | {0, 0x37, "Dial"}, | ||
57 | {0, 0x38, "Wheel"}, | ||
58 | {0, 0x39, "HatSwitch"}, | ||
59 | {0, 0x3a, "CountedBuffer"}, | ||
60 | {0, 0x3b, "ByteCount"}, | ||
61 | {0, 0x3c, "MotionWakeup"}, | ||
62 | {0, 0x3d, "Start"}, | ||
63 | {0, 0x3e, "Select"}, | ||
64 | {0, 0x40, "Vx"}, | ||
65 | {0, 0x41, "Vy"}, | ||
66 | {0, 0x42, "Vz"}, | ||
67 | {0, 0x43, "Vbrx"}, | ||
68 | {0, 0x44, "Vbry"}, | ||
69 | {0, 0x45, "Vbrz"}, | ||
70 | {0, 0x46, "Vno"}, | ||
71 | {0, 0x80, "SystemControl"}, | ||
72 | {0, 0x81, "SystemPowerDown"}, | ||
73 | {0, 0x82, "SystemSleep"}, | ||
74 | {0, 0x83, "SystemWakeUp"}, | ||
75 | {0, 0x84, "SystemContextMenu"}, | ||
76 | {0, 0x85, "SystemMainMenu"}, | ||
77 | {0, 0x86, "SystemAppMenu"}, | ||
78 | {0, 0x87, "SystemMenuHelp"}, | ||
79 | {0, 0x88, "SystemMenuExit"}, | ||
80 | {0, 0x89, "SystemMenuSelect"}, | ||
81 | {0, 0x8a, "SystemMenuRight"}, | ||
82 | {0, 0x8b, "SystemMenuLeft"}, | ||
83 | {0, 0x8c, "SystemMenuUp"}, | ||
84 | {0, 0x8d, "SystemMenuDown"}, | ||
85 | {0, 0x90, "D-PadUp"}, | ||
86 | {0, 0x91, "D-PadDown"}, | ||
87 | {0, 0x92, "D-PadRight"}, | ||
88 | {0, 0x93, "D-PadLeft"}, | ||
89 | { 2, 0, "Simulation" }, | ||
90 | {0, 0xb0, "Aileron"}, | ||
91 | {0, 0xb1, "AileronTrim"}, | ||
92 | {0, 0xb2, "Anti-Torque"}, | ||
93 | {0, 0xb3, "Autopilot"}, | ||
94 | {0, 0xb4, "Chaff"}, | ||
95 | {0, 0xb5, "Collective"}, | ||
96 | {0, 0xb6, "DiveBrake"}, | ||
97 | {0, 0xb7, "ElectronicCountermeasures"}, | ||
98 | {0, 0xb8, "Elevator"}, | ||
99 | {0, 0xb9, "ElevatorTrim"}, | ||
100 | {0, 0xba, "Rudder"}, | ||
101 | {0, 0xbb, "Throttle"}, | ||
102 | {0, 0xbc, "FlightCommunications"}, | ||
103 | {0, 0xbd, "FlareRelease"}, | ||
104 | {0, 0xbe, "LandingGear"}, | ||
105 | {0, 0xbf, "ToeBrake"}, | ||
106 | { 7, 0, "Keyboard" }, | ||
107 | { 8, 0, "LED" }, | ||
108 | {0, 0x01, "NumLock"}, | ||
109 | {0, 0x02, "CapsLock"}, | ||
110 | {0, 0x03, "ScrollLock"}, | ||
111 | {0, 0x04, "Compose"}, | ||
112 | {0, 0x05, "Kana"}, | ||
113 | {0, 0x4b, "GenericIndicator"}, | ||
114 | { 9, 0, "Button" }, | ||
115 | { 10, 0, "Ordinal" }, | ||
116 | { 12, 0, "Consumer" }, | ||
117 | {0, 0x238, "HorizontalWheel"}, | ||
118 | { 13, 0, "Digitizers" }, | ||
119 | {0, 0x01, "Digitizer"}, | ||
120 | {0, 0x02, "Pen"}, | ||
121 | {0, 0x03, "LightPen"}, | ||
122 | {0, 0x04, "TouchScreen"}, | ||
123 | {0, 0x05, "TouchPad"}, | ||
124 | {0, 0x20, "Stylus"}, | ||
125 | {0, 0x21, "Puck"}, | ||
126 | {0, 0x22, "Finger"}, | ||
127 | {0, 0x30, "TipPressure"}, | ||
128 | {0, 0x31, "BarrelPressure"}, | ||
129 | {0, 0x32, "InRange"}, | ||
130 | {0, 0x33, "Touch"}, | ||
131 | {0, 0x34, "UnTouch"}, | ||
132 | {0, 0x35, "Tap"}, | ||
133 | {0, 0x39, "TabletFunctionKey"}, | ||
134 | {0, 0x3a, "ProgramChangeKey"}, | ||
135 | {0, 0x3c, "Invert"}, | ||
136 | {0, 0x42, "TipSwitch"}, | ||
137 | {0, 0x43, "SecondaryTipSwitch"}, | ||
138 | {0, 0x44, "BarrelSwitch"}, | ||
139 | {0, 0x45, "Eraser"}, | ||
140 | {0, 0x46, "TabletPick"}, | ||
141 | { 15, 0, "PhysicalInterfaceDevice" }, | ||
142 | {0, 0x00, "Undefined"}, | ||
143 | {0, 0x01, "Physical_Interface_Device"}, | ||
144 | {0, 0x20, "Normal"}, | ||
145 | {0, 0x21, "Set_Effect_Report"}, | ||
146 | {0, 0x22, "Effect_Block_Index"}, | ||
147 | {0, 0x23, "Parameter_Block_Offset"}, | ||
148 | {0, 0x24, "ROM_Flag"}, | ||
149 | {0, 0x25, "Effect_Type"}, | ||
150 | {0, 0x26, "ET_Constant_Force"}, | ||
151 | {0, 0x27, "ET_Ramp"}, | ||
152 | {0, 0x28, "ET_Custom_Force_Data"}, | ||
153 | {0, 0x30, "ET_Square"}, | ||
154 | {0, 0x31, "ET_Sine"}, | ||
155 | {0, 0x32, "ET_Triangle"}, | ||
156 | {0, 0x33, "ET_Sawtooth_Up"}, | ||
157 | {0, 0x34, "ET_Sawtooth_Down"}, | ||
158 | {0, 0x40, "ET_Spring"}, | ||
159 | {0, 0x41, "ET_Damper"}, | ||
160 | {0, 0x42, "ET_Inertia"}, | ||
161 | {0, 0x43, "ET_Friction"}, | ||
162 | {0, 0x50, "Duration"}, | ||
163 | {0, 0x51, "Sample_Period"}, | ||
164 | {0, 0x52, "Gain"}, | ||
165 | {0, 0x53, "Trigger_Button"}, | ||
166 | {0, 0x54, "Trigger_Repeat_Interval"}, | ||
167 | {0, 0x55, "Axes_Enable"}, | ||
168 | {0, 0x56, "Direction_Enable"}, | ||
169 | {0, 0x57, "Direction"}, | ||
170 | {0, 0x58, "Type_Specific_Block_Offset"}, | ||
171 | {0, 0x59, "Block_Type"}, | ||
172 | {0, 0x5A, "Set_Envelope_Report"}, | ||
173 | {0, 0x5B, "Attack_Level"}, | ||
174 | {0, 0x5C, "Attack_Time"}, | ||
175 | {0, 0x5D, "Fade_Level"}, | ||
176 | {0, 0x5E, "Fade_Time"}, | ||
177 | {0, 0x5F, "Set_Condition_Report"}, | ||
178 | {0, 0x60, "CP_Offset"}, | ||
179 | {0, 0x61, "Positive_Coefficient"}, | ||
180 | {0, 0x62, "Negative_Coefficient"}, | ||
181 | {0, 0x63, "Positive_Saturation"}, | ||
182 | {0, 0x64, "Negative_Saturation"}, | ||
183 | {0, 0x65, "Dead_Band"}, | ||
184 | {0, 0x66, "Download_Force_Sample"}, | ||
185 | {0, 0x67, "Isoch_Custom_Force_Enable"}, | ||
186 | {0, 0x68, "Custom_Force_Data_Report"}, | ||
187 | {0, 0x69, "Custom_Force_Data"}, | ||
188 | {0, 0x6A, "Custom_Force_Vendor_Defined_Data"}, | ||
189 | {0, 0x6B, "Set_Custom_Force_Report"}, | ||
190 | {0, 0x6C, "Custom_Force_Data_Offset"}, | ||
191 | {0, 0x6D, "Sample_Count"}, | ||
192 | {0, 0x6E, "Set_Periodic_Report"}, | ||
193 | {0, 0x6F, "Offset"}, | ||
194 | {0, 0x70, "Magnitude"}, | ||
195 | {0, 0x71, "Phase"}, | ||
196 | {0, 0x72, "Period"}, | ||
197 | {0, 0x73, "Set_Constant_Force_Report"}, | ||
198 | {0, 0x74, "Set_Ramp_Force_Report"}, | ||
199 | {0, 0x75, "Ramp_Start"}, | ||
200 | {0, 0x76, "Ramp_End"}, | ||
201 | {0, 0x77, "Effect_Operation_Report"}, | ||
202 | {0, 0x78, "Effect_Operation"}, | ||
203 | {0, 0x79, "Op_Effect_Start"}, | ||
204 | {0, 0x7A, "Op_Effect_Start_Solo"}, | ||
205 | {0, 0x7B, "Op_Effect_Stop"}, | ||
206 | {0, 0x7C, "Loop_Count"}, | ||
207 | {0, 0x7D, "Device_Gain_Report"}, | ||
208 | {0, 0x7E, "Device_Gain"}, | ||
209 | {0, 0x7F, "PID_Pool_Report"}, | ||
210 | {0, 0x80, "RAM_Pool_Size"}, | ||
211 | {0, 0x81, "ROM_Pool_Size"}, | ||
212 | {0, 0x82, "ROM_Effect_Block_Count"}, | ||
213 | {0, 0x83, "Simultaneous_Effects_Max"}, | ||
214 | {0, 0x84, "Pool_Alignment"}, | ||
215 | {0, 0x85, "PID_Pool_Move_Report"}, | ||
216 | {0, 0x86, "Move_Source"}, | ||
217 | {0, 0x87, "Move_Destination"}, | ||
218 | {0, 0x88, "Move_Length"}, | ||
219 | {0, 0x89, "PID_Block_Load_Report"}, | ||
220 | {0, 0x8B, "Block_Load_Status"}, | ||
221 | {0, 0x8C, "Block_Load_Success"}, | ||
222 | {0, 0x8D, "Block_Load_Full"}, | ||
223 | {0, 0x8E, "Block_Load_Error"}, | ||
224 | {0, 0x8F, "Block_Handle"}, | ||
225 | {0, 0x90, "PID_Block_Free_Report"}, | ||
226 | {0, 0x91, "Type_Specific_Block_Handle"}, | ||
227 | {0, 0x92, "PID_State_Report"}, | ||
228 | {0, 0x94, "Effect_Playing"}, | ||
229 | {0, 0x95, "PID_Device_Control_Report"}, | ||
230 | {0, 0x96, "PID_Device_Control"}, | ||
231 | {0, 0x97, "DC_Enable_Actuators"}, | ||
232 | {0, 0x98, "DC_Disable_Actuators"}, | ||
233 | {0, 0x99, "DC_Stop_All_Effects"}, | ||
234 | {0, 0x9A, "DC_Device_Reset"}, | ||
235 | {0, 0x9B, "DC_Device_Pause"}, | ||
236 | {0, 0x9C, "DC_Device_Continue"}, | ||
237 | {0, 0x9F, "Device_Paused"}, | ||
238 | {0, 0xA0, "Actuators_Enabled"}, | ||
239 | {0, 0xA4, "Safety_Switch"}, | ||
240 | {0, 0xA5, "Actuator_Override_Switch"}, | ||
241 | {0, 0xA6, "Actuator_Power"}, | ||
242 | {0, 0xA7, "Start_Delay"}, | ||
243 | {0, 0xA8, "Parameter_Block_Size"}, | ||
244 | {0, 0xA9, "Device_Managed_Pool"}, | ||
245 | {0, 0xAA, "Shared_Parameter_Blocks"}, | ||
246 | {0, 0xAB, "Create_New_Effect_Report"}, | ||
247 | {0, 0xAC, "RAM_Pool_Available"}, | ||
248 | { 0x84, 0, "Power Device" }, | ||
249 | { 0x84, 0x02, "PresentStatus" }, | ||
250 | { 0x84, 0x03, "ChangeStatus" }, | ||
251 | { 0x84, 0x04, "UPS" }, | ||
252 | { 0x84, 0x05, "PowerSupply" }, | ||
253 | { 0x84, 0x10, "BatterySystem" }, | ||
254 | { 0x84, 0x11, "BatterySystemID" }, | ||
255 | { 0x84, 0x12, "Battery" }, | ||
256 | { 0x84, 0x13, "BatteryID" }, | ||
257 | { 0x84, 0x14, "Charger" }, | ||
258 | { 0x84, 0x15, "ChargerID" }, | ||
259 | { 0x84, 0x16, "PowerConverter" }, | ||
260 | { 0x84, 0x17, "PowerConverterID" }, | ||
261 | { 0x84, 0x18, "OutletSystem" }, | ||
262 | { 0x84, 0x19, "OutletSystemID" }, | ||
263 | { 0x84, 0x1a, "Input" }, | ||
264 | { 0x84, 0x1b, "InputID" }, | ||
265 | { 0x84, 0x1c, "Output" }, | ||
266 | { 0x84, 0x1d, "OutputID" }, | ||
267 | { 0x84, 0x1e, "Flow" }, | ||
268 | { 0x84, 0x1f, "FlowID" }, | ||
269 | { 0x84, 0x20, "Outlet" }, | ||
270 | { 0x84, 0x21, "OutletID" }, | ||
271 | { 0x84, 0x22, "Gang" }, | ||
272 | { 0x84, 0x24, "PowerSummary" }, | ||
273 | { 0x84, 0x25, "PowerSummaryID" }, | ||
274 | { 0x84, 0x30, "Voltage" }, | ||
275 | { 0x84, 0x31, "Current" }, | ||
276 | { 0x84, 0x32, "Frequency" }, | ||
277 | { 0x84, 0x33, "ApparentPower" }, | ||
278 | { 0x84, 0x35, "PercentLoad" }, | ||
279 | { 0x84, 0x40, "ConfigVoltage" }, | ||
280 | { 0x84, 0x41, "ConfigCurrent" }, | ||
281 | { 0x84, 0x43, "ConfigApparentPower" }, | ||
282 | { 0x84, 0x53, "LowVoltageTransfer" }, | ||
283 | { 0x84, 0x54, "HighVoltageTransfer" }, | ||
284 | { 0x84, 0x56, "DelayBeforeStartup" }, | ||
285 | { 0x84, 0x57, "DelayBeforeShutdown" }, | ||
286 | { 0x84, 0x58, "Test" }, | ||
287 | { 0x84, 0x5a, "AudibleAlarmControl" }, | ||
288 | { 0x84, 0x60, "Present" }, | ||
289 | { 0x84, 0x61, "Good" }, | ||
290 | { 0x84, 0x62, "InternalFailure" }, | ||
291 | { 0x84, 0x65, "Overload" }, | ||
292 | { 0x84, 0x66, "OverCharged" }, | ||
293 | { 0x84, 0x67, "OverTemperature" }, | ||
294 | { 0x84, 0x68, "ShutdownRequested" }, | ||
295 | { 0x84, 0x69, "ShutdownImminent" }, | ||
296 | { 0x84, 0x6b, "SwitchOn/Off" }, | ||
297 | { 0x84, 0x6c, "Switchable" }, | ||
298 | { 0x84, 0x6d, "Used" }, | ||
299 | { 0x84, 0x6e, "Boost" }, | ||
300 | { 0x84, 0x73, "CommunicationLost" }, | ||
301 | { 0x84, 0xfd, "iManufacturer" }, | ||
302 | { 0x84, 0xfe, "iProduct" }, | ||
303 | { 0x84, 0xff, "iSerialNumber" }, | ||
304 | { 0x85, 0, "Battery System" }, | ||
305 | { 0x85, 0x01, "SMBBatteryMode" }, | ||
306 | { 0x85, 0x02, "SMBBatteryStatus" }, | ||
307 | { 0x85, 0x03, "SMBAlarmWarning" }, | ||
308 | { 0x85, 0x04, "SMBChargerMode" }, | ||
309 | { 0x85, 0x05, "SMBChargerStatus" }, | ||
310 | { 0x85, 0x06, "SMBChargerSpecInfo" }, | ||
311 | { 0x85, 0x07, "SMBSelectorState" }, | ||
312 | { 0x85, 0x08, "SMBSelectorPresets" }, | ||
313 | { 0x85, 0x09, "SMBSelectorInfo" }, | ||
314 | { 0x85, 0x29, "RemainingCapacityLimit" }, | ||
315 | { 0x85, 0x2c, "CapacityMode" }, | ||
316 | { 0x85, 0x42, "BelowRemainingCapacityLimit" }, | ||
317 | { 0x85, 0x44, "Charging" }, | ||
318 | { 0x85, 0x45, "Discharging" }, | ||
319 | { 0x85, 0x4b, "NeedReplacement" }, | ||
320 | { 0x85, 0x66, "RemainingCapacity" }, | ||
321 | { 0x85, 0x68, "RunTimeToEmpty" }, | ||
322 | { 0x85, 0x6a, "AverageTimeToFull" }, | ||
323 | { 0x85, 0x83, "DesignCapacity" }, | ||
324 | { 0x85, 0x85, "ManufacturerDate" }, | ||
325 | { 0x85, 0x89, "iDeviceChemistry" }, | ||
326 | { 0x85, 0x8b, "Rechargable" }, | ||
327 | { 0x85, 0x8f, "iOEMInformation" }, | ||
328 | { 0x85, 0x8d, "CapacityGranularity1" }, | ||
329 | { 0x85, 0xd0, "ACPresent" }, | ||
330 | /* pages 0xff00 to 0xffff are vendor-specific */ | ||
331 | { 0xffff, 0, "Vendor-specific-FF" }, | ||
332 | { 0, 0, NULL } | ||
333 | }; | ||
334 | |||
335 | static void resolv_usage_page(unsigned page) { | ||
336 | const struct hid_usage_entry *p; | ||
337 | |||
338 | for (p = hid_usage_table; p->description; p++) | ||
339 | if (p->page == page) { | ||
340 | printk("%s", p->description); | ||
341 | return; | ||
342 | } | ||
343 | printk("%04x", page); | ||
344 | } | ||
345 | |||
346 | void hid_resolv_usage(unsigned usage) { | ||
347 | const struct hid_usage_entry *p; | ||
348 | |||
349 | resolv_usage_page(usage >> 16); | ||
350 | printk("."); | ||
351 | for (p = hid_usage_table; p->description; p++) | ||
352 | if (p->page == (usage >> 16)) { | ||
353 | for(++p; p->description && p->usage != 0; p++) | ||
354 | if (p->usage == (usage & 0xffff)) { | ||
355 | printk("%s", p->description); | ||
356 | return; | ||
357 | } | ||
358 | break; | ||
359 | } | ||
360 | printk("%04x", usage & 0xffff); | ||
361 | } | ||
362 | EXPORT_SYMBOL_GPL(hid_resolv_usage); | ||
363 | |||
364 | __inline__ static void tab(int n) { | ||
365 | while (n--) printk(" "); | ||
366 | } | ||
367 | |||
368 | void hid_dump_field(struct hid_field *field, int n) { | ||
369 | int j; | ||
370 | |||
371 | if (field->physical) { | ||
372 | tab(n); | ||
373 | printk("Physical("); | ||
374 | hid_resolv_usage(field->physical); printk(")\n"); | ||
375 | } | ||
376 | if (field->logical) { | ||
377 | tab(n); | ||
378 | printk("Logical("); | ||
379 | hid_resolv_usage(field->logical); printk(")\n"); | ||
380 | } | ||
381 | tab(n); printk("Usage(%d)\n", field->maxusage); | ||
382 | for (j = 0; j < field->maxusage; j++) { | ||
383 | tab(n+2); hid_resolv_usage(field->usage[j].hid); printk("\n"); | ||
384 | } | ||
385 | if (field->logical_minimum != field->logical_maximum) { | ||
386 | tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum); | ||
387 | tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum); | ||
388 | } | ||
389 | if (field->physical_minimum != field->physical_maximum) { | ||
390 | tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum); | ||
391 | tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum); | ||
392 | } | ||
393 | if (field->unit_exponent) { | ||
394 | tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent); | ||
395 | } | ||
396 | if (field->unit) { | ||
397 | char *systems[5] = { "None", "SI Linear", "SI Rotation", "English Linear", "English Rotation" }; | ||
398 | char *units[5][8] = { | ||
399 | { "None", "None", "None", "None", "None", "None", "None", "None" }, | ||
400 | { "None", "Centimeter", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" }, | ||
401 | { "None", "Radians", "Gram", "Seconds", "Kelvin", "Ampere", "Candela", "None" }, | ||
402 | { "None", "Inch", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" }, | ||
403 | { "None", "Degrees", "Slug", "Seconds", "Fahrenheit", "Ampere", "Candela", "None" } | ||
404 | }; | ||
405 | |||
406 | int i; | ||
407 | int sys; | ||
408 | __u32 data = field->unit; | ||
409 | |||
410 | /* First nibble tells us which system we're in. */ | ||
411 | sys = data & 0xf; | ||
412 | data >>= 4; | ||
413 | |||
414 | if(sys > 4) { | ||
415 | tab(n); printk("Unit(Invalid)\n"); | ||
416 | } | ||
417 | else { | ||
418 | int earlier_unit = 0; | ||
419 | |||
420 | tab(n); printk("Unit(%s : ", systems[sys]); | ||
421 | |||
422 | for (i=1 ; i<sizeof(__u32)*2 ; i++) { | ||
423 | char nibble = data & 0xf; | ||
424 | data >>= 4; | ||
425 | if (nibble != 0) { | ||
426 | if(earlier_unit++ > 0) | ||
427 | printk("*"); | ||
428 | printk("%s", units[sys][i]); | ||
429 | if(nibble != 1) { | ||
430 | /* This is a _signed_ nibble(!) */ | ||
431 | |||
432 | int val = nibble & 0x7; | ||
433 | if(nibble & 0x08) | ||
434 | val = -((0x7 & ~val) +1); | ||
435 | printk("^%d", val); | ||
436 | } | ||
437 | } | ||
438 | } | ||
439 | printk(")\n"); | ||
440 | } | ||
441 | } | ||
442 | tab(n); printk("Report Size(%u)\n", field->report_size); | ||
443 | tab(n); printk("Report Count(%u)\n", field->report_count); | ||
444 | tab(n); printk("Report Offset(%u)\n", field->report_offset); | ||
445 | |||
446 | tab(n); printk("Flags( "); | ||
447 | j = field->flags; | ||
448 | printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : ""); | ||
449 | printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array "); | ||
450 | printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute "); | ||
451 | printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : ""); | ||
452 | printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : ""); | ||
453 | printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : ""); | ||
454 | printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : ""); | ||
455 | printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : ""); | ||
456 | printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : ""); | ||
457 | printk(")\n"); | ||
458 | } | ||
459 | EXPORT_SYMBOL_GPL(hid_dump_field); | ||
460 | |||
461 | void hid_dump_device(struct hid_device *device) { | ||
462 | struct hid_report_enum *report_enum; | ||
463 | struct hid_report *report; | ||
464 | struct list_head *list; | ||
465 | unsigned i,k; | ||
466 | static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; | ||
467 | |||
468 | for (i = 0; i < HID_REPORT_TYPES; i++) { | ||
469 | report_enum = device->report_enum + i; | ||
470 | list = report_enum->report_list.next; | ||
471 | while (list != &report_enum->report_list) { | ||
472 | report = (struct hid_report *) list; | ||
473 | tab(2); | ||
474 | printk("%s", table[i]); | ||
475 | if (report->id) | ||
476 | printk("(%d)", report->id); | ||
477 | printk("[%s]", table[report->type]); | ||
478 | printk("\n"); | ||
479 | for (k = 0; k < report->maxfield; k++) { | ||
480 | tab(4); | ||
481 | printk("Field(%d)\n", k); | ||
482 | hid_dump_field(report->field[k], 6); | ||
483 | } | ||
484 | list = list->next; | ||
485 | } | ||
486 | } | ||
487 | } | ||
488 | EXPORT_SYMBOL_GPL(hid_dump_device); | ||
489 | |||
490 | void hid_dump_input(struct hid_usage *usage, __s32 value) { | ||
491 | printk("hid-debug: input "); | ||
492 | hid_resolv_usage(usage->hid); | ||
493 | printk(" = %d\n", value); | ||
494 | } | ||
495 | EXPORT_SYMBOL_GPL(hid_dump_input); | ||
496 | |||
497 | static char *events[EV_MAX + 1] = { | ||
498 | [EV_SYN] = "Sync", [EV_KEY] = "Key", | ||
499 | [EV_REL] = "Relative", [EV_ABS] = "Absolute", | ||
500 | [EV_MSC] = "Misc", [EV_LED] = "LED", | ||
501 | [EV_SND] = "Sound", [EV_REP] = "Repeat", | ||
502 | [EV_FF] = "ForceFeedback", [EV_PWR] = "Power", | ||
503 | [EV_FF_STATUS] = "ForceFeedbackStatus", | ||
504 | }; | ||
505 | |||
506 | static char *syncs[2] = { | ||
507 | [SYN_REPORT] = "Report", [SYN_CONFIG] = "Config", | ||
508 | }; | ||
509 | static char *keys[KEY_MAX + 1] = { | ||
510 | [KEY_RESERVED] = "Reserved", [KEY_ESC] = "Esc", | ||
511 | [KEY_1] = "1", [KEY_2] = "2", | ||
512 | [KEY_3] = "3", [KEY_4] = "4", | ||
513 | [KEY_5] = "5", [KEY_6] = "6", | ||
514 | [KEY_7] = "7", [KEY_8] = "8", | ||
515 | [KEY_9] = "9", [KEY_0] = "0", | ||
516 | [KEY_MINUS] = "Minus", [KEY_EQUAL] = "Equal", | ||
517 | [KEY_BACKSPACE] = "Backspace", [KEY_TAB] = "Tab", | ||
518 | [KEY_Q] = "Q", [KEY_W] = "W", | ||
519 | [KEY_E] = "E", [KEY_R] = "R", | ||
520 | [KEY_T] = "T", [KEY_Y] = "Y", | ||
521 | [KEY_U] = "U", [KEY_I] = "I", | ||
522 | [KEY_O] = "O", [KEY_P] = "P", | ||
523 | [KEY_LEFTBRACE] = "LeftBrace", [KEY_RIGHTBRACE] = "RightBrace", | ||
524 | [KEY_ENTER] = "Enter", [KEY_LEFTCTRL] = "LeftControl", | ||
525 | [KEY_A] = "A", [KEY_S] = "S", | ||
526 | [KEY_D] = "D", [KEY_F] = "F", | ||
527 | [KEY_G] = "G", [KEY_H] = "H", | ||
528 | [KEY_J] = "J", [KEY_K] = "K", | ||
529 | [KEY_L] = "L", [KEY_SEMICOLON] = "Semicolon", | ||
530 | [KEY_APOSTROPHE] = "Apostrophe", [KEY_GRAVE] = "Grave", | ||
531 | [KEY_LEFTSHIFT] = "LeftShift", [KEY_BACKSLASH] = "BackSlash", | ||
532 | [KEY_Z] = "Z", [KEY_X] = "X", | ||
533 | [KEY_C] = "C", [KEY_V] = "V", | ||
534 | [KEY_B] = "B", [KEY_N] = "N", | ||
535 | [KEY_M] = "M", [KEY_COMMA] = "Comma", | ||
536 | [KEY_DOT] = "Dot", [KEY_SLASH] = "Slash", | ||
537 | [KEY_RIGHTSHIFT] = "RightShift", [KEY_KPASTERISK] = "KPAsterisk", | ||
538 | [KEY_LEFTALT] = "LeftAlt", [KEY_SPACE] = "Space", | ||
539 | [KEY_CAPSLOCK] = "CapsLock", [KEY_F1] = "F1", | ||
540 | [KEY_F2] = "F2", [KEY_F3] = "F3", | ||
541 | [KEY_F4] = "F4", [KEY_F5] = "F5", | ||
542 | [KEY_F6] = "F6", [KEY_F7] = "F7", | ||
543 | [KEY_F8] = "F8", [KEY_F9] = "F9", | ||
544 | [KEY_F10] = "F10", [KEY_NUMLOCK] = "NumLock", | ||
545 | [KEY_SCROLLLOCK] = "ScrollLock", [KEY_KP7] = "KP7", | ||
546 | [KEY_KP8] = "KP8", [KEY_KP9] = "KP9", | ||
547 | [KEY_KPMINUS] = "KPMinus", [KEY_KP4] = "KP4", | ||
548 | [KEY_KP5] = "KP5", [KEY_KP6] = "KP6", | ||
549 | [KEY_KPPLUS] = "KPPlus", [KEY_KP1] = "KP1", | ||
550 | [KEY_KP2] = "KP2", [KEY_KP3] = "KP3", | ||
551 | [KEY_KP0] = "KP0", [KEY_KPDOT] = "KPDot", | ||
552 | [KEY_ZENKAKUHANKAKU] = "Zenkaku/Hankaku", [KEY_102ND] = "102nd", | ||
553 | [KEY_F11] = "F11", [KEY_F12] = "F12", | ||
554 | [KEY_RO] = "RO", [KEY_KATAKANA] = "Katakana", | ||
555 | [KEY_HIRAGANA] = "HIRAGANA", [KEY_HENKAN] = "Henkan", | ||
556 | [KEY_KATAKANAHIRAGANA] = "Katakana/Hiragana", [KEY_MUHENKAN] = "Muhenkan", | ||
557 | [KEY_KPJPCOMMA] = "KPJpComma", [KEY_KPENTER] = "KPEnter", | ||
558 | [KEY_RIGHTCTRL] = "RightCtrl", [KEY_KPSLASH] = "KPSlash", | ||
559 | [KEY_SYSRQ] = "SysRq", [KEY_RIGHTALT] = "RightAlt", | ||
560 | [KEY_LINEFEED] = "LineFeed", [KEY_HOME] = "Home", | ||
561 | [KEY_UP] = "Up", [KEY_PAGEUP] = "PageUp", | ||
562 | [KEY_LEFT] = "Left", [KEY_RIGHT] = "Right", | ||
563 | [KEY_END] = "End", [KEY_DOWN] = "Down", | ||
564 | [KEY_PAGEDOWN] = "PageDown", [KEY_INSERT] = "Insert", | ||
565 | [KEY_DELETE] = "Delete", [KEY_MACRO] = "Macro", | ||
566 | [KEY_MUTE] = "Mute", [KEY_VOLUMEDOWN] = "VolumeDown", | ||
567 | [KEY_VOLUMEUP] = "VolumeUp", [KEY_POWER] = "Power", | ||
568 | [KEY_KPEQUAL] = "KPEqual", [KEY_KPPLUSMINUS] = "KPPlusMinus", | ||
569 | [KEY_PAUSE] = "Pause", [KEY_KPCOMMA] = "KPComma", | ||
570 | [KEY_HANGUEL] = "Hangeul", [KEY_HANJA] = "Hanja", | ||
571 | [KEY_YEN] = "Yen", [KEY_LEFTMETA] = "LeftMeta", | ||
572 | [KEY_RIGHTMETA] = "RightMeta", [KEY_COMPOSE] = "Compose", | ||
573 | [KEY_STOP] = "Stop", [KEY_AGAIN] = "Again", | ||
574 | [KEY_PROPS] = "Props", [KEY_UNDO] = "Undo", | ||
575 | [KEY_FRONT] = "Front", [KEY_COPY] = "Copy", | ||
576 | [KEY_OPEN] = "Open", [KEY_PASTE] = "Paste", | ||
577 | [KEY_FIND] = "Find", [KEY_CUT] = "Cut", | ||
578 | [KEY_HELP] = "Help", [KEY_MENU] = "Menu", | ||
579 | [KEY_CALC] = "Calc", [KEY_SETUP] = "Setup", | ||
580 | [KEY_SLEEP] = "Sleep", [KEY_WAKEUP] = "WakeUp", | ||
581 | [KEY_FILE] = "File", [KEY_SENDFILE] = "SendFile", | ||
582 | [KEY_DELETEFILE] = "DeleteFile", [KEY_XFER] = "X-fer", | ||
583 | [KEY_PROG1] = "Prog1", [KEY_PROG2] = "Prog2", | ||
584 | [KEY_WWW] = "WWW", [KEY_MSDOS] = "MSDOS", | ||
585 | [KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction", | ||
586 | [KEY_CYCLEWINDOWS] = "CycleWindows", [KEY_MAIL] = "Mail", | ||
587 | [KEY_BOOKMARKS] = "Bookmarks", [KEY_COMPUTER] = "Computer", | ||
588 | [KEY_BACK] = "Back", [KEY_FORWARD] = "Forward", | ||
589 | [KEY_CLOSECD] = "CloseCD", [KEY_EJECTCD] = "EjectCD", | ||
590 | [KEY_EJECTCLOSECD] = "EjectCloseCD", [KEY_NEXTSONG] = "NextSong", | ||
591 | [KEY_PLAYPAUSE] = "PlayPause", [KEY_PREVIOUSSONG] = "PreviousSong", | ||
592 | [KEY_STOPCD] = "StopCD", [KEY_RECORD] = "Record", | ||
593 | [KEY_REWIND] = "Rewind", [KEY_PHONE] = "Phone", | ||
594 | [KEY_ISO] = "ISOKey", [KEY_CONFIG] = "Config", | ||
595 | [KEY_HOMEPAGE] = "HomePage", [KEY_REFRESH] = "Refresh", | ||
596 | [KEY_EXIT] = "Exit", [KEY_MOVE] = "Move", | ||
597 | [KEY_EDIT] = "Edit", [KEY_SCROLLUP] = "ScrollUp", | ||
598 | [KEY_SCROLLDOWN] = "ScrollDown", [KEY_KPLEFTPAREN] = "KPLeftParenthesis", | ||
599 | [KEY_KPRIGHTPAREN] = "KPRightParenthesis", [KEY_NEW] = "New", | ||
600 | [KEY_REDO] = "Redo", [KEY_F13] = "F13", | ||
601 | [KEY_F14] = "F14", [KEY_F15] = "F15", | ||
602 | [KEY_F16] = "F16", [KEY_F17] = "F17", | ||
603 | [KEY_F18] = "F18", [KEY_F19] = "F19", | ||
604 | [KEY_F20] = "F20", [KEY_F21] = "F21", | ||
605 | [KEY_F22] = "F22", [KEY_F23] = "F23", | ||
606 | [KEY_F24] = "F24", [KEY_PLAYCD] = "PlayCD", | ||
607 | [KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3", | ||
608 | [KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend", | ||
609 | [KEY_CLOSE] = "Close", [KEY_PLAY] = "Play", | ||
610 | [KEY_FASTFORWARD] = "FastForward", [KEY_BASSBOOST] = "BassBoost", | ||
611 | [KEY_PRINT] = "Print", [KEY_HP] = "HP", | ||
612 | [KEY_CAMERA] = "Camera", [KEY_SOUND] = "Sound", | ||
613 | [KEY_QUESTION] = "Question", [KEY_EMAIL] = "Email", | ||
614 | [KEY_CHAT] = "Chat", [KEY_SEARCH] = "Search", | ||
615 | [KEY_CONNECT] = "Connect", [KEY_FINANCE] = "Finance", | ||
616 | [KEY_SPORT] = "Sport", [KEY_SHOP] = "Shop", | ||
617 | [KEY_ALTERASE] = "AlternateErase", [KEY_CANCEL] = "Cancel", | ||
618 | [KEY_BRIGHTNESSDOWN] = "BrightnessDown", [KEY_BRIGHTNESSUP] = "BrightnessUp", | ||
619 | [KEY_MEDIA] = "Media", [KEY_UNKNOWN] = "Unknown", | ||
620 | [BTN_0] = "Btn0", [BTN_1] = "Btn1", | ||
621 | [BTN_2] = "Btn2", [BTN_3] = "Btn3", | ||
622 | [BTN_4] = "Btn4", [BTN_5] = "Btn5", | ||
623 | [BTN_6] = "Btn6", [BTN_7] = "Btn7", | ||
624 | [BTN_8] = "Btn8", [BTN_9] = "Btn9", | ||
625 | [BTN_LEFT] = "LeftBtn", [BTN_RIGHT] = "RightBtn", | ||
626 | [BTN_MIDDLE] = "MiddleBtn", [BTN_SIDE] = "SideBtn", | ||
627 | [BTN_EXTRA] = "ExtraBtn", [BTN_FORWARD] = "ForwardBtn", | ||
628 | [BTN_BACK] = "BackBtn", [BTN_TASK] = "TaskBtn", | ||
629 | [BTN_TRIGGER] = "Trigger", [BTN_THUMB] = "ThumbBtn", | ||
630 | [BTN_THUMB2] = "ThumbBtn2", [BTN_TOP] = "TopBtn", | ||
631 | [BTN_TOP2] = "TopBtn2", [BTN_PINKIE] = "PinkieBtn", | ||
632 | [BTN_BASE] = "BaseBtn", [BTN_BASE2] = "BaseBtn2", | ||
633 | [BTN_BASE3] = "BaseBtn3", [BTN_BASE4] = "BaseBtn4", | ||
634 | [BTN_BASE5] = "BaseBtn5", [BTN_BASE6] = "BaseBtn6", | ||
635 | [BTN_DEAD] = "BtnDead", [BTN_A] = "BtnA", | ||
636 | [BTN_B] = "BtnB", [BTN_C] = "BtnC", | ||
637 | [BTN_X] = "BtnX", [BTN_Y] = "BtnY", | ||
638 | [BTN_Z] = "BtnZ", [BTN_TL] = "BtnTL", | ||
639 | [BTN_TR] = "BtnTR", [BTN_TL2] = "BtnTL2", | ||
640 | [BTN_TR2] = "BtnTR2", [BTN_SELECT] = "BtnSelect", | ||
641 | [BTN_START] = "BtnStart", [BTN_MODE] = "BtnMode", | ||
642 | [BTN_THUMBL] = "BtnThumbL", [BTN_THUMBR] = "BtnThumbR", | ||
643 | [BTN_TOOL_PEN] = "ToolPen", [BTN_TOOL_RUBBER] = "ToolRubber", | ||
644 | [BTN_TOOL_BRUSH] = "ToolBrush", [BTN_TOOL_PENCIL] = "ToolPencil", | ||
645 | [BTN_TOOL_AIRBRUSH] = "ToolAirbrush", [BTN_TOOL_FINGER] = "ToolFinger", | ||
646 | [BTN_TOOL_MOUSE] = "ToolMouse", [BTN_TOOL_LENS] = "ToolLens", | ||
647 | [BTN_TOUCH] = "Touch", [BTN_STYLUS] = "Stylus", | ||
648 | [BTN_STYLUS2] = "Stylus2", [BTN_TOOL_DOUBLETAP] = "ToolDoubleTap", | ||
649 | [BTN_TOOL_TRIPLETAP] = "ToolTripleTap", [BTN_GEAR_DOWN] = "WheelBtn", | ||
650 | [BTN_GEAR_UP] = "Gear up", [KEY_OK] = "Ok", | ||
651 | [KEY_SELECT] = "Select", [KEY_GOTO] = "Goto", | ||
652 | [KEY_CLEAR] = "Clear", [KEY_POWER2] = "Power2", | ||
653 | [KEY_OPTION] = "Option", [KEY_INFO] = "Info", | ||
654 | [KEY_TIME] = "Time", [KEY_VENDOR] = "Vendor", | ||
655 | [KEY_ARCHIVE] = "Archive", [KEY_PROGRAM] = "Program", | ||
656 | [KEY_CHANNEL] = "Channel", [KEY_FAVORITES] = "Favorites", | ||
657 | [KEY_EPG] = "EPG", [KEY_PVR] = "PVR", | ||
658 | [KEY_MHP] = "MHP", [KEY_LANGUAGE] = "Language", | ||
659 | [KEY_TITLE] = "Title", [KEY_SUBTITLE] = "Subtitle", | ||
660 | [KEY_ANGLE] = "Angle", [KEY_ZOOM] = "Zoom", | ||
661 | [KEY_MODE] = "Mode", [KEY_KEYBOARD] = "Keyboard", | ||
662 | [KEY_SCREEN] = "Screen", [KEY_PC] = "PC", | ||
663 | [KEY_TV] = "TV", [KEY_TV2] = "TV2", | ||
664 | [KEY_VCR] = "VCR", [KEY_VCR2] = "VCR2", | ||
665 | [KEY_SAT] = "Sat", [KEY_SAT2] = "Sat2", | ||
666 | [KEY_CD] = "CD", [KEY_TAPE] = "Tape", | ||
667 | [KEY_RADIO] = "Radio", [KEY_TUNER] = "Tuner", | ||
668 | [KEY_PLAYER] = "Player", [KEY_TEXT] = "Text", | ||
669 | [KEY_DVD] = "DVD", [KEY_AUX] = "Aux", | ||
670 | [KEY_MP3] = "MP3", [KEY_AUDIO] = "Audio", | ||
671 | [KEY_VIDEO] = "Video", [KEY_DIRECTORY] = "Directory", | ||
672 | [KEY_LIST] = "List", [KEY_MEMO] = "Memo", | ||
673 | [KEY_CALENDAR] = "Calendar", [KEY_RED] = "Red", | ||
674 | [KEY_GREEN] = "Green", [KEY_YELLOW] = "Yellow", | ||
675 | [KEY_BLUE] = "Blue", [KEY_CHANNELUP] = "ChannelUp", | ||
676 | [KEY_CHANNELDOWN] = "ChannelDown", [KEY_FIRST] = "First", | ||
677 | [KEY_LAST] = "Last", [KEY_AB] = "AB", | ||
678 | [KEY_NEXT] = "Next", [KEY_RESTART] = "Restart", | ||
679 | [KEY_SLOW] = "Slow", [KEY_SHUFFLE] = "Shuffle", | ||
680 | [KEY_BREAK] = "Break", [KEY_PREVIOUS] = "Previous", | ||
681 | [KEY_DIGITS] = "Digits", [KEY_TEEN] = "TEEN", | ||
682 | [KEY_TWEN] = "TWEN", [KEY_DEL_EOL] = "DeleteEOL", | ||
683 | [KEY_DEL_EOS] = "DeleteEOS", [KEY_INS_LINE] = "InsertLine", | ||
684 | [KEY_DEL_LINE] = "DeleteLine", | ||
685 | [KEY_SEND] = "Send", [KEY_REPLY] = "Reply", | ||
686 | [KEY_FORWARDMAIL] = "ForwardMail", [KEY_SAVE] = "Save", | ||
687 | [KEY_DOCUMENTS] = "Documents", | ||
688 | [KEY_FN] = "Fn", [KEY_FN_ESC] = "Fn+ESC", | ||
689 | [KEY_FN_1] = "Fn+1", [KEY_FN_2] = "Fn+2", | ||
690 | [KEY_FN_B] = "Fn+B", [KEY_FN_D] = "Fn+D", | ||
691 | [KEY_FN_E] = "Fn+E", [KEY_FN_F] = "Fn+F", | ||
692 | [KEY_FN_S] = "Fn+S", | ||
693 | [KEY_FN_F1] = "Fn+F1", [KEY_FN_F2] = "Fn+F2", | ||
694 | [KEY_FN_F3] = "Fn+F3", [KEY_FN_F4] = "Fn+F4", | ||
695 | [KEY_FN_F5] = "Fn+F5", [KEY_FN_F6] = "Fn+F6", | ||
696 | [KEY_FN_F7] = "Fn+F7", [KEY_FN_F8] = "Fn+F8", | ||
697 | [KEY_FN_F9] = "Fn+F9", [KEY_FN_F10] = "Fn+F10", | ||
698 | [KEY_FN_F11] = "Fn+F11", [KEY_FN_F12] = "Fn+F12", | ||
699 | [KEY_KBDILLUMTOGGLE] = "KbdIlluminationToggle", | ||
700 | [KEY_KBDILLUMDOWN] = "KbdIlluminationDown", | ||
701 | [KEY_KBDILLUMUP] = "KbdIlluminationUp", | ||
702 | [KEY_SWITCHVIDEOMODE] = "SwitchVideoMode", | ||
703 | }; | ||
704 | |||
705 | static char *relatives[REL_MAX + 1] = { | ||
706 | [REL_X] = "X", [REL_Y] = "Y", | ||
707 | [REL_Z] = "Z", [REL_RX] = "Rx", | ||
708 | [REL_RY] = "Ry", [REL_RZ] = "Rz", | ||
709 | [REL_HWHEEL] = "HWheel", [REL_DIAL] = "Dial", | ||
710 | [REL_WHEEL] = "Wheel", [REL_MISC] = "Misc", | ||
711 | }; | ||
712 | |||
713 | static char *absolutes[ABS_MAX + 1] = { | ||
714 | [ABS_X] = "X", [ABS_Y] = "Y", | ||
715 | [ABS_Z] = "Z", [ABS_RX] = "Rx", | ||
716 | [ABS_RY] = "Ry", [ABS_RZ] = "Rz", | ||
717 | [ABS_THROTTLE] = "Throttle", [ABS_RUDDER] = "Rudder", | ||
718 | [ABS_WHEEL] = "Wheel", [ABS_GAS] = "Gas", | ||
719 | [ABS_BRAKE] = "Brake", [ABS_HAT0X] = "Hat0X", | ||
720 | [ABS_HAT0Y] = "Hat0Y", [ABS_HAT1X] = "Hat1X", | ||
721 | [ABS_HAT1Y] = "Hat1Y", [ABS_HAT2X] = "Hat2X", | ||
722 | [ABS_HAT2Y] = "Hat2Y", [ABS_HAT3X] = "Hat3X", | ||
723 | [ABS_HAT3Y] = "Hat 3Y", [ABS_PRESSURE] = "Pressure", | ||
724 | [ABS_DISTANCE] = "Distance", [ABS_TILT_X] = "XTilt", | ||
725 | [ABS_TILT_Y] = "YTilt", [ABS_TOOL_WIDTH] = "Tool Width", | ||
726 | [ABS_VOLUME] = "Volume", [ABS_MISC] = "Misc", | ||
727 | }; | ||
728 | |||
729 | static char *misc[MSC_MAX + 1] = { | ||
730 | [MSC_SERIAL] = "Serial", [MSC_PULSELED] = "Pulseled", | ||
731 | [MSC_GESTURE] = "Gesture", [MSC_RAW] = "RawData" | ||
732 | }; | ||
733 | |||
734 | static char *leds[LED_MAX + 1] = { | ||
735 | [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", | ||
736 | [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", | ||
737 | [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", | ||
738 | [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", | ||
739 | [LED_MISC] = "Misc", | ||
740 | }; | ||
741 | |||
742 | static char *repeats[REP_MAX + 1] = { | ||
743 | [REP_DELAY] = "Delay", [REP_PERIOD] = "Period" | ||
744 | }; | ||
745 | |||
746 | static char *sounds[SND_MAX + 1] = { | ||
747 | [SND_CLICK] = "Click", [SND_BELL] = "Bell", | ||
748 | [SND_TONE] = "Tone" | ||
749 | }; | ||
750 | |||
751 | static char **names[EV_MAX + 1] = { | ||
752 | [EV_SYN] = syncs, [EV_KEY] = keys, | ||
753 | [EV_REL] = relatives, [EV_ABS] = absolutes, | ||
754 | [EV_MSC] = misc, [EV_LED] = leds, | ||
755 | [EV_SND] = sounds, [EV_REP] = repeats, | ||
756 | }; | ||
757 | |||
758 | void hid_resolv_event(__u8 type, __u16 code) { | ||
759 | |||
760 | printk("%s.%s", events[type] ? events[type] : "?", | ||
761 | names[type] ? (names[type][code] ? names[type][code] : "?") : "?"); | ||
762 | } | ||
763 | EXPORT_SYMBOL_GPL(hid_resolv_event); | ||
764 | |||
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index c7a6833f6821..25d180a24fc4 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -31,9 +31,8 @@ | |||
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/kernel.h> | 32 | #include <linux/kernel.h> |
33 | 33 | ||
34 | #undef DEBUG | ||
35 | |||
36 | #include <linux/hid.h> | 34 | #include <linux/hid.h> |
35 | #include <linux/hid-debug.h> | ||
37 | 36 | ||
38 | static int hid_pb_fnmode = 1; | 37 | static int hid_pb_fnmode = 1; |
39 | module_param_named(pb_fnmode, hid_pb_fnmode, int, 0644); | 38 | module_param_named(pb_fnmode, hid_pb_fnmode, int, 0644); |
@@ -252,9 +251,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
252 | 251 | ||
253 | field->hidinput = hidinput; | 252 | field->hidinput = hidinput; |
254 | 253 | ||
255 | #ifdef DEBUG | 254 | #ifdef CONFIG_HID_DEBUG |
256 | printk(KERN_DEBUG "Mapping: "); | 255 | printk(KERN_DEBUG "Mapping: "); |
257 | resolv_usage(usage->hid); | 256 | hid_resolv_usage(usage->hid); |
258 | printk(" ---> "); | 257 | printk(" ---> "); |
259 | #endif | 258 | #endif |
260 | 259 | ||
@@ -682,14 +681,14 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
682 | field->dpad = usage->code; | 681 | field->dpad = usage->code; |
683 | } | 682 | } |
684 | 683 | ||
685 | #ifdef DEBUG | 684 | hid_resolv_event(usage->type, usage->code); |
686 | resolv_event(usage->type, usage->code); | 685 | #ifdef CONFIG_HID_DEBUG |
687 | printk("\n"); | 686 | printk("\n"); |
688 | #endif | 687 | #endif |
689 | return; | 688 | return; |
690 | 689 | ||
691 | ignore: | 690 | ignore: |
692 | #ifdef DEBUG | 691 | #ifdef CONFIG_HID_DEBUG |
693 | printk("IGNORED\n"); | 692 | printk("IGNORED\n"); |
694 | #endif | 693 | #endif |
695 | return; | 694 | return; |
@@ -804,6 +803,18 @@ int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int | |||
804 | } | 803 | } |
805 | EXPORT_SYMBOL_GPL(hidinput_find_field); | 804 | EXPORT_SYMBOL_GPL(hidinput_find_field); |
806 | 805 | ||
806 | static int hidinput_open(struct input_dev *dev) | ||
807 | { | ||
808 | struct hid_device *hid = dev->private; | ||
809 | return hid->hid_open(hid); | ||
810 | } | ||
811 | |||
812 | static void hidinput_close(struct input_dev *dev) | ||
813 | { | ||
814 | struct hid_device *hid = dev->private; | ||
815 | hid->hid_close(hid); | ||
816 | } | ||
817 | |||
807 | /* | 818 | /* |
808 | * Register the input device; print a message. | 819 | * Register the input device; print a message. |
809 | * Configure the input layer interface | 820 | * Configure the input layer interface |
@@ -816,6 +827,7 @@ int hidinput_connect(struct hid_device *hid) | |||
816 | struct hid_input *hidinput = NULL; | 827 | struct hid_input *hidinput = NULL; |
817 | struct input_dev *input_dev; | 828 | struct input_dev *input_dev; |
818 | int i, j, k; | 829 | int i, j, k; |
830 | int max_report_type = HID_OUTPUT_REPORT; | ||
819 | 831 | ||
820 | INIT_LIST_HEAD(&hid->inputs); | 832 | INIT_LIST_HEAD(&hid->inputs); |
821 | 833 | ||
@@ -828,7 +840,10 @@ int hidinput_connect(struct hid_device *hid) | |||
828 | if (i == hid->maxcollection) | 840 | if (i == hid->maxcollection) |
829 | return -1; | 841 | return -1; |
830 | 842 | ||
831 | for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) | 843 | if (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS) |
844 | max_report_type = HID_INPUT_REPORT; | ||
845 | |||
846 | for (k = HID_INPUT_REPORT; k <= max_report_type; k++) | ||
832 | list_for_each_entry(report, &hid->report_enum[k].report_list, list) { | 847 | list_for_each_entry(report, &hid->report_enum[k].report_list, list) { |
833 | 848 | ||
834 | if (!report->maxfield) | 849 | if (!report->maxfield) |
@@ -846,8 +861,8 @@ int hidinput_connect(struct hid_device *hid) | |||
846 | 861 | ||
847 | input_dev->private = hid; | 862 | input_dev->private = hid; |
848 | input_dev->event = hid->hidinput_input_event; | 863 | input_dev->event = hid->hidinput_input_event; |
849 | input_dev->open = hid->hidinput_open; | 864 | input_dev->open = hidinput_open; |
850 | input_dev->close = hid->hidinput_close; | 865 | input_dev->close = hidinput_close; |
851 | 866 | ||
852 | input_dev->name = hid->name; | 867 | input_dev->name = hid->name; |
853 | input_dev->phys = hid->phys; | 868 | input_dev->phys = hid->phys; |
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index af939796750d..d2bb5a9a303f 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c | |||
@@ -360,8 +360,7 @@ static int netevent_callback(struct notifier_block *self, unsigned long event, | |||
360 | if (event == NETEVENT_NEIGH_UPDATE) { | 360 | if (event == NETEVENT_NEIGH_UPDATE) { |
361 | struct neighbour *neigh = ctx; | 361 | struct neighbour *neigh = ctx; |
362 | 362 | ||
363 | if (neigh->dev->type == ARPHRD_INFINIBAND && | 363 | if (neigh->nud_state & NUD_VALID) { |
364 | (neigh->nud_state & NUD_VALID)) { | ||
365 | set_timeout(jiffies); | 364 | set_timeout(jiffies); |
366 | } | 365 | } |
367 | } | 366 | } |
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 5ed141ebd1c8..13efd4170349 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c | |||
@@ -642,7 +642,8 @@ static void snoop_recv(struct ib_mad_qp_info *qp_info, | |||
642 | spin_unlock_irqrestore(&qp_info->snoop_lock, flags); | 642 | spin_unlock_irqrestore(&qp_info->snoop_lock, flags); |
643 | } | 643 | } |
644 | 644 | ||
645 | static void build_smp_wc(u64 wr_id, u16 slid, u16 pkey_index, u8 port_num, | 645 | static void build_smp_wc(struct ib_qp *qp, |
646 | u64 wr_id, u16 slid, u16 pkey_index, u8 port_num, | ||
646 | struct ib_wc *wc) | 647 | struct ib_wc *wc) |
647 | { | 648 | { |
648 | memset(wc, 0, sizeof *wc); | 649 | memset(wc, 0, sizeof *wc); |
@@ -652,7 +653,7 @@ static void build_smp_wc(u64 wr_id, u16 slid, u16 pkey_index, u8 port_num, | |||
652 | wc->pkey_index = pkey_index; | 653 | wc->pkey_index = pkey_index; |
653 | wc->byte_len = sizeof(struct ib_mad) + sizeof(struct ib_grh); | 654 | wc->byte_len = sizeof(struct ib_mad) + sizeof(struct ib_grh); |
654 | wc->src_qp = IB_QP0; | 655 | wc->src_qp = IB_QP0; |
655 | wc->qp_num = IB_QP0; | 656 | wc->qp = qp; |
656 | wc->slid = slid; | 657 | wc->slid = slid; |
657 | wc->sl = 0; | 658 | wc->sl = 0; |
658 | wc->dlid_path_bits = 0; | 659 | wc->dlid_path_bits = 0; |
@@ -713,7 +714,8 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, | |||
713 | goto out; | 714 | goto out; |
714 | } | 715 | } |
715 | 716 | ||
716 | build_smp_wc(send_wr->wr_id, be16_to_cpu(smp->dr_slid), | 717 | build_smp_wc(mad_agent_priv->agent.qp, |
718 | send_wr->wr_id, be16_to_cpu(smp->dr_slid), | ||
717 | send_wr->wr.ud.pkey_index, | 719 | send_wr->wr.ud.pkey_index, |
718 | send_wr->wr.ud.port_num, &mad_wc); | 720 | send_wr->wr.ud.port_num, &mad_wc); |
719 | 721 | ||
@@ -2355,7 +2357,8 @@ static void local_completions(struct work_struct *work) | |||
2355 | * Defined behavior is to complete response | 2357 | * Defined behavior is to complete response |
2356 | * before request | 2358 | * before request |
2357 | */ | 2359 | */ |
2358 | build_smp_wc((unsigned long) local->mad_send_wr, | 2360 | build_smp_wc(recv_mad_agent->agent.qp, |
2361 | (unsigned long) local->mad_send_wr, | ||
2359 | be16_to_cpu(IB_LID_PERMISSIVE), | 2362 | be16_to_cpu(IB_LID_PERMISSIVE), |
2360 | 0, recv_mad_agent->agent.port_num, &wc); | 2363 | 0, recv_mad_agent->agent.port_num, &wc); |
2361 | 2364 | ||
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 743247ec065e..df1efbc10882 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
@@ -933,7 +933,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, | |||
933 | resp->wc[i].vendor_err = wc[i].vendor_err; | 933 | resp->wc[i].vendor_err = wc[i].vendor_err; |
934 | resp->wc[i].byte_len = wc[i].byte_len; | 934 | resp->wc[i].byte_len = wc[i].byte_len; |
935 | resp->wc[i].imm_data = (__u32 __force) wc[i].imm_data; | 935 | resp->wc[i].imm_data = (__u32 __force) wc[i].imm_data; |
936 | resp->wc[i].qp_num = wc[i].qp_num; | 936 | resp->wc[i].qp_num = wc[i].qp->qp_num; |
937 | resp->wc[i].src_qp = wc[i].src_qp; | 937 | resp->wc[i].src_qp = wc[i].src_qp; |
938 | resp->wc[i].wc_flags = wc[i].wc_flags; | 938 | resp->wc[i].wc_flags = wc[i].wc_flags; |
939 | resp->wc[i].pkey_index = wc[i].pkey_index; | 939 | resp->wc[i].pkey_index = wc[i].pkey_index; |
diff --git a/drivers/infiniband/hw/amso1100/c2_cq.c b/drivers/infiniband/hw/amso1100/c2_cq.c index 05c9154d46f4..5175c99ee586 100644 --- a/drivers/infiniband/hw/amso1100/c2_cq.c +++ b/drivers/infiniband/hw/amso1100/c2_cq.c | |||
@@ -153,7 +153,7 @@ static inline int c2_poll_one(struct c2_dev *c2dev, | |||
153 | 153 | ||
154 | entry->status = c2_cqe_status_to_openib(c2_wr_get_result(ce)); | 154 | entry->status = c2_cqe_status_to_openib(c2_wr_get_result(ce)); |
155 | entry->wr_id = ce->hdr.context; | 155 | entry->wr_id = ce->hdr.context; |
156 | entry->qp_num = ce->handle; | 156 | entry->qp = &qp->ibqp; |
157 | entry->wc_flags = 0; | 157 | entry->wc_flags = 0; |
158 | entry->slid = 0; | 158 | entry->slid = 0; |
159 | entry->sl = 0; | 159 | entry->sl = 0; |
diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h index 1c722032319c..cf95ee474b0f 100644 --- a/drivers/infiniband/hw/ehca/ehca_classes.h +++ b/drivers/infiniband/hw/ehca/ehca_classes.h | |||
@@ -119,13 +119,14 @@ struct ehca_qp { | |||
119 | struct ipz_qp_handle ipz_qp_handle; | 119 | struct ipz_qp_handle ipz_qp_handle; |
120 | struct ehca_pfqp pf; | 120 | struct ehca_pfqp pf; |
121 | struct ib_qp_init_attr init_attr; | 121 | struct ib_qp_init_attr init_attr; |
122 | u64 uspace_squeue; | ||
123 | u64 uspace_rqueue; | ||
124 | u64 uspace_fwh; | ||
125 | struct ehca_cq *send_cq; | 122 | struct ehca_cq *send_cq; |
126 | struct ehca_cq *recv_cq; | 123 | struct ehca_cq *recv_cq; |
127 | unsigned int sqerr_purgeflag; | 124 | unsigned int sqerr_purgeflag; |
128 | struct hlist_node list_entries; | 125 | struct hlist_node list_entries; |
126 | /* mmap counter for resources mapped into user space */ | ||
127 | u32 mm_count_squeue; | ||
128 | u32 mm_count_rqueue; | ||
129 | u32 mm_count_galpa; | ||
129 | }; | 130 | }; |
130 | 131 | ||
131 | /* must be power of 2 */ | 132 | /* must be power of 2 */ |
@@ -142,13 +143,14 @@ struct ehca_cq { | |||
142 | struct ipz_cq_handle ipz_cq_handle; | 143 | struct ipz_cq_handle ipz_cq_handle; |
143 | struct ehca_pfcq pf; | 144 | struct ehca_pfcq pf; |
144 | spinlock_t cb_lock; | 145 | spinlock_t cb_lock; |
145 | u64 uspace_queue; | ||
146 | u64 uspace_fwh; | ||
147 | struct hlist_head qp_hashtab[QP_HASHTAB_LEN]; | 146 | struct hlist_head qp_hashtab[QP_HASHTAB_LEN]; |
148 | struct list_head entry; | 147 | struct list_head entry; |
149 | u32 nr_callbacks; | 148 | u32 nr_callbacks; |
150 | spinlock_t task_lock; | 149 | spinlock_t task_lock; |
151 | u32 ownpid; | 150 | u32 ownpid; |
151 | /* mmap counter for resources mapped into user space */ | ||
152 | u32 mm_count_queue; | ||
153 | u32 mm_count_galpa; | ||
152 | }; | 154 | }; |
153 | 155 | ||
154 | enum ehca_mr_flag { | 156 | enum ehca_mr_flag { |
@@ -248,20 +250,6 @@ struct ehca_ucontext { | |||
248 | struct ib_ucontext ib_ucontext; | 250 | struct ib_ucontext ib_ucontext; |
249 | }; | 251 | }; |
250 | 252 | ||
251 | struct ehca_module *ehca_module_new(void); | ||
252 | |||
253 | int ehca_module_delete(struct ehca_module *me); | ||
254 | |||
255 | int ehca_eq_ctor(struct ehca_eq *eq); | ||
256 | |||
257 | int ehca_eq_dtor(struct ehca_eq *eq); | ||
258 | |||
259 | struct ehca_shca *ehca_shca_new(void); | ||
260 | |||
261 | int ehca_shca_delete(struct ehca_shca *me); | ||
262 | |||
263 | struct ehca_sport *ehca_sport_new(struct ehca_shca *anchor); | ||
264 | |||
265 | int ehca_init_pd_cache(void); | 253 | int ehca_init_pd_cache(void); |
266 | void ehca_cleanup_pd_cache(void); | 254 | void ehca_cleanup_pd_cache(void); |
267 | int ehca_init_cq_cache(void); | 255 | int ehca_init_cq_cache(void); |
@@ -283,7 +271,6 @@ extern int ehca_port_act_time; | |||
283 | extern int ehca_use_hp_mr; | 271 | extern int ehca_use_hp_mr; |
284 | 272 | ||
285 | struct ipzu_queue_resp { | 273 | struct ipzu_queue_resp { |
286 | u64 queue; /* points to first queue entry */ | ||
287 | u32 qe_size; /* queue entry size */ | 274 | u32 qe_size; /* queue entry size */ |
288 | u32 act_nr_of_sg; | 275 | u32 act_nr_of_sg; |
289 | u32 queue_length; /* queue length allocated in bytes */ | 276 | u32 queue_length; /* queue length allocated in bytes */ |
@@ -296,7 +283,6 @@ struct ehca_create_cq_resp { | |||
296 | u32 cq_number; | 283 | u32 cq_number; |
297 | u32 token; | 284 | u32 token; |
298 | struct ipzu_queue_resp ipz_queue; | 285 | struct ipzu_queue_resp ipz_queue; |
299 | struct h_galpas galpas; | ||
300 | }; | 286 | }; |
301 | 287 | ||
302 | struct ehca_create_qp_resp { | 288 | struct ehca_create_qp_resp { |
@@ -309,7 +295,6 @@ struct ehca_create_qp_resp { | |||
309 | u32 dummy; /* padding for 8 byte alignment */ | 295 | u32 dummy; /* padding for 8 byte alignment */ |
310 | struct ipzu_queue_resp ipz_squeue; | 296 | struct ipzu_queue_resp ipz_squeue; |
311 | struct ipzu_queue_resp ipz_rqueue; | 297 | struct ipzu_queue_resp ipz_rqueue; |
312 | struct h_galpas galpas; | ||
313 | }; | 298 | }; |
314 | 299 | ||
315 | struct ehca_alloc_cq_parms { | 300 | struct ehca_alloc_cq_parms { |
diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c index 6074c897f51c..9291a86ca053 100644 --- a/drivers/infiniband/hw/ehca/ehca_cq.c +++ b/drivers/infiniband/hw/ehca/ehca_cq.c | |||
@@ -267,7 +267,6 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, | |||
267 | if (context) { | 267 | if (context) { |
268 | struct ipz_queue *ipz_queue = &my_cq->ipz_queue; | 268 | struct ipz_queue *ipz_queue = &my_cq->ipz_queue; |
269 | struct ehca_create_cq_resp resp; | 269 | struct ehca_create_cq_resp resp; |
270 | struct vm_area_struct *vma; | ||
271 | memset(&resp, 0, sizeof(resp)); | 270 | memset(&resp, 0, sizeof(resp)); |
272 | resp.cq_number = my_cq->cq_number; | 271 | resp.cq_number = my_cq->cq_number; |
273 | resp.token = my_cq->token; | 272 | resp.token = my_cq->token; |
@@ -276,40 +275,14 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, | |||
276 | resp.ipz_queue.queue_length = ipz_queue->queue_length; | 275 | resp.ipz_queue.queue_length = ipz_queue->queue_length; |
277 | resp.ipz_queue.pagesize = ipz_queue->pagesize; | 276 | resp.ipz_queue.pagesize = ipz_queue->pagesize; |
278 | resp.ipz_queue.toggle_state = ipz_queue->toggle_state; | 277 | resp.ipz_queue.toggle_state = ipz_queue->toggle_state; |
279 | ret = ehca_mmap_nopage(((u64)(my_cq->token) << 32) | 0x12000000, | ||
280 | ipz_queue->queue_length, | ||
281 | (void**)&resp.ipz_queue.queue, | ||
282 | &vma); | ||
283 | if (ret) { | ||
284 | ehca_err(device, "Could not mmap queue pages"); | ||
285 | cq = ERR_PTR(ret); | ||
286 | goto create_cq_exit4; | ||
287 | } | ||
288 | my_cq->uspace_queue = resp.ipz_queue.queue; | ||
289 | resp.galpas = my_cq->galpas; | ||
290 | ret = ehca_mmap_register(my_cq->galpas.user.fw_handle, | ||
291 | (void**)&resp.galpas.kernel.fw_handle, | ||
292 | &vma); | ||
293 | if (ret) { | ||
294 | ehca_err(device, "Could not mmap fw_handle"); | ||
295 | cq = ERR_PTR(ret); | ||
296 | goto create_cq_exit5; | ||
297 | } | ||
298 | my_cq->uspace_fwh = (u64)resp.galpas.kernel.fw_handle; | ||
299 | if (ib_copy_to_udata(udata, &resp, sizeof(resp))) { | 278 | if (ib_copy_to_udata(udata, &resp, sizeof(resp))) { |
300 | ehca_err(device, "Copy to udata failed."); | 279 | ehca_err(device, "Copy to udata failed."); |
301 | goto create_cq_exit6; | 280 | goto create_cq_exit4; |
302 | } | 281 | } |
303 | } | 282 | } |
304 | 283 | ||
305 | return cq; | 284 | return cq; |
306 | 285 | ||
307 | create_cq_exit6: | ||
308 | ehca_munmap(my_cq->uspace_fwh, EHCA_PAGESIZE); | ||
309 | |||
310 | create_cq_exit5: | ||
311 | ehca_munmap(my_cq->uspace_queue, my_cq->ipz_queue.queue_length); | ||
312 | |||
313 | create_cq_exit4: | 286 | create_cq_exit4: |
314 | ipz_queue_dtor(&my_cq->ipz_queue); | 287 | ipz_queue_dtor(&my_cq->ipz_queue); |
315 | 288 | ||
@@ -333,7 +306,6 @@ create_cq_exit1: | |||
333 | int ehca_destroy_cq(struct ib_cq *cq) | 306 | int ehca_destroy_cq(struct ib_cq *cq) |
334 | { | 307 | { |
335 | u64 h_ret; | 308 | u64 h_ret; |
336 | int ret; | ||
337 | struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); | 309 | struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); |
338 | int cq_num = my_cq->cq_number; | 310 | int cq_num = my_cq->cq_number; |
339 | struct ib_device *device = cq->device; | 311 | struct ib_device *device = cq->device; |
@@ -343,6 +315,20 @@ int ehca_destroy_cq(struct ib_cq *cq) | |||
343 | u32 cur_pid = current->tgid; | 315 | u32 cur_pid = current->tgid; |
344 | unsigned long flags; | 316 | unsigned long flags; |
345 | 317 | ||
318 | if (cq->uobject) { | ||
319 | if (my_cq->mm_count_galpa || my_cq->mm_count_queue) { | ||
320 | ehca_err(device, "Resources still referenced in " | ||
321 | "user space cq_num=%x", my_cq->cq_number); | ||
322 | return -EINVAL; | ||
323 | } | ||
324 | if (my_cq->ownpid != cur_pid) { | ||
325 | ehca_err(device, "Invalid caller pid=%x ownpid=%x " | ||
326 | "cq_num=%x", | ||
327 | cur_pid, my_cq->ownpid, my_cq->cq_number); | ||
328 | return -EINVAL; | ||
329 | } | ||
330 | } | ||
331 | |||
346 | spin_lock_irqsave(&ehca_cq_idr_lock, flags); | 332 | spin_lock_irqsave(&ehca_cq_idr_lock, flags); |
347 | while (my_cq->nr_callbacks) { | 333 | while (my_cq->nr_callbacks) { |
348 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); | 334 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); |
@@ -353,25 +339,6 @@ int ehca_destroy_cq(struct ib_cq *cq) | |||
353 | idr_remove(&ehca_cq_idr, my_cq->token); | 339 | idr_remove(&ehca_cq_idr, my_cq->token); |
354 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); | 340 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); |
355 | 341 | ||
356 | if (my_cq->uspace_queue && my_cq->ownpid != cur_pid) { | ||
357 | ehca_err(device, "Invalid caller pid=%x ownpid=%x", | ||
358 | cur_pid, my_cq->ownpid); | ||
359 | return -EINVAL; | ||
360 | } | ||
361 | |||
362 | /* un-mmap if vma alloc */ | ||
363 | if (my_cq->uspace_queue ) { | ||
364 | ret = ehca_munmap(my_cq->uspace_queue, | ||
365 | my_cq->ipz_queue.queue_length); | ||
366 | if (ret) | ||
367 | ehca_err(device, "Could not munmap queue ehca_cq=%p " | ||
368 | "cq_num=%x", my_cq, cq_num); | ||
369 | ret = ehca_munmap(my_cq->uspace_fwh, EHCA_PAGESIZE); | ||
370 | if (ret) | ||
371 | ehca_err(device, "Could not munmap fwh ehca_cq=%p " | ||
372 | "cq_num=%x", my_cq, cq_num); | ||
373 | } | ||
374 | |||
375 | h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0); | 342 | h_ret = hipz_h_destroy_cq(adapter_handle, my_cq, 0); |
376 | if (h_ret == H_R_STATE) { | 343 | if (h_ret == H_R_STATE) { |
377 | /* cq in err: read err data and destroy it forcibly */ | 344 | /* cq in err: read err data and destroy it forcibly */ |
@@ -400,7 +367,7 @@ int ehca_resize_cq(struct ib_cq *cq, int cqe, struct ib_udata *udata) | |||
400 | struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); | 367 | struct ehca_cq *my_cq = container_of(cq, struct ehca_cq, ib_cq); |
401 | u32 cur_pid = current->tgid; | 368 | u32 cur_pid = current->tgid; |
402 | 369 | ||
403 | if (my_cq->uspace_queue && my_cq->ownpid != cur_pid) { | 370 | if (cq->uobject && my_cq->ownpid != cur_pid) { |
404 | ehca_err(cq->device, "Invalid caller pid=%x ownpid=%x", | 371 | ehca_err(cq->device, "Invalid caller pid=%x ownpid=%x", |
405 | cur_pid, my_cq->ownpid); | 372 | cur_pid, my_cq->ownpid); |
406 | return -EINVAL; | 373 | return -EINVAL; |
diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h index cd7789f0d08e..95fd59fb4528 100644 --- a/drivers/infiniband/hw/ehca/ehca_iverbs.h +++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h | |||
@@ -171,14 +171,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma); | |||
171 | 171 | ||
172 | void ehca_poll_eqs(unsigned long data); | 172 | void ehca_poll_eqs(unsigned long data); |
173 | 173 | ||
174 | int ehca_mmap_nopage(u64 foffset,u64 length,void **mapped, | ||
175 | struct vm_area_struct **vma); | ||
176 | |||
177 | int ehca_mmap_register(u64 physical,void **mapped, | ||
178 | struct vm_area_struct **vma); | ||
179 | |||
180 | int ehca_munmap(unsigned long addr, size_t len); | ||
181 | |||
182 | #ifdef CONFIG_PPC_64K_PAGES | 174 | #ifdef CONFIG_PPC_64K_PAGES |
183 | void *ehca_alloc_fw_ctrlblock(gfp_t flags); | 175 | void *ehca_alloc_fw_ctrlblock(gfp_t flags); |
184 | void ehca_free_fw_ctrlblock(void *ptr); | 176 | void ehca_free_fw_ctrlblock(void *ptr); |
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index 6574fbbaead5..1155bcf48212 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c | |||
@@ -52,7 +52,7 @@ | |||
52 | MODULE_LICENSE("Dual BSD/GPL"); | 52 | MODULE_LICENSE("Dual BSD/GPL"); |
53 | MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>"); | 53 | MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>"); |
54 | MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver"); | 54 | MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver"); |
55 | MODULE_VERSION("SVNEHCA_0019"); | 55 | MODULE_VERSION("SVNEHCA_0020"); |
56 | 56 | ||
57 | int ehca_open_aqp1 = 0; | 57 | int ehca_open_aqp1 = 0; |
58 | int ehca_debug_level = 0; | 58 | int ehca_debug_level = 0; |
@@ -288,7 +288,7 @@ int ehca_init_device(struct ehca_shca *shca) | |||
288 | strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX); | 288 | strlcpy(shca->ib_device.name, "ehca%d", IB_DEVICE_NAME_MAX); |
289 | shca->ib_device.owner = THIS_MODULE; | 289 | shca->ib_device.owner = THIS_MODULE; |
290 | 290 | ||
291 | shca->ib_device.uverbs_abi_ver = 5; | 291 | shca->ib_device.uverbs_abi_ver = 6; |
292 | shca->ib_device.uverbs_cmd_mask = | 292 | shca->ib_device.uverbs_cmd_mask = |
293 | (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | | 293 | (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | |
294 | (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | | 294 | (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | |
@@ -790,7 +790,7 @@ int __init ehca_module_init(void) | |||
790 | int ret; | 790 | int ret; |
791 | 791 | ||
792 | printk(KERN_INFO "eHCA Infiniband Device Driver " | 792 | printk(KERN_INFO "eHCA Infiniband Device Driver " |
793 | "(Rel.: SVNEHCA_0019)\n"); | 793 | "(Rel.: SVNEHCA_0020)\n"); |
794 | idr_init(&ehca_qp_idr); | 794 | idr_init(&ehca_qp_idr); |
795 | idr_init(&ehca_cq_idr); | 795 | idr_init(&ehca_cq_idr); |
796 | spin_lock_init(&ehca_qp_idr_lock); | 796 | spin_lock_init(&ehca_qp_idr_lock); |
diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index 34b85556d01e..95efef921f1d 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c | |||
@@ -637,7 +637,6 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd, | |||
637 | struct ipz_queue *ipz_rqueue = &my_qp->ipz_rqueue; | 637 | struct ipz_queue *ipz_rqueue = &my_qp->ipz_rqueue; |
638 | struct ipz_queue *ipz_squeue = &my_qp->ipz_squeue; | 638 | struct ipz_queue *ipz_squeue = &my_qp->ipz_squeue; |
639 | struct ehca_create_qp_resp resp; | 639 | struct ehca_create_qp_resp resp; |
640 | struct vm_area_struct * vma; | ||
641 | memset(&resp, 0, sizeof(resp)); | 640 | memset(&resp, 0, sizeof(resp)); |
642 | 641 | ||
643 | resp.qp_num = my_qp->real_qp_num; | 642 | resp.qp_num = my_qp->real_qp_num; |
@@ -651,59 +650,21 @@ struct ib_qp *ehca_create_qp(struct ib_pd *pd, | |||
651 | resp.ipz_rqueue.queue_length = ipz_rqueue->queue_length; | 650 | resp.ipz_rqueue.queue_length = ipz_rqueue->queue_length; |
652 | resp.ipz_rqueue.pagesize = ipz_rqueue->pagesize; | 651 | resp.ipz_rqueue.pagesize = ipz_rqueue->pagesize; |
653 | resp.ipz_rqueue.toggle_state = ipz_rqueue->toggle_state; | 652 | resp.ipz_rqueue.toggle_state = ipz_rqueue->toggle_state; |
654 | ret = ehca_mmap_nopage(((u64)(my_qp->token) << 32) | 0x22000000, | ||
655 | ipz_rqueue->queue_length, | ||
656 | (void**)&resp.ipz_rqueue.queue, | ||
657 | &vma); | ||
658 | if (ret) { | ||
659 | ehca_err(pd->device, "Could not mmap rqueue pages"); | ||
660 | goto create_qp_exit3; | ||
661 | } | ||
662 | my_qp->uspace_rqueue = resp.ipz_rqueue.queue; | ||
663 | /* squeue properties */ | 653 | /* squeue properties */ |
664 | resp.ipz_squeue.qe_size = ipz_squeue->qe_size; | 654 | resp.ipz_squeue.qe_size = ipz_squeue->qe_size; |
665 | resp.ipz_squeue.act_nr_of_sg = ipz_squeue->act_nr_of_sg; | 655 | resp.ipz_squeue.act_nr_of_sg = ipz_squeue->act_nr_of_sg; |
666 | resp.ipz_squeue.queue_length = ipz_squeue->queue_length; | 656 | resp.ipz_squeue.queue_length = ipz_squeue->queue_length; |
667 | resp.ipz_squeue.pagesize = ipz_squeue->pagesize; | 657 | resp.ipz_squeue.pagesize = ipz_squeue->pagesize; |
668 | resp.ipz_squeue.toggle_state = ipz_squeue->toggle_state; | 658 | resp.ipz_squeue.toggle_state = ipz_squeue->toggle_state; |
669 | ret = ehca_mmap_nopage(((u64)(my_qp->token) << 32) | 0x23000000, | ||
670 | ipz_squeue->queue_length, | ||
671 | (void**)&resp.ipz_squeue.queue, | ||
672 | &vma); | ||
673 | if (ret) { | ||
674 | ehca_err(pd->device, "Could not mmap squeue pages"); | ||
675 | goto create_qp_exit4; | ||
676 | } | ||
677 | my_qp->uspace_squeue = resp.ipz_squeue.queue; | ||
678 | /* fw_handle */ | ||
679 | resp.galpas = my_qp->galpas; | ||
680 | ret = ehca_mmap_register(my_qp->galpas.user.fw_handle, | ||
681 | (void**)&resp.galpas.kernel.fw_handle, | ||
682 | &vma); | ||
683 | if (ret) { | ||
684 | ehca_err(pd->device, "Could not mmap fw_handle"); | ||
685 | goto create_qp_exit5; | ||
686 | } | ||
687 | my_qp->uspace_fwh = (u64)resp.galpas.kernel.fw_handle; | ||
688 | |||
689 | if (ib_copy_to_udata(udata, &resp, sizeof resp)) { | 659 | if (ib_copy_to_udata(udata, &resp, sizeof resp)) { |
690 | ehca_err(pd->device, "Copy to udata failed"); | 660 | ehca_err(pd->device, "Copy to udata failed"); |
691 | ret = -EINVAL; | 661 | ret = -EINVAL; |
692 | goto create_qp_exit6; | 662 | goto create_qp_exit3; |
693 | } | 663 | } |
694 | } | 664 | } |
695 | 665 | ||
696 | return &my_qp->ib_qp; | 666 | return &my_qp->ib_qp; |
697 | 667 | ||
698 | create_qp_exit6: | ||
699 | ehca_munmap(my_qp->uspace_fwh, EHCA_PAGESIZE); | ||
700 | |||
701 | create_qp_exit5: | ||
702 | ehca_munmap(my_qp->uspace_squeue, my_qp->ipz_squeue.queue_length); | ||
703 | |||
704 | create_qp_exit4: | ||
705 | ehca_munmap(my_qp->uspace_rqueue, my_qp->ipz_rqueue.queue_length); | ||
706 | |||
707 | create_qp_exit3: | 668 | create_qp_exit3: |
708 | ipz_queue_dtor(&my_qp->ipz_rqueue); | 669 | ipz_queue_dtor(&my_qp->ipz_rqueue); |
709 | ipz_queue_dtor(&my_qp->ipz_squeue); | 670 | ipz_queue_dtor(&my_qp->ipz_squeue); |
@@ -931,7 +892,7 @@ static int internal_modify_qp(struct ib_qp *ibqp, | |||
931 | my_qp->qp_type == IB_QPT_SMI) && | 892 | my_qp->qp_type == IB_QPT_SMI) && |
932 | statetrans == IB_QPST_SQE2RTS) { | 893 | statetrans == IB_QPST_SQE2RTS) { |
933 | /* mark next free wqe if kernel */ | 894 | /* mark next free wqe if kernel */ |
934 | if (my_qp->uspace_squeue == 0) { | 895 | if (!ibqp->uobject) { |
935 | struct ehca_wqe *wqe; | 896 | struct ehca_wqe *wqe; |
936 | /* lock send queue */ | 897 | /* lock send queue */ |
937 | spin_lock_irqsave(&my_qp->spinlock_s, spl_flags); | 898 | spin_lock_irqsave(&my_qp->spinlock_s, spl_flags); |
@@ -1417,11 +1378,18 @@ int ehca_destroy_qp(struct ib_qp *ibqp) | |||
1417 | enum ib_qp_type qp_type; | 1378 | enum ib_qp_type qp_type; |
1418 | unsigned long flags; | 1379 | unsigned long flags; |
1419 | 1380 | ||
1420 | if (my_pd->ib_pd.uobject && my_pd->ib_pd.uobject->context && | 1381 | if (ibqp->uobject) { |
1421 | my_pd->ownpid != cur_pid) { | 1382 | if (my_qp->mm_count_galpa || |
1422 | ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x", | 1383 | my_qp->mm_count_rqueue || my_qp->mm_count_squeue) { |
1423 | cur_pid, my_pd->ownpid); | 1384 | ehca_err(ibqp->device, "Resources still referenced in " |
1424 | return -EINVAL; | 1385 | "user space qp_num=%x", ibqp->qp_num); |
1386 | return -EINVAL; | ||
1387 | } | ||
1388 | if (my_pd->ownpid != cur_pid) { | ||
1389 | ehca_err(ibqp->device, "Invalid caller pid=%x ownpid=%x", | ||
1390 | cur_pid, my_pd->ownpid); | ||
1391 | return -EINVAL; | ||
1392 | } | ||
1425 | } | 1393 | } |
1426 | 1394 | ||
1427 | if (my_qp->send_cq) { | 1395 | if (my_qp->send_cq) { |
@@ -1439,24 +1407,6 @@ int ehca_destroy_qp(struct ib_qp *ibqp) | |||
1439 | idr_remove(&ehca_qp_idr, my_qp->token); | 1407 | idr_remove(&ehca_qp_idr, my_qp->token); |
1440 | spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); | 1408 | spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); |
1441 | 1409 | ||
1442 | /* un-mmap if vma alloc */ | ||
1443 | if (my_qp->uspace_rqueue) { | ||
1444 | ret = ehca_munmap(my_qp->uspace_rqueue, | ||
1445 | my_qp->ipz_rqueue.queue_length); | ||
1446 | if (ret) | ||
1447 | ehca_err(ibqp->device, "Could not munmap rqueue " | ||
1448 | "qp_num=%x", qp_num); | ||
1449 | ret = ehca_munmap(my_qp->uspace_squeue, | ||
1450 | my_qp->ipz_squeue.queue_length); | ||
1451 | if (ret) | ||
1452 | ehca_err(ibqp->device, "Could not munmap squeue " | ||
1453 | "qp_num=%x", qp_num); | ||
1454 | ret = ehca_munmap(my_qp->uspace_fwh, EHCA_PAGESIZE); | ||
1455 | if (ret) | ||
1456 | ehca_err(ibqp->device, "Could not munmap fwh qp_num=%x", | ||
1457 | qp_num); | ||
1458 | } | ||
1459 | |||
1460 | h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp); | 1410 | h_ret = hipz_h_destroy_qp(shca->ipz_hca_handle, my_qp); |
1461 | if (h_ret != H_SUCCESS) { | 1411 | if (h_ret != H_SUCCESS) { |
1462 | ehca_err(ibqp->device, "hipz_h_destroy_qp() failed rc=%lx " | 1412 | ehca_err(ibqp->device, "hipz_h_destroy_qp() failed rc=%lx " |
diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c index b46bda1bf85d..08d3f892d9f3 100644 --- a/drivers/infiniband/hw/ehca/ehca_reqs.c +++ b/drivers/infiniband/hw/ehca/ehca_reqs.c | |||
@@ -579,7 +579,7 @@ poll_cq_one_read_cqe: | |||
579 | } else | 579 | } else |
580 | wc->status = IB_WC_SUCCESS; | 580 | wc->status = IB_WC_SUCCESS; |
581 | 581 | ||
582 | wc->qp_num = cqe->local_qp_number; | 582 | wc->qp = NULL; |
583 | wc->byte_len = cqe->nr_bytes_transferred; | 583 | wc->byte_len = cqe->nr_bytes_transferred; |
584 | wc->pkey_index = cqe->pkey_index; | 584 | wc->pkey_index = cqe->pkey_index; |
585 | wc->slid = cqe->rlid; | 585 | wc->slid = cqe->rlid; |
diff --git a/drivers/infiniband/hw/ehca/ehca_uverbs.c b/drivers/infiniband/hw/ehca/ehca_uverbs.c index e08764e4aef2..73db920b6945 100644 --- a/drivers/infiniband/hw/ehca/ehca_uverbs.c +++ b/drivers/infiniband/hw/ehca/ehca_uverbs.c | |||
@@ -68,105 +68,183 @@ int ehca_dealloc_ucontext(struct ib_ucontext *context) | |||
68 | return 0; | 68 | return 0; |
69 | } | 69 | } |
70 | 70 | ||
71 | struct page *ehca_nopage(struct vm_area_struct *vma, | 71 | static void ehca_mm_open(struct vm_area_struct *vma) |
72 | unsigned long address, int *type) | ||
73 | { | 72 | { |
74 | struct page *mypage = NULL; | 73 | u32 *count = (u32*)vma->vm_private_data; |
75 | u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT; | 74 | if (!count) { |
76 | u32 idr_handle = fileoffset >> 32; | 75 | ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx", |
77 | u32 q_type = (fileoffset >> 28) & 0xF; /* CQ, QP,... */ | 76 | vma->vm_start, vma->vm_end); |
78 | u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */ | 77 | return; |
79 | u32 cur_pid = current->tgid; | 78 | } |
80 | unsigned long flags; | 79 | (*count)++; |
81 | struct ehca_cq *cq; | 80 | if (!(*count)) |
82 | struct ehca_qp *qp; | 81 | ehca_gen_err("Use count overflow vm_start=%lx vm_end=%lx", |
83 | struct ehca_pd *pd; | 82 | vma->vm_start, vma->vm_end); |
84 | u64 offset; | 83 | ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x", |
85 | void *vaddr; | 84 | vma->vm_start, vma->vm_end, *count); |
85 | } | ||
86 | 86 | ||
87 | switch (q_type) { | 87 | static void ehca_mm_close(struct vm_area_struct *vma) |
88 | case 1: /* CQ */ | 88 | { |
89 | spin_lock_irqsave(&ehca_cq_idr_lock, flags); | 89 | u32 *count = (u32*)vma->vm_private_data; |
90 | cq = idr_find(&ehca_cq_idr, idr_handle); | 90 | if (!count) { |
91 | spin_unlock_irqrestore(&ehca_cq_idr_lock, flags); | 91 | ehca_gen_err("Invalid vma struct vm_start=%lx vm_end=%lx", |
92 | vma->vm_start, vma->vm_end); | ||
93 | return; | ||
94 | } | ||
95 | (*count)--; | ||
96 | ehca_gen_dbg("vm_start=%lx vm_end=%lx count=%x", | ||
97 | vma->vm_start, vma->vm_end, *count); | ||
98 | } | ||
92 | 99 | ||
93 | /* make sure this mmap really belongs to the authorized user */ | 100 | static struct vm_operations_struct vm_ops = { |
94 | if (!cq) { | 101 | .open = ehca_mm_open, |
95 | ehca_gen_err("cq is NULL ret=NOPAGE_SIGBUS"); | 102 | .close = ehca_mm_close, |
96 | return NOPAGE_SIGBUS; | 103 | }; |
104 | |||
105 | static int ehca_mmap_fw(struct vm_area_struct *vma, struct h_galpas *galpas, | ||
106 | u32 *mm_count) | ||
107 | { | ||
108 | int ret; | ||
109 | u64 vsize, physical; | ||
110 | |||
111 | vsize = vma->vm_end - vma->vm_start; | ||
112 | if (vsize != EHCA_PAGESIZE) { | ||
113 | ehca_gen_err("invalid vsize=%lx", vma->vm_end - vma->vm_start); | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | |||
117 | physical = galpas->user.fw_handle; | ||
118 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
119 | ehca_gen_dbg("vsize=%lx physical=%lx", vsize, physical); | ||
120 | /* VM_IO | VM_RESERVED are set by remap_pfn_range() */ | ||
121 | ret = remap_pfn_range(vma, vma->vm_start, physical >> PAGE_SHIFT, | ||
122 | vsize, vma->vm_page_prot); | ||
123 | if (unlikely(ret)) { | ||
124 | ehca_gen_err("remap_pfn_range() failed ret=%x", ret); | ||
125 | return -ENOMEM; | ||
126 | } | ||
127 | |||
128 | vma->vm_private_data = mm_count; | ||
129 | (*mm_count)++; | ||
130 | vma->vm_ops = &vm_ops; | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int ehca_mmap_queue(struct vm_area_struct *vma, struct ipz_queue *queue, | ||
136 | u32 *mm_count) | ||
137 | { | ||
138 | int ret; | ||
139 | u64 start, ofs; | ||
140 | struct page *page; | ||
141 | |||
142 | vma->vm_flags |= VM_RESERVED; | ||
143 | start = vma->vm_start; | ||
144 | for (ofs = 0; ofs < queue->queue_length; ofs += PAGE_SIZE) { | ||
145 | u64 virt_addr = (u64)ipz_qeit_calc(queue, ofs); | ||
146 | page = virt_to_page(virt_addr); | ||
147 | ret = vm_insert_page(vma, start, page); | ||
148 | if (unlikely(ret)) { | ||
149 | ehca_gen_err("vm_insert_page() failed rc=%x", ret); | ||
150 | return ret; | ||
97 | } | 151 | } |
152 | start += PAGE_SIZE; | ||
153 | } | ||
154 | vma->vm_private_data = mm_count; | ||
155 | (*mm_count)++; | ||
156 | vma->vm_ops = &vm_ops; | ||
98 | 157 | ||
99 | if (cq->ownpid != cur_pid) { | 158 | return 0; |
159 | } | ||
160 | |||
161 | static int ehca_mmap_cq(struct vm_area_struct *vma, struct ehca_cq *cq, | ||
162 | u32 rsrc_type) | ||
163 | { | ||
164 | int ret; | ||
165 | |||
166 | switch (rsrc_type) { | ||
167 | case 1: /* galpa fw handle */ | ||
168 | ehca_dbg(cq->ib_cq.device, "cq_num=%x fw", cq->cq_number); | ||
169 | ret = ehca_mmap_fw(vma, &cq->galpas, &cq->mm_count_galpa); | ||
170 | if (unlikely(ret)) { | ||
100 | ehca_err(cq->ib_cq.device, | 171 | ehca_err(cq->ib_cq.device, |
101 | "Invalid caller pid=%x ownpid=%x", | 172 | "ehca_mmap_fw() failed rc=%x cq_num=%x", |
102 | cur_pid, cq->ownpid); | 173 | ret, cq->cq_number); |
103 | return NOPAGE_SIGBUS; | 174 | return ret; |
104 | } | 175 | } |
176 | break; | ||
105 | 177 | ||
106 | if (rsrc_type == 2) { | 178 | case 2: /* cq queue_addr */ |
107 | ehca_dbg(cq->ib_cq.device, "cq=%p cq queuearea", cq); | 179 | ehca_dbg(cq->ib_cq.device, "cq_num=%x queue", cq->cq_number); |
108 | offset = address - vma->vm_start; | 180 | ret = ehca_mmap_queue(vma, &cq->ipz_queue, &cq->mm_count_queue); |
109 | vaddr = ipz_qeit_calc(&cq->ipz_queue, offset); | 181 | if (unlikely(ret)) { |
110 | ehca_dbg(cq->ib_cq.device, "offset=%lx vaddr=%p", | 182 | ehca_err(cq->ib_cq.device, |
111 | offset, vaddr); | 183 | "ehca_mmap_queue() failed rc=%x cq_num=%x", |
112 | mypage = virt_to_page(vaddr); | 184 | ret, cq->cq_number); |
185 | return ret; | ||
113 | } | 186 | } |
114 | break; | 187 | break; |
115 | 188 | ||
116 | case 2: /* QP */ | 189 | default: |
117 | spin_lock_irqsave(&ehca_qp_idr_lock, flags); | 190 | ehca_err(cq->ib_cq.device, "bad resource type=%x cq_num=%x", |
118 | qp = idr_find(&ehca_qp_idr, idr_handle); | 191 | rsrc_type, cq->cq_number); |
119 | spin_unlock_irqrestore(&ehca_qp_idr_lock, flags); | 192 | return -EINVAL; |
193 | } | ||
120 | 194 | ||
121 | /* make sure this mmap really belongs to the authorized user */ | 195 | return 0; |
122 | if (!qp) { | 196 | } |
123 | ehca_gen_err("qp is NULL ret=NOPAGE_SIGBUS"); | 197 | |
124 | return NOPAGE_SIGBUS; | 198 | static int ehca_mmap_qp(struct vm_area_struct *vma, struct ehca_qp *qp, |
199 | u32 rsrc_type) | ||
200 | { | ||
201 | int ret; | ||
202 | |||
203 | switch (rsrc_type) { | ||
204 | case 1: /* galpa fw handle */ | ||
205 | ehca_dbg(qp->ib_qp.device, "qp_num=%x fw", qp->ib_qp.qp_num); | ||
206 | ret = ehca_mmap_fw(vma, &qp->galpas, &qp->mm_count_galpa); | ||
207 | if (unlikely(ret)) { | ||
208 | ehca_err(qp->ib_qp.device, | ||
209 | "remap_pfn_range() failed ret=%x qp_num=%x", | ||
210 | ret, qp->ib_qp.qp_num); | ||
211 | return -ENOMEM; | ||
125 | } | 212 | } |
213 | break; | ||
126 | 214 | ||
127 | pd = container_of(qp->ib_qp.pd, struct ehca_pd, ib_pd); | 215 | case 2: /* qp rqueue_addr */ |
128 | if (pd->ownpid != cur_pid) { | 216 | ehca_dbg(qp->ib_qp.device, "qp_num=%x rqueue", |
217 | qp->ib_qp.qp_num); | ||
218 | ret = ehca_mmap_queue(vma, &qp->ipz_rqueue, &qp->mm_count_rqueue); | ||
219 | if (unlikely(ret)) { | ||
129 | ehca_err(qp->ib_qp.device, | 220 | ehca_err(qp->ib_qp.device, |
130 | "Invalid caller pid=%x ownpid=%x", | 221 | "ehca_mmap_queue(rq) failed rc=%x qp_num=%x", |
131 | cur_pid, pd->ownpid); | 222 | ret, qp->ib_qp.qp_num); |
132 | return NOPAGE_SIGBUS; | 223 | return ret; |
133 | } | 224 | } |
225 | break; | ||
134 | 226 | ||
135 | if (rsrc_type == 2) { /* rqueue */ | 227 | case 3: /* qp squeue_addr */ |
136 | ehca_dbg(qp->ib_qp.device, "qp=%p qp rqueuearea", qp); | 228 | ehca_dbg(qp->ib_qp.device, "qp_num=%x squeue", |
137 | offset = address - vma->vm_start; | 229 | qp->ib_qp.qp_num); |
138 | vaddr = ipz_qeit_calc(&qp->ipz_rqueue, offset); | 230 | ret = ehca_mmap_queue(vma, &qp->ipz_squeue, &qp->mm_count_squeue); |
139 | ehca_dbg(qp->ib_qp.device, "offset=%lx vaddr=%p", | 231 | if (unlikely(ret)) { |
140 | offset, vaddr); | 232 | ehca_err(qp->ib_qp.device, |
141 | mypage = virt_to_page(vaddr); | 233 | "ehca_mmap_queue(sq) failed rc=%x qp_num=%x", |
142 | } else if (rsrc_type == 3) { /* squeue */ | 234 | ret, qp->ib_qp.qp_num); |
143 | ehca_dbg(qp->ib_qp.device, "qp=%p qp squeuearea", qp); | 235 | return ret; |
144 | offset = address - vma->vm_start; | ||
145 | vaddr = ipz_qeit_calc(&qp->ipz_squeue, offset); | ||
146 | ehca_dbg(qp->ib_qp.device, "offset=%lx vaddr=%p", | ||
147 | offset, vaddr); | ||
148 | mypage = virt_to_page(vaddr); | ||
149 | } | 236 | } |
150 | break; | 237 | break; |
151 | 238 | ||
152 | default: | 239 | default: |
153 | ehca_gen_err("bad queue type %x", q_type); | 240 | ehca_err(qp->ib_qp.device, "bad resource type=%x qp=num=%x", |
154 | return NOPAGE_SIGBUS; | 241 | rsrc_type, qp->ib_qp.qp_num); |
155 | } | 242 | return -EINVAL; |
156 | |||
157 | if (!mypage) { | ||
158 | ehca_gen_err("Invalid page adr==NULL ret=NOPAGE_SIGBUS"); | ||
159 | return NOPAGE_SIGBUS; | ||
160 | } | 243 | } |
161 | get_page(mypage); | ||
162 | 244 | ||
163 | return mypage; | 245 | return 0; |
164 | } | 246 | } |
165 | 247 | ||
166 | static struct vm_operations_struct ehcau_vm_ops = { | ||
167 | .nopage = ehca_nopage, | ||
168 | }; | ||
169 | |||
170 | int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) | 248 | int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) |
171 | { | 249 | { |
172 | u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT; | 250 | u64 fileoffset = vma->vm_pgoff << PAGE_SHIFT; |
@@ -175,7 +253,6 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) | |||
175 | u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */ | 253 | u32 rsrc_type = (fileoffset >> 24) & 0xF; /* sq,rq,cmnd_window */ |
176 | u32 cur_pid = current->tgid; | 254 | u32 cur_pid = current->tgid; |
177 | u32 ret; | 255 | u32 ret; |
178 | u64 vsize, physical; | ||
179 | unsigned long flags; | 256 | unsigned long flags; |
180 | struct ehca_cq *cq; | 257 | struct ehca_cq *cq; |
181 | struct ehca_qp *qp; | 258 | struct ehca_qp *qp; |
@@ -201,44 +278,12 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) | |||
201 | if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context) | 278 | if (!cq->ib_cq.uobject || cq->ib_cq.uobject->context != context) |
202 | return -EINVAL; | 279 | return -EINVAL; |
203 | 280 | ||
204 | switch (rsrc_type) { | 281 | ret = ehca_mmap_cq(vma, cq, rsrc_type); |
205 | case 1: /* galpa fw handle */ | 282 | if (unlikely(ret)) { |
206 | ehca_dbg(cq->ib_cq.device, "cq=%p cq triggerarea", cq); | 283 | ehca_err(cq->ib_cq.device, |
207 | vma->vm_flags |= VM_RESERVED; | 284 | "ehca_mmap_cq() failed rc=%x cq_num=%x", |
208 | vsize = vma->vm_end - vma->vm_start; | 285 | ret, cq->cq_number); |
209 | if (vsize != EHCA_PAGESIZE) { | 286 | return ret; |
210 | ehca_err(cq->ib_cq.device, "invalid vsize=%lx", | ||
211 | vma->vm_end - vma->vm_start); | ||
212 | return -EINVAL; | ||
213 | } | ||
214 | |||
215 | physical = cq->galpas.user.fw_handle; | ||
216 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
217 | vma->vm_flags |= VM_IO | VM_RESERVED; | ||
218 | |||
219 | ehca_dbg(cq->ib_cq.device, | ||
220 | "vsize=%lx physical=%lx", vsize, physical); | ||
221 | ret = remap_pfn_range(vma, vma->vm_start, | ||
222 | physical >> PAGE_SHIFT, vsize, | ||
223 | vma->vm_page_prot); | ||
224 | if (ret) { | ||
225 | ehca_err(cq->ib_cq.device, | ||
226 | "remap_pfn_range() failed ret=%x", | ||
227 | ret); | ||
228 | return -ENOMEM; | ||
229 | } | ||
230 | break; | ||
231 | |||
232 | case 2: /* cq queue_addr */ | ||
233 | ehca_dbg(cq->ib_cq.device, "cq=%p cq q_addr", cq); | ||
234 | vma->vm_flags |= VM_RESERVED; | ||
235 | vma->vm_ops = &ehcau_vm_ops; | ||
236 | break; | ||
237 | |||
238 | default: | ||
239 | ehca_err(cq->ib_cq.device, "bad resource type %x", | ||
240 | rsrc_type); | ||
241 | return -EINVAL; | ||
242 | } | 287 | } |
243 | break; | 288 | break; |
244 | 289 | ||
@@ -262,50 +307,12 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) | |||
262 | if (!qp->ib_qp.uobject || qp->ib_qp.uobject->context != context) | 307 | if (!qp->ib_qp.uobject || qp->ib_qp.uobject->context != context) |
263 | return -EINVAL; | 308 | return -EINVAL; |
264 | 309 | ||
265 | switch (rsrc_type) { | 310 | ret = ehca_mmap_qp(vma, qp, rsrc_type); |
266 | case 1: /* galpa fw handle */ | 311 | if (unlikely(ret)) { |
267 | ehca_dbg(qp->ib_qp.device, "qp=%p qp triggerarea", qp); | 312 | ehca_err(qp->ib_qp.device, |
268 | vma->vm_flags |= VM_RESERVED; | 313 | "ehca_mmap_qp() failed rc=%x qp_num=%x", |
269 | vsize = vma->vm_end - vma->vm_start; | 314 | ret, qp->ib_qp.qp_num); |
270 | if (vsize != EHCA_PAGESIZE) { | 315 | return ret; |
271 | ehca_err(qp->ib_qp.device, "invalid vsize=%lx", | ||
272 | vma->vm_end - vma->vm_start); | ||
273 | return -EINVAL; | ||
274 | } | ||
275 | |||
276 | physical = qp->galpas.user.fw_handle; | ||
277 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
278 | vma->vm_flags |= VM_IO | VM_RESERVED; | ||
279 | |||
280 | ehca_dbg(qp->ib_qp.device, "vsize=%lx physical=%lx", | ||
281 | vsize, physical); | ||
282 | ret = remap_pfn_range(vma, vma->vm_start, | ||
283 | physical >> PAGE_SHIFT, vsize, | ||
284 | vma->vm_page_prot); | ||
285 | if (ret) { | ||
286 | ehca_err(qp->ib_qp.device, | ||
287 | "remap_pfn_range() failed ret=%x", | ||
288 | ret); | ||
289 | return -ENOMEM; | ||
290 | } | ||
291 | break; | ||
292 | |||
293 | case 2: /* qp rqueue_addr */ | ||
294 | ehca_dbg(qp->ib_qp.device, "qp=%p qp rqueue_addr", qp); | ||
295 | vma->vm_flags |= VM_RESERVED; | ||
296 | vma->vm_ops = &ehcau_vm_ops; | ||
297 | break; | ||
298 | |||
299 | case 3: /* qp squeue_addr */ | ||
300 | ehca_dbg(qp->ib_qp.device, "qp=%p qp squeue_addr", qp); | ||
301 | vma->vm_flags |= VM_RESERVED; | ||
302 | vma->vm_ops = &ehcau_vm_ops; | ||
303 | break; | ||
304 | |||
305 | default: | ||
306 | ehca_err(qp->ib_qp.device, "bad resource type %x", | ||
307 | rsrc_type); | ||
308 | return -EINVAL; | ||
309 | } | 316 | } |
310 | break; | 317 | break; |
311 | 318 | ||
@@ -316,77 +323,3 @@ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) | |||
316 | 323 | ||
317 | return 0; | 324 | return 0; |
318 | } | 325 | } |
319 | |||
320 | int ehca_mmap_nopage(u64 foffset, u64 length, void **mapped, | ||
321 | struct vm_area_struct **vma) | ||
322 | { | ||
323 | down_write(¤t->mm->mmap_sem); | ||
324 | *mapped = (void*)do_mmap(NULL,0, length, PROT_WRITE, | ||
325 | MAP_SHARED | MAP_ANONYMOUS, | ||
326 | foffset); | ||
327 | up_write(¤t->mm->mmap_sem); | ||
328 | if (!(*mapped)) { | ||
329 | ehca_gen_err("couldn't mmap foffset=%lx length=%lx", | ||
330 | foffset, length); | ||
331 | return -EINVAL; | ||
332 | } | ||
333 | |||
334 | *vma = find_vma(current->mm, (u64)*mapped); | ||
335 | if (!(*vma)) { | ||
336 | down_write(¤t->mm->mmap_sem); | ||
337 | do_munmap(current->mm, 0, length); | ||
338 | up_write(¤t->mm->mmap_sem); | ||
339 | ehca_gen_err("couldn't find vma queue=%p", *mapped); | ||
340 | return -EINVAL; | ||
341 | } | ||
342 | (*vma)->vm_flags |= VM_RESERVED; | ||
343 | (*vma)->vm_ops = &ehcau_vm_ops; | ||
344 | |||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | int ehca_mmap_register(u64 physical, void **mapped, | ||
349 | struct vm_area_struct **vma) | ||
350 | { | ||
351 | int ret; | ||
352 | unsigned long vsize; | ||
353 | /* ehca hw supports only 4k page */ | ||
354 | ret = ehca_mmap_nopage(0, EHCA_PAGESIZE, mapped, vma); | ||
355 | if (ret) { | ||
356 | ehca_gen_err("could'nt mmap physical=%lx", physical); | ||
357 | return ret; | ||
358 | } | ||
359 | |||
360 | (*vma)->vm_flags |= VM_RESERVED; | ||
361 | vsize = (*vma)->vm_end - (*vma)->vm_start; | ||
362 | if (vsize != EHCA_PAGESIZE) { | ||
363 | ehca_gen_err("invalid vsize=%lx", | ||
364 | (*vma)->vm_end - (*vma)->vm_start); | ||
365 | return -EINVAL; | ||
366 | } | ||
367 | |||
368 | (*vma)->vm_page_prot = pgprot_noncached((*vma)->vm_page_prot); | ||
369 | (*vma)->vm_flags |= VM_IO | VM_RESERVED; | ||
370 | |||
371 | ret = remap_pfn_range((*vma), (*vma)->vm_start, | ||
372 | physical >> PAGE_SHIFT, vsize, | ||
373 | (*vma)->vm_page_prot); | ||
374 | if (ret) { | ||
375 | ehca_gen_err("remap_pfn_range() failed ret=%x", ret); | ||
376 | return -ENOMEM; | ||
377 | } | ||
378 | |||
379 | return 0; | ||
380 | |||
381 | } | ||
382 | |||
383 | int ehca_munmap(unsigned long addr, size_t len) { | ||
384 | int ret = 0; | ||
385 | struct mm_struct *mm = current->mm; | ||
386 | if (mm) { | ||
387 | down_write(&mm->mmap_sem); | ||
388 | ret = do_munmap(mm, addr, len); | ||
389 | up_write(&mm->mmap_sem); | ||
390 | } | ||
391 | return ret; | ||
392 | } | ||
diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c index 46c1c89bf6ae..64f07b19349f 100644 --- a/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/drivers/infiniband/hw/ipath/ipath_qp.c | |||
@@ -379,7 +379,7 @@ void ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err) | |||
379 | wc.vendor_err = 0; | 379 | wc.vendor_err = 0; |
380 | wc.byte_len = 0; | 380 | wc.byte_len = 0; |
381 | wc.imm_data = 0; | 381 | wc.imm_data = 0; |
382 | wc.qp_num = qp->ibqp.qp_num; | 382 | wc.qp = &qp->ibqp; |
383 | wc.src_qp = 0; | 383 | wc.src_qp = 0; |
384 | wc.wc_flags = 0; | 384 | wc.wc_flags = 0; |
385 | wc.pkey_index = 0; | 385 | wc.pkey_index = 0; |
diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index ce6038743c5c..5ff20cb04494 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c | |||
@@ -702,7 +702,7 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc) | |||
702 | wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; | 702 | wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; |
703 | wc->vendor_err = 0; | 703 | wc->vendor_err = 0; |
704 | wc->byte_len = 0; | 704 | wc->byte_len = 0; |
705 | wc->qp_num = qp->ibqp.qp_num; | 705 | wc->qp = &qp->ibqp; |
706 | wc->src_qp = qp->remote_qpn; | 706 | wc->src_qp = qp->remote_qpn; |
707 | wc->pkey_index = 0; | 707 | wc->pkey_index = 0; |
708 | wc->slid = qp->remote_ah_attr.dlid; | 708 | wc->slid = qp->remote_ah_attr.dlid; |
@@ -836,7 +836,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) | |||
836 | wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; | 836 | wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; |
837 | wc.vendor_err = 0; | 837 | wc.vendor_err = 0; |
838 | wc.byte_len = wqe->length; | 838 | wc.byte_len = wqe->length; |
839 | wc.qp_num = qp->ibqp.qp_num; | 839 | wc.qp = &qp->ibqp; |
840 | wc.src_qp = qp->remote_qpn; | 840 | wc.src_qp = qp->remote_qpn; |
841 | wc.pkey_index = 0; | 841 | wc.pkey_index = 0; |
842 | wc.slid = qp->remote_ah_attr.dlid; | 842 | wc.slid = qp->remote_ah_attr.dlid; |
@@ -951,7 +951,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) | |||
951 | wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; | 951 | wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; |
952 | wc.vendor_err = 0; | 952 | wc.vendor_err = 0; |
953 | wc.byte_len = 0; | 953 | wc.byte_len = 0; |
954 | wc.qp_num = qp->ibqp.qp_num; | 954 | wc.qp = &qp->ibqp; |
955 | wc.src_qp = qp->remote_qpn; | 955 | wc.src_qp = qp->remote_qpn; |
956 | wc.pkey_index = 0; | 956 | wc.pkey_index = 0; |
957 | wc.slid = qp->remote_ah_attr.dlid; | 957 | wc.slid = qp->remote_ah_attr.dlid; |
@@ -1511,7 +1511,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
1511 | wc.status = IB_WC_SUCCESS; | 1511 | wc.status = IB_WC_SUCCESS; |
1512 | wc.opcode = IB_WC_RECV; | 1512 | wc.opcode = IB_WC_RECV; |
1513 | wc.vendor_err = 0; | 1513 | wc.vendor_err = 0; |
1514 | wc.qp_num = qp->ibqp.qp_num; | 1514 | wc.qp = &qp->ibqp; |
1515 | wc.src_qp = qp->remote_qpn; | 1515 | wc.src_qp = qp->remote_qpn; |
1516 | wc.pkey_index = 0; | 1516 | wc.pkey_index = 0; |
1517 | wc.slid = qp->remote_ah_attr.dlid; | 1517 | wc.slid = qp->remote_ah_attr.dlid; |
diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c index f7530512045d..e86cb171872e 100644 --- a/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/drivers/infiniband/hw/ipath/ipath_ruc.c | |||
@@ -137,7 +137,7 @@ bad_lkey: | |||
137 | wc.vendor_err = 0; | 137 | wc.vendor_err = 0; |
138 | wc.byte_len = 0; | 138 | wc.byte_len = 0; |
139 | wc.imm_data = 0; | 139 | wc.imm_data = 0; |
140 | wc.qp_num = qp->ibqp.qp_num; | 140 | wc.qp = &qp->ibqp; |
141 | wc.src_qp = 0; | 141 | wc.src_qp = 0; |
142 | wc.wc_flags = 0; | 142 | wc.wc_flags = 0; |
143 | wc.pkey_index = 0; | 143 | wc.pkey_index = 0; |
@@ -336,7 +336,7 @@ again: | |||
336 | wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; | 336 | wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; |
337 | wc.vendor_err = 0; | 337 | wc.vendor_err = 0; |
338 | wc.byte_len = 0; | 338 | wc.byte_len = 0; |
339 | wc.qp_num = sqp->ibqp.qp_num; | 339 | wc.qp = &sqp->ibqp; |
340 | wc.src_qp = sqp->remote_qpn; | 340 | wc.src_qp = sqp->remote_qpn; |
341 | wc.pkey_index = 0; | 341 | wc.pkey_index = 0; |
342 | wc.slid = sqp->remote_ah_attr.dlid; | 342 | wc.slid = sqp->remote_ah_attr.dlid; |
@@ -426,7 +426,7 @@ again: | |||
426 | wc.status = IB_WC_SUCCESS; | 426 | wc.status = IB_WC_SUCCESS; |
427 | wc.vendor_err = 0; | 427 | wc.vendor_err = 0; |
428 | wc.byte_len = wqe->length; | 428 | wc.byte_len = wqe->length; |
429 | wc.qp_num = qp->ibqp.qp_num; | 429 | wc.qp = &qp->ibqp; |
430 | wc.src_qp = qp->remote_qpn; | 430 | wc.src_qp = qp->remote_qpn; |
431 | /* XXX do we know which pkey matched? Only needed for GSI. */ | 431 | /* XXX do we know which pkey matched? Only needed for GSI. */ |
432 | wc.pkey_index = 0; | 432 | wc.pkey_index = 0; |
@@ -447,7 +447,7 @@ send_comp: | |||
447 | wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; | 447 | wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; |
448 | wc.vendor_err = 0; | 448 | wc.vendor_err = 0; |
449 | wc.byte_len = wqe->length; | 449 | wc.byte_len = wqe->length; |
450 | wc.qp_num = sqp->ibqp.qp_num; | 450 | wc.qp = &sqp->ibqp; |
451 | wc.src_qp = 0; | 451 | wc.src_qp = 0; |
452 | wc.pkey_index = 0; | 452 | wc.pkey_index = 0; |
453 | wc.slid = 0; | 453 | wc.slid = 0; |
diff --git a/drivers/infiniband/hw/ipath/ipath_uc.c b/drivers/infiniband/hw/ipath/ipath_uc.c index e636cfd67a82..325d6634ff53 100644 --- a/drivers/infiniband/hw/ipath/ipath_uc.c +++ b/drivers/infiniband/hw/ipath/ipath_uc.c | |||
@@ -49,7 +49,7 @@ static void complete_last_send(struct ipath_qp *qp, struct ipath_swqe *wqe, | |||
49 | wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; | 49 | wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; |
50 | wc->vendor_err = 0; | 50 | wc->vendor_err = 0; |
51 | wc->byte_len = wqe->length; | 51 | wc->byte_len = wqe->length; |
52 | wc->qp_num = qp->ibqp.qp_num; | 52 | wc->qp = &qp->ibqp; |
53 | wc->src_qp = qp->remote_qpn; | 53 | wc->src_qp = qp->remote_qpn; |
54 | wc->pkey_index = 0; | 54 | wc->pkey_index = 0; |
55 | wc->slid = qp->remote_ah_attr.dlid; | 55 | wc->slid = qp->remote_ah_attr.dlid; |
@@ -411,7 +411,7 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
411 | wc.status = IB_WC_SUCCESS; | 411 | wc.status = IB_WC_SUCCESS; |
412 | wc.opcode = IB_WC_RECV; | 412 | wc.opcode = IB_WC_RECV; |
413 | wc.vendor_err = 0; | 413 | wc.vendor_err = 0; |
414 | wc.qp_num = qp->ibqp.qp_num; | 414 | wc.qp = &qp->ibqp; |
415 | wc.src_qp = qp->remote_qpn; | 415 | wc.src_qp = qp->remote_qpn; |
416 | wc.pkey_index = 0; | 416 | wc.pkey_index = 0; |
417 | wc.slid = qp->remote_ah_attr.dlid; | 417 | wc.slid = qp->remote_ah_attr.dlid; |
diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c index 49f1102af8b3..9a3e54664ee4 100644 --- a/drivers/infiniband/hw/ipath/ipath_ud.c +++ b/drivers/infiniband/hw/ipath/ipath_ud.c | |||
@@ -66,7 +66,7 @@ bad_lkey: | |||
66 | wc.vendor_err = 0; | 66 | wc.vendor_err = 0; |
67 | wc.byte_len = 0; | 67 | wc.byte_len = 0; |
68 | wc.imm_data = 0; | 68 | wc.imm_data = 0; |
69 | wc.qp_num = qp->ibqp.qp_num; | 69 | wc.qp = &qp->ibqp; |
70 | wc.src_qp = 0; | 70 | wc.src_qp = 0; |
71 | wc.wc_flags = 0; | 71 | wc.wc_flags = 0; |
72 | wc.pkey_index = 0; | 72 | wc.pkey_index = 0; |
@@ -255,7 +255,7 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, | |||
255 | wc->status = IB_WC_SUCCESS; | 255 | wc->status = IB_WC_SUCCESS; |
256 | wc->opcode = IB_WC_RECV; | 256 | wc->opcode = IB_WC_RECV; |
257 | wc->vendor_err = 0; | 257 | wc->vendor_err = 0; |
258 | wc->qp_num = qp->ibqp.qp_num; | 258 | wc->qp = &qp->ibqp; |
259 | wc->src_qp = sqp->ibqp.qp_num; | 259 | wc->src_qp = sqp->ibqp.qp_num; |
260 | /* XXX do we know which pkey matched? Only needed for GSI. */ | 260 | /* XXX do we know which pkey matched? Only needed for GSI. */ |
261 | wc->pkey_index = 0; | 261 | wc->pkey_index = 0; |
@@ -474,7 +474,7 @@ done: | |||
474 | wc.vendor_err = 0; | 474 | wc.vendor_err = 0; |
475 | wc.opcode = IB_WC_SEND; | 475 | wc.opcode = IB_WC_SEND; |
476 | wc.byte_len = len; | 476 | wc.byte_len = len; |
477 | wc.qp_num = qp->ibqp.qp_num; | 477 | wc.qp = &qp->ibqp; |
478 | wc.src_qp = 0; | 478 | wc.src_qp = 0; |
479 | wc.wc_flags = 0; | 479 | wc.wc_flags = 0; |
480 | /* XXX initialize other fields? */ | 480 | /* XXX initialize other fields? */ |
@@ -651,7 +651,7 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, | |||
651 | wc.status = IB_WC_SUCCESS; | 651 | wc.status = IB_WC_SUCCESS; |
652 | wc.opcode = IB_WC_RECV; | 652 | wc.opcode = IB_WC_RECV; |
653 | wc.vendor_err = 0; | 653 | wc.vendor_err = 0; |
654 | wc.qp_num = qp->ibqp.qp_num; | 654 | wc.qp = &qp->ibqp; |
655 | wc.src_qp = src_qp; | 655 | wc.src_qp = src_qp; |
656 | /* XXX do we know which pkey matched? Only needed for GSI. */ | 656 | /* XXX do we know which pkey matched? Only needed for GSI. */ |
657 | wc.pkey_index = 0; | 657 | wc.pkey_index = 0; |
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 768df7265b81..968d1519761c 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c | |||
@@ -1854,7 +1854,7 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, | |||
1854 | 1854 | ||
1855 | memset(inbox + 256, 0, 256); | 1855 | memset(inbox + 256, 0, 256); |
1856 | 1856 | ||
1857 | MTHCA_PUT(inbox, in_wc->qp_num, MAD_IFC_MY_QPN_OFFSET); | 1857 | MTHCA_PUT(inbox, in_wc->qp->qp_num, MAD_IFC_MY_QPN_OFFSET); |
1858 | MTHCA_PUT(inbox, in_wc->src_qp, MAD_IFC_RQPN_OFFSET); | 1858 | MTHCA_PUT(inbox, in_wc->src_qp, MAD_IFC_RQPN_OFFSET); |
1859 | 1859 | ||
1860 | val = in_wc->sl << 4; | 1860 | val = in_wc->sl << 4; |
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index 1159c8a0f2c5..efd79ef109a6 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c | |||
@@ -534,7 +534,7 @@ static inline int mthca_poll_one(struct mthca_dev *dev, | |||
534 | } | 534 | } |
535 | } | 535 | } |
536 | 536 | ||
537 | entry->qp_num = (*cur_qp)->qpn; | 537 | entry->qp = &(*cur_qp)->ibqp; |
538 | 538 | ||
539 | if (is_send) { | 539 | if (is_send) { |
540 | wq = &(*cur_qp)->sq; | 540 | wq = &(*cur_qp)->sq; |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 72611fd15103..5e8ac577f0ad 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -548,6 +548,7 @@ static int srp_reconnect_target(struct srp_target_port *target) | |||
548 | target->tx_head = 0; | 548 | target->tx_head = 0; |
549 | target->tx_tail = 0; | 549 | target->tx_tail = 0; |
550 | 550 | ||
551 | target->qp_in_error = 0; | ||
551 | ret = srp_connect_target(target); | 552 | ret = srp_connect_target(target); |
552 | if (ret) | 553 | if (ret) |
553 | goto err; | 554 | goto err; |
@@ -878,6 +879,7 @@ static void srp_completion(struct ib_cq *cq, void *target_ptr) | |||
878 | printk(KERN_ERR PFX "failed %s status %d\n", | 879 | printk(KERN_ERR PFX "failed %s status %d\n", |
879 | wc.wr_id & SRP_OP_RECV ? "receive" : "send", | 880 | wc.wr_id & SRP_OP_RECV ? "receive" : "send", |
880 | wc.status); | 881 | wc.status); |
882 | target->qp_in_error = 1; | ||
881 | break; | 883 | break; |
882 | } | 884 | } |
883 | 885 | ||
@@ -1337,6 +1339,8 @@ static int srp_abort(struct scsi_cmnd *scmnd) | |||
1337 | 1339 | ||
1338 | printk(KERN_ERR "SRP abort called\n"); | 1340 | printk(KERN_ERR "SRP abort called\n"); |
1339 | 1341 | ||
1342 | if (target->qp_in_error) | ||
1343 | return FAILED; | ||
1340 | if (srp_find_req(target, scmnd, &req)) | 1344 | if (srp_find_req(target, scmnd, &req)) |
1341 | return FAILED; | 1345 | return FAILED; |
1342 | if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK)) | 1346 | if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK)) |
@@ -1365,6 +1369,8 @@ static int srp_reset_device(struct scsi_cmnd *scmnd) | |||
1365 | 1369 | ||
1366 | printk(KERN_ERR "SRP reset_device called\n"); | 1370 | printk(KERN_ERR "SRP reset_device called\n"); |
1367 | 1371 | ||
1372 | if (target->qp_in_error) | ||
1373 | return FAILED; | ||
1368 | if (srp_find_req(target, scmnd, &req)) | 1374 | if (srp_find_req(target, scmnd, &req)) |
1369 | return FAILED; | 1375 | return FAILED; |
1370 | if (srp_send_tsk_mgmt(target, req, SRP_TSK_LUN_RESET)) | 1376 | if (srp_send_tsk_mgmt(target, req, SRP_TSK_LUN_RESET)) |
@@ -1801,6 +1807,7 @@ static ssize_t srp_create_target(struct class_device *class_dev, | |||
1801 | goto err_free; | 1807 | goto err_free; |
1802 | } | 1808 | } |
1803 | 1809 | ||
1810 | target->qp_in_error = 0; | ||
1804 | ret = srp_connect_target(target); | 1811 | ret = srp_connect_target(target); |
1805 | if (ret) { | 1812 | if (ret) { |
1806 | printk(KERN_ERR PFX "Connection failed\n"); | 1813 | printk(KERN_ERR PFX "Connection failed\n"); |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h index c21772317b86..2f3319c719a5 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.h +++ b/drivers/infiniband/ulp/srp/ib_srp.h | |||
@@ -158,6 +158,7 @@ struct srp_target_port { | |||
158 | struct completion done; | 158 | struct completion done; |
159 | int status; | 159 | int status; |
160 | enum srp_target_state state; | 160 | enum srp_target_state state; |
161 | int qp_in_error; | ||
161 | }; | 162 | }; |
162 | 163 | ||
163 | struct srp_iu { | 164 | struct srp_iu { |
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index 2ab7add78f94..e21e490fedb0 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c | |||
@@ -11,66 +11,25 @@ | |||
11 | 11 | ||
12 | #include <linux/tifm.h> | 12 | #include <linux/tifm.h> |
13 | #include <linux/dma-mapping.h> | 13 | #include <linux/dma-mapping.h> |
14 | #include <linux/freezer.h> | ||
14 | 15 | ||
15 | #define DRIVER_NAME "tifm_7xx1" | 16 | #define DRIVER_NAME "tifm_7xx1" |
16 | #define DRIVER_VERSION "0.6" | 17 | #define DRIVER_VERSION "0.7" |
17 | 18 | ||
18 | static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) | 19 | static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) |
19 | { | 20 | { |
20 | int cnt; | ||
21 | unsigned long flags; | ||
22 | |||
23 | spin_lock_irqsave(&fm->lock, flags); | ||
24 | if (!fm->inhibit_new_cards) { | ||
25 | for (cnt = 0; cnt < fm->max_sockets; cnt++) { | ||
26 | if (fm->sockets[cnt] == sock) { | ||
27 | fm->remove_mask |= (1 << cnt); | ||
28 | queue_work(fm->wq, &fm->media_remover); | ||
29 | break; | ||
30 | } | ||
31 | } | ||
32 | } | ||
33 | spin_unlock_irqrestore(&fm->lock, flags); | ||
34 | } | ||
35 | |||
36 | static void tifm_7xx1_remove_media(struct work_struct *work) | ||
37 | { | ||
38 | struct tifm_adapter *fm = | ||
39 | container_of(work, struct tifm_adapter, media_remover); | ||
40 | unsigned long flags; | 21 | unsigned long flags; |
41 | int cnt; | ||
42 | struct tifm_dev *sock; | ||
43 | 22 | ||
44 | if (!class_device_get(&fm->cdev)) | ||
45 | return; | ||
46 | spin_lock_irqsave(&fm->lock, flags); | 23 | spin_lock_irqsave(&fm->lock, flags); |
47 | for (cnt = 0; cnt < fm->max_sockets; cnt++) { | 24 | fm->socket_change_set |= 1 << sock->socket_id; |
48 | if (fm->sockets[cnt] && (fm->remove_mask & (1 << cnt))) { | 25 | wake_up_all(&fm->change_set_notify); |
49 | printk(KERN_INFO DRIVER_NAME | ||
50 | ": demand removing card from socket %d\n", cnt); | ||
51 | sock = fm->sockets[cnt]; | ||
52 | fm->sockets[cnt] = NULL; | ||
53 | fm->remove_mask &= ~(1 << cnt); | ||
54 | |||
55 | writel(0x0e00, sock->addr + SOCK_CONTROL); | ||
56 | |||
57 | writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt, | ||
58 | fm->addr + FM_CLEAR_INTERRUPT_ENABLE); | ||
59 | writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt, | ||
60 | fm->addr + FM_SET_INTERRUPT_ENABLE); | ||
61 | |||
62 | spin_unlock_irqrestore(&fm->lock, flags); | ||
63 | device_unregister(&sock->dev); | ||
64 | spin_lock_irqsave(&fm->lock, flags); | ||
65 | } | ||
66 | } | ||
67 | spin_unlock_irqrestore(&fm->lock, flags); | 26 | spin_unlock_irqrestore(&fm->lock, flags); |
68 | class_device_put(&fm->cdev); | ||
69 | } | 27 | } |
70 | 28 | ||
71 | static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id) | 29 | static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id) |
72 | { | 30 | { |
73 | struct tifm_adapter *fm = dev_id; | 31 | struct tifm_adapter *fm = dev_id; |
32 | struct tifm_dev *sock; | ||
74 | unsigned int irq_status; | 33 | unsigned int irq_status; |
75 | unsigned int sock_irq_status, cnt; | 34 | unsigned int sock_irq_status, cnt; |
76 | 35 | ||
@@ -84,42 +43,32 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id) | |||
84 | if (irq_status & TIFM_IRQ_ENABLE) { | 43 | if (irq_status & TIFM_IRQ_ENABLE) { |
85 | writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); | 44 | writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); |
86 | 45 | ||
87 | for (cnt = 0; cnt < fm->max_sockets; cnt++) { | 46 | for (cnt = 0; cnt < fm->num_sockets; cnt++) { |
88 | sock_irq_status = (irq_status >> cnt) & | 47 | sock = fm->sockets[cnt]; |
89 | (TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK); | 48 | sock_irq_status = (irq_status >> cnt) |
90 | 49 | & (TIFM_IRQ_FIFOMASK(1) | |
91 | if (fm->sockets[cnt]) { | 50 | | TIFM_IRQ_CARDMASK(1)); |
92 | if (sock_irq_status && | ||
93 | fm->sockets[cnt]->signal_irq) | ||
94 | sock_irq_status = fm->sockets[cnt]-> | ||
95 | signal_irq(fm->sockets[cnt], | ||
96 | sock_irq_status); | ||
97 | 51 | ||
98 | if (irq_status & (1 << cnt)) | 52 | if (sock && sock_irq_status) |
99 | fm->remove_mask |= 1 << cnt; | 53 | sock->signal_irq(sock, sock_irq_status); |
100 | } else { | ||
101 | if (irq_status & (1 << cnt)) | ||
102 | fm->insert_mask |= 1 << cnt; | ||
103 | } | ||
104 | } | 54 | } |
55 | |||
56 | fm->socket_change_set |= irq_status | ||
57 | & ((1 << fm->num_sockets) - 1); | ||
105 | } | 58 | } |
106 | writel(irq_status, fm->addr + FM_INTERRUPT_STATUS); | 59 | writel(irq_status, fm->addr + FM_INTERRUPT_STATUS); |
107 | 60 | ||
108 | if (!fm->inhibit_new_cards) { | 61 | if (!fm->socket_change_set) |
109 | if (!fm->remove_mask && !fm->insert_mask) { | 62 | writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE); |
110 | writel(TIFM_IRQ_ENABLE, | 63 | else |
111 | fm->addr + FM_SET_INTERRUPT_ENABLE); | 64 | wake_up_all(&fm->change_set_notify); |
112 | } else { | ||
113 | queue_work(fm->wq, &fm->media_remover); | ||
114 | queue_work(fm->wq, &fm->media_inserter); | ||
115 | } | ||
116 | } | ||
117 | 65 | ||
118 | spin_unlock(&fm->lock); | 66 | spin_unlock(&fm->lock); |
119 | return IRQ_HANDLED; | 67 | return IRQ_HANDLED; |
120 | } | 68 | } |
121 | 69 | ||
122 | static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, int is_x2) | 70 | static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, |
71 | int is_x2) | ||
123 | { | 72 | { |
124 | unsigned int s_state; | 73 | unsigned int s_state; |
125 | int cnt; | 74 | int cnt; |
@@ -127,8 +76,8 @@ static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, int is | |||
127 | writel(0x0e00, sock_addr + SOCK_CONTROL); | 76 | writel(0x0e00, sock_addr + SOCK_CONTROL); |
128 | 77 | ||
129 | for (cnt = 0; cnt < 100; cnt++) { | 78 | for (cnt = 0; cnt < 100; cnt++) { |
130 | if (!(TIFM_SOCK_STATE_POWERED & | 79 | if (!(TIFM_SOCK_STATE_POWERED |
131 | readl(sock_addr + SOCK_PRESENT_STATE))) | 80 | & readl(sock_addr + SOCK_PRESENT_STATE))) |
132 | break; | 81 | break; |
133 | msleep(10); | 82 | msleep(10); |
134 | } | 83 | } |
@@ -151,8 +100,8 @@ static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, int is | |||
151 | } | 100 | } |
152 | 101 | ||
153 | for (cnt = 0; cnt < 100; cnt++) { | 102 | for (cnt = 0; cnt < 100; cnt++) { |
154 | if ((TIFM_SOCK_STATE_POWERED & | 103 | if ((TIFM_SOCK_STATE_POWERED |
155 | readl(sock_addr + SOCK_PRESENT_STATE))) | 104 | & readl(sock_addr + SOCK_PRESENT_STATE))) |
156 | break; | 105 | break; |
157 | msleep(10); | 106 | msleep(10); |
158 | } | 107 | } |
@@ -170,130 +119,209 @@ tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num) | |||
170 | return base_addr + ((sock_num + 1) << 10); | 119 | return base_addr + ((sock_num + 1) << 10); |
171 | } | 120 | } |
172 | 121 | ||
173 | static void tifm_7xx1_insert_media(struct work_struct *work) | 122 | static int tifm_7xx1_switch_media(void *data) |
174 | { | 123 | { |
175 | struct tifm_adapter *fm = | 124 | struct tifm_adapter *fm = data; |
176 | container_of(work, struct tifm_adapter, media_inserter); | ||
177 | unsigned long flags; | 125 | unsigned long flags; |
178 | tifm_media_id media_id; | 126 | tifm_media_id media_id; |
179 | char *card_name = "xx"; | 127 | char *card_name = "xx"; |
180 | int cnt, ok_to_register; | 128 | int cnt, rc; |
181 | unsigned int insert_mask; | 129 | struct tifm_dev *sock; |
182 | struct tifm_dev *new_sock = NULL; | 130 | unsigned int socket_change_set; |
183 | 131 | ||
184 | if (!class_device_get(&fm->cdev)) | 132 | while (1) { |
185 | return; | 133 | rc = wait_event_interruptible(fm->change_set_notify, |
186 | spin_lock_irqsave(&fm->lock, flags); | 134 | fm->socket_change_set); |
187 | insert_mask = fm->insert_mask; | 135 | if (rc == -ERESTARTSYS) |
188 | fm->insert_mask = 0; | 136 | try_to_freeze(); |
189 | if (fm->inhibit_new_cards) { | 137 | |
138 | spin_lock_irqsave(&fm->lock, flags); | ||
139 | socket_change_set = fm->socket_change_set; | ||
140 | fm->socket_change_set = 0; | ||
141 | |||
142 | dev_dbg(fm->dev, "checking media set %x\n", | ||
143 | socket_change_set); | ||
144 | |||
145 | if (kthread_should_stop()) | ||
146 | socket_change_set = (1 << fm->num_sockets) - 1; | ||
190 | spin_unlock_irqrestore(&fm->lock, flags); | 147 | spin_unlock_irqrestore(&fm->lock, flags); |
191 | class_device_put(&fm->cdev); | ||
192 | return; | ||
193 | } | ||
194 | spin_unlock_irqrestore(&fm->lock, flags); | ||
195 | 148 | ||
196 | for (cnt = 0; cnt < fm->max_sockets; cnt++) { | 149 | if (!socket_change_set) |
197 | if (!(insert_mask & (1 << cnt))) | ||
198 | continue; | 150 | continue; |
199 | 151 | ||
200 | media_id = tifm_7xx1_toggle_sock_power(tifm_7xx1_sock_addr(fm->addr, cnt), | 152 | spin_lock_irqsave(&fm->lock, flags); |
201 | fm->max_sockets == 2); | 153 | for (cnt = 0; cnt < fm->num_sockets; cnt++) { |
202 | if (media_id) { | 154 | if (!(socket_change_set & (1 << cnt))) |
203 | ok_to_register = 0; | 155 | continue; |
204 | new_sock = tifm_alloc_device(fm, cnt); | 156 | sock = fm->sockets[cnt]; |
205 | if (new_sock) { | 157 | if (sock) { |
206 | new_sock->addr = tifm_7xx1_sock_addr(fm->addr, | ||
207 | cnt); | ||
208 | new_sock->media_id = media_id; | ||
209 | switch (media_id) { | ||
210 | case 1: | ||
211 | card_name = "xd"; | ||
212 | break; | ||
213 | case 2: | ||
214 | card_name = "ms"; | ||
215 | break; | ||
216 | case 3: | ||
217 | card_name = "sd"; | ||
218 | break; | ||
219 | default: | ||
220 | break; | ||
221 | } | ||
222 | snprintf(new_sock->dev.bus_id, BUS_ID_SIZE, | ||
223 | "tifm_%s%u:%u", card_name, fm->id, cnt); | ||
224 | printk(KERN_INFO DRIVER_NAME | 158 | printk(KERN_INFO DRIVER_NAME |
225 | ": %s card detected in socket %d\n", | 159 | ": demand removing card from socket %d\n", |
226 | card_name, cnt); | 160 | cnt); |
161 | fm->sockets[cnt] = NULL; | ||
162 | spin_unlock_irqrestore(&fm->lock, flags); | ||
163 | device_unregister(&sock->dev); | ||
227 | spin_lock_irqsave(&fm->lock, flags); | 164 | spin_lock_irqsave(&fm->lock, flags); |
228 | if (!fm->sockets[cnt]) { | 165 | writel(0x0e00, |
229 | fm->sockets[cnt] = new_sock; | 166 | tifm_7xx1_sock_addr(fm->addr, cnt) |
230 | ok_to_register = 1; | 167 | + SOCK_CONTROL); |
168 | } | ||
169 | if (kthread_should_stop()) | ||
170 | continue; | ||
171 | |||
172 | spin_unlock_irqrestore(&fm->lock, flags); | ||
173 | media_id = tifm_7xx1_toggle_sock_power( | ||
174 | tifm_7xx1_sock_addr(fm->addr, cnt), | ||
175 | fm->num_sockets == 2); | ||
176 | if (media_id) { | ||
177 | sock = tifm_alloc_device(fm); | ||
178 | if (sock) { | ||
179 | sock->addr = tifm_7xx1_sock_addr(fm->addr, | ||
180 | cnt); | ||
181 | sock->media_id = media_id; | ||
182 | sock->socket_id = cnt; | ||
183 | switch (media_id) { | ||
184 | case 1: | ||
185 | card_name = "xd"; | ||
186 | break; | ||
187 | case 2: | ||
188 | card_name = "ms"; | ||
189 | break; | ||
190 | case 3: | ||
191 | card_name = "sd"; | ||
192 | break; | ||
193 | default: | ||
194 | tifm_free_device(&sock->dev); | ||
195 | spin_lock_irqsave(&fm->lock, flags); | ||
196 | continue; | ||
197 | } | ||
198 | snprintf(sock->dev.bus_id, BUS_ID_SIZE, | ||
199 | "tifm_%s%u:%u", card_name, | ||
200 | fm->id, cnt); | ||
201 | printk(KERN_INFO DRIVER_NAME | ||
202 | ": %s card detected in socket %d\n", | ||
203 | card_name, cnt); | ||
204 | if (!device_register(&sock->dev)) { | ||
205 | spin_lock_irqsave(&fm->lock, flags); | ||
206 | if (!fm->sockets[cnt]) { | ||
207 | fm->sockets[cnt] = sock; | ||
208 | sock = NULL; | ||
209 | } | ||
210 | spin_unlock_irqrestore(&fm->lock, flags); | ||
211 | } | ||
212 | if (sock) | ||
213 | tifm_free_device(&sock->dev); | ||
231 | } | 214 | } |
215 | spin_lock_irqsave(&fm->lock, flags); | ||
216 | } | ||
217 | } | ||
218 | |||
219 | if (!kthread_should_stop()) { | ||
220 | writel(TIFM_IRQ_FIFOMASK(socket_change_set) | ||
221 | | TIFM_IRQ_CARDMASK(socket_change_set), | ||
222 | fm->addr + FM_CLEAR_INTERRUPT_ENABLE); | ||
223 | writel(TIFM_IRQ_FIFOMASK(socket_change_set) | ||
224 | | TIFM_IRQ_CARDMASK(socket_change_set), | ||
225 | fm->addr + FM_SET_INTERRUPT_ENABLE); | ||
226 | writel(TIFM_IRQ_ENABLE, | ||
227 | fm->addr + FM_SET_INTERRUPT_ENABLE); | ||
228 | spin_unlock_irqrestore(&fm->lock, flags); | ||
229 | } else { | ||
230 | for (cnt = 0; cnt < fm->num_sockets; cnt++) { | ||
231 | if (fm->sockets[cnt]) | ||
232 | fm->socket_change_set |= 1 << cnt; | ||
233 | } | ||
234 | if (!fm->socket_change_set) { | ||
235 | spin_unlock_irqrestore(&fm->lock, flags); | ||
236 | return 0; | ||
237 | } else { | ||
232 | spin_unlock_irqrestore(&fm->lock, flags); | 238 | spin_unlock_irqrestore(&fm->lock, flags); |
233 | if (!ok_to_register || | ||
234 | device_register(&new_sock->dev)) { | ||
235 | spin_lock_irqsave(&fm->lock, flags); | ||
236 | fm->sockets[cnt] = NULL; | ||
237 | spin_unlock_irqrestore(&fm->lock, | ||
238 | flags); | ||
239 | tifm_free_device(&new_sock->dev); | ||
240 | } | ||
241 | } | 239 | } |
242 | } | 240 | } |
243 | writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt, | ||
244 | fm->addr + FM_CLEAR_INTERRUPT_ENABLE); | ||
245 | writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt, | ||
246 | fm->addr + FM_SET_INTERRUPT_ENABLE); | ||
247 | } | 241 | } |
248 | 242 | return 0; | |
249 | writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE); | ||
250 | class_device_put(&fm->cdev); | ||
251 | } | 243 | } |
252 | 244 | ||
245 | #ifdef CONFIG_PM | ||
246 | |||
253 | static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state) | 247 | static int tifm_7xx1_suspend(struct pci_dev *dev, pm_message_t state) |
254 | { | 248 | { |
255 | struct tifm_adapter *fm = pci_get_drvdata(dev); | 249 | dev_dbg(&dev->dev, "suspending host\n"); |
256 | unsigned long flags; | ||
257 | 250 | ||
258 | spin_lock_irqsave(&fm->lock, flags); | 251 | pci_save_state(dev); |
259 | fm->inhibit_new_cards = 1; | 252 | pci_enable_wake(dev, pci_choose_state(dev, state), 0); |
260 | fm->remove_mask = 0xf; | 253 | pci_disable_device(dev); |
261 | fm->insert_mask = 0; | 254 | pci_set_power_state(dev, pci_choose_state(dev, state)); |
262 | writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); | ||
263 | spin_unlock_irqrestore(&fm->lock, flags); | ||
264 | flush_workqueue(fm->wq); | ||
265 | |||
266 | tifm_7xx1_remove_media(&fm->media_remover); | ||
267 | |||
268 | pci_set_power_state(dev, PCI_D3hot); | ||
269 | pci_disable_device(dev); | ||
270 | pci_save_state(dev); | ||
271 | return 0; | 255 | return 0; |
272 | } | 256 | } |
273 | 257 | ||
274 | static int tifm_7xx1_resume(struct pci_dev *dev) | 258 | static int tifm_7xx1_resume(struct pci_dev *dev) |
275 | { | 259 | { |
276 | struct tifm_adapter *fm = pci_get_drvdata(dev); | 260 | struct tifm_adapter *fm = pci_get_drvdata(dev); |
261 | int cnt, rc; | ||
277 | unsigned long flags; | 262 | unsigned long flags; |
263 | tifm_media_id new_ids[fm->num_sockets]; | ||
278 | 264 | ||
265 | pci_set_power_state(dev, PCI_D0); | ||
279 | pci_restore_state(dev); | 266 | pci_restore_state(dev); |
280 | pci_enable_device(dev); | 267 | rc = pci_enable_device(dev); |
281 | pci_set_power_state(dev, PCI_D0); | 268 | if (rc) |
282 | pci_set_master(dev); | 269 | return rc; |
270 | pci_set_master(dev); | ||
283 | 271 | ||
272 | dev_dbg(&dev->dev, "resuming host\n"); | ||
273 | |||
274 | for (cnt = 0; cnt < fm->num_sockets; cnt++) | ||
275 | new_ids[cnt] = tifm_7xx1_toggle_sock_power( | ||
276 | tifm_7xx1_sock_addr(fm->addr, cnt), | ||
277 | fm->num_sockets == 2); | ||
284 | spin_lock_irqsave(&fm->lock, flags); | 278 | spin_lock_irqsave(&fm->lock, flags); |
285 | fm->inhibit_new_cards = 0; | 279 | fm->socket_change_set = 0; |
286 | writel(TIFM_IRQ_SETALL, fm->addr + FM_INTERRUPT_STATUS); | 280 | for (cnt = 0; cnt < fm->num_sockets; cnt++) { |
287 | writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); | 281 | if (fm->sockets[cnt]) { |
288 | writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SETALLSOCK, | 282 | if (fm->sockets[cnt]->media_id == new_ids[cnt]) |
289 | fm->addr + FM_SET_INTERRUPT_ENABLE); | 283 | fm->socket_change_set |= 1 << cnt; |
290 | fm->insert_mask = 0xf; | 284 | |
285 | fm->sockets[cnt]->media_id = new_ids[cnt]; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), | ||
290 | fm->addr + FM_SET_INTERRUPT_ENABLE); | ||
291 | if (!fm->socket_change_set) { | ||
292 | spin_unlock_irqrestore(&fm->lock, flags); | ||
293 | return 0; | ||
294 | } else { | ||
295 | fm->socket_change_set = 0; | ||
296 | spin_unlock_irqrestore(&fm->lock, flags); | ||
297 | } | ||
298 | |||
299 | wait_event_timeout(fm->change_set_notify, fm->socket_change_set, HZ); | ||
300 | |||
301 | spin_lock_irqsave(&fm->lock, flags); | ||
302 | writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set) | ||
303 | | TIFM_IRQ_CARDMASK(fm->socket_change_set), | ||
304 | fm->addr + FM_CLEAR_INTERRUPT_ENABLE); | ||
305 | writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set) | ||
306 | | TIFM_IRQ_CARDMASK(fm->socket_change_set), | ||
307 | fm->addr + FM_SET_INTERRUPT_ENABLE); | ||
308 | writel(TIFM_IRQ_ENABLE, | ||
309 | fm->addr + FM_SET_INTERRUPT_ENABLE); | ||
310 | fm->socket_change_set = 0; | ||
311 | |||
291 | spin_unlock_irqrestore(&fm->lock, flags); | 312 | spin_unlock_irqrestore(&fm->lock, flags); |
292 | return 0; | 313 | return 0; |
293 | } | 314 | } |
294 | 315 | ||
316 | #else | ||
317 | |||
318 | #define tifm_7xx1_suspend NULL | ||
319 | #define tifm_7xx1_resume NULL | ||
320 | |||
321 | #endif /* CONFIG_PM */ | ||
322 | |||
295 | static int tifm_7xx1_probe(struct pci_dev *dev, | 323 | static int tifm_7xx1_probe(struct pci_dev *dev, |
296 | const struct pci_device_id *dev_id) | 324 | const struct pci_device_id *dev_id) |
297 | { | 325 | { |
298 | struct tifm_adapter *fm; | 326 | struct tifm_adapter *fm; |
299 | int pci_dev_busy = 0; | 327 | int pci_dev_busy = 0; |
@@ -324,19 +352,18 @@ static int tifm_7xx1_probe(struct pci_dev *dev, | |||
324 | } | 352 | } |
325 | 353 | ||
326 | fm->dev = &dev->dev; | 354 | fm->dev = &dev->dev; |
327 | fm->max_sockets = (dev->device == 0x803B) ? 2 : 4; | 355 | fm->num_sockets = (dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM) |
328 | fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->max_sockets, | 356 | ? 4 : 2; |
329 | GFP_KERNEL); | 357 | fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->num_sockets, |
358 | GFP_KERNEL); | ||
330 | if (!fm->sockets) | 359 | if (!fm->sockets) |
331 | goto err_out_free; | 360 | goto err_out_free; |
332 | 361 | ||
333 | INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media); | ||
334 | INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media); | ||
335 | fm->eject = tifm_7xx1_eject; | 362 | fm->eject = tifm_7xx1_eject; |
336 | pci_set_drvdata(dev, fm); | 363 | pci_set_drvdata(dev, fm); |
337 | 364 | ||
338 | fm->addr = ioremap(pci_resource_start(dev, 0), | 365 | fm->addr = ioremap(pci_resource_start(dev, 0), |
339 | pci_resource_len(dev, 0)); | 366 | pci_resource_len(dev, 0)); |
340 | if (!fm->addr) | 367 | if (!fm->addr) |
341 | goto err_out_free; | 368 | goto err_out_free; |
342 | 369 | ||
@@ -344,16 +371,15 @@ static int tifm_7xx1_probe(struct pci_dev *dev, | |||
344 | if (rc) | 371 | if (rc) |
345 | goto err_out_unmap; | 372 | goto err_out_unmap; |
346 | 373 | ||
347 | rc = tifm_add_adapter(fm); | 374 | init_waitqueue_head(&fm->change_set_notify); |
375 | rc = tifm_add_adapter(fm, tifm_7xx1_switch_media); | ||
348 | if (rc) | 376 | if (rc) |
349 | goto err_out_irq; | 377 | goto err_out_irq; |
350 | 378 | ||
351 | writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); | 379 | writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); |
352 | writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SETALLSOCK, | 380 | writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), |
353 | fm->addr + FM_SET_INTERRUPT_ENABLE); | 381 | fm->addr + FM_SET_INTERRUPT_ENABLE); |
354 | 382 | wake_up_process(fm->media_switcher); | |
355 | fm->insert_mask = 0xf; | ||
356 | |||
357 | return 0; | 383 | return 0; |
358 | 384 | ||
359 | err_out_irq: | 385 | err_out_irq: |
@@ -377,19 +403,15 @@ static void tifm_7xx1_remove(struct pci_dev *dev) | |||
377 | struct tifm_adapter *fm = pci_get_drvdata(dev); | 403 | struct tifm_adapter *fm = pci_get_drvdata(dev); |
378 | unsigned long flags; | 404 | unsigned long flags; |
379 | 405 | ||
406 | writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); | ||
407 | mmiowb(); | ||
408 | free_irq(dev->irq, fm); | ||
409 | |||
380 | spin_lock_irqsave(&fm->lock, flags); | 410 | spin_lock_irqsave(&fm->lock, flags); |
381 | fm->inhibit_new_cards = 1; | 411 | fm->socket_change_set = (1 << fm->num_sockets) - 1; |
382 | fm->remove_mask = 0xf; | ||
383 | fm->insert_mask = 0; | ||
384 | writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); | ||
385 | spin_unlock_irqrestore(&fm->lock, flags); | 412 | spin_unlock_irqrestore(&fm->lock, flags); |
386 | 413 | ||
387 | flush_workqueue(fm->wq); | 414 | kthread_stop(fm->media_switcher); |
388 | |||
389 | tifm_7xx1_remove_media(&fm->media_remover); | ||
390 | |||
391 | writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); | ||
392 | free_irq(dev->irq, fm); | ||
393 | 415 | ||
394 | tifm_remove_adapter(fm); | 416 | tifm_remove_adapter(fm); |
395 | 417 | ||
@@ -404,10 +426,12 @@ static void tifm_7xx1_remove(struct pci_dev *dev) | |||
404 | } | 426 | } |
405 | 427 | ||
406 | static struct pci_device_id tifm_7xx1_pci_tbl [] = { | 428 | static struct pci_device_id tifm_7xx1_pci_tbl [] = { |
407 | { PCI_VENDOR_ID_TI, 0x8033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 429 | { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11_FM, PCI_ANY_ID, |
408 | 0 }, /* xx21 - the one I have */ | 430 | PCI_ANY_ID, 0, 0, 0 }, /* xx21 - the one I have */ |
409 | { PCI_VENDOR_ID_TI, 0x803B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 431 | { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX12_FM, PCI_ANY_ID, |
410 | 0 }, /* xx12 - should be also supported */ | 432 | PCI_ANY_ID, 0, 0, 0 }, |
433 | { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX20_FM, PCI_ANY_ID, | ||
434 | PCI_ANY_ID, 0, 0, 0 }, | ||
411 | { } | 435 | { } |
412 | }; | 436 | }; |
413 | 437 | ||
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index d61df5c3ac36..6b10ebe9d936 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/idr.h> | 14 | #include <linux/idr.h> |
15 | 15 | ||
16 | #define DRIVER_NAME "tifm_core" | 16 | #define DRIVER_NAME "tifm_core" |
17 | #define DRIVER_VERSION "0.6" | 17 | #define DRIVER_VERSION "0.7" |
18 | 18 | ||
19 | static DEFINE_IDR(tifm_adapter_idr); | 19 | static DEFINE_IDR(tifm_adapter_idr); |
20 | static DEFINE_SPINLOCK(tifm_adapter_lock); | 20 | static DEFINE_SPINLOCK(tifm_adapter_lock); |
@@ -60,10 +60,41 @@ static int tifm_uevent(struct device *dev, char **envp, int num_envp, | |||
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | #ifdef CONFIG_PM | ||
64 | |||
65 | static int tifm_device_suspend(struct device *dev, pm_message_t state) | ||
66 | { | ||
67 | struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); | ||
68 | struct tifm_driver *drv = fm_dev->drv; | ||
69 | |||
70 | if (drv && drv->suspend) | ||
71 | return drv->suspend(fm_dev, state); | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static int tifm_device_resume(struct device *dev) | ||
76 | { | ||
77 | struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); | ||
78 | struct tifm_driver *drv = fm_dev->drv; | ||
79 | |||
80 | if (drv && drv->resume) | ||
81 | return drv->resume(fm_dev); | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | #else | ||
86 | |||
87 | #define tifm_device_suspend NULL | ||
88 | #define tifm_device_resume NULL | ||
89 | |||
90 | #endif /* CONFIG_PM */ | ||
91 | |||
63 | static struct bus_type tifm_bus_type = { | 92 | static struct bus_type tifm_bus_type = { |
64 | .name = "tifm", | 93 | .name = "tifm", |
65 | .match = tifm_match, | 94 | .match = tifm_match, |
66 | .uevent = tifm_uevent, | 95 | .uevent = tifm_uevent, |
96 | .suspend = tifm_device_suspend, | ||
97 | .resume = tifm_device_resume | ||
67 | }; | 98 | }; |
68 | 99 | ||
69 | static void tifm_free(struct class_device *cdev) | 100 | static void tifm_free(struct class_device *cdev) |
@@ -71,8 +102,6 @@ static void tifm_free(struct class_device *cdev) | |||
71 | struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev); | 102 | struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev); |
72 | 103 | ||
73 | kfree(fm->sockets); | 104 | kfree(fm->sockets); |
74 | if (fm->wq) | ||
75 | destroy_workqueue(fm->wq); | ||
76 | kfree(fm); | 105 | kfree(fm); |
77 | } | 106 | } |
78 | 107 | ||
@@ -101,7 +130,8 @@ void tifm_free_adapter(struct tifm_adapter *fm) | |||
101 | } | 130 | } |
102 | EXPORT_SYMBOL(tifm_free_adapter); | 131 | EXPORT_SYMBOL(tifm_free_adapter); |
103 | 132 | ||
104 | int tifm_add_adapter(struct tifm_adapter *fm) | 133 | int tifm_add_adapter(struct tifm_adapter *fm, |
134 | int (*mediathreadfn)(void *data)) | ||
105 | { | 135 | { |
106 | int rc; | 136 | int rc; |
107 | 137 | ||
@@ -113,10 +143,10 @@ int tifm_add_adapter(struct tifm_adapter *fm) | |||
113 | spin_unlock(&tifm_adapter_lock); | 143 | spin_unlock(&tifm_adapter_lock); |
114 | if (!rc) { | 144 | if (!rc) { |
115 | snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id); | 145 | snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id); |
116 | strncpy(fm->wq_name, fm->cdev.class_id, KOBJ_NAME_LEN); | 146 | fm->media_switcher = kthread_create(mediathreadfn, |
147 | fm, "tifm/%u", fm->id); | ||
117 | 148 | ||
118 | fm->wq = create_singlethread_workqueue(fm->wq_name); | 149 | if (!IS_ERR(fm->media_switcher)) |
119 | if (fm->wq) | ||
120 | return class_device_add(&fm->cdev); | 150 | return class_device_add(&fm->cdev); |
121 | 151 | ||
122 | spin_lock(&tifm_adapter_lock); | 152 | spin_lock(&tifm_adapter_lock); |
@@ -141,27 +171,27 @@ EXPORT_SYMBOL(tifm_remove_adapter); | |||
141 | void tifm_free_device(struct device *dev) | 171 | void tifm_free_device(struct device *dev) |
142 | { | 172 | { |
143 | struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); | 173 | struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); |
144 | if (fm_dev->wq) | ||
145 | destroy_workqueue(fm_dev->wq); | ||
146 | kfree(fm_dev); | 174 | kfree(fm_dev); |
147 | } | 175 | } |
148 | EXPORT_SYMBOL(tifm_free_device); | 176 | EXPORT_SYMBOL(tifm_free_device); |
149 | 177 | ||
150 | struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id) | 178 | static void tifm_dummy_signal_irq(struct tifm_dev *sock, |
179 | unsigned int sock_irq_status) | ||
180 | { | ||
181 | return; | ||
182 | } | ||
183 | |||
184 | struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm) | ||
151 | { | 185 | { |
152 | struct tifm_dev *dev = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL); | 186 | struct tifm_dev *dev = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL); |
153 | 187 | ||
154 | if (dev) { | 188 | if (dev) { |
155 | spin_lock_init(&dev->lock); | 189 | spin_lock_init(&dev->lock); |
156 | snprintf(dev->wq_name, KOBJ_NAME_LEN, "tifm%u:%u", fm->id, id); | 190 | |
157 | dev->wq = create_singlethread_workqueue(dev->wq_name); | ||
158 | if (!dev->wq) { | ||
159 | kfree(dev); | ||
160 | return NULL; | ||
161 | } | ||
162 | dev->dev.parent = fm->dev; | 191 | dev->dev.parent = fm->dev; |
163 | dev->dev.bus = &tifm_bus_type; | 192 | dev->dev.bus = &tifm_bus_type; |
164 | dev->dev.release = tifm_free_device; | 193 | dev->dev.release = tifm_free_device; |
194 | dev->signal_irq = tifm_dummy_signal_irq; | ||
165 | } | 195 | } |
166 | return dev; | 196 | return dev; |
167 | } | 197 | } |
@@ -219,6 +249,7 @@ static int tifm_device_remove(struct device *dev) | |||
219 | struct tifm_driver *drv = fm_dev->drv; | 249 | struct tifm_driver *drv = fm_dev->drv; |
220 | 250 | ||
221 | if (drv) { | 251 | if (drv) { |
252 | fm_dev->signal_irq = tifm_dummy_signal_irq; | ||
222 | if (drv->remove) | 253 | if (drv->remove) |
223 | drv->remove(fm_dev); | 254 | drv->remove(fm_dev); |
224 | fm_dev->drv = NULL; | 255 | fm_dev->drv = NULL; |
@@ -233,6 +264,8 @@ int tifm_register_driver(struct tifm_driver *drv) | |||
233 | drv->driver.bus = &tifm_bus_type; | 264 | drv->driver.bus = &tifm_bus_type; |
234 | drv->driver.probe = tifm_device_probe; | 265 | drv->driver.probe = tifm_device_probe; |
235 | drv->driver.remove = tifm_device_remove; | 266 | drv->driver.remove = tifm_device_remove; |
267 | drv->driver.suspend = tifm_device_suspend; | ||
268 | drv->driver.resume = tifm_device_resume; | ||
236 | 269 | ||
237 | return driver_register(&drv->driver); | 270 | return driver_register(&drv->driver); |
238 | } | 271 | } |
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c index aa152f31851e..2ce50f38e3c7 100644 --- a/drivers/mmc/at91_mci.c +++ b/drivers/mmc/at91_mci.c | |||
@@ -823,6 +823,9 @@ static int __init at91_mci_probe(struct platform_device *pdev) | |||
823 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 823 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
824 | mmc->caps = MMC_CAP_BYTEBLOCK; | 824 | mmc->caps = MMC_CAP_BYTEBLOCK; |
825 | 825 | ||
826 | mmc->max_blk_size = 4095; | ||
827 | mmc->max_blk_count = mmc->max_req_size; | ||
828 | |||
826 | host = mmc_priv(mmc); | 829 | host = mmc_priv(mmc); |
827 | host->mmc = mmc; | 830 | host->mmc = mmc; |
828 | host->buffer = NULL; | 831 | host->buffer = NULL; |
diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c index 800527cf40d5..b834be261ab7 100644 --- a/drivers/mmc/au1xmmc.c +++ b/drivers/mmc/au1xmmc.c | |||
@@ -152,8 +152,9 @@ static inline int au1xmmc_card_inserted(struct au1xmmc_host *host) | |||
152 | ? 1 : 0; | 152 | ? 1 : 0; |
153 | } | 153 | } |
154 | 154 | ||
155 | static inline int au1xmmc_card_readonly(struct au1xmmc_host *host) | 155 | static int au1xmmc_card_readonly(struct mmc_host *mmc) |
156 | { | 156 | { |
157 | struct au1xmmc_host *host = mmc_priv(mmc); | ||
157 | return (bcsr->status & au1xmmc_card_table[host->id].wpstatus) | 158 | return (bcsr->status & au1xmmc_card_table[host->id].wpstatus) |
158 | ? 1 : 0; | 159 | ? 1 : 0; |
159 | } | 160 | } |
@@ -193,6 +194,8 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, | |||
193 | u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT); | 194 | u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT); |
194 | 195 | ||
195 | switch (mmc_resp_type(cmd)) { | 196 | switch (mmc_resp_type(cmd)) { |
197 | case MMC_RSP_NONE: | ||
198 | break; | ||
196 | case MMC_RSP_R1: | 199 | case MMC_RSP_R1: |
197 | mmccmd |= SD_CMD_RT_1; | 200 | mmccmd |= SD_CMD_RT_1; |
198 | break; | 201 | break; |
@@ -205,6 +208,10 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, | |||
205 | case MMC_RSP_R3: | 208 | case MMC_RSP_R3: |
206 | mmccmd |= SD_CMD_RT_3; | 209 | mmccmd |= SD_CMD_RT_3; |
207 | break; | 210 | break; |
211 | default: | ||
212 | printk(KERN_INFO "au1xmmc: unhandled response type %02x\n", | ||
213 | mmc_resp_type(cmd)); | ||
214 | return MMC_ERR_INVALID; | ||
208 | } | 215 | } |
209 | 216 | ||
210 | switch(cmd->opcode) { | 217 | switch(cmd->opcode) { |
@@ -878,6 +885,7 @@ static void au1xmmc_init_dma(struct au1xmmc_host *host) | |||
878 | static const struct mmc_host_ops au1xmmc_ops = { | 885 | static const struct mmc_host_ops au1xmmc_ops = { |
879 | .request = au1xmmc_request, | 886 | .request = au1xmmc_request, |
880 | .set_ios = au1xmmc_set_ios, | 887 | .set_ios = au1xmmc_set_ios, |
888 | .get_ro = au1xmmc_card_readonly, | ||
881 | }; | 889 | }; |
882 | 890 | ||
883 | static int __devinit au1xmmc_probe(struct platform_device *pdev) | 891 | static int __devinit au1xmmc_probe(struct platform_device *pdev) |
@@ -914,6 +922,9 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev) | |||
914 | mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE; | 922 | mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE; |
915 | mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT; | 923 | mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT; |
916 | 924 | ||
925 | mmc->max_blk_size = 2048; | ||
926 | mmc->max_blk_count = 512; | ||
927 | |||
917 | mmc->ocr_avail = AU1XMMC_OCR; | 928 | mmc->ocr_avail = AU1XMMC_OCR; |
918 | 929 | ||
919 | host = mmc_priv(mmc); | 930 | host = mmc_priv(mmc); |
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c index bfb9ff693208..b060d4bfba29 100644 --- a/drivers/mmc/imxmmc.c +++ b/drivers/mmc/imxmmc.c | |||
@@ -958,8 +958,10 @@ static int imxmci_probe(struct platform_device *pdev) | |||
958 | /* MMC core transfer sizes tunable parameters */ | 958 | /* MMC core transfer sizes tunable parameters */ |
959 | mmc->max_hw_segs = 64; | 959 | mmc->max_hw_segs = 64; |
960 | mmc->max_phys_segs = 64; | 960 | mmc->max_phys_segs = 64; |
961 | mmc->max_sectors = 64; /* default 1 << (PAGE_CACHE_SHIFT - 9) */ | ||
962 | mmc->max_seg_size = 64*512; /* default PAGE_CACHE_SIZE */ | 961 | mmc->max_seg_size = 64*512; /* default PAGE_CACHE_SIZE */ |
962 | mmc->max_req_size = 64*512; /* default PAGE_CACHE_SIZE */ | ||
963 | mmc->max_blk_size = 2048; | ||
964 | mmc->max_blk_count = 65535; | ||
963 | 965 | ||
964 | host = mmc_priv(mmc); | 966 | host = mmc_priv(mmc); |
965 | host->mmc = mmc; | 967 | host->mmc = mmc; |
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 6f2a282e2b97..5046a1661342 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c | |||
@@ -103,11 +103,16 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) | |||
103 | mmc_hostname(host), mrq->cmd->opcode, | 103 | mmc_hostname(host), mrq->cmd->opcode, |
104 | mrq->cmd->arg, mrq->cmd->flags); | 104 | mrq->cmd->arg, mrq->cmd->flags); |
105 | 105 | ||
106 | WARN_ON(host->card_busy == NULL); | 106 | WARN_ON(!host->claimed); |
107 | 107 | ||
108 | mrq->cmd->error = 0; | 108 | mrq->cmd->error = 0; |
109 | mrq->cmd->mrq = mrq; | 109 | mrq->cmd->mrq = mrq; |
110 | if (mrq->data) { | 110 | if (mrq->data) { |
111 | BUG_ON(mrq->data->blksz > host->max_blk_size); | ||
112 | BUG_ON(mrq->data->blocks > host->max_blk_count); | ||
113 | BUG_ON(mrq->data->blocks * mrq->data->blksz > | ||
114 | host->max_req_size); | ||
115 | |||
111 | mrq->cmd->data = mrq->data; | 116 | mrq->cmd->data = mrq->data; |
112 | mrq->data->error = 0; | 117 | mrq->data->error = 0; |
113 | mrq->data->mrq = mrq; | 118 | mrq->data->mrq = mrq; |
@@ -157,7 +162,7 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries | |||
157 | { | 162 | { |
158 | struct mmc_request mrq; | 163 | struct mmc_request mrq; |
159 | 164 | ||
160 | BUG_ON(host->card_busy == NULL); | 165 | BUG_ON(!host->claimed); |
161 | 166 | ||
162 | memset(&mrq, 0, sizeof(struct mmc_request)); | 167 | memset(&mrq, 0, sizeof(struct mmc_request)); |
163 | 168 | ||
@@ -195,7 +200,7 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca, | |||
195 | 200 | ||
196 | int i, err; | 201 | int i, err; |
197 | 202 | ||
198 | BUG_ON(host->card_busy == NULL); | 203 | BUG_ON(!host->claimed); |
199 | BUG_ON(retries < 0); | 204 | BUG_ON(retries < 0); |
200 | 205 | ||
201 | err = MMC_ERR_INVALID; | 206 | err = MMC_ERR_INVALID; |
@@ -289,7 +294,10 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card, | |||
289 | else | 294 | else |
290 | limit_us = 100000; | 295 | limit_us = 100000; |
291 | 296 | ||
292 | if (timeout_us > limit_us) { | 297 | /* |
298 | * SDHC cards always use these fixed values. | ||
299 | */ | ||
300 | if (timeout_us > limit_us || mmc_card_blockaddr(card)) { | ||
293 | data->timeout_ns = limit_us * 1000; | 301 | data->timeout_ns = limit_us * 1000; |
294 | data->timeout_clks = 0; | 302 | data->timeout_clks = 0; |
295 | } | 303 | } |
@@ -320,14 +328,14 @@ int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card) | |||
320 | spin_lock_irqsave(&host->lock, flags); | 328 | spin_lock_irqsave(&host->lock, flags); |
321 | while (1) { | 329 | while (1) { |
322 | set_current_state(TASK_UNINTERRUPTIBLE); | 330 | set_current_state(TASK_UNINTERRUPTIBLE); |
323 | if (host->card_busy == NULL) | 331 | if (!host->claimed) |
324 | break; | 332 | break; |
325 | spin_unlock_irqrestore(&host->lock, flags); | 333 | spin_unlock_irqrestore(&host->lock, flags); |
326 | schedule(); | 334 | schedule(); |
327 | spin_lock_irqsave(&host->lock, flags); | 335 | spin_lock_irqsave(&host->lock, flags); |
328 | } | 336 | } |
329 | set_current_state(TASK_RUNNING); | 337 | set_current_state(TASK_RUNNING); |
330 | host->card_busy = card; | 338 | host->claimed = 1; |
331 | spin_unlock_irqrestore(&host->lock, flags); | 339 | spin_unlock_irqrestore(&host->lock, flags); |
332 | remove_wait_queue(&host->wq, &wait); | 340 | remove_wait_queue(&host->wq, &wait); |
333 | 341 | ||
@@ -353,10 +361,10 @@ void mmc_release_host(struct mmc_host *host) | |||
353 | { | 361 | { |
354 | unsigned long flags; | 362 | unsigned long flags; |
355 | 363 | ||
356 | BUG_ON(host->card_busy == NULL); | 364 | BUG_ON(!host->claimed); |
357 | 365 | ||
358 | spin_lock_irqsave(&host->lock, flags); | 366 | spin_lock_irqsave(&host->lock, flags); |
359 | host->card_busy = NULL; | 367 | host->claimed = 0; |
360 | spin_unlock_irqrestore(&host->lock, flags); | 368 | spin_unlock_irqrestore(&host->lock, flags); |
361 | 369 | ||
362 | wake_up(&host->wq); | 370 | wake_up(&host->wq); |
@@ -372,7 +380,7 @@ static inline void mmc_set_ios(struct mmc_host *host) | |||
372 | mmc_hostname(host), ios->clock, ios->bus_mode, | 380 | mmc_hostname(host), ios->clock, ios->bus_mode, |
373 | ios->power_mode, ios->chip_select, ios->vdd, | 381 | ios->power_mode, ios->chip_select, ios->vdd, |
374 | ios->bus_width); | 382 | ios->bus_width); |
375 | 383 | ||
376 | host->ops->set_ios(host, ios); | 384 | host->ops->set_ios(host, ios); |
377 | } | 385 | } |
378 | 386 | ||
@@ -381,7 +389,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card) | |||
381 | int err; | 389 | int err; |
382 | struct mmc_command cmd; | 390 | struct mmc_command cmd; |
383 | 391 | ||
384 | BUG_ON(host->card_busy == NULL); | 392 | BUG_ON(!host->claimed); |
385 | 393 | ||
386 | if (host->card_selected == card) | 394 | if (host->card_selected == card) |
387 | return MMC_ERR_NONE; | 395 | return MMC_ERR_NONE; |
@@ -588,34 +596,65 @@ static void mmc_decode_csd(struct mmc_card *card) | |||
588 | 596 | ||
589 | if (mmc_card_sd(card)) { | 597 | if (mmc_card_sd(card)) { |
590 | csd_struct = UNSTUFF_BITS(resp, 126, 2); | 598 | csd_struct = UNSTUFF_BITS(resp, 126, 2); |
591 | if (csd_struct != 0) { | 599 | |
600 | switch (csd_struct) { | ||
601 | case 0: | ||
602 | m = UNSTUFF_BITS(resp, 115, 4); | ||
603 | e = UNSTUFF_BITS(resp, 112, 3); | ||
604 | csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; | ||
605 | csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; | ||
606 | |||
607 | m = UNSTUFF_BITS(resp, 99, 4); | ||
608 | e = UNSTUFF_BITS(resp, 96, 3); | ||
609 | csd->max_dtr = tran_exp[e] * tran_mant[m]; | ||
610 | csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); | ||
611 | |||
612 | e = UNSTUFF_BITS(resp, 47, 3); | ||
613 | m = UNSTUFF_BITS(resp, 62, 12); | ||
614 | csd->capacity = (1 + m) << (e + 2); | ||
615 | |||
616 | csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); | ||
617 | csd->read_partial = UNSTUFF_BITS(resp, 79, 1); | ||
618 | csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); | ||
619 | csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); | ||
620 | csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); | ||
621 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); | ||
622 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); | ||
623 | break; | ||
624 | case 1: | ||
625 | /* | ||
626 | * This is a block-addressed SDHC card. Most | ||
627 | * interesting fields are unused and have fixed | ||
628 | * values. To avoid getting tripped by buggy cards, | ||
629 | * we assume those fixed values ourselves. | ||
630 | */ | ||
631 | mmc_card_set_blockaddr(card); | ||
632 | |||
633 | csd->tacc_ns = 0; /* Unused */ | ||
634 | csd->tacc_clks = 0; /* Unused */ | ||
635 | |||
636 | m = UNSTUFF_BITS(resp, 99, 4); | ||
637 | e = UNSTUFF_BITS(resp, 96, 3); | ||
638 | csd->max_dtr = tran_exp[e] * tran_mant[m]; | ||
639 | csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); | ||
640 | |||
641 | m = UNSTUFF_BITS(resp, 48, 22); | ||
642 | csd->capacity = (1 + m) << 10; | ||
643 | |||
644 | csd->read_blkbits = 9; | ||
645 | csd->read_partial = 0; | ||
646 | csd->write_misalign = 0; | ||
647 | csd->read_misalign = 0; | ||
648 | csd->r2w_factor = 4; /* Unused */ | ||
649 | csd->write_blkbits = 9; | ||
650 | csd->write_partial = 0; | ||
651 | break; | ||
652 | default: | ||
592 | printk("%s: unrecognised CSD structure version %d\n", | 653 | printk("%s: unrecognised CSD structure version %d\n", |
593 | mmc_hostname(card->host), csd_struct); | 654 | mmc_hostname(card->host), csd_struct); |
594 | mmc_card_set_bad(card); | 655 | mmc_card_set_bad(card); |
595 | return; | 656 | return; |
596 | } | 657 | } |
597 | |||
598 | m = UNSTUFF_BITS(resp, 115, 4); | ||
599 | e = UNSTUFF_BITS(resp, 112, 3); | ||
600 | csd->tacc_ns = (tacc_exp[e] * tacc_mant[m] + 9) / 10; | ||
601 | csd->tacc_clks = UNSTUFF_BITS(resp, 104, 8) * 100; | ||
602 | |||
603 | m = UNSTUFF_BITS(resp, 99, 4); | ||
604 | e = UNSTUFF_BITS(resp, 96, 3); | ||
605 | csd->max_dtr = tran_exp[e] * tran_mant[m]; | ||
606 | csd->cmdclass = UNSTUFF_BITS(resp, 84, 12); | ||
607 | |||
608 | e = UNSTUFF_BITS(resp, 47, 3); | ||
609 | m = UNSTUFF_BITS(resp, 62, 12); | ||
610 | csd->capacity = (1 + m) << (e + 2); | ||
611 | |||
612 | csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4); | ||
613 | csd->read_partial = UNSTUFF_BITS(resp, 79, 1); | ||
614 | csd->write_misalign = UNSTUFF_BITS(resp, 78, 1); | ||
615 | csd->read_misalign = UNSTUFF_BITS(resp, 77, 1); | ||
616 | csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3); | ||
617 | csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4); | ||
618 | csd->write_partial = UNSTUFF_BITS(resp, 21, 1); | ||
619 | } else { | 658 | } else { |
620 | /* | 659 | /* |
621 | * We only understand CSD structure v1.1 and v1.2. | 660 | * We only understand CSD structure v1.1 and v1.2. |
@@ -848,6 +887,41 @@ static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr) | |||
848 | return err; | 887 | return err; |
849 | } | 888 | } |
850 | 889 | ||
890 | static int mmc_send_if_cond(struct mmc_host *host, u32 ocr, int *rsd2) | ||
891 | { | ||
892 | struct mmc_command cmd; | ||
893 | int err, sd2; | ||
894 | static const u8 test_pattern = 0xAA; | ||
895 | |||
896 | /* | ||
897 | * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND | ||
898 | * before SD_APP_OP_COND. This command will harmlessly fail for | ||
899 | * SD 1.0 cards. | ||
900 | */ | ||
901 | cmd.opcode = SD_SEND_IF_COND; | ||
902 | cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern; | ||
903 | cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR; | ||
904 | |||
905 | err = mmc_wait_for_cmd(host, &cmd, 0); | ||
906 | if (err == MMC_ERR_NONE) { | ||
907 | if ((cmd.resp[0] & 0xFF) == test_pattern) { | ||
908 | sd2 = 1; | ||
909 | } else { | ||
910 | sd2 = 0; | ||
911 | err = MMC_ERR_FAILED; | ||
912 | } | ||
913 | } else { | ||
914 | /* | ||
915 | * Treat errors as SD 1.0 card. | ||
916 | */ | ||
917 | sd2 = 0; | ||
918 | err = MMC_ERR_NONE; | ||
919 | } | ||
920 | if (rsd2) | ||
921 | *rsd2 = sd2; | ||
922 | return err; | ||
923 | } | ||
924 | |||
851 | /* | 925 | /* |
852 | * Discover cards by requesting their CID. If this command | 926 | * Discover cards by requesting their CID. If this command |
853 | * times out, it is not an error; there are no further cards | 927 | * times out, it is not an error; there are no further cards |
@@ -1018,7 +1092,8 @@ static void mmc_process_ext_csds(struct mmc_host *host) | |||
1018 | mmc_wait_for_req(host, &mrq); | 1092 | mmc_wait_for_req(host, &mrq); |
1019 | 1093 | ||
1020 | if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { | 1094 | if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { |
1021 | mmc_card_set_dead(card); | 1095 | printk("%s: unable to read EXT_CSD, performance " |
1096 | "might suffer.\n", mmc_hostname(card->host)); | ||
1022 | continue; | 1097 | continue; |
1023 | } | 1098 | } |
1024 | 1099 | ||
@@ -1034,7 +1109,6 @@ static void mmc_process_ext_csds(struct mmc_host *host) | |||
1034 | printk("%s: card is mmc v4 but doesn't support " | 1109 | printk("%s: card is mmc v4 but doesn't support " |
1035 | "any high-speed modes.\n", | 1110 | "any high-speed modes.\n", |
1036 | mmc_hostname(card->host)); | 1111 | mmc_hostname(card->host)); |
1037 | mmc_card_set_bad(card); | ||
1038 | continue; | 1112 | continue; |
1039 | } | 1113 | } |
1040 | 1114 | ||
@@ -1215,7 +1289,9 @@ static void mmc_read_switch_caps(struct mmc_host *host) | |||
1215 | mmc_wait_for_req(host, &mrq); | 1289 | mmc_wait_for_req(host, &mrq); |
1216 | 1290 | ||
1217 | if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { | 1291 | if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { |
1218 | mmc_card_set_dead(card); | 1292 | printk("%s: unable to read switch capabilities, " |
1293 | "performance might suffer.\n", | ||
1294 | mmc_hostname(card->host)); | ||
1219 | continue; | 1295 | continue; |
1220 | } | 1296 | } |
1221 | 1297 | ||
@@ -1247,12 +1323,8 @@ static void mmc_read_switch_caps(struct mmc_host *host) | |||
1247 | 1323 | ||
1248 | mmc_wait_for_req(host, &mrq); | 1324 | mmc_wait_for_req(host, &mrq); |
1249 | 1325 | ||
1250 | if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { | 1326 | if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE || |
1251 | mmc_card_set_dead(card); | 1327 | (status[16] & 0xF) != 1) { |
1252 | continue; | ||
1253 | } | ||
1254 | |||
1255 | if ((status[16] & 0xF) != 1) { | ||
1256 | printk(KERN_WARNING "%s: Problem switching card " | 1328 | printk(KERN_WARNING "%s: Problem switching card " |
1257 | "into high-speed mode!\n", | 1329 | "into high-speed mode!\n", |
1258 | mmc_hostname(host)); | 1330 | mmc_hostname(host)); |
@@ -1334,6 +1406,10 @@ static void mmc_setup(struct mmc_host *host) | |||
1334 | mmc_power_up(host); | 1406 | mmc_power_up(host); |
1335 | mmc_idle_cards(host); | 1407 | mmc_idle_cards(host); |
1336 | 1408 | ||
1409 | err = mmc_send_if_cond(host, host->ocr_avail, NULL); | ||
1410 | if (err != MMC_ERR_NONE) { | ||
1411 | return; | ||
1412 | } | ||
1337 | err = mmc_send_app_op_cond(host, 0, &ocr); | 1413 | err = mmc_send_app_op_cond(host, 0, &ocr); |
1338 | 1414 | ||
1339 | /* | 1415 | /* |
@@ -1386,10 +1462,21 @@ static void mmc_setup(struct mmc_host *host) | |||
1386 | * all get the idea that they should be ready for CMD2. | 1462 | * all get the idea that they should be ready for CMD2. |
1387 | * (My SanDisk card seems to need this.) | 1463 | * (My SanDisk card seems to need this.) |
1388 | */ | 1464 | */ |
1389 | if (host->mode == MMC_MODE_SD) | 1465 | if (host->mode == MMC_MODE_SD) { |
1390 | mmc_send_app_op_cond(host, host->ocr, NULL); | 1466 | int err, sd2; |
1391 | else | 1467 | err = mmc_send_if_cond(host, host->ocr, &sd2); |
1468 | if (err == MMC_ERR_NONE) { | ||
1469 | /* | ||
1470 | * If SD_SEND_IF_COND indicates an SD 2.0 | ||
1471 | * compliant card and we should set bit 30 | ||
1472 | * of the ocr to indicate that we can handle | ||
1473 | * block-addressed SDHC cards. | ||
1474 | */ | ||
1475 | mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL); | ||
1476 | } | ||
1477 | } else { | ||
1392 | mmc_send_op_cond(host, host->ocr, NULL); | 1478 | mmc_send_op_cond(host, host->ocr, NULL); |
1479 | } | ||
1393 | 1480 | ||
1394 | mmc_discover_cards(host); | 1481 | mmc_discover_cards(host); |
1395 | 1482 | ||
@@ -1519,8 +1606,11 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) | |||
1519 | */ | 1606 | */ |
1520 | host->max_hw_segs = 1; | 1607 | host->max_hw_segs = 1; |
1521 | host->max_phys_segs = 1; | 1608 | host->max_phys_segs = 1; |
1522 | host->max_sectors = 1 << (PAGE_CACHE_SHIFT - 9); | ||
1523 | host->max_seg_size = PAGE_CACHE_SIZE; | 1609 | host->max_seg_size = PAGE_CACHE_SIZE; |
1610 | |||
1611 | host->max_req_size = PAGE_CACHE_SIZE; | ||
1612 | host->max_blk_size = 512; | ||
1613 | host->max_blk_count = PAGE_CACHE_SIZE / 512; | ||
1524 | } | 1614 | } |
1525 | 1615 | ||
1526 | return host; | 1616 | return host; |
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index 87713572293f..05ba8ace70e7 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c | |||
@@ -237,13 +237,17 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
237 | brq.mrq.cmd = &brq.cmd; | 237 | brq.mrq.cmd = &brq.cmd; |
238 | brq.mrq.data = &brq.data; | 238 | brq.mrq.data = &brq.data; |
239 | 239 | ||
240 | brq.cmd.arg = req->sector << 9; | 240 | brq.cmd.arg = req->sector; |
241 | if (!mmc_card_blockaddr(card)) | ||
242 | brq.cmd.arg <<= 9; | ||
241 | brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | 243 | brq.cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; |
242 | brq.data.blksz = 1 << md->block_bits; | 244 | brq.data.blksz = 1 << md->block_bits; |
243 | brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); | ||
244 | brq.stop.opcode = MMC_STOP_TRANSMISSION; | 245 | brq.stop.opcode = MMC_STOP_TRANSMISSION; |
245 | brq.stop.arg = 0; | 246 | brq.stop.arg = 0; |
246 | brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC; | 247 | brq.stop.flags = MMC_RSP_R1B | MMC_CMD_AC; |
248 | brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); | ||
249 | if (brq.data.blocks > card->host->max_blk_count) | ||
250 | brq.data.blocks = card->host->max_blk_count; | ||
247 | 251 | ||
248 | mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ); | 252 | mmc_set_data_timeout(&brq.data, card, rq_data_dir(req) != READ); |
249 | 253 | ||
@@ -375,9 +379,10 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
375 | spin_unlock_irq(&md->lock); | 379 | spin_unlock_irq(&md->lock); |
376 | } | 380 | } |
377 | 381 | ||
382 | flush_queue: | ||
383 | |||
378 | mmc_card_release_host(card); | 384 | mmc_card_release_host(card); |
379 | 385 | ||
380 | flush_queue: | ||
381 | spin_lock_irq(&md->lock); | 386 | spin_lock_irq(&md->lock); |
382 | while (ret) { | 387 | while (ret) { |
383 | ret = end_that_request_chunk(req, 0, | 388 | ret = end_that_request_chunk(req, 0, |
@@ -494,6 +499,10 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) | |||
494 | struct mmc_command cmd; | 499 | struct mmc_command cmd; |
495 | int err; | 500 | int err; |
496 | 501 | ||
502 | /* Block-addressed cards ignore MMC_SET_BLOCKLEN. */ | ||
503 | if (mmc_card_blockaddr(card)) | ||
504 | return 0; | ||
505 | |||
497 | mmc_card_claim_host(card); | 506 | mmc_card_claim_host(card); |
498 | cmd.opcode = MMC_SET_BLOCKLEN; | 507 | cmd.opcode = MMC_SET_BLOCKLEN; |
499 | cmd.arg = 1 << md->block_bits; | 508 | cmd.arg = 1 << md->block_bits; |
diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c index 3e35a43819fb..c27e42645cdb 100644 --- a/drivers/mmc/mmc_queue.c +++ b/drivers/mmc/mmc_queue.c | |||
@@ -147,7 +147,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock | |||
147 | 147 | ||
148 | blk_queue_prep_rq(mq->queue, mmc_prep_request); | 148 | blk_queue_prep_rq(mq->queue, mmc_prep_request); |
149 | blk_queue_bounce_limit(mq->queue, limit); | 149 | blk_queue_bounce_limit(mq->queue, limit); |
150 | blk_queue_max_sectors(mq->queue, host->max_sectors); | 150 | blk_queue_max_sectors(mq->queue, host->max_req_size / 512); |
151 | blk_queue_max_phys_segments(mq->queue, host->max_phys_segs); | 151 | blk_queue_max_phys_segments(mq->queue, host->max_phys_segs); |
152 | blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); | 152 | blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); |
153 | blk_queue_max_segment_size(mq->queue, host->max_seg_size); | 153 | blk_queue_max_segment_size(mq->queue, host->max_seg_size); |
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c index e334acd045bc..d32698b02d7f 100644 --- a/drivers/mmc/mmc_sysfs.c +++ b/drivers/mmc/mmc_sysfs.c | |||
@@ -199,7 +199,7 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host) | |||
199 | memset(card, 0, sizeof(struct mmc_card)); | 199 | memset(card, 0, sizeof(struct mmc_card)); |
200 | card->host = host; | 200 | card->host = host; |
201 | device_initialize(&card->dev); | 201 | device_initialize(&card->dev); |
202 | card->dev.parent = mmc_dev(host); | 202 | card->dev.parent = mmc_classdev(host); |
203 | card->dev.bus = &mmc_bus_type; | 203 | card->dev.bus = &mmc_bus_type; |
204 | card->dev.release = mmc_release_card; | 204 | card->dev.release = mmc_release_card; |
205 | } | 205 | } |
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index ccfe6561be24..5941dd951e82 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c | |||
@@ -524,15 +524,24 @@ static int mmci_probe(struct amba_device *dev, void *id) | |||
524 | /* | 524 | /* |
525 | * Since we only have a 16-bit data length register, we must | 525 | * Since we only have a 16-bit data length register, we must |
526 | * ensure that we don't exceed 2^16-1 bytes in a single request. | 526 | * ensure that we don't exceed 2^16-1 bytes in a single request. |
527 | * Choose 64 (512-byte) sectors as the limit. | ||
528 | */ | 527 | */ |
529 | mmc->max_sectors = 64; | 528 | mmc->max_req_size = 65535; |
530 | 529 | ||
531 | /* | 530 | /* |
532 | * Set the maximum segment size. Since we aren't doing DMA | 531 | * Set the maximum segment size. Since we aren't doing DMA |
533 | * (yet) we are only limited by the data length register. | 532 | * (yet) we are only limited by the data length register. |
534 | */ | 533 | */ |
535 | mmc->max_seg_size = mmc->max_sectors << 9; | 534 | mmc->max_seg_size = mmc->max_req_size; |
535 | |||
536 | /* | ||
537 | * Block size can be up to 2048 bytes, but must be a power of two. | ||
538 | */ | ||
539 | mmc->max_blk_size = 2048; | ||
540 | |||
541 | /* | ||
542 | * No limit on the number of blocks transferred. | ||
543 | */ | ||
544 | mmc->max_blk_count = mmc->max_req_size; | ||
536 | 545 | ||
537 | spin_lock_init(&host->lock); | 546 | spin_lock_init(&host->lock); |
538 | 547 | ||
diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index d30540b27614..1e96a2f65022 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c | |||
@@ -1099,8 +1099,10 @@ static int __init mmc_omap_probe(struct platform_device *pdev) | |||
1099 | */ | 1099 | */ |
1100 | mmc->max_phys_segs = 32; | 1100 | mmc->max_phys_segs = 32; |
1101 | mmc->max_hw_segs = 32; | 1101 | mmc->max_hw_segs = 32; |
1102 | mmc->max_sectors = 256; /* NBLK max 11-bits, OMAP also limited by DMA */ | 1102 | mmc->max_blk_size = 2048; /* BLEN is 11 bits (+1) */ |
1103 | mmc->max_seg_size = mmc->max_sectors * 512; | 1103 | mmc->max_blk_count = 2048; /* NBLK is 11 bits (+1) */ |
1104 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | ||
1105 | mmc->max_seg_size = mmc->max_req_size; | ||
1104 | 1106 | ||
1105 | if (host->power_pin >= 0) { | 1107 | if (host->power_pin >= 0) { |
1106 | if ((ret = omap_request_gpio(host->power_pin)) != 0) { | 1108 | if ((ret = omap_request_gpio(host->power_pin)) != 0) { |
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index 6073d998b11f..9774fc68b61a 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c | |||
@@ -450,6 +450,16 @@ static int pxamci_probe(struct platform_device *pdev) | |||
450 | */ | 450 | */ |
451 | mmc->max_seg_size = PAGE_SIZE; | 451 | mmc->max_seg_size = PAGE_SIZE; |
452 | 452 | ||
453 | /* | ||
454 | * Block length register is 10 bits. | ||
455 | */ | ||
456 | mmc->max_blk_size = 1023; | ||
457 | |||
458 | /* | ||
459 | * Block count register is 16 bits. | ||
460 | */ | ||
461 | mmc->max_blk_count = 65535; | ||
462 | |||
453 | host = mmc_priv(mmc); | 463 | host = mmc_priv(mmc); |
454 | host->mmc = mmc; | 464 | host->mmc = mmc; |
455 | host->dma = -1; | 465 | host->dma = -1; |
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index c2d13d7e9911..4bf1fea5e2c4 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c | |||
@@ -37,6 +37,7 @@ static unsigned int debug_quirks = 0; | |||
37 | #define SDHCI_QUIRK_FORCE_DMA (1<<1) | 37 | #define SDHCI_QUIRK_FORCE_DMA (1<<1) |
38 | /* Controller doesn't like some resets when there is no card inserted. */ | 38 | /* Controller doesn't like some resets when there is no card inserted. */ |
39 | #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) | 39 | #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) |
40 | #define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) | ||
40 | 41 | ||
41 | static const struct pci_device_id pci_ids[] __devinitdata = { | 42 | static const struct pci_device_id pci_ids[] __devinitdata = { |
42 | { | 43 | { |
@@ -65,6 +66,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = { | |||
65 | .driver_data = SDHCI_QUIRK_FORCE_DMA, | 66 | .driver_data = SDHCI_QUIRK_FORCE_DMA, |
66 | }, | 67 | }, |
67 | 68 | ||
69 | { | ||
70 | .vendor = PCI_VENDOR_ID_ENE, | ||
71 | .device = PCI_DEVICE_ID_ENE_CB712_SD, | ||
72 | .subvendor = PCI_ANY_ID, | ||
73 | .subdevice = PCI_ANY_ID, | ||
74 | .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE, | ||
75 | }, | ||
76 | |||
68 | { /* Generic SD host controller */ | 77 | { /* Generic SD host controller */ |
69 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) | 78 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) |
70 | }, | 79 | }, |
@@ -197,15 +206,9 @@ static void sdhci_deactivate_led(struct sdhci_host *host) | |||
197 | * * | 206 | * * |
198 | \*****************************************************************************/ | 207 | \*****************************************************************************/ |
199 | 208 | ||
200 | static inline char* sdhci_kmap_sg(struct sdhci_host* host) | 209 | static inline char* sdhci_sg_to_buffer(struct sdhci_host* host) |
201 | { | 210 | { |
202 | host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ); | 211 | return page_address(host->cur_sg->page) + host->cur_sg->offset; |
203 | return host->mapped_sg + host->cur_sg->offset; | ||
204 | } | ||
205 | |||
206 | static inline void sdhci_kunmap_sg(struct sdhci_host* host) | ||
207 | { | ||
208 | kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ); | ||
209 | } | 212 | } |
210 | 213 | ||
211 | static inline int sdhci_next_sg(struct sdhci_host* host) | 214 | static inline int sdhci_next_sg(struct sdhci_host* host) |
@@ -240,7 +243,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host) | |||
240 | chunk_remain = 0; | 243 | chunk_remain = 0; |
241 | data = 0; | 244 | data = 0; |
242 | 245 | ||
243 | buffer = sdhci_kmap_sg(host) + host->offset; | 246 | buffer = sdhci_sg_to_buffer(host) + host->offset; |
244 | 247 | ||
245 | while (blksize) { | 248 | while (blksize) { |
246 | if (chunk_remain == 0) { | 249 | if (chunk_remain == 0) { |
@@ -264,16 +267,13 @@ static void sdhci_read_block_pio(struct sdhci_host *host) | |||
264 | } | 267 | } |
265 | 268 | ||
266 | if (host->remain == 0) { | 269 | if (host->remain == 0) { |
267 | sdhci_kunmap_sg(host); | ||
268 | if (sdhci_next_sg(host) == 0) { | 270 | if (sdhci_next_sg(host) == 0) { |
269 | BUG_ON(blksize != 0); | 271 | BUG_ON(blksize != 0); |
270 | return; | 272 | return; |
271 | } | 273 | } |
272 | buffer = sdhci_kmap_sg(host); | 274 | buffer = sdhci_sg_to_buffer(host); |
273 | } | 275 | } |
274 | } | 276 | } |
275 | |||
276 | sdhci_kunmap_sg(host); | ||
277 | } | 277 | } |
278 | 278 | ||
279 | static void sdhci_write_block_pio(struct sdhci_host *host) | 279 | static void sdhci_write_block_pio(struct sdhci_host *host) |
@@ -290,7 +290,7 @@ static void sdhci_write_block_pio(struct sdhci_host *host) | |||
290 | data = 0; | 290 | data = 0; |
291 | 291 | ||
292 | bytes = 0; | 292 | bytes = 0; |
293 | buffer = sdhci_kmap_sg(host) + host->offset; | 293 | buffer = sdhci_sg_to_buffer(host) + host->offset; |
294 | 294 | ||
295 | while (blksize) { | 295 | while (blksize) { |
296 | size = min(host->size, host->remain); | 296 | size = min(host->size, host->remain); |
@@ -314,16 +314,13 @@ static void sdhci_write_block_pio(struct sdhci_host *host) | |||
314 | } | 314 | } |
315 | 315 | ||
316 | if (host->remain == 0) { | 316 | if (host->remain == 0) { |
317 | sdhci_kunmap_sg(host); | ||
318 | if (sdhci_next_sg(host) == 0) { | 317 | if (sdhci_next_sg(host) == 0) { |
319 | BUG_ON(blksize != 0); | 318 | BUG_ON(blksize != 0); |
320 | return; | 319 | return; |
321 | } | 320 | } |
322 | buffer = sdhci_kmap_sg(host); | 321 | buffer = sdhci_sg_to_buffer(host); |
323 | } | 322 | } |
324 | } | 323 | } |
325 | |||
326 | sdhci_kunmap_sg(host); | ||
327 | } | 324 | } |
328 | 325 | ||
329 | static void sdhci_transfer_pio(struct sdhci_host *host) | 326 | static void sdhci_transfer_pio(struct sdhci_host *host) |
@@ -372,7 +369,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
372 | 369 | ||
373 | /* Sanity checks */ | 370 | /* Sanity checks */ |
374 | BUG_ON(data->blksz * data->blocks > 524288); | 371 | BUG_ON(data->blksz * data->blocks > 524288); |
375 | BUG_ON(data->blksz > host->max_block); | 372 | BUG_ON(data->blksz > host->mmc->max_blk_size); |
376 | BUG_ON(data->blocks > 65535); | 373 | BUG_ON(data->blocks > 65535); |
377 | 374 | ||
378 | /* timeout in us */ | 375 | /* timeout in us */ |
@@ -674,10 +671,17 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) | |||
674 | if (host->power == power) | 671 | if (host->power == power) |
675 | return; | 672 | return; |
676 | 673 | ||
677 | writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); | 674 | if (power == (unsigned short)-1) { |
678 | 675 | writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); | |
679 | if (power == (unsigned short)-1) | ||
680 | goto out; | 676 | goto out; |
677 | } | ||
678 | |||
679 | /* | ||
680 | * Spec says that we should clear the power reg before setting | ||
681 | * a new value. Some controllers don't seem to like this though. | ||
682 | */ | ||
683 | if (!(host->chip->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) | ||
684 | writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); | ||
681 | 685 | ||
682 | pwr = SDHCI_POWER_ON; | 686 | pwr = SDHCI_POWER_ON; |
683 | 687 | ||
@@ -1109,7 +1113,9 @@ static int sdhci_resume (struct pci_dev *pdev) | |||
1109 | 1113 | ||
1110 | pci_set_power_state(pdev, PCI_D0); | 1114 | pci_set_power_state(pdev, PCI_D0); |
1111 | pci_restore_state(pdev); | 1115 | pci_restore_state(pdev); |
1112 | pci_enable_device(pdev); | 1116 | ret = pci_enable_device(pdev); |
1117 | if (ret) | ||
1118 | return ret; | ||
1113 | 1119 | ||
1114 | for (i = 0;i < chip->num_slots;i++) { | 1120 | for (i = 0;i < chip->num_slots;i++) { |
1115 | if (!chip->hosts[i]) | 1121 | if (!chip->hosts[i]) |
@@ -1274,15 +1280,6 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1274 | if (caps & SDHCI_TIMEOUT_CLK_UNIT) | 1280 | if (caps & SDHCI_TIMEOUT_CLK_UNIT) |
1275 | host->timeout_clk *= 1000; | 1281 | host->timeout_clk *= 1000; |
1276 | 1282 | ||
1277 | host->max_block = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT; | ||
1278 | if (host->max_block >= 3) { | ||
1279 | printk(KERN_ERR "%s: Invalid maximum block size.\n", | ||
1280 | host->slot_descr); | ||
1281 | ret = -ENODEV; | ||
1282 | goto unmap; | ||
1283 | } | ||
1284 | host->max_block = 512 << host->max_block; | ||
1285 | |||
1286 | /* | 1283 | /* |
1287 | * Set host parameters. | 1284 | * Set host parameters. |
1288 | */ | 1285 | */ |
@@ -1294,9 +1291,9 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1294 | mmc->ocr_avail = 0; | 1291 | mmc->ocr_avail = 0; |
1295 | if (caps & SDHCI_CAN_VDD_330) | 1292 | if (caps & SDHCI_CAN_VDD_330) |
1296 | mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; | 1293 | mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; |
1297 | else if (caps & SDHCI_CAN_VDD_300) | 1294 | if (caps & SDHCI_CAN_VDD_300) |
1298 | mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31; | 1295 | mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31; |
1299 | else if (caps & SDHCI_CAN_VDD_180) | 1296 | if (caps & SDHCI_CAN_VDD_180) |
1300 | mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19; | 1297 | mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19; |
1301 | 1298 | ||
1302 | if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) { | 1299 | if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) { |
@@ -1326,15 +1323,33 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1326 | 1323 | ||
1327 | /* | 1324 | /* |
1328 | * Maximum number of sectors in one transfer. Limited by DMA boundary | 1325 | * Maximum number of sectors in one transfer. Limited by DMA boundary |
1329 | * size (512KiB), which means (512 KiB/512=) 1024 entries. | 1326 | * size (512KiB). |
1330 | */ | 1327 | */ |
1331 | mmc->max_sectors = 1024; | 1328 | mmc->max_req_size = 524288; |
1332 | 1329 | ||
1333 | /* | 1330 | /* |
1334 | * Maximum segment size. Could be one segment with the maximum number | 1331 | * Maximum segment size. Could be one segment with the maximum number |
1335 | * of sectors. | 1332 | * of bytes. |
1333 | */ | ||
1334 | mmc->max_seg_size = mmc->max_req_size; | ||
1335 | |||
1336 | /* | ||
1337 | * Maximum block size. This varies from controller to controller and | ||
1338 | * is specified in the capabilities register. | ||
1339 | */ | ||
1340 | mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT; | ||
1341 | if (mmc->max_blk_size >= 3) { | ||
1342 | printk(KERN_ERR "%s: Invalid maximum block size.\n", | ||
1343 | host->slot_descr); | ||
1344 | ret = -ENODEV; | ||
1345 | goto unmap; | ||
1346 | } | ||
1347 | mmc->max_blk_size = 512 << mmc->max_blk_size; | ||
1348 | |||
1349 | /* | ||
1350 | * Maximum block count. | ||
1336 | */ | 1351 | */ |
1337 | mmc->max_seg_size = mmc->max_sectors * 512; | 1352 | mmc->max_blk_count = 65535; |
1338 | 1353 | ||
1339 | /* | 1354 | /* |
1340 | * Init tasklets. | 1355 | * Init tasklets. |
diff --git a/drivers/mmc/sdhci.h b/drivers/mmc/sdhci.h index f9d1a0a6f03a..e324f0a623dc 100644 --- a/drivers/mmc/sdhci.h +++ b/drivers/mmc/sdhci.h | |||
@@ -174,7 +174,6 @@ struct sdhci_host { | |||
174 | 174 | ||
175 | unsigned int max_clk; /* Max possible freq (MHz) */ | 175 | unsigned int max_clk; /* Max possible freq (MHz) */ |
176 | unsigned int timeout_clk; /* Timeout freq (KHz) */ | 176 | unsigned int timeout_clk; /* Timeout freq (KHz) */ |
177 | unsigned int max_block; /* Max block size (bytes) */ | ||
178 | 177 | ||
179 | unsigned int clock; /* Current clock (MHz) */ | 178 | unsigned int clock; /* Current clock (MHz) */ |
180 | unsigned short power; /* Current voltage */ | 179 | unsigned short power; /* Current voltage */ |
@@ -184,7 +183,6 @@ struct sdhci_host { | |||
184 | struct mmc_data *data; /* Current data request */ | 183 | struct mmc_data *data; /* Current data request */ |
185 | 184 | ||
186 | struct scatterlist *cur_sg; /* We're working on this */ | 185 | struct scatterlist *cur_sg; /* We're working on this */ |
187 | char *mapped_sg; /* This is where it's mapped */ | ||
188 | int num_sg; /* Entries left */ | 186 | int num_sg; /* Entries left */ |
189 | int offset; /* Offset into current sg */ | 187 | int offset; /* Offset into current sg */ |
190 | int remain; /* Bytes left in current */ | 188 | int remain; /* Bytes left in current */ |
diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c index fa4a52886b97..e65f8a0a9349 100644 --- a/drivers/mmc/tifm_sd.c +++ b/drivers/mmc/tifm_sd.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <asm/io.h> | 17 | #include <asm/io.h> |
18 | 18 | ||
19 | #define DRIVER_NAME "tifm_sd" | 19 | #define DRIVER_NAME "tifm_sd" |
20 | #define DRIVER_VERSION "0.6" | 20 | #define DRIVER_VERSION "0.7" |
21 | 21 | ||
22 | static int no_dma = 0; | 22 | static int no_dma = 0; |
23 | static int fixed_timeout = 0; | 23 | static int fixed_timeout = 0; |
@@ -79,7 +79,6 @@ typedef enum { | |||
79 | 79 | ||
80 | enum { | 80 | enum { |
81 | FIFO_RDY = 0x0001, /* hardware dependent value */ | 81 | FIFO_RDY = 0x0001, /* hardware dependent value */ |
82 | HOST_REG = 0x0002, | ||
83 | EJECT = 0x0004, | 82 | EJECT = 0x0004, |
84 | EJECT_DONE = 0x0008, | 83 | EJECT_DONE = 0x0008, |
85 | CARD_BUSY = 0x0010, | 84 | CARD_BUSY = 0x0010, |
@@ -95,46 +94,53 @@ struct tifm_sd { | |||
95 | card_state_t state; | 94 | card_state_t state; |
96 | unsigned int clk_freq; | 95 | unsigned int clk_freq; |
97 | unsigned int clk_div; | 96 | unsigned int clk_div; |
98 | unsigned long timeout_jiffies; // software timeout - 2 sec | 97 | unsigned long timeout_jiffies; |
99 | 98 | ||
99 | struct tasklet_struct finish_tasklet; | ||
100 | struct timer_list timer; | ||
100 | struct mmc_request *req; | 101 | struct mmc_request *req; |
101 | struct work_struct cmd_handler; | 102 | wait_queue_head_t notify; |
102 | struct delayed_work abort_handler; | ||
103 | wait_queue_head_t can_eject; | ||
104 | 103 | ||
105 | size_t written_blocks; | 104 | size_t written_blocks; |
106 | char *buffer; | ||
107 | size_t buffer_size; | 105 | size_t buffer_size; |
108 | size_t buffer_pos; | 106 | size_t buffer_pos; |
109 | 107 | ||
110 | }; | 108 | }; |
111 | 109 | ||
110 | static char* tifm_sd_data_buffer(struct mmc_data *data) | ||
111 | { | ||
112 | return page_address(data->sg->page) + data->sg->offset; | ||
113 | } | ||
114 | |||
112 | static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host, | 115 | static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host, |
113 | unsigned int host_status) | 116 | unsigned int host_status) |
114 | { | 117 | { |
115 | struct mmc_command *cmd = host->req->cmd; | 118 | struct mmc_command *cmd = host->req->cmd; |
116 | unsigned int t_val = 0, cnt = 0; | 119 | unsigned int t_val = 0, cnt = 0; |
120 | char *buffer; | ||
117 | 121 | ||
118 | if (host_status & TIFM_MMCSD_BRS) { | 122 | if (host_status & TIFM_MMCSD_BRS) { |
119 | /* in non-dma rx mode BRS fires when fifo is still not empty */ | 123 | /* in non-dma rx mode BRS fires when fifo is still not empty */ |
120 | if (host->buffer && (cmd->data->flags & MMC_DATA_READ)) { | 124 | if (no_dma && (cmd->data->flags & MMC_DATA_READ)) { |
125 | buffer = tifm_sd_data_buffer(host->req->data); | ||
121 | while (host->buffer_size > host->buffer_pos) { | 126 | while (host->buffer_size > host->buffer_pos) { |
122 | t_val = readl(sock->addr + SOCK_MMCSD_DATA); | 127 | t_val = readl(sock->addr + SOCK_MMCSD_DATA); |
123 | host->buffer[host->buffer_pos++] = t_val & 0xff; | 128 | buffer[host->buffer_pos++] = t_val & 0xff; |
124 | host->buffer[host->buffer_pos++] = | 129 | buffer[host->buffer_pos++] = |
125 | (t_val >> 8) & 0xff; | 130 | (t_val >> 8) & 0xff; |
126 | } | 131 | } |
127 | } | 132 | } |
128 | return 1; | 133 | return 1; |
129 | } else if (host->buffer) { | 134 | } else if (no_dma) { |
135 | buffer = tifm_sd_data_buffer(host->req->data); | ||
130 | if ((cmd->data->flags & MMC_DATA_READ) && | 136 | if ((cmd->data->flags & MMC_DATA_READ) && |
131 | (host_status & TIFM_MMCSD_AF)) { | 137 | (host_status & TIFM_MMCSD_AF)) { |
132 | for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { | 138 | for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { |
133 | t_val = readl(sock->addr + SOCK_MMCSD_DATA); | 139 | t_val = readl(sock->addr + SOCK_MMCSD_DATA); |
134 | if (host->buffer_size > host->buffer_pos) { | 140 | if (host->buffer_size > host->buffer_pos) { |
135 | host->buffer[host->buffer_pos++] = | 141 | buffer[host->buffer_pos++] = |
136 | t_val & 0xff; | 142 | t_val & 0xff; |
137 | host->buffer[host->buffer_pos++] = | 143 | buffer[host->buffer_pos++] = |
138 | (t_val >> 8) & 0xff; | 144 | (t_val >> 8) & 0xff; |
139 | } | 145 | } |
140 | } | 146 | } |
@@ -142,11 +148,12 @@ static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host, | |||
142 | && (host_status & TIFM_MMCSD_AE)) { | 148 | && (host_status & TIFM_MMCSD_AE)) { |
143 | for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { | 149 | for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { |
144 | if (host->buffer_size > host->buffer_pos) { | 150 | if (host->buffer_size > host->buffer_pos) { |
145 | t_val = host->buffer[host->buffer_pos++] & 0x00ff; | 151 | t_val = buffer[host->buffer_pos++] |
146 | t_val |= ((host->buffer[host->buffer_pos++]) << 8) | 152 | & 0x00ff; |
147 | & 0xff00; | 153 | t_val |= ((buffer[host->buffer_pos++]) |
154 | << 8) & 0xff00; | ||
148 | writel(t_val, | 155 | writel(t_val, |
149 | sock->addr + SOCK_MMCSD_DATA); | 156 | sock->addr + SOCK_MMCSD_DATA); |
150 | } | 157 | } |
151 | } | 158 | } |
152 | } | 159 | } |
@@ -206,7 +213,7 @@ static void tifm_sd_exec(struct tifm_sd *host, struct mmc_command *cmd) | |||
206 | cmd_mask |= TIFM_MMCSD_READ; | 213 | cmd_mask |= TIFM_MMCSD_READ; |
207 | 214 | ||
208 | dev_dbg(&sock->dev, "executing opcode 0x%x, arg: 0x%x, mask: 0x%x\n", | 215 | dev_dbg(&sock->dev, "executing opcode 0x%x, arg: 0x%x, mask: 0x%x\n", |
209 | cmd->opcode, cmd->arg, cmd_mask); | 216 | cmd->opcode, cmd->arg, cmd_mask); |
210 | 217 | ||
211 | writel((cmd->arg >> 16) & 0xffff, sock->addr + SOCK_MMCSD_ARG_HIGH); | 218 | writel((cmd->arg >> 16) & 0xffff, sock->addr + SOCK_MMCSD_ARG_HIGH); |
212 | writel(cmd->arg & 0xffff, sock->addr + SOCK_MMCSD_ARG_LOW); | 219 | writel(cmd->arg & 0xffff, sock->addr + SOCK_MMCSD_ARG_LOW); |
@@ -239,65 +246,78 @@ change_state: | |||
239 | tifm_sd_fetch_resp(cmd, sock); | 246 | tifm_sd_fetch_resp(cmd, sock); |
240 | if (cmd->data) { | 247 | if (cmd->data) { |
241 | host->state = BRS; | 248 | host->state = BRS; |
242 | } else | 249 | } else { |
243 | host->state = READY; | 250 | host->state = READY; |
251 | } | ||
244 | goto change_state; | 252 | goto change_state; |
245 | } | 253 | } |
246 | break; | 254 | break; |
247 | case BRS: | 255 | case BRS: |
248 | if (tifm_sd_transfer_data(sock, host, host_status)) { | 256 | if (tifm_sd_transfer_data(sock, host, host_status)) { |
249 | if (!host->req->stop) { | 257 | if (cmd->data->flags & MMC_DATA_WRITE) { |
250 | if (cmd->data->flags & MMC_DATA_WRITE) { | 258 | host->state = CARD; |
251 | host->state = CARD; | 259 | } else { |
260 | if (no_dma) { | ||
261 | if (host->req->stop) { | ||
262 | tifm_sd_exec(host, host->req->stop); | ||
263 | host->state = SCMD; | ||
264 | } else { | ||
265 | host->state = READY; | ||
266 | } | ||
252 | } else { | 267 | } else { |
253 | host->state = | 268 | host->state = FIFO; |
254 | host->buffer ? READY : FIFO; | ||
255 | } | 269 | } |
256 | goto change_state; | ||
257 | } | 270 | } |
258 | tifm_sd_exec(host, host->req->stop); | 271 | goto change_state; |
259 | host->state = SCMD; | ||
260 | } | 272 | } |
261 | break; | 273 | break; |
262 | case SCMD: | 274 | case SCMD: |
263 | if (host_status & TIFM_MMCSD_EOC) { | 275 | if (host_status & TIFM_MMCSD_EOC) { |
264 | tifm_sd_fetch_resp(host->req->stop, sock); | 276 | tifm_sd_fetch_resp(host->req->stop, sock); |
265 | if (cmd->error) { | 277 | host->state = READY; |
266 | host->state = READY; | ||
267 | } else if (cmd->data->flags & MMC_DATA_WRITE) { | ||
268 | host->state = CARD; | ||
269 | } else { | ||
270 | host->state = host->buffer ? READY : FIFO; | ||
271 | } | ||
272 | goto change_state; | 278 | goto change_state; |
273 | } | 279 | } |
274 | break; | 280 | break; |
275 | case CARD: | 281 | case CARD: |
282 | dev_dbg(&sock->dev, "waiting for CARD, have %zd blocks\n", | ||
283 | host->written_blocks); | ||
276 | if (!(host->flags & CARD_BUSY) | 284 | if (!(host->flags & CARD_BUSY) |
277 | && (host->written_blocks == cmd->data->blocks)) { | 285 | && (host->written_blocks == cmd->data->blocks)) { |
278 | host->state = host->buffer ? READY : FIFO; | 286 | if (no_dma) { |
287 | if (host->req->stop) { | ||
288 | tifm_sd_exec(host, host->req->stop); | ||
289 | host->state = SCMD; | ||
290 | } else { | ||
291 | host->state = READY; | ||
292 | } | ||
293 | } else { | ||
294 | host->state = FIFO; | ||
295 | } | ||
279 | goto change_state; | 296 | goto change_state; |
280 | } | 297 | } |
281 | break; | 298 | break; |
282 | case FIFO: | 299 | case FIFO: |
283 | if (host->flags & FIFO_RDY) { | 300 | if (host->flags & FIFO_RDY) { |
284 | host->state = READY; | ||
285 | host->flags &= ~FIFO_RDY; | 301 | host->flags &= ~FIFO_RDY; |
302 | if (host->req->stop) { | ||
303 | tifm_sd_exec(host, host->req->stop); | ||
304 | host->state = SCMD; | ||
305 | } else { | ||
306 | host->state = READY; | ||
307 | } | ||
286 | goto change_state; | 308 | goto change_state; |
287 | } | 309 | } |
288 | break; | 310 | break; |
289 | case READY: | 311 | case READY: |
290 | queue_work(sock->wq, &host->cmd_handler); | 312 | tasklet_schedule(&host->finish_tasklet); |
291 | return; | 313 | return; |
292 | } | 314 | } |
293 | 315 | ||
294 | queue_delayed_work(sock->wq, &host->abort_handler, | ||
295 | host->timeout_jiffies); | ||
296 | } | 316 | } |
297 | 317 | ||
298 | /* Called from interrupt handler */ | 318 | /* Called from interrupt handler */ |
299 | static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock, | 319 | static void tifm_sd_signal_irq(struct tifm_dev *sock, |
300 | unsigned int sock_irq_status) | 320 | unsigned int sock_irq_status) |
301 | { | 321 | { |
302 | struct tifm_sd *host; | 322 | struct tifm_sd *host; |
303 | unsigned int host_status = 0, fifo_status = 0; | 323 | unsigned int host_status = 0, fifo_status = 0; |
@@ -305,7 +325,6 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock, | |||
305 | 325 | ||
306 | spin_lock(&sock->lock); | 326 | spin_lock(&sock->lock); |
307 | host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock)); | 327 | host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock)); |
308 | cancel_delayed_work(&host->abort_handler); | ||
309 | 328 | ||
310 | if (sock_irq_status & FIFO_EVENT) { | 329 | if (sock_irq_status & FIFO_EVENT) { |
311 | fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS); | 330 | fifo_status = readl(sock->addr + SOCK_DMA_FIFO_STATUS); |
@@ -318,19 +337,17 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock, | |||
318 | host_status = readl(sock->addr + SOCK_MMCSD_STATUS); | 337 | host_status = readl(sock->addr + SOCK_MMCSD_STATUS); |
319 | writel(host_status, sock->addr + SOCK_MMCSD_STATUS); | 338 | writel(host_status, sock->addr + SOCK_MMCSD_STATUS); |
320 | 339 | ||
321 | if (!(host->flags & HOST_REG)) | ||
322 | queue_work(sock->wq, &host->cmd_handler); | ||
323 | if (!host->req) | 340 | if (!host->req) |
324 | goto done; | 341 | goto done; |
325 | 342 | ||
326 | if (host_status & TIFM_MMCSD_ERRMASK) { | 343 | if (host_status & TIFM_MMCSD_ERRMASK) { |
327 | if (host_status & TIFM_MMCSD_CERR) | 344 | if (host_status & TIFM_MMCSD_CERR) |
328 | error_code = MMC_ERR_FAILED; | 345 | error_code = MMC_ERR_FAILED; |
329 | else if (host_status & | 346 | else if (host_status |
330 | (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO)) | 347 | & (TIFM_MMCSD_CTO | TIFM_MMCSD_DTO)) |
331 | error_code = MMC_ERR_TIMEOUT; | 348 | error_code = MMC_ERR_TIMEOUT; |
332 | else if (host_status & | 349 | else if (host_status |
333 | (TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC)) | 350 | & (TIFM_MMCSD_CCRC | TIFM_MMCSD_DCRC)) |
334 | error_code = MMC_ERR_BADCRC; | 351 | error_code = MMC_ERR_BADCRC; |
335 | 352 | ||
336 | writel(TIFM_FIFO_INT_SETALL, | 353 | writel(TIFM_FIFO_INT_SETALL, |
@@ -340,12 +357,11 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock, | |||
340 | if (host->req->stop) { | 357 | if (host->req->stop) { |
341 | if (host->state == SCMD) { | 358 | if (host->state == SCMD) { |
342 | host->req->stop->error = error_code; | 359 | host->req->stop->error = error_code; |
343 | } else if(host->state == BRS) { | 360 | } else if (host->state == BRS |
361 | || host->state == CARD | ||
362 | || host->state == FIFO) { | ||
344 | host->req->cmd->error = error_code; | 363 | host->req->cmd->error = error_code; |
345 | tifm_sd_exec(host, host->req->stop); | 364 | tifm_sd_exec(host, host->req->stop); |
346 | queue_delayed_work(sock->wq, | ||
347 | &host->abort_handler, | ||
348 | host->timeout_jiffies); | ||
349 | host->state = SCMD; | 365 | host->state = SCMD; |
350 | goto done; | 366 | goto done; |
351 | } else { | 367 | } else { |
@@ -359,8 +375,8 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock, | |||
359 | 375 | ||
360 | if (host_status & TIFM_MMCSD_CB) | 376 | if (host_status & TIFM_MMCSD_CB) |
361 | host->flags |= CARD_BUSY; | 377 | host->flags |= CARD_BUSY; |
362 | if ((host_status & TIFM_MMCSD_EOFB) && | 378 | if ((host_status & TIFM_MMCSD_EOFB) |
363 | (host->flags & CARD_BUSY)) { | 379 | && (host->flags & CARD_BUSY)) { |
364 | host->written_blocks++; | 380 | host->written_blocks++; |
365 | host->flags &= ~CARD_BUSY; | 381 | host->flags &= ~CARD_BUSY; |
366 | } | 382 | } |
@@ -370,22 +386,22 @@ static unsigned int tifm_sd_signal_irq(struct tifm_dev *sock, | |||
370 | tifm_sd_process_cmd(sock, host, host_status); | 386 | tifm_sd_process_cmd(sock, host, host_status); |
371 | done: | 387 | done: |
372 | dev_dbg(&sock->dev, "host_status %x, fifo_status %x\n", | 388 | dev_dbg(&sock->dev, "host_status %x, fifo_status %x\n", |
373 | host_status, fifo_status); | 389 | host_status, fifo_status); |
374 | spin_unlock(&sock->lock); | 390 | spin_unlock(&sock->lock); |
375 | return sock_irq_status; | ||
376 | } | 391 | } |
377 | 392 | ||
378 | static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd) | 393 | static void tifm_sd_prepare_data(struct tifm_sd *host, struct mmc_command *cmd) |
379 | { | 394 | { |
380 | struct tifm_dev *sock = card->dev; | 395 | struct tifm_dev *sock = host->dev; |
381 | unsigned int dest_cnt; | 396 | unsigned int dest_cnt; |
382 | 397 | ||
383 | /* DMA style IO */ | 398 | /* DMA style IO */ |
384 | 399 | dev_dbg(&sock->dev, "setting dma for %d blocks\n", | |
400 | cmd->data->blocks); | ||
385 | writel(TIFM_FIFO_INT_SETALL, | 401 | writel(TIFM_FIFO_INT_SETALL, |
386 | sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); | 402 | sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); |
387 | writel(ilog2(cmd->data->blksz) - 2, | 403 | writel(ilog2(cmd->data->blksz) - 2, |
388 | sock->addr + SOCK_FIFO_PAGE_SIZE); | 404 | sock->addr + SOCK_FIFO_PAGE_SIZE); |
389 | writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL); | 405 | writel(TIFM_FIFO_ENABLE, sock->addr + SOCK_FIFO_CONTROL); |
390 | writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); | 406 | writel(TIFM_FIFO_INTMASK, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); |
391 | 407 | ||
@@ -399,7 +415,7 @@ static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd) | |||
399 | if (cmd->data->flags & MMC_DATA_WRITE) { | 415 | if (cmd->data->flags & MMC_DATA_WRITE) { |
400 | writel(TIFM_MMCSD_TXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); | 416 | writel(TIFM_MMCSD_TXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); |
401 | writel(dest_cnt | TIFM_DMA_TX | TIFM_DMA_EN, | 417 | writel(dest_cnt | TIFM_DMA_TX | TIFM_DMA_EN, |
402 | sock->addr + SOCK_DMA_CONTROL); | 418 | sock->addr + SOCK_DMA_CONTROL); |
403 | } else { | 419 | } else { |
404 | writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); | 420 | writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); |
405 | writel(dest_cnt | TIFM_DMA_EN, sock->addr + SOCK_DMA_CONTROL); | 421 | writel(dest_cnt | TIFM_DMA_EN, sock->addr + SOCK_DMA_CONTROL); |
@@ -407,7 +423,7 @@ static void tifm_sd_prepare_data(struct tifm_sd *card, struct mmc_command *cmd) | |||
407 | } | 423 | } |
408 | 424 | ||
409 | static void tifm_sd_set_data_timeout(struct tifm_sd *host, | 425 | static void tifm_sd_set_data_timeout(struct tifm_sd *host, |
410 | struct mmc_data *data) | 426 | struct mmc_data *data) |
411 | { | 427 | { |
412 | struct tifm_dev *sock = host->dev; | 428 | struct tifm_dev *sock = host->dev; |
413 | unsigned int data_timeout = data->timeout_clks; | 429 | unsigned int data_timeout = data->timeout_clks; |
@@ -416,22 +432,21 @@ static void tifm_sd_set_data_timeout(struct tifm_sd *host, | |||
416 | return; | 432 | return; |
417 | 433 | ||
418 | data_timeout += data->timeout_ns / | 434 | data_timeout += data->timeout_ns / |
419 | ((1000000000 / host->clk_freq) * host->clk_div); | 435 | ((1000000000UL / host->clk_freq) * host->clk_div); |
420 | data_timeout *= 10; // call it fudge factor for now | ||
421 | 436 | ||
422 | if (data_timeout < 0xffff) { | 437 | if (data_timeout < 0xffff) { |
423 | writel((~TIFM_MMCSD_DPE) & | ||
424 | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG), | ||
425 | sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG); | ||
426 | writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO); | 438 | writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO); |
439 | writel((~TIFM_MMCSD_DPE) | ||
440 | & readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG), | ||
441 | sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG); | ||
427 | } else { | 442 | } else { |
428 | writel(TIFM_MMCSD_DPE | | ||
429 | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG), | ||
430 | sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG); | ||
431 | data_timeout = (data_timeout >> 10) + 1; | 443 | data_timeout = (data_timeout >> 10) + 1; |
432 | if(data_timeout > 0xffff) | 444 | if (data_timeout > 0xffff) |
433 | data_timeout = 0; /* set to unlimited */ | 445 | data_timeout = 0; /* set to unlimited */ |
434 | writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO); | 446 | writel(data_timeout, sock->addr + SOCK_MMCSD_DATA_TO); |
447 | writel(TIFM_MMCSD_DPE | ||
448 | | readl(sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG), | ||
449 | sock->addr + SOCK_MMCSD_SDIO_MODE_CONFIG); | ||
435 | } | 450 | } |
436 | } | 451 | } |
437 | 452 | ||
@@ -474,11 +489,10 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
474 | } | 489 | } |
475 | 490 | ||
476 | host->req = mrq; | 491 | host->req = mrq; |
492 | mod_timer(&host->timer, jiffies + host->timeout_jiffies); | ||
477 | host->state = CMD; | 493 | host->state = CMD; |
478 | queue_delayed_work(sock->wq, &host->abort_handler, | ||
479 | host->timeout_jiffies); | ||
480 | writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), | 494 | writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), |
481 | sock->addr + SOCK_CONTROL); | 495 | sock->addr + SOCK_CONTROL); |
482 | tifm_sd_exec(host, mrq->cmd); | 496 | tifm_sd_exec(host, mrq->cmd); |
483 | spin_unlock_irqrestore(&sock->lock, flags); | 497 | spin_unlock_irqrestore(&sock->lock, flags); |
484 | return; | 498 | return; |
@@ -493,9 +507,9 @@ err_out: | |||
493 | mmc_request_done(mmc, mrq); | 507 | mmc_request_done(mmc, mrq); |
494 | } | 508 | } |
495 | 509 | ||
496 | static void tifm_sd_end_cmd(struct work_struct *work) | 510 | static void tifm_sd_end_cmd(unsigned long data) |
497 | { | 511 | { |
498 | struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); | 512 | struct tifm_sd *host = (struct tifm_sd*)data; |
499 | struct tifm_dev *sock = host->dev; | 513 | struct tifm_dev *sock = host->dev; |
500 | struct mmc_host *mmc = tifm_get_drvdata(sock); | 514 | struct mmc_host *mmc = tifm_get_drvdata(sock); |
501 | struct mmc_request *mrq; | 515 | struct mmc_request *mrq; |
@@ -504,6 +518,7 @@ static void tifm_sd_end_cmd(struct work_struct *work) | |||
504 | 518 | ||
505 | spin_lock_irqsave(&sock->lock, flags); | 519 | spin_lock_irqsave(&sock->lock, flags); |
506 | 520 | ||
521 | del_timer(&host->timer); | ||
507 | mrq = host->req; | 522 | mrq = host->req; |
508 | host->req = NULL; | 523 | host->req = NULL; |
509 | host->state = IDLE; | 524 | host->state = IDLE; |
@@ -517,8 +532,8 @@ static void tifm_sd_end_cmd(struct work_struct *work) | |||
517 | r_data = mrq->cmd->data; | 532 | r_data = mrq->cmd->data; |
518 | if (r_data) { | 533 | if (r_data) { |
519 | if (r_data->flags & MMC_DATA_WRITE) { | 534 | if (r_data->flags & MMC_DATA_WRITE) { |
520 | r_data->bytes_xfered = host->written_blocks * | 535 | r_data->bytes_xfered = host->written_blocks |
521 | r_data->blksz; | 536 | * r_data->blksz; |
522 | } else { | 537 | } else { |
523 | r_data->bytes_xfered = r_data->blocks - | 538 | r_data->bytes_xfered = r_data->blocks - |
524 | readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; | 539 | readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; |
@@ -532,7 +547,7 @@ static void tifm_sd_end_cmd(struct work_struct *work) | |||
532 | } | 547 | } |
533 | 548 | ||
534 | writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), | 549 | writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), |
535 | sock->addr + SOCK_CONTROL); | 550 | sock->addr + SOCK_CONTROL); |
536 | 551 | ||
537 | spin_unlock_irqrestore(&sock->lock, flags); | 552 | spin_unlock_irqrestore(&sock->lock, flags); |
538 | mmc_request_done(mmc, mrq); | 553 | mmc_request_done(mmc, mrq); |
@@ -544,15 +559,6 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) | |||
544 | struct tifm_dev *sock = host->dev; | 559 | struct tifm_dev *sock = host->dev; |
545 | unsigned long flags; | 560 | unsigned long flags; |
546 | struct mmc_data *r_data = mrq->cmd->data; | 561 | struct mmc_data *r_data = mrq->cmd->data; |
547 | char *t_buffer = NULL; | ||
548 | |||
549 | if (r_data) { | ||
550 | t_buffer = kmap(r_data->sg->page); | ||
551 | if (!t_buffer) { | ||
552 | printk(KERN_ERR DRIVER_NAME ": kmap failed\n"); | ||
553 | goto err_out; | ||
554 | } | ||
555 | } | ||
556 | 562 | ||
557 | spin_lock_irqsave(&sock->lock, flags); | 563 | spin_lock_irqsave(&sock->lock, flags); |
558 | if (host->flags & EJECT) { | 564 | if (host->flags & EJECT) { |
@@ -569,15 +575,14 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) | |||
569 | if (r_data) { | 575 | if (r_data) { |
570 | tifm_sd_set_data_timeout(host, r_data); | 576 | tifm_sd_set_data_timeout(host, r_data); |
571 | 577 | ||
572 | host->buffer = t_buffer + r_data->sg->offset; | 578 | host->buffer_size = mrq->cmd->data->blocks |
573 | host->buffer_size = mrq->cmd->data->blocks * | 579 | * mrq->cmd->data->blksz; |
574 | mrq->cmd->data->blksz; | ||
575 | 580 | ||
576 | writel(TIFM_MMCSD_BUFINT | | 581 | writel(TIFM_MMCSD_BUFINT |
577 | readl(sock->addr + SOCK_MMCSD_INT_ENABLE), | 582 | | readl(sock->addr + SOCK_MMCSD_INT_ENABLE), |
578 | sock->addr + SOCK_MMCSD_INT_ENABLE); | 583 | sock->addr + SOCK_MMCSD_INT_ENABLE); |
579 | writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8) | | 584 | writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8) |
580 | (TIFM_MMCSD_FIFO_SIZE - 1), | 585 | | (TIFM_MMCSD_FIFO_SIZE - 1), |
581 | sock->addr + SOCK_MMCSD_BUFFER_CONFIG); | 586 | sock->addr + SOCK_MMCSD_BUFFER_CONFIG); |
582 | 587 | ||
583 | host->written_blocks = 0; | 588 | host->written_blocks = 0; |
@@ -588,26 +593,22 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) | |||
588 | } | 593 | } |
589 | 594 | ||
590 | host->req = mrq; | 595 | host->req = mrq; |
596 | mod_timer(&host->timer, jiffies + host->timeout_jiffies); | ||
591 | host->state = CMD; | 597 | host->state = CMD; |
592 | queue_delayed_work(sock->wq, &host->abort_handler, | ||
593 | host->timeout_jiffies); | ||
594 | writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), | 598 | writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), |
595 | sock->addr + SOCK_CONTROL); | 599 | sock->addr + SOCK_CONTROL); |
596 | tifm_sd_exec(host, mrq->cmd); | 600 | tifm_sd_exec(host, mrq->cmd); |
597 | spin_unlock_irqrestore(&sock->lock, flags); | 601 | spin_unlock_irqrestore(&sock->lock, flags); |
598 | return; | 602 | return; |
599 | 603 | ||
600 | err_out: | 604 | err_out: |
601 | if (t_buffer) | ||
602 | kunmap(r_data->sg->page); | ||
603 | |||
604 | mrq->cmd->error = MMC_ERR_TIMEOUT; | 605 | mrq->cmd->error = MMC_ERR_TIMEOUT; |
605 | mmc_request_done(mmc, mrq); | 606 | mmc_request_done(mmc, mrq); |
606 | } | 607 | } |
607 | 608 | ||
608 | static void tifm_sd_end_cmd_nodma(struct work_struct *work) | 609 | static void tifm_sd_end_cmd_nodma(unsigned long data) |
609 | { | 610 | { |
610 | struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); | 611 | struct tifm_sd *host = (struct tifm_sd*)data; |
611 | struct tifm_dev *sock = host->dev; | 612 | struct tifm_dev *sock = host->dev; |
612 | struct mmc_host *mmc = tifm_get_drvdata(sock); | 613 | struct mmc_host *mmc = tifm_get_drvdata(sock); |
613 | struct mmc_request *mrq; | 614 | struct mmc_request *mrq; |
@@ -616,6 +617,7 @@ static void tifm_sd_end_cmd_nodma(struct work_struct *work) | |||
616 | 617 | ||
617 | spin_lock_irqsave(&sock->lock, flags); | 618 | spin_lock_irqsave(&sock->lock, flags); |
618 | 619 | ||
620 | del_timer(&host->timer); | ||
619 | mrq = host->req; | 621 | mrq = host->req; |
620 | host->req = NULL; | 622 | host->req = NULL; |
621 | host->state = IDLE; | 623 | host->state = IDLE; |
@@ -633,8 +635,8 @@ static void tifm_sd_end_cmd_nodma(struct work_struct *work) | |||
633 | sock->addr + SOCK_MMCSD_INT_ENABLE); | 635 | sock->addr + SOCK_MMCSD_INT_ENABLE); |
634 | 636 | ||
635 | if (r_data->flags & MMC_DATA_WRITE) { | 637 | if (r_data->flags & MMC_DATA_WRITE) { |
636 | r_data->bytes_xfered = host->written_blocks * | 638 | r_data->bytes_xfered = host->written_blocks |
637 | r_data->blksz; | 639 | * r_data->blksz; |
638 | } else { | 640 | } else { |
639 | r_data->bytes_xfered = r_data->blocks - | 641 | r_data->bytes_xfered = r_data->blocks - |
640 | readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; | 642 | readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; |
@@ -642,29 +644,44 @@ static void tifm_sd_end_cmd_nodma(struct work_struct *work) | |||
642 | r_data->bytes_xfered += r_data->blksz - | 644 | r_data->bytes_xfered += r_data->blksz - |
643 | readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1; | 645 | readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1; |
644 | } | 646 | } |
645 | host->buffer = NULL; | ||
646 | host->buffer_pos = 0; | 647 | host->buffer_pos = 0; |
647 | host->buffer_size = 0; | 648 | host->buffer_size = 0; |
648 | } | 649 | } |
649 | 650 | ||
650 | writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), | 651 | writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), |
651 | sock->addr + SOCK_CONTROL); | 652 | sock->addr + SOCK_CONTROL); |
652 | 653 | ||
653 | spin_unlock_irqrestore(&sock->lock, flags); | 654 | spin_unlock_irqrestore(&sock->lock, flags); |
654 | 655 | ||
655 | if (r_data) | ||
656 | kunmap(r_data->sg->page); | ||
657 | |||
658 | mmc_request_done(mmc, mrq); | 656 | mmc_request_done(mmc, mrq); |
659 | } | 657 | } |
660 | 658 | ||
661 | static void tifm_sd_abort(struct work_struct *work) | 659 | static void tifm_sd_terminate(struct tifm_sd *host) |
660 | { | ||
661 | struct tifm_dev *sock = host->dev; | ||
662 | unsigned long flags; | ||
663 | |||
664 | writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); | ||
665 | mmiowb(); | ||
666 | spin_lock_irqsave(&sock->lock, flags); | ||
667 | host->flags |= EJECT; | ||
668 | if (host->req) { | ||
669 | writel(TIFM_FIFO_INT_SETALL, | ||
670 | sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); | ||
671 | writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); | ||
672 | tasklet_schedule(&host->finish_tasklet); | ||
673 | } | ||
674 | spin_unlock_irqrestore(&sock->lock, flags); | ||
675 | } | ||
676 | |||
677 | static void tifm_sd_abort(unsigned long data) | ||
662 | { | 678 | { |
663 | struct tifm_sd *host = | 679 | struct tifm_sd *host = (struct tifm_sd*)data; |
664 | container_of(work, struct tifm_sd, abort_handler.work); | ||
665 | 680 | ||
666 | printk(KERN_ERR DRIVER_NAME | 681 | printk(KERN_ERR DRIVER_NAME |
667 | ": card failed to respond for a long period of time"); | 682 | ": card failed to respond for a long period of time"); |
683 | |||
684 | tifm_sd_terminate(host); | ||
668 | tifm_eject(host->dev); | 685 | tifm_eject(host->dev); |
669 | } | 686 | } |
670 | 687 | ||
@@ -683,9 +700,9 @@ static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
683 | writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG), | 700 | writel(TIFM_MMCSD_4BBUS | readl(sock->addr + SOCK_MMCSD_CONFIG), |
684 | sock->addr + SOCK_MMCSD_CONFIG); | 701 | sock->addr + SOCK_MMCSD_CONFIG); |
685 | } else { | 702 | } else { |
686 | writel((~TIFM_MMCSD_4BBUS) & | 703 | writel((~TIFM_MMCSD_4BBUS) |
687 | readl(sock->addr + SOCK_MMCSD_CONFIG), | 704 | & readl(sock->addr + SOCK_MMCSD_CONFIG), |
688 | sock->addr + SOCK_MMCSD_CONFIG); | 705 | sock->addr + SOCK_MMCSD_CONFIG); |
689 | } | 706 | } |
690 | 707 | ||
691 | if (ios->clock) { | 708 | if (ios->clock) { |
@@ -704,23 +721,24 @@ static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
704 | if ((20000000 / clk_div1) > (24000000 / clk_div2)) { | 721 | if ((20000000 / clk_div1) > (24000000 / clk_div2)) { |
705 | host->clk_freq = 20000000; | 722 | host->clk_freq = 20000000; |
706 | host->clk_div = clk_div1; | 723 | host->clk_div = clk_div1; |
707 | writel((~TIFM_CTRL_FAST_CLK) & | 724 | writel((~TIFM_CTRL_FAST_CLK) |
708 | readl(sock->addr + SOCK_CONTROL), | 725 | & readl(sock->addr + SOCK_CONTROL), |
709 | sock->addr + SOCK_CONTROL); | 726 | sock->addr + SOCK_CONTROL); |
710 | } else { | 727 | } else { |
711 | host->clk_freq = 24000000; | 728 | host->clk_freq = 24000000; |
712 | host->clk_div = clk_div2; | 729 | host->clk_div = clk_div2; |
713 | writel(TIFM_CTRL_FAST_CLK | | 730 | writel(TIFM_CTRL_FAST_CLK |
714 | readl(sock->addr + SOCK_CONTROL), | 731 | | readl(sock->addr + SOCK_CONTROL), |
715 | sock->addr + SOCK_CONTROL); | 732 | sock->addr + SOCK_CONTROL); |
716 | } | 733 | } |
717 | } else { | 734 | } else { |
718 | host->clk_div = 0; | 735 | host->clk_div = 0; |
719 | } | 736 | } |
720 | host->clk_div &= TIFM_MMCSD_CLKMASK; | 737 | host->clk_div &= TIFM_MMCSD_CLKMASK; |
721 | writel(host->clk_div | ((~TIFM_MMCSD_CLKMASK) & | 738 | writel(host->clk_div |
722 | readl(sock->addr + SOCK_MMCSD_CONFIG)), | 739 | | ((~TIFM_MMCSD_CLKMASK) |
723 | sock->addr + SOCK_MMCSD_CONFIG); | 740 | & readl(sock->addr + SOCK_MMCSD_CONFIG)), |
741 | sock->addr + SOCK_MMCSD_CONFIG); | ||
724 | 742 | ||
725 | if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) | 743 | if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) |
726 | host->flags |= OPENDRAIN; | 744 | host->flags |= OPENDRAIN; |
@@ -734,7 +752,7 @@ static void tifm_sd_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
734 | // allow removal. | 752 | // allow removal. |
735 | if ((host->flags & EJECT) && ios->power_mode == MMC_POWER_OFF) { | 753 | if ((host->flags & EJECT) && ios->power_mode == MMC_POWER_OFF) { |
736 | host->flags |= EJECT_DONE; | 754 | host->flags |= EJECT_DONE; |
737 | wake_up_all(&host->can_eject); | 755 | wake_up_all(&host->notify); |
738 | } | 756 | } |
739 | 757 | ||
740 | spin_unlock_irqrestore(&sock->lock, flags); | 758 | spin_unlock_irqrestore(&sock->lock, flags); |
@@ -762,20 +780,67 @@ static struct mmc_host_ops tifm_sd_ops = { | |||
762 | .get_ro = tifm_sd_ro | 780 | .get_ro = tifm_sd_ro |
763 | }; | 781 | }; |
764 | 782 | ||
765 | static void tifm_sd_register_host(struct work_struct *work) | 783 | static int tifm_sd_initialize_host(struct tifm_sd *host) |
766 | { | 784 | { |
767 | struct tifm_sd *host = container_of(work, struct tifm_sd, cmd_handler); | 785 | int rc; |
786 | unsigned int host_status = 0; | ||
768 | struct tifm_dev *sock = host->dev; | 787 | struct tifm_dev *sock = host->dev; |
769 | struct mmc_host *mmc = tifm_get_drvdata(sock); | ||
770 | unsigned long flags; | ||
771 | 788 | ||
772 | spin_lock_irqsave(&sock->lock, flags); | 789 | writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); |
773 | host->flags |= HOST_REG; | 790 | mmiowb(); |
774 | PREPARE_WORK(&host->cmd_handler, | 791 | host->clk_div = 61; |
775 | no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd); | 792 | host->clk_freq = 20000000; |
776 | spin_unlock_irqrestore(&sock->lock, flags); | 793 | writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL); |
777 | dev_dbg(&sock->dev, "adding host\n"); | 794 | writel(host->clk_div | TIFM_MMCSD_POWER, |
778 | mmc_add_host(mmc); | 795 | sock->addr + SOCK_MMCSD_CONFIG); |
796 | |||
797 | /* wait up to 0.51 sec for reset */ | ||
798 | for (rc = 2; rc <= 256; rc <<= 1) { | ||
799 | if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) { | ||
800 | rc = 0; | ||
801 | break; | ||
802 | } | ||
803 | msleep(rc); | ||
804 | } | ||
805 | |||
806 | if (rc) { | ||
807 | printk(KERN_ERR DRIVER_NAME | ||
808 | ": controller failed to reset\n"); | ||
809 | return -ENODEV; | ||
810 | } | ||
811 | |||
812 | writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS); | ||
813 | writel(host->clk_div | TIFM_MMCSD_POWER, | ||
814 | sock->addr + SOCK_MMCSD_CONFIG); | ||
815 | writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); | ||
816 | |||
817 | // command timeout fixed to 64 clocks for now | ||
818 | writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO); | ||
819 | writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND); | ||
820 | |||
821 | /* INAB should take much less than reset */ | ||
822 | for (rc = 1; rc <= 16; rc <<= 1) { | ||
823 | host_status = readl(sock->addr + SOCK_MMCSD_STATUS); | ||
824 | writel(host_status, sock->addr + SOCK_MMCSD_STATUS); | ||
825 | if (!(host_status & TIFM_MMCSD_ERRMASK) | ||
826 | && (host_status & TIFM_MMCSD_EOC)) { | ||
827 | rc = 0; | ||
828 | break; | ||
829 | } | ||
830 | msleep(rc); | ||
831 | } | ||
832 | |||
833 | if (rc) { | ||
834 | printk(KERN_ERR DRIVER_NAME | ||
835 | ": card not ready - probe failed on initialization\n"); | ||
836 | return -ENODEV; | ||
837 | } | ||
838 | |||
839 | writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK, | ||
840 | sock->addr + SOCK_MMCSD_INT_ENABLE); | ||
841 | mmiowb(); | ||
842 | |||
843 | return 0; | ||
779 | } | 844 | } |
780 | 845 | ||
781 | static int tifm_sd_probe(struct tifm_dev *sock) | 846 | static int tifm_sd_probe(struct tifm_dev *sock) |
@@ -784,8 +849,8 @@ static int tifm_sd_probe(struct tifm_dev *sock) | |||
784 | struct tifm_sd *host; | 849 | struct tifm_sd *host; |
785 | int rc = -EIO; | 850 | int rc = -EIO; |
786 | 851 | ||
787 | if (!(TIFM_SOCK_STATE_OCCUPIED & | 852 | if (!(TIFM_SOCK_STATE_OCCUPIED |
788 | readl(sock->addr + SOCK_PRESENT_STATE))) { | 853 | & readl(sock->addr + SOCK_PRESENT_STATE))) { |
789 | printk(KERN_WARNING DRIVER_NAME ": card gone, unexpectedly\n"); | 854 | printk(KERN_WARNING DRIVER_NAME ": card gone, unexpectedly\n"); |
790 | return rc; | 855 | return rc; |
791 | } | 856 | } |
@@ -795,109 +860,99 @@ static int tifm_sd_probe(struct tifm_dev *sock) | |||
795 | return -ENOMEM; | 860 | return -ENOMEM; |
796 | 861 | ||
797 | host = mmc_priv(mmc); | 862 | host = mmc_priv(mmc); |
798 | host->dev = sock; | ||
799 | host->clk_div = 61; | ||
800 | init_waitqueue_head(&host->can_eject); | ||
801 | INIT_WORK(&host->cmd_handler, tifm_sd_register_host); | ||
802 | INIT_DELAYED_WORK(&host->abort_handler, tifm_sd_abort); | ||
803 | |||
804 | tifm_set_drvdata(sock, mmc); | 863 | tifm_set_drvdata(sock, mmc); |
805 | sock->signal_irq = tifm_sd_signal_irq; | 864 | host->dev = sock; |
806 | |||
807 | host->clk_freq = 20000000; | ||
808 | host->timeout_jiffies = msecs_to_jiffies(1000); | 865 | host->timeout_jiffies = msecs_to_jiffies(1000); |
809 | 866 | ||
867 | init_waitqueue_head(&host->notify); | ||
868 | tasklet_init(&host->finish_tasklet, | ||
869 | no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd, | ||
870 | (unsigned long)host); | ||
871 | setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host); | ||
872 | |||
810 | tifm_sd_ops.request = no_dma ? tifm_sd_request_nodma : tifm_sd_request; | 873 | tifm_sd_ops.request = no_dma ? tifm_sd_request_nodma : tifm_sd_request; |
811 | mmc->ops = &tifm_sd_ops; | 874 | mmc->ops = &tifm_sd_ops; |
812 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 875 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
813 | mmc->caps = MMC_CAP_4_BIT_DATA; | 876 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE; |
814 | mmc->f_min = 20000000 / 60; | 877 | mmc->f_min = 20000000 / 60; |
815 | mmc->f_max = 24000000; | 878 | mmc->f_max = 24000000; |
816 | mmc->max_hw_segs = 1; | 879 | mmc->max_hw_segs = 1; |
817 | mmc->max_phys_segs = 1; | 880 | mmc->max_phys_segs = 1; |
818 | mmc->max_sectors = 127; | 881 | // limited by DMA counter - it's safer to stick with |
819 | mmc->max_seg_size = mmc->max_sectors << 11; //2k maximum hw block length | 882 | // block counter has 11 bits though |
820 | 883 | mmc->max_blk_count = 256; | |
821 | writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); | 884 | // 2k maximum hw block length |
822 | writel(TIFM_MMCSD_RESET, sock->addr + SOCK_MMCSD_SYSTEM_CONTROL); | 885 | mmc->max_blk_size = 2048; |
823 | writel(host->clk_div | TIFM_MMCSD_POWER, | 886 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
824 | sock->addr + SOCK_MMCSD_CONFIG); | 887 | mmc->max_seg_size = mmc->max_req_size; |
888 | sock->signal_irq = tifm_sd_signal_irq; | ||
889 | rc = tifm_sd_initialize_host(host); | ||
825 | 890 | ||
826 | for (rc = 0; rc < 50; rc++) { | 891 | if (!rc) |
827 | /* Wait for reset ack */ | 892 | rc = mmc_add_host(mmc); |
828 | if (1 & readl(sock->addr + SOCK_MMCSD_SYSTEM_STATUS)) { | 893 | if (rc) |
829 | rc = 0; | 894 | goto out_free_mmc; |
830 | break; | ||
831 | } | ||
832 | msleep(10); | ||
833 | } | ||
834 | 895 | ||
835 | if (rc) { | 896 | return 0; |
836 | printk(KERN_ERR DRIVER_NAME | 897 | out_free_mmc: |
837 | ": card not ready - probe failed\n"); | 898 | mmc_free_host(mmc); |
838 | mmc_free_host(mmc); | 899 | return rc; |
839 | return -ENODEV; | 900 | } |
840 | } | ||
841 | 901 | ||
842 | writel(0, sock->addr + SOCK_MMCSD_NUM_BLOCKS); | 902 | static void tifm_sd_remove(struct tifm_dev *sock) |
843 | writel(host->clk_div | TIFM_MMCSD_POWER, | 903 | { |
844 | sock->addr + SOCK_MMCSD_CONFIG); | 904 | struct mmc_host *mmc = tifm_get_drvdata(sock); |
845 | writel(TIFM_MMCSD_RXDE, sock->addr + SOCK_MMCSD_BUFFER_CONFIG); | 905 | struct tifm_sd *host = mmc_priv(mmc); |
846 | writel(TIFM_MMCSD_DATAMASK | TIFM_MMCSD_ERRMASK, | ||
847 | sock->addr + SOCK_MMCSD_INT_ENABLE); | ||
848 | 906 | ||
849 | writel(64, sock->addr + SOCK_MMCSD_COMMAND_TO); // command timeout 64 clocks for now | 907 | del_timer_sync(&host->timer); |
850 | writel(TIFM_MMCSD_INAB, sock->addr + SOCK_MMCSD_COMMAND); | 908 | tifm_sd_terminate(host); |
851 | writel(host->clk_div | TIFM_MMCSD_POWER, | 909 | wait_event_timeout(host->notify, host->flags & EJECT_DONE, |
852 | sock->addr + SOCK_MMCSD_CONFIG); | 910 | host->timeout_jiffies); |
911 | tasklet_kill(&host->finish_tasklet); | ||
912 | mmc_remove_host(mmc); | ||
853 | 913 | ||
854 | queue_delayed_work(sock->wq, &host->abort_handler, | 914 | /* The meaning of the bit majority in this constant is unknown. */ |
855 | host->timeout_jiffies); | 915 | writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), |
916 | sock->addr + SOCK_CONTROL); | ||
856 | 917 | ||
857 | return 0; | 918 | tifm_set_drvdata(sock, NULL); |
919 | mmc_free_host(mmc); | ||
858 | } | 920 | } |
859 | 921 | ||
860 | static int tifm_sd_host_is_down(struct tifm_dev *sock) | 922 | #ifdef CONFIG_PM |
923 | |||
924 | static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state) | ||
861 | { | 925 | { |
862 | struct mmc_host *mmc = tifm_get_drvdata(sock); | 926 | struct mmc_host *mmc = tifm_get_drvdata(sock); |
863 | struct tifm_sd *host = mmc_priv(mmc); | 927 | int rc; |
864 | unsigned long flags; | ||
865 | int rc = 0; | ||
866 | 928 | ||
867 | spin_lock_irqsave(&sock->lock, flags); | 929 | rc = mmc_suspend_host(mmc, state); |
868 | rc = (host->flags & EJECT_DONE); | 930 | /* The meaning of the bit majority in this constant is unknown. */ |
869 | spin_unlock_irqrestore(&sock->lock, flags); | 931 | writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), |
932 | sock->addr + SOCK_CONTROL); | ||
870 | return rc; | 933 | return rc; |
871 | } | 934 | } |
872 | 935 | ||
873 | static void tifm_sd_remove(struct tifm_dev *sock) | 936 | static int tifm_sd_resume(struct tifm_dev *sock) |
874 | { | 937 | { |
875 | struct mmc_host *mmc = tifm_get_drvdata(sock); | 938 | struct mmc_host *mmc = tifm_get_drvdata(sock); |
876 | struct tifm_sd *host = mmc_priv(mmc); | 939 | struct tifm_sd *host = mmc_priv(mmc); |
877 | unsigned long flags; | ||
878 | 940 | ||
879 | spin_lock_irqsave(&sock->lock, flags); | 941 | if (sock->media_id != FM_SD |
880 | host->flags |= EJECT; | 942 | || tifm_sd_initialize_host(host)) { |
881 | if (host->req) | 943 | tifm_eject(sock); |
882 | queue_work(sock->wq, &host->cmd_handler); | 944 | return 0; |
883 | spin_unlock_irqrestore(&sock->lock, flags); | 945 | } else { |
884 | wait_event_timeout(host->can_eject, tifm_sd_host_is_down(sock), | 946 | return mmc_resume_host(mmc); |
885 | host->timeout_jiffies); | 947 | } |
948 | } | ||
886 | 949 | ||
887 | if (host->flags & HOST_REG) | 950 | #else |
888 | mmc_remove_host(mmc); | ||
889 | 951 | ||
890 | /* The meaning of the bit majority in this constant is unknown. */ | 952 | #define tifm_sd_suspend NULL |
891 | writel(0xfff8 & readl(sock->addr + SOCK_CONTROL), | 953 | #define tifm_sd_resume NULL |
892 | sock->addr + SOCK_CONTROL); | ||
893 | writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); | ||
894 | writel(TIFM_FIFO_INT_SETALL, | ||
895 | sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); | ||
896 | writel(0, sock->addr + SOCK_DMA_FIFO_INT_ENABLE_SET); | ||
897 | 954 | ||
898 | tifm_set_drvdata(sock, NULL); | 955 | #endif /* CONFIG_PM */ |
899 | mmc_free_host(mmc); | ||
900 | } | ||
901 | 956 | ||
902 | static tifm_media_id tifm_sd_id_tbl[] = { | 957 | static tifm_media_id tifm_sd_id_tbl[] = { |
903 | FM_SD, 0 | 958 | FM_SD, 0 |
@@ -910,7 +965,9 @@ static struct tifm_driver tifm_sd_driver = { | |||
910 | }, | 965 | }, |
911 | .id_table = tifm_sd_id_tbl, | 966 | .id_table = tifm_sd_id_tbl, |
912 | .probe = tifm_sd_probe, | 967 | .probe = tifm_sd_probe, |
913 | .remove = tifm_sd_remove | 968 | .remove = tifm_sd_remove, |
969 | .suspend = tifm_sd_suspend, | ||
970 | .resume = tifm_sd_resume | ||
914 | }; | 971 | }; |
915 | 972 | ||
916 | static int __init tifm_sd_init(void) | 973 | static int __init tifm_sd_init(void) |
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index 7a282672f8e9..a44d8777ab9f 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver | 2 | * linux/drivers/mmc/wbsd.c - Winbond W83L51xD SD/MMC driver |
3 | * | 3 | * |
4 | * Copyright (C) 2004-2005 Pierre Ossman, All Rights Reserved. | 4 | * Copyright (C) 2004-2006 Pierre Ossman, All Rights Reserved. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -272,16 +272,9 @@ static inline int wbsd_next_sg(struct wbsd_host *host) | |||
272 | return host->num_sg; | 272 | return host->num_sg; |
273 | } | 273 | } |
274 | 274 | ||
275 | static inline char *wbsd_kmap_sg(struct wbsd_host *host) | 275 | static inline char *wbsd_sg_to_buffer(struct wbsd_host *host) |
276 | { | 276 | { |
277 | host->mapped_sg = kmap_atomic(host->cur_sg->page, KM_BIO_SRC_IRQ) + | 277 | return page_address(host->cur_sg->page) + host->cur_sg->offset; |
278 | host->cur_sg->offset; | ||
279 | return host->mapped_sg; | ||
280 | } | ||
281 | |||
282 | static inline void wbsd_kunmap_sg(struct wbsd_host *host) | ||
283 | { | ||
284 | kunmap_atomic(host->mapped_sg, KM_BIO_SRC_IRQ); | ||
285 | } | 278 | } |
286 | 279 | ||
287 | static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data) | 280 | static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data) |
@@ -302,12 +295,11 @@ static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data) | |||
302 | * we do not transfer too much. | 295 | * we do not transfer too much. |
303 | */ | 296 | */ |
304 | for (i = 0; i < len; i++) { | 297 | for (i = 0; i < len; i++) { |
305 | sgbuf = kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset; | 298 | sgbuf = page_address(sg[i].page) + sg[i].offset; |
306 | if (size < sg[i].length) | 299 | if (size < sg[i].length) |
307 | memcpy(dmabuf, sgbuf, size); | 300 | memcpy(dmabuf, sgbuf, size); |
308 | else | 301 | else |
309 | memcpy(dmabuf, sgbuf, sg[i].length); | 302 | memcpy(dmabuf, sgbuf, sg[i].length); |
310 | kunmap_atomic(sgbuf, KM_BIO_SRC_IRQ); | ||
311 | dmabuf += sg[i].length; | 303 | dmabuf += sg[i].length; |
312 | 304 | ||
313 | if (size < sg[i].length) | 305 | if (size < sg[i].length) |
@@ -347,7 +339,7 @@ static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data) | |||
347 | * we do not transfer too much. | 339 | * we do not transfer too much. |
348 | */ | 340 | */ |
349 | for (i = 0; i < len; i++) { | 341 | for (i = 0; i < len; i++) { |
350 | sgbuf = kmap_atomic(sg[i].page, KM_BIO_SRC_IRQ) + sg[i].offset; | 342 | sgbuf = page_address(sg[i].page) + sg[i].offset; |
351 | if (size < sg[i].length) | 343 | if (size < sg[i].length) |
352 | memcpy(sgbuf, dmabuf, size); | 344 | memcpy(sgbuf, dmabuf, size); |
353 | else | 345 | else |
@@ -497,7 +489,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host) | |||
497 | if (data->bytes_xfered == host->size) | 489 | if (data->bytes_xfered == host->size) |
498 | return; | 490 | return; |
499 | 491 | ||
500 | buffer = wbsd_kmap_sg(host) + host->offset; | 492 | buffer = wbsd_sg_to_buffer(host) + host->offset; |
501 | 493 | ||
502 | /* | 494 | /* |
503 | * Drain the fifo. This has a tendency to loop longer | 495 | * Drain the fifo. This has a tendency to loop longer |
@@ -526,17 +518,13 @@ static void wbsd_empty_fifo(struct wbsd_host *host) | |||
526 | /* | 518 | /* |
527 | * Transfer done? | 519 | * Transfer done? |
528 | */ | 520 | */ |
529 | if (data->bytes_xfered == host->size) { | 521 | if (data->bytes_xfered == host->size) |
530 | wbsd_kunmap_sg(host); | ||
531 | return; | 522 | return; |
532 | } | ||
533 | 523 | ||
534 | /* | 524 | /* |
535 | * End of scatter list entry? | 525 | * End of scatter list entry? |
536 | */ | 526 | */ |
537 | if (host->remain == 0) { | 527 | if (host->remain == 0) { |
538 | wbsd_kunmap_sg(host); | ||
539 | |||
540 | /* | 528 | /* |
541 | * Get next entry. Check if last. | 529 | * Get next entry. Check if last. |
542 | */ | 530 | */ |
@@ -554,13 +542,11 @@ static void wbsd_empty_fifo(struct wbsd_host *host) | |||
554 | return; | 542 | return; |
555 | } | 543 | } |
556 | 544 | ||
557 | buffer = wbsd_kmap_sg(host); | 545 | buffer = wbsd_sg_to_buffer(host); |
558 | } | 546 | } |
559 | } | 547 | } |
560 | } | 548 | } |
561 | 549 | ||
562 | wbsd_kunmap_sg(host); | ||
563 | |||
564 | /* | 550 | /* |
565 | * This is a very dirty hack to solve a | 551 | * This is a very dirty hack to solve a |
566 | * hardware problem. The chip doesn't trigger | 552 | * hardware problem. The chip doesn't trigger |
@@ -583,7 +569,7 @@ static void wbsd_fill_fifo(struct wbsd_host *host) | |||
583 | if (data->bytes_xfered == host->size) | 569 | if (data->bytes_xfered == host->size) |
584 | return; | 570 | return; |
585 | 571 | ||
586 | buffer = wbsd_kmap_sg(host) + host->offset; | 572 | buffer = wbsd_sg_to_buffer(host) + host->offset; |
587 | 573 | ||
588 | /* | 574 | /* |
589 | * Fill the fifo. This has a tendency to loop longer | 575 | * Fill the fifo. This has a tendency to loop longer |
@@ -612,17 +598,13 @@ static void wbsd_fill_fifo(struct wbsd_host *host) | |||
612 | /* | 598 | /* |
613 | * Transfer done? | 599 | * Transfer done? |
614 | */ | 600 | */ |
615 | if (data->bytes_xfered == host->size) { | 601 | if (data->bytes_xfered == host->size) |
616 | wbsd_kunmap_sg(host); | ||
617 | return; | 602 | return; |
618 | } | ||
619 | 603 | ||
620 | /* | 604 | /* |
621 | * End of scatter list entry? | 605 | * End of scatter list entry? |
622 | */ | 606 | */ |
623 | if (host->remain == 0) { | 607 | if (host->remain == 0) { |
624 | wbsd_kunmap_sg(host); | ||
625 | |||
626 | /* | 608 | /* |
627 | * Get next entry. Check if last. | 609 | * Get next entry. Check if last. |
628 | */ | 610 | */ |
@@ -640,13 +622,11 @@ static void wbsd_fill_fifo(struct wbsd_host *host) | |||
640 | return; | 622 | return; |
641 | } | 623 | } |
642 | 624 | ||
643 | buffer = wbsd_kmap_sg(host); | 625 | buffer = wbsd_sg_to_buffer(host); |
644 | } | 626 | } |
645 | } | 627 | } |
646 | } | 628 | } |
647 | 629 | ||
648 | wbsd_kunmap_sg(host); | ||
649 | |||
650 | /* | 630 | /* |
651 | * The controller stops sending interrupts for | 631 | * The controller stops sending interrupts for |
652 | * 'FIFO empty' under certain conditions. So we | 632 | * 'FIFO empty' under certain conditions. So we |
@@ -910,6 +890,45 @@ static void wbsd_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
910 | */ | 890 | */ |
911 | if (cmd->data && (cmd->error == MMC_ERR_NONE)) { | 891 | if (cmd->data && (cmd->error == MMC_ERR_NONE)) { |
912 | /* | 892 | /* |
893 | * The hardware is so delightfully stupid that it has a list | ||
894 | * of "data" commands. If a command isn't on this list, it'll | ||
895 | * just go back to the idle state and won't send any data | ||
896 | * interrupts. | ||
897 | */ | ||
898 | switch (cmd->opcode) { | ||
899 | case 11: | ||
900 | case 17: | ||
901 | case 18: | ||
902 | case 20: | ||
903 | case 24: | ||
904 | case 25: | ||
905 | case 26: | ||
906 | case 27: | ||
907 | case 30: | ||
908 | case 42: | ||
909 | case 56: | ||
910 | break; | ||
911 | |||
912 | /* ACMDs. We don't keep track of state, so we just treat them | ||
913 | * like any other command. */ | ||
914 | case 51: | ||
915 | break; | ||
916 | |||
917 | default: | ||
918 | #ifdef CONFIG_MMC_DEBUG | ||
919 | printk(KERN_WARNING "%s: Data command %d is not " | ||
920 | "supported by this controller.\n", | ||
921 | mmc_hostname(host->mmc), cmd->opcode); | ||
922 | #endif | ||
923 | cmd->data->error = MMC_ERR_INVALID; | ||
924 | |||
925 | if (cmd->data->stop) | ||
926 | wbsd_send_command(host, cmd->data->stop); | ||
927 | |||
928 | goto done; | ||
929 | }; | ||
930 | |||
931 | /* | ||
913 | * Dirty fix for hardware bug. | 932 | * Dirty fix for hardware bug. |
914 | */ | 933 | */ |
915 | if (host->dma == -1) | 934 | if (host->dma == -1) |
@@ -1343,16 +1362,27 @@ static int __devinit wbsd_alloc_mmc(struct device *dev) | |||
1343 | mmc->max_phys_segs = 128; | 1362 | mmc->max_phys_segs = 128; |
1344 | 1363 | ||
1345 | /* | 1364 | /* |
1346 | * Maximum number of sectors in one transfer. Also limited by 64kB | 1365 | * Maximum request size. Also limited by 64KiB buffer. |
1347 | * buffer. | ||
1348 | */ | 1366 | */ |
1349 | mmc->max_sectors = 128; | 1367 | mmc->max_req_size = 65536; |
1350 | 1368 | ||
1351 | /* | 1369 | /* |
1352 | * Maximum segment size. Could be one segment with the maximum number | 1370 | * Maximum segment size. Could be one segment with the maximum number |
1353 | * of segments. | 1371 | * of bytes. |
1372 | */ | ||
1373 | mmc->max_seg_size = mmc->max_req_size; | ||
1374 | |||
1375 | /* | ||
1376 | * Maximum block size. We have 12 bits (= 4095) but have to subtract | ||
1377 | * space for CRC. So the maximum is 4095 - 4*2 = 4087. | ||
1378 | */ | ||
1379 | mmc->max_blk_size = 4087; | ||
1380 | |||
1381 | /* | ||
1382 | * Maximum block count. There is no real limit so the maximum | ||
1383 | * request size will be the only restriction. | ||
1354 | */ | 1384 | */ |
1355 | mmc->max_seg_size = mmc->max_sectors * 512; | 1385 | mmc->max_blk_count = mmc->max_req_size; |
1356 | 1386 | ||
1357 | dev_set_drvdata(dev, mmc); | 1387 | dev_set_drvdata(dev, mmc); |
1358 | 1388 | ||
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h index 6072993f01e3..d06718b0e2ab 100644 --- a/drivers/mmc/wbsd.h +++ b/drivers/mmc/wbsd.h | |||
@@ -154,7 +154,6 @@ struct wbsd_host | |||
154 | 154 | ||
155 | struct scatterlist* cur_sg; /* Current SG entry */ | 155 | struct scatterlist* cur_sg; /* Current SG entry */ |
156 | unsigned int num_sg; /* Number of entries left */ | 156 | unsigned int num_sg; /* Number of entries left */ |
157 | void* mapped_sg; /* vaddr of mapped sg */ | ||
158 | 157 | ||
159 | unsigned int offset; /* Offset into current entry */ | 158 | unsigned int offset; /* Offset into current entry */ |
160 | unsigned int remain; /* Data left in curren entry */ | 159 | unsigned int remain; /* Data left in curren entry */ |
diff --git a/drivers/s390/Kconfig b/drivers/s390/Kconfig index ae89b9b88743..165af398fdea 100644 --- a/drivers/s390/Kconfig +++ b/drivers/s390/Kconfig | |||
@@ -103,14 +103,8 @@ config CCW_CONSOLE | |||
103 | depends on TN3215_CONSOLE || TN3270_CONSOLE | 103 | depends on TN3215_CONSOLE || TN3270_CONSOLE |
104 | default y | 104 | default y |
105 | 105 | ||
106 | config SCLP | ||
107 | bool "Support for SCLP" | ||
108 | help | ||
109 | Include support for the SCLP interface to the service element. | ||
110 | |||
111 | config SCLP_TTY | 106 | config SCLP_TTY |
112 | bool "Support for SCLP line mode terminal" | 107 | bool "Support for SCLP line mode terminal" |
113 | depends on SCLP | ||
114 | help | 108 | help |
115 | Include support for IBM SCLP line-mode terminals. | 109 | Include support for IBM SCLP line-mode terminals. |
116 | 110 | ||
@@ -123,7 +117,6 @@ config SCLP_CONSOLE | |||
123 | 117 | ||
124 | config SCLP_VT220_TTY | 118 | config SCLP_VT220_TTY |
125 | bool "Support for SCLP VT220-compatible terminal" | 119 | bool "Support for SCLP VT220-compatible terminal" |
126 | depends on SCLP | ||
127 | help | 120 | help |
128 | Include support for an IBM SCLP VT220-compatible terminal. | 121 | Include support for an IBM SCLP VT220-compatible terminal. |
129 | 122 | ||
@@ -136,7 +129,6 @@ config SCLP_VT220_CONSOLE | |||
136 | 129 | ||
137 | config SCLP_CPI | 130 | config SCLP_CPI |
138 | tristate "Control-Program Identification" | 131 | tristate "Control-Program Identification" |
139 | depends on SCLP | ||
140 | help | 132 | help |
141 | This option enables the hardware console interface for system | 133 | This option enables the hardware console interface for system |
142 | identification. This is commonly used for workload management and | 134 | identification. This is commonly used for workload management and |
diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile index 9803c9352d78..5a888704a8d0 100644 --- a/drivers/s390/Makefile +++ b/drivers/s390/Makefile | |||
@@ -2,6 +2,8 @@ | |||
2 | # Makefile for the S/390 specific device drivers | 2 | # Makefile for the S/390 specific device drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w | ||
6 | |||
5 | obj-y += s390mach.o sysinfo.o s390_rdev.o | 7 | obj-y += s390mach.o sysinfo.o s390_rdev.o |
6 | obj-y += cio/ block/ char/ crypto/ net/ scsi/ | 8 | obj-y += cio/ block/ char/ crypto/ net/ scsi/ |
7 | 9 | ||
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 492b68bcd7cc..eb5dc62f0d9c 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -37,6 +37,7 @@ | |||
37 | */ | 37 | */ |
38 | debug_info_t *dasd_debug_area; | 38 | debug_info_t *dasd_debug_area; |
39 | struct dasd_discipline *dasd_diag_discipline_pointer; | 39 | struct dasd_discipline *dasd_diag_discipline_pointer; |
40 | void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *); | ||
40 | 41 | ||
41 | MODULE_AUTHOR("Holger Smolinski <Holger.Smolinski@de.ibm.com>"); | 42 | MODULE_AUTHOR("Holger Smolinski <Holger.Smolinski@de.ibm.com>"); |
42 | MODULE_DESCRIPTION("Linux on S/390 DASD device driver," | 43 | MODULE_DESCRIPTION("Linux on S/390 DASD device driver," |
@@ -51,7 +52,6 @@ static int dasd_alloc_queue(struct dasd_device * device); | |||
51 | static void dasd_setup_queue(struct dasd_device * device); | 52 | static void dasd_setup_queue(struct dasd_device * device); |
52 | static void dasd_free_queue(struct dasd_device * device); | 53 | static void dasd_free_queue(struct dasd_device * device); |
53 | static void dasd_flush_request_queue(struct dasd_device *); | 54 | static void dasd_flush_request_queue(struct dasd_device *); |
54 | static void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *); | ||
55 | static int dasd_flush_ccw_queue(struct dasd_device *, int); | 55 | static int dasd_flush_ccw_queue(struct dasd_device *, int); |
56 | static void dasd_tasklet(struct dasd_device *); | 56 | static void dasd_tasklet(struct dasd_device *); |
57 | static void do_kick_device(struct work_struct *); | 57 | static void do_kick_device(struct work_struct *); |
@@ -483,7 +483,7 @@ unsigned int dasd_profile_level = DASD_PROFILE_OFF; | |||
483 | /* | 483 | /* |
484 | * Add profiling information for cqr before execution. | 484 | * Add profiling information for cqr before execution. |
485 | */ | 485 | */ |
486 | static inline void | 486 | static void |
487 | dasd_profile_start(struct dasd_device *device, struct dasd_ccw_req * cqr, | 487 | dasd_profile_start(struct dasd_device *device, struct dasd_ccw_req * cqr, |
488 | struct request *req) | 488 | struct request *req) |
489 | { | 489 | { |
@@ -505,7 +505,7 @@ dasd_profile_start(struct dasd_device *device, struct dasd_ccw_req * cqr, | |||
505 | /* | 505 | /* |
506 | * Add profiling information for cqr after execution. | 506 | * Add profiling information for cqr after execution. |
507 | */ | 507 | */ |
508 | static inline void | 508 | static void |
509 | dasd_profile_end(struct dasd_device *device, struct dasd_ccw_req * cqr, | 509 | dasd_profile_end(struct dasd_device *device, struct dasd_ccw_req * cqr, |
510 | struct request *req) | 510 | struct request *req) |
511 | { | 511 | { |
@@ -1022,8 +1022,6 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1022 | irb->scsw.cstat == 0 && | 1022 | irb->scsw.cstat == 0 && |
1023 | !irb->esw.esw0.erw.cons) | 1023 | !irb->esw.esw0.erw.cons) |
1024 | era = dasd_era_none; | 1024 | era = dasd_era_none; |
1025 | else if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags)) | ||
1026 | era = dasd_era_fatal; /* don't recover this request */ | ||
1027 | else if (irb->esw.esw0.erw.cons) | 1025 | else if (irb->esw.esw0.erw.cons) |
1028 | era = device->discipline->examine_error(cqr, irb); | 1026 | era = device->discipline->examine_error(cqr, irb); |
1029 | else | 1027 | else |
@@ -1104,7 +1102,7 @@ __dasd_process_erp(struct dasd_device *device, struct dasd_ccw_req *cqr) | |||
1104 | /* | 1102 | /* |
1105 | * Process ccw request queue. | 1103 | * Process ccw request queue. |
1106 | */ | 1104 | */ |
1107 | static inline void | 1105 | static void |
1108 | __dasd_process_ccw_queue(struct dasd_device * device, | 1106 | __dasd_process_ccw_queue(struct dasd_device * device, |
1109 | struct list_head *final_queue) | 1107 | struct list_head *final_queue) |
1110 | { | 1108 | { |
@@ -1127,7 +1125,9 @@ restart: | |||
1127 | cqr->status = DASD_CQR_FAILED; | 1125 | cqr->status = DASD_CQR_FAILED; |
1128 | cqr->stopclk = get_clock(); | 1126 | cqr->stopclk = get_clock(); |
1129 | } else { | 1127 | } else { |
1130 | if (cqr->irb.esw.esw0.erw.cons) { | 1128 | if (cqr->irb.esw.esw0.erw.cons && |
1129 | test_bit(DASD_CQR_FLAGS_USE_ERP, | ||
1130 | &cqr->flags)) { | ||
1131 | erp_fn = device->discipline-> | 1131 | erp_fn = device->discipline-> |
1132 | erp_action(cqr); | 1132 | erp_action(cqr); |
1133 | erp_fn(cqr); | 1133 | erp_fn(cqr); |
@@ -1181,7 +1181,7 @@ dasd_end_request_cb(struct dasd_ccw_req * cqr, void *data) | |||
1181 | /* | 1181 | /* |
1182 | * Fetch requests from the block device queue. | 1182 | * Fetch requests from the block device queue. |
1183 | */ | 1183 | */ |
1184 | static inline void | 1184 | static void |
1185 | __dasd_process_blk_queue(struct dasd_device * device) | 1185 | __dasd_process_blk_queue(struct dasd_device * device) |
1186 | { | 1186 | { |
1187 | request_queue_t *queue; | 1187 | request_queue_t *queue; |
@@ -1232,6 +1232,19 @@ __dasd_process_blk_queue(struct dasd_device * device) | |||
1232 | if (IS_ERR(cqr)) { | 1232 | if (IS_ERR(cqr)) { |
1233 | if (PTR_ERR(cqr) == -ENOMEM) | 1233 | if (PTR_ERR(cqr) == -ENOMEM) |
1234 | break; /* terminate request queue loop */ | 1234 | break; /* terminate request queue loop */ |
1235 | if (PTR_ERR(cqr) == -EAGAIN) { | ||
1236 | /* | ||
1237 | * The current request cannot be build right | ||
1238 | * now, we have to try later. If this request | ||
1239 | * is the head-of-queue we stop the device | ||
1240 | * for 1/2 second. | ||
1241 | */ | ||
1242 | if (!list_empty(&device->ccw_queue)) | ||
1243 | break; | ||
1244 | device->stopped |= DASD_STOPPED_PENDING; | ||
1245 | dasd_set_timer(device, HZ/2); | ||
1246 | break; | ||
1247 | } | ||
1235 | DBF_DEV_EVENT(DBF_ERR, device, | 1248 | DBF_DEV_EVENT(DBF_ERR, device, |
1236 | "CCW creation failed (rc=%ld) " | 1249 | "CCW creation failed (rc=%ld) " |
1237 | "on request %p", | 1250 | "on request %p", |
@@ -1254,7 +1267,7 @@ __dasd_process_blk_queue(struct dasd_device * device) | |||
1254 | * Take a look at the first request on the ccw queue and check | 1267 | * Take a look at the first request on the ccw queue and check |
1255 | * if it reached its expire time. If so, terminate the IO. | 1268 | * if it reached its expire time. If so, terminate the IO. |
1256 | */ | 1269 | */ |
1257 | static inline void | 1270 | static void |
1258 | __dasd_check_expire(struct dasd_device * device) | 1271 | __dasd_check_expire(struct dasd_device * device) |
1259 | { | 1272 | { |
1260 | struct dasd_ccw_req *cqr; | 1273 | struct dasd_ccw_req *cqr; |
@@ -1285,7 +1298,7 @@ __dasd_check_expire(struct dasd_device * device) | |||
1285 | * Take a look at the first request on the ccw queue and check | 1298 | * Take a look at the first request on the ccw queue and check |
1286 | * if it needs to be started. | 1299 | * if it needs to be started. |
1287 | */ | 1300 | */ |
1288 | static inline void | 1301 | static void |
1289 | __dasd_start_head(struct dasd_device * device) | 1302 | __dasd_start_head(struct dasd_device * device) |
1290 | { | 1303 | { |
1291 | struct dasd_ccw_req *cqr; | 1304 | struct dasd_ccw_req *cqr; |
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 4d01040c2c63..8b9d68f6e016 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c | |||
@@ -170,7 +170,6 @@ dasd_3990_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb) | |||
170 | /* log the erp chain if fatal error occurred */ | 170 | /* log the erp chain if fatal error occurred */ |
171 | if ((era == dasd_era_fatal) && (device->state >= DASD_STATE_READY)) { | 171 | if ((era == dasd_era_fatal) && (device->state >= DASD_STATE_READY)) { |
172 | dasd_log_sense(cqr, irb); | 172 | dasd_log_sense(cqr, irb); |
173 | dasd_log_ccw(cqr, 0, irb->scsw.cpa); | ||
174 | } | 173 | } |
175 | 174 | ||
176 | return era; | 175 | return era; |
@@ -2640,7 +2639,6 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) | |||
2640 | 2639 | ||
2641 | struct dasd_ccw_req *erp = NULL; | 2640 | struct dasd_ccw_req *erp = NULL; |
2642 | struct dasd_device *device = cqr->device; | 2641 | struct dasd_device *device = cqr->device; |
2643 | __u32 cpa = cqr->irb.scsw.cpa; | ||
2644 | struct dasd_ccw_req *temp_erp = NULL; | 2642 | struct dasd_ccw_req *temp_erp = NULL; |
2645 | 2643 | ||
2646 | if (device->features & DASD_FEATURE_ERPLOG) { | 2644 | if (device->features & DASD_FEATURE_ERPLOG) { |
@@ -2706,9 +2704,6 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) | |||
2706 | } | 2704 | } |
2707 | } | 2705 | } |
2708 | 2706 | ||
2709 | if (erp->status == DASD_CQR_FAILED) | ||
2710 | dasd_log_ccw(erp, 1, cpa); | ||
2711 | |||
2712 | /* enqueue added ERP request */ | 2707 | /* enqueue added ERP request */ |
2713 | if (erp->status == DASD_CQR_FILLED) { | 2708 | if (erp->status == DASD_CQR_FILLED) { |
2714 | erp->status = DASD_CQR_QUEUED; | 2709 | erp->status = DASD_CQR_QUEUED; |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 5943266152f5..ed70852cc915 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
@@ -136,7 +136,7 @@ __setup ("dasd=", dasd_call_setup); | |||
136 | /* | 136 | /* |
137 | * Read a device busid/devno from a string. | 137 | * Read a device busid/devno from a string. |
138 | */ | 138 | */ |
139 | static inline int | 139 | static int |
140 | dasd_busid(char **str, int *id0, int *id1, int *devno) | 140 | dasd_busid(char **str, int *id0, int *id1, int *devno) |
141 | { | 141 | { |
142 | int val, old_style; | 142 | int val, old_style; |
@@ -182,7 +182,7 @@ dasd_busid(char **str, int *id0, int *id1, int *devno) | |||
182 | * only one: "ro" for read-only devices. The default feature set | 182 | * only one: "ro" for read-only devices. The default feature set |
183 | * is empty (value 0). | 183 | * is empty (value 0). |
184 | */ | 184 | */ |
185 | static inline int | 185 | static int |
186 | dasd_feature_list(char *str, char **endp) | 186 | dasd_feature_list(char *str, char **endp) |
187 | { | 187 | { |
188 | int features, len, rc; | 188 | int features, len, rc; |
@@ -341,7 +341,7 @@ dasd_parse_range( char *parsestring ) { | |||
341 | return ERR_PTR(-EINVAL); | 341 | return ERR_PTR(-EINVAL); |
342 | } | 342 | } |
343 | 343 | ||
344 | static inline char * | 344 | static char * |
345 | dasd_parse_next_element( char *parsestring ) { | 345 | dasd_parse_next_element( char *parsestring ) { |
346 | char * residual_str; | 346 | char * residual_str; |
347 | residual_str = dasd_parse_keyword(parsestring); | 347 | residual_str = dasd_parse_keyword(parsestring); |
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 53db58a68617..ab782bb46ac1 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
@@ -43,7 +43,7 @@ MODULE_LICENSE("GPL"); | |||
43 | #define DIAG_MAX_RETRIES 32 | 43 | #define DIAG_MAX_RETRIES 32 |
44 | #define DIAG_TIMEOUT 50 * HZ | 44 | #define DIAG_TIMEOUT 50 * HZ |
45 | 45 | ||
46 | struct dasd_discipline dasd_diag_discipline; | 46 | static struct dasd_discipline dasd_diag_discipline; |
47 | 47 | ||
48 | struct dasd_diag_private { | 48 | struct dasd_diag_private { |
49 | struct dasd_diag_characteristics rdc_data; | 49 | struct dasd_diag_characteristics rdc_data; |
@@ -90,7 +90,7 @@ static inline int dia250(void *iob, int cmd) | |||
90 | * block offset. On success, return zero and set end_block to contain the | 90 | * block offset. On success, return zero and set end_block to contain the |
91 | * number of blocks on the device minus the specified offset. Return non-zero | 91 | * number of blocks on the device minus the specified offset. Return non-zero |
92 | * otherwise. */ | 92 | * otherwise. */ |
93 | static __inline__ int | 93 | static inline int |
94 | mdsk_init_io(struct dasd_device *device, unsigned int blocksize, | 94 | mdsk_init_io(struct dasd_device *device, unsigned int blocksize, |
95 | blocknum_t offset, blocknum_t *end_block) | 95 | blocknum_t offset, blocknum_t *end_block) |
96 | { | 96 | { |
@@ -117,7 +117,7 @@ mdsk_init_io(struct dasd_device *device, unsigned int blocksize, | |||
117 | 117 | ||
118 | /* Remove block I/O environment for device. Return zero on success, non-zero | 118 | /* Remove block I/O environment for device. Return zero on success, non-zero |
119 | * otherwise. */ | 119 | * otherwise. */ |
120 | static __inline__ int | 120 | static inline int |
121 | mdsk_term_io(struct dasd_device * device) | 121 | mdsk_term_io(struct dasd_device * device) |
122 | { | 122 | { |
123 | struct dasd_diag_private *private; | 123 | struct dasd_diag_private *private; |
@@ -576,7 +576,7 @@ dasd_diag_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, | |||
576 | "dump sense not available for DIAG data"); | 576 | "dump sense not available for DIAG data"); |
577 | } | 577 | } |
578 | 578 | ||
579 | struct dasd_discipline dasd_diag_discipline = { | 579 | static struct dasd_discipline dasd_diag_discipline = { |
580 | .owner = THIS_MODULE, | 580 | .owner = THIS_MODULE, |
581 | .name = "DIAG", | 581 | .name = "DIAG", |
582 | .ebcname = "DIAG", | 582 | .ebcname = "DIAG", |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index fdaa471e845f..cecab2274a6e 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -134,44 +134,7 @@ ceil_quot(unsigned int d1, unsigned int d2) | |||
134 | return (d1 + (d2 - 1)) / d2; | 134 | return (d1 + (d2 - 1)) / d2; |
135 | } | 135 | } |
136 | 136 | ||
137 | static inline int | 137 | static unsigned int |
138 | bytes_per_record(struct dasd_eckd_characteristics *rdc, int kl, int dl) | ||
139 | { | ||
140 | unsigned int fl1, fl2, int1, int2; | ||
141 | int bpr; | ||
142 | |||
143 | switch (rdc->formula) { | ||
144 | case 0x01: | ||
145 | fl1 = round_up_multiple(ECKD_F2(rdc) + dl, ECKD_F1(rdc)); | ||
146 | fl2 = round_up_multiple(kl ? ECKD_F2(rdc) + kl : 0, | ||
147 | ECKD_F1(rdc)); | ||
148 | bpr = fl1 + fl2; | ||
149 | break; | ||
150 | case 0x02: | ||
151 | int1 = ceil_quot(dl + ECKD_F6(rdc), ECKD_F5(rdc) << 1); | ||
152 | int2 = ceil_quot(kl + ECKD_F6(rdc), ECKD_F5(rdc) << 1); | ||
153 | fl1 = round_up_multiple(ECKD_F1(rdc) * ECKD_F2(rdc) + dl + | ||
154 | ECKD_F6(rdc) + ECKD_F4(rdc) * int1, | ||
155 | ECKD_F1(rdc)); | ||
156 | fl2 = round_up_multiple(ECKD_F1(rdc) * ECKD_F3(rdc) + kl + | ||
157 | ECKD_F6(rdc) + ECKD_F4(rdc) * int2, | ||
158 | ECKD_F1(rdc)); | ||
159 | bpr = fl1 + fl2; | ||
160 | break; | ||
161 | default: | ||
162 | bpr = 0; | ||
163 | break; | ||
164 | } | ||
165 | return bpr; | ||
166 | } | ||
167 | |||
168 | static inline unsigned int | ||
169 | bytes_per_track(struct dasd_eckd_characteristics *rdc) | ||
170 | { | ||
171 | return *(unsigned int *) (rdc->byte_per_track) >> 8; | ||
172 | } | ||
173 | |||
174 | static inline unsigned int | ||
175 | recs_per_track(struct dasd_eckd_characteristics * rdc, | 138 | recs_per_track(struct dasd_eckd_characteristics * rdc, |
176 | unsigned int kl, unsigned int dl) | 139 | unsigned int kl, unsigned int dl) |
177 | { | 140 | { |
@@ -204,37 +167,39 @@ recs_per_track(struct dasd_eckd_characteristics * rdc, | |||
204 | return 0; | 167 | return 0; |
205 | } | 168 | } |
206 | 169 | ||
207 | static inline void | 170 | static int |
208 | check_XRC (struct ccw1 *de_ccw, | 171 | check_XRC (struct ccw1 *de_ccw, |
209 | struct DE_eckd_data *data, | 172 | struct DE_eckd_data *data, |
210 | struct dasd_device *device) | 173 | struct dasd_device *device) |
211 | { | 174 | { |
212 | struct dasd_eckd_private *private; | 175 | struct dasd_eckd_private *private; |
176 | int rc; | ||
213 | 177 | ||
214 | private = (struct dasd_eckd_private *) device->private; | 178 | private = (struct dasd_eckd_private *) device->private; |
179 | if (!private->rdc_data.facilities.XRC_supported) | ||
180 | return 0; | ||
215 | 181 | ||
216 | /* switch on System Time Stamp - needed for XRC Support */ | 182 | /* switch on System Time Stamp - needed for XRC Support */ |
217 | if (private->rdc_data.facilities.XRC_supported) { | 183 | data->ga_extended |= 0x08; /* switch on 'Time Stamp Valid' */ |
218 | 184 | data->ga_extended |= 0x02; /* switch on 'Extended Parameter' */ | |
219 | data->ga_extended |= 0x08; /* switch on 'Time Stamp Valid' */ | ||
220 | data->ga_extended |= 0x02; /* switch on 'Extended Parameter' */ | ||
221 | |||
222 | data->ep_sys_time = get_clock (); | ||
223 | |||
224 | de_ccw->count = sizeof (struct DE_eckd_data); | ||
225 | de_ccw->flags |= CCW_FLAG_SLI; | ||
226 | } | ||
227 | 185 | ||
228 | return; | 186 | rc = get_sync_clock(&data->ep_sys_time); |
187 | /* Ignore return code if sync clock is switched off. */ | ||
188 | if (rc == -ENOSYS || rc == -EACCES) | ||
189 | rc = 0; | ||
229 | 190 | ||
230 | } /* end check_XRC */ | 191 | de_ccw->count = sizeof (struct DE_eckd_data); |
192 | de_ccw->flags |= CCW_FLAG_SLI; | ||
193 | return rc; | ||
194 | } | ||
231 | 195 | ||
232 | static inline void | 196 | static int |
233 | define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, | 197 | define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, |
234 | int totrk, int cmd, struct dasd_device * device) | 198 | int totrk, int cmd, struct dasd_device * device) |
235 | { | 199 | { |
236 | struct dasd_eckd_private *private; | 200 | struct dasd_eckd_private *private; |
237 | struct ch_t geo, beg, end; | 201 | struct ch_t geo, beg, end; |
202 | int rc = 0; | ||
238 | 203 | ||
239 | private = (struct dasd_eckd_private *) device->private; | 204 | private = (struct dasd_eckd_private *) device->private; |
240 | 205 | ||
@@ -263,12 +228,12 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, | |||
263 | case DASD_ECKD_CCW_WRITE_KD_MT: | 228 | case DASD_ECKD_CCW_WRITE_KD_MT: |
264 | data->mask.perm = 0x02; | 229 | data->mask.perm = 0x02; |
265 | data->attributes.operation = private->attrib.operation; | 230 | data->attributes.operation = private->attrib.operation; |
266 | check_XRC (ccw, data, device); | 231 | rc = check_XRC (ccw, data, device); |
267 | break; | 232 | break; |
268 | case DASD_ECKD_CCW_WRITE_CKD: | 233 | case DASD_ECKD_CCW_WRITE_CKD: |
269 | case DASD_ECKD_CCW_WRITE_CKD_MT: | 234 | case DASD_ECKD_CCW_WRITE_CKD_MT: |
270 | data->attributes.operation = DASD_BYPASS_CACHE; | 235 | data->attributes.operation = DASD_BYPASS_CACHE; |
271 | check_XRC (ccw, data, device); | 236 | rc = check_XRC (ccw, data, device); |
272 | break; | 237 | break; |
273 | case DASD_ECKD_CCW_ERASE: | 238 | case DASD_ECKD_CCW_ERASE: |
274 | case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: | 239 | case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: |
@@ -276,7 +241,7 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, | |||
276 | data->mask.perm = 0x3; | 241 | data->mask.perm = 0x3; |
277 | data->mask.auth = 0x1; | 242 | data->mask.auth = 0x1; |
278 | data->attributes.operation = DASD_BYPASS_CACHE; | 243 | data->attributes.operation = DASD_BYPASS_CACHE; |
279 | check_XRC (ccw, data, device); | 244 | rc = check_XRC (ccw, data, device); |
280 | break; | 245 | break; |
281 | default: | 246 | default: |
282 | DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd); | 247 | DEV_MESSAGE(KERN_ERR, device, "unknown opcode 0x%x", cmd); |
@@ -312,9 +277,10 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, | |||
312 | data->beg_ext.head = beg.head; | 277 | data->beg_ext.head = beg.head; |
313 | data->end_ext.cyl = end.cyl; | 278 | data->end_ext.cyl = end.cyl; |
314 | data->end_ext.head = end.head; | 279 | data->end_ext.head = end.head; |
280 | return rc; | ||
315 | } | 281 | } |
316 | 282 | ||
317 | static inline void | 283 | static void |
318 | locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk, | 284 | locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk, |
319 | int rec_on_trk, int no_rec, int cmd, | 285 | int rec_on_trk, int no_rec, int cmd, |
320 | struct dasd_device * device, int reclen) | 286 | struct dasd_device * device, int reclen) |
@@ -548,7 +514,7 @@ dasd_eckd_read_conf(struct dasd_device *device) | |||
548 | /* | 514 | /* |
549 | * Build CP for Perform Subsystem Function - SSC. | 515 | * Build CP for Perform Subsystem Function - SSC. |
550 | */ | 516 | */ |
551 | struct dasd_ccw_req * | 517 | static struct dasd_ccw_req * |
552 | dasd_eckd_build_psf_ssc(struct dasd_device *device) | 518 | dasd_eckd_build_psf_ssc(struct dasd_device *device) |
553 | { | 519 | { |
554 | struct dasd_ccw_req *cqr; | 520 | struct dasd_ccw_req *cqr; |
@@ -1200,7 +1166,12 @@ dasd_eckd_build_cp(struct dasd_device * device, struct request *req) | |||
1200 | return cqr; | 1166 | return cqr; |
1201 | ccw = cqr->cpaddr; | 1167 | ccw = cqr->cpaddr; |
1202 | /* First ccw is define extent. */ | 1168 | /* First ccw is define extent. */ |
1203 | define_extent(ccw++, cqr->data, first_trk, last_trk, cmd, device); | 1169 | if (define_extent(ccw++, cqr->data, first_trk, |
1170 | last_trk, cmd, device) == -EAGAIN) { | ||
1171 | /* Clock not in sync and XRC is enabled. Try again later. */ | ||
1172 | dasd_sfree_request(cqr, device); | ||
1173 | return ERR_PTR(-EAGAIN); | ||
1174 | } | ||
1204 | /* Build locate_record+read/write/ccws. */ | 1175 | /* Build locate_record+read/write/ccws. */ |
1205 | idaws = (unsigned long *) (cqr->data + sizeof(struct DE_eckd_data)); | 1176 | idaws = (unsigned long *) (cqr->data + sizeof(struct DE_eckd_data)); |
1206 | LO_data = (struct LO_eckd_data *) (idaws + cidaw); | 1177 | LO_data = (struct LO_eckd_data *) (idaws + cidaw); |
@@ -1380,7 +1351,7 @@ dasd_eckd_release(struct dasd_device *device) | |||
1380 | cqr->device = device; | 1351 | cqr->device = device; |
1381 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | 1352 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); |
1382 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); | 1353 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); |
1383 | cqr->retries = 0; | 1354 | cqr->retries = 2; /* set retry counter to enable basic ERP */ |
1384 | cqr->expires = 2 * HZ; | 1355 | cqr->expires = 2 * HZ; |
1385 | cqr->buildclk = get_clock(); | 1356 | cqr->buildclk = get_clock(); |
1386 | cqr->status = DASD_CQR_FILLED; | 1357 | cqr->status = DASD_CQR_FILLED; |
@@ -1420,7 +1391,7 @@ dasd_eckd_reserve(struct dasd_device *device) | |||
1420 | cqr->device = device; | 1391 | cqr->device = device; |
1421 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | 1392 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); |
1422 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); | 1393 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); |
1423 | cqr->retries = 0; | 1394 | cqr->retries = 2; /* set retry counter to enable basic ERP */ |
1424 | cqr->expires = 2 * HZ; | 1395 | cqr->expires = 2 * HZ; |
1425 | cqr->buildclk = get_clock(); | 1396 | cqr->buildclk = get_clock(); |
1426 | cqr->status = DASD_CQR_FILLED; | 1397 | cqr->status = DASD_CQR_FILLED; |
@@ -1459,7 +1430,7 @@ dasd_eckd_steal_lock(struct dasd_device *device) | |||
1459 | cqr->device = device; | 1430 | cqr->device = device; |
1460 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | 1431 | clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); |
1461 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); | 1432 | set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags); |
1462 | cqr->retries = 0; | 1433 | cqr->retries = 2; /* set retry counter to enable basic ERP */ |
1463 | cqr->expires = 2 * HZ; | 1434 | cqr->expires = 2 * HZ; |
1464 | cqr->buildclk = get_clock(); | 1435 | cqr->buildclk = get_clock(); |
1465 | cqr->status = DASD_CQR_FILLED; | 1436 | cqr->status = DASD_CQR_FILLED; |
@@ -1609,7 +1580,7 @@ dasd_eckd_ioctl(struct dasd_device *device, unsigned int cmd, void __user *argp) | |||
1609 | * Dump the range of CCWs into 'page' buffer | 1580 | * Dump the range of CCWs into 'page' buffer |
1610 | * and return number of printed chars. | 1581 | * and return number of printed chars. |
1611 | */ | 1582 | */ |
1612 | static inline int | 1583 | static int |
1613 | dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page) | 1584 | dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page) |
1614 | { | 1585 | { |
1615 | int len, count; | 1586 | int len, count; |
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index e0bf30ebb215..6cedc914077e 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c | |||
@@ -658,18 +658,24 @@ static struct file_operations dasd_eer_fops = { | |||
658 | .owner = THIS_MODULE, | 658 | .owner = THIS_MODULE, |
659 | }; | 659 | }; |
660 | 660 | ||
661 | static struct miscdevice dasd_eer_dev = { | 661 | static struct miscdevice *dasd_eer_dev = NULL; |
662 | .minor = MISC_DYNAMIC_MINOR, | ||
663 | .name = "dasd_eer", | ||
664 | .fops = &dasd_eer_fops, | ||
665 | }; | ||
666 | 662 | ||
667 | int __init dasd_eer_init(void) | 663 | int __init dasd_eer_init(void) |
668 | { | 664 | { |
669 | int rc; | 665 | int rc; |
670 | 666 | ||
671 | rc = misc_register(&dasd_eer_dev); | 667 | dasd_eer_dev = kzalloc(sizeof(*dasd_eer_dev), GFP_KERNEL); |
668 | if (!dasd_eer_dev) | ||
669 | return -ENOMEM; | ||
670 | |||
671 | dasd_eer_dev->minor = MISC_DYNAMIC_MINOR; | ||
672 | dasd_eer_dev->name = "dasd_eer"; | ||
673 | dasd_eer_dev->fops = &dasd_eer_fops; | ||
674 | |||
675 | rc = misc_register(dasd_eer_dev); | ||
672 | if (rc) { | 676 | if (rc) { |
677 | kfree(dasd_eer_dev); | ||
678 | dasd_eer_dev = NULL; | ||
673 | MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " | 679 | MESSAGE(KERN_ERR, "%s", "dasd_eer_init could not " |
674 | "register misc device"); | 680 | "register misc device"); |
675 | return rc; | 681 | return rc; |
@@ -680,5 +686,9 @@ int __init dasd_eer_init(void) | |||
680 | 686 | ||
681 | void dasd_eer_exit(void) | 687 | void dasd_eer_exit(void) |
682 | { | 688 | { |
683 | WARN_ON(misc_deregister(&dasd_eer_dev) != 0); | 689 | if (dasd_eer_dev) { |
690 | WARN_ON(misc_deregister(dasd_eer_dev) != 0); | ||
691 | kfree(dasd_eer_dev); | ||
692 | dasd_eer_dev = NULL; | ||
693 | } | ||
684 | } | 694 | } |
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c index 58a65097922b..caa5d91420f8 100644 --- a/drivers/s390/block/dasd_erp.c +++ b/drivers/s390/block/dasd_erp.c | |||
@@ -152,25 +152,6 @@ dasd_default_erp_postaction(struct dasd_ccw_req * cqr) | |||
152 | 152 | ||
153 | } /* end default_erp_postaction */ | 153 | } /* end default_erp_postaction */ |
154 | 154 | ||
155 | /* | ||
156 | * Print the hex dump of the memory used by a request. This includes | ||
157 | * all error recovery ccws that have been chained in from of the | ||
158 | * real request. | ||
159 | */ | ||
160 | static inline void | ||
161 | hex_dump_memory(struct dasd_device *device, void *data, int len) | ||
162 | { | ||
163 | int *pint; | ||
164 | |||
165 | pint = (int *) data; | ||
166 | while (len > 0) { | ||
167 | DEV_MESSAGE(KERN_ERR, device, "%p: %08x %08x %08x %08x", | ||
168 | pint, pint[0], pint[1], pint[2], pint[3]); | ||
169 | pint += 4; | ||
170 | len -= 16; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | void | 155 | void |
175 | dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb) | 156 | dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb) |
176 | { | 157 | { |
@@ -182,69 +163,8 @@ dasd_log_sense(struct dasd_ccw_req *cqr, struct irb *irb) | |||
182 | device->discipline->dump_sense(device, cqr, irb); | 163 | device->discipline->dump_sense(device, cqr, irb); |
183 | } | 164 | } |
184 | 165 | ||
185 | void | ||
186 | dasd_log_ccw(struct dasd_ccw_req * cqr, int caller, __u32 cpa) | ||
187 | { | ||
188 | struct dasd_device *device; | ||
189 | struct dasd_ccw_req *lcqr; | ||
190 | struct ccw1 *ccw; | ||
191 | int cplength; | ||
192 | |||
193 | device = cqr->device; | ||
194 | /* log the channel program */ | ||
195 | for (lcqr = cqr; lcqr != NULL; lcqr = lcqr->refers) { | ||
196 | DEV_MESSAGE(KERN_ERR, device, | ||
197 | "(%s) ERP chain report for req: %p", | ||
198 | caller == 0 ? "EXAMINE" : "ACTION", lcqr); | ||
199 | hex_dump_memory(device, lcqr, sizeof(struct dasd_ccw_req)); | ||
200 | |||
201 | cplength = 1; | ||
202 | ccw = lcqr->cpaddr; | ||
203 | while (ccw++->flags & (CCW_FLAG_DC | CCW_FLAG_CC)) | ||
204 | cplength++; | ||
205 | |||
206 | if (cplength > 40) { /* log only parts of the CP */ | ||
207 | DEV_MESSAGE(KERN_ERR, device, "%s", | ||
208 | "Start of channel program:"); | ||
209 | hex_dump_memory(device, lcqr->cpaddr, | ||
210 | 40*sizeof(struct ccw1)); | ||
211 | |||
212 | DEV_MESSAGE(KERN_ERR, device, "%s", | ||
213 | "End of channel program:"); | ||
214 | hex_dump_memory(device, lcqr->cpaddr + cplength - 10, | ||
215 | 10*sizeof(struct ccw1)); | ||
216 | } else { /* log the whole CP */ | ||
217 | DEV_MESSAGE(KERN_ERR, device, "%s", | ||
218 | "Channel program (complete):"); | ||
219 | hex_dump_memory(device, lcqr->cpaddr, | ||
220 | cplength*sizeof(struct ccw1)); | ||
221 | } | ||
222 | |||
223 | if (lcqr != cqr) | ||
224 | continue; | ||
225 | |||
226 | /* | ||
227 | * Log bytes arround failed CCW but only if we did | ||
228 | * not log the whole CP of the CCW is outside the | ||
229 | * logged CP. | ||
230 | */ | ||
231 | if (cplength > 40 || | ||
232 | ((addr_t) cpa < (addr_t) lcqr->cpaddr && | ||
233 | (addr_t) cpa > (addr_t) (lcqr->cpaddr + cplength + 4))) { | ||
234 | |||
235 | DEV_MESSAGE(KERN_ERR, device, | ||
236 | "Failed CCW (%p) (area):", | ||
237 | (void *) (long) cpa); | ||
238 | hex_dump_memory(device, cqr->cpaddr - 10, | ||
239 | 20*sizeof(struct ccw1)); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | } /* end log_erp_chain */ | ||
244 | |||
245 | EXPORT_SYMBOL(dasd_default_erp_action); | 166 | EXPORT_SYMBOL(dasd_default_erp_action); |
246 | EXPORT_SYMBOL(dasd_default_erp_postaction); | 167 | EXPORT_SYMBOL(dasd_default_erp_postaction); |
247 | EXPORT_SYMBOL(dasd_alloc_erp_request); | 168 | EXPORT_SYMBOL(dasd_alloc_erp_request); |
248 | EXPORT_SYMBOL(dasd_free_erp_request); | 169 | EXPORT_SYMBOL(dasd_free_erp_request); |
249 | EXPORT_SYMBOL(dasd_log_sense); | 170 | EXPORT_SYMBOL(dasd_log_sense); |
250 | EXPORT_SYMBOL(dasd_log_ccw); | ||
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index b857fd5893fd..be0909e39226 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c | |||
@@ -75,7 +75,7 @@ static struct ccw_driver dasd_fba_driver = { | |||
75 | .notify = dasd_generic_notify, | 75 | .notify = dasd_generic_notify, |
76 | }; | 76 | }; |
77 | 77 | ||
78 | static inline void | 78 | static void |
79 | define_extent(struct ccw1 * ccw, struct DE_fba_data *data, int rw, | 79 | define_extent(struct ccw1 * ccw, struct DE_fba_data *data, int rw, |
80 | int blksize, int beg, int nr) | 80 | int blksize, int beg, int nr) |
81 | { | 81 | { |
@@ -95,7 +95,7 @@ define_extent(struct ccw1 * ccw, struct DE_fba_data *data, int rw, | |||
95 | data->ext_end = nr - 1; | 95 | data->ext_end = nr - 1; |
96 | } | 96 | } |
97 | 97 | ||
98 | static inline void | 98 | static void |
99 | locate_record(struct ccw1 * ccw, struct LO_fba_data *data, int rw, | 99 | locate_record(struct ccw1 * ccw, struct LO_fba_data *data, int rw, |
100 | int block_nr, int block_ct) | 100 | int block_nr, int block_ct) |
101 | { | 101 | { |
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c index d163632101d2..47ba4462708d 100644 --- a/drivers/s390/block/dasd_genhd.c +++ b/drivers/s390/block/dasd_genhd.c | |||
@@ -147,7 +147,7 @@ dasd_destroy_partitions(struct dasd_device * device) | |||
147 | */ | 147 | */ |
148 | memset(&bpart, 0, sizeof(struct blkpg_partition)); | 148 | memset(&bpart, 0, sizeof(struct blkpg_partition)); |
149 | memset(&barg, 0, sizeof(struct blkpg_ioctl_arg)); | 149 | memset(&barg, 0, sizeof(struct blkpg_ioctl_arg)); |
150 | barg.data = (void __user *) &bpart; | 150 | barg.data = (void __force __user *) &bpart; |
151 | barg.op = BLKPG_DEL_PARTITION; | 151 | barg.op = BLKPG_DEL_PARTITION; |
152 | for (bpart.pno = device->gdp->minors - 1; bpart.pno > 0; bpart.pno--) | 152 | for (bpart.pno = device->gdp->minors - 1; bpart.pno > 0; bpart.pno--) |
153 | ioctl_by_bdev(bdev, BLKPG, (unsigned long) &barg); | 153 | ioctl_by_bdev(bdev, BLKPG, (unsigned long) &barg); |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index fb725e3b08fe..a2cc69e11410 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -559,7 +559,6 @@ struct dasd_ccw_req *dasd_alloc_erp_request(char *, int, int, | |||
559 | struct dasd_device *); | 559 | struct dasd_device *); |
560 | void dasd_free_erp_request(struct dasd_ccw_req *, struct dasd_device *); | 560 | void dasd_free_erp_request(struct dasd_ccw_req *, struct dasd_device *); |
561 | void dasd_log_sense(struct dasd_ccw_req *, struct irb *); | 561 | void dasd_log_sense(struct dasd_ccw_req *, struct irb *); |
562 | void dasd_log_ccw(struct dasd_ccw_req *, int, __u32); | ||
563 | 562 | ||
564 | /* externals in dasd_3370_erp.c */ | 563 | /* externals in dasd_3370_erp.c */ |
565 | dasd_era_t dasd_3370_erp_examine(struct dasd_ccw_req *, struct irb *); | 564 | dasd_era_t dasd_3370_erp_examine(struct dasd_ccw_req *, struct irb *); |
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index bfa010f6dab2..8b7e11815d70 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c | |||
@@ -28,7 +28,7 @@ static struct proc_dir_entry *dasd_proc_root_entry = NULL; | |||
28 | static struct proc_dir_entry *dasd_devices_entry = NULL; | 28 | static struct proc_dir_entry *dasd_devices_entry = NULL; |
29 | static struct proc_dir_entry *dasd_statistics_entry = NULL; | 29 | static struct proc_dir_entry *dasd_statistics_entry = NULL; |
30 | 30 | ||
31 | static inline char * | 31 | static char * |
32 | dasd_get_user_string(const char __user *user_buf, size_t user_len) | 32 | dasd_get_user_string(const char __user *user_buf, size_t user_len) |
33 | { | 33 | { |
34 | char *buffer; | 34 | char *buffer; |
@@ -154,7 +154,7 @@ static struct file_operations dasd_devices_file_ops = { | |||
154 | .release = seq_release, | 154 | .release = seq_release, |
155 | }; | 155 | }; |
156 | 156 | ||
157 | static inline int | 157 | static int |
158 | dasd_calc_metrics(char *page, char **start, off_t off, | 158 | dasd_calc_metrics(char *page, char **start, off_t off, |
159 | int count, int *eof, int len) | 159 | int count, int *eof, int len) |
160 | { | 160 | { |
@@ -167,8 +167,8 @@ dasd_calc_metrics(char *page, char **start, off_t off, | |||
167 | return len; | 167 | return len; |
168 | } | 168 | } |
169 | 169 | ||
170 | static inline char * | 170 | static char * |
171 | dasd_statistics_array(char *str, int *array, int shift) | 171 | dasd_statistics_array(char *str, unsigned int *array, int shift) |
172 | { | 172 | { |
173 | int i; | 173 | int i; |
174 | 174 | ||
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index be9b05347b4f..1340451ea408 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c | |||
@@ -102,7 +102,7 @@ dcssblk_release_segment(struct device *dev) | |||
102 | * device needs to be enqueued before the semaphore is | 102 | * device needs to be enqueued before the semaphore is |
103 | * freed. | 103 | * freed. |
104 | */ | 104 | */ |
105 | static inline int | 105 | static int |
106 | dcssblk_assign_free_minor(struct dcssblk_dev_info *dev_info) | 106 | dcssblk_assign_free_minor(struct dcssblk_dev_info *dev_info) |
107 | { | 107 | { |
108 | int minor, found; | 108 | int minor, found; |
@@ -230,7 +230,7 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch | |||
230 | SEGMENT_SHARED); | 230 | SEGMENT_SHARED); |
231 | if (rc < 0) { | 231 | if (rc < 0) { |
232 | BUG_ON(rc == -EINVAL); | 232 | BUG_ON(rc == -EINVAL); |
233 | if (rc == -EIO || rc == -ENOENT) | 233 | if (rc != -EAGAIN) |
234 | goto removeseg; | 234 | goto removeseg; |
235 | } else { | 235 | } else { |
236 | dev_info->is_shared = 1; | 236 | dev_info->is_shared = 1; |
@@ -253,7 +253,7 @@ dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const ch | |||
253 | SEGMENT_EXCLUSIVE); | 253 | SEGMENT_EXCLUSIVE); |
254 | if (rc < 0) { | 254 | if (rc < 0) { |
255 | BUG_ON(rc == -EINVAL); | 255 | BUG_ON(rc == -EINVAL); |
256 | if (rc == -EIO || rc == -ENOENT) | 256 | if (rc != -EAGAIN) |
257 | goto removeseg; | 257 | goto removeseg; |
258 | } else { | 258 | } else { |
259 | dev_info->is_shared = 0; | 259 | dev_info->is_shared = 0; |
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index c3e97b4fc186..293e667b50f2 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile | |||
@@ -2,7 +2,8 @@ | |||
2 | # S/390 character devices | 2 | # S/390 character devices |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += ctrlchar.o keyboard.o defkeymap.o | 5 | obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \ |
6 | sclp_info.o | ||
6 | 7 | ||
7 | obj-$(CONFIG_TN3270) += raw3270.o | 8 | obj-$(CONFIG_TN3270) += raw3270.o |
8 | obj-$(CONFIG_TN3270_CONSOLE) += con3270.o | 9 | obj-$(CONFIG_TN3270_CONSOLE) += con3270.o |
@@ -11,7 +12,6 @@ obj-$(CONFIG_TN3270_FS) += fs3270.o | |||
11 | 12 | ||
12 | obj-$(CONFIG_TN3215) += con3215.o | 13 | obj-$(CONFIG_TN3215) += con3215.o |
13 | 14 | ||
14 | obj-$(CONFIG_SCLP) += sclp.o sclp_rw.o sclp_quiesce.o | ||
15 | obj-$(CONFIG_SCLP_TTY) += sclp_tty.o | 15 | obj-$(CONFIG_SCLP_TTY) += sclp_tty.o |
16 | obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o | 16 | obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o |
17 | obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o | 17 | obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o |
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 25b5d7a66417..9a328f14a641 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c | |||
@@ -1121,7 +1121,7 @@ static const struct tty_operations tty3215_ops = { | |||
1121 | * 3215 tty registration code called from tty_init(). | 1121 | * 3215 tty registration code called from tty_init(). |
1122 | * Most kernel services (incl. kmalloc) are available at this poimt. | 1122 | * Most kernel services (incl. kmalloc) are available at this poimt. |
1123 | */ | 1123 | */ |
1124 | int __init | 1124 | static int __init |
1125 | tty3215_init(void) | 1125 | tty3215_init(void) |
1126 | { | 1126 | { |
1127 | struct tty_driver *driver; | 1127 | struct tty_driver *driver; |
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index 7566be890688..8e7f2d7633d6 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c | |||
@@ -69,8 +69,7 @@ static void con3270_update(struct con3270 *); | |||
69 | /* | 69 | /* |
70 | * Setup timeout for a device. On timeout trigger an update. | 70 | * Setup timeout for a device. On timeout trigger an update. |
71 | */ | 71 | */ |
72 | void | 72 | static void con3270_set_timer(struct con3270 *cp, int expires) |
73 | con3270_set_timer(struct con3270 *cp, int expires) | ||
74 | { | 73 | { |
75 | if (expires == 0) { | 74 | if (expires == 0) { |
76 | if (timer_pending(&cp->timer)) | 75 | if (timer_pending(&cp->timer)) |
diff --git a/drivers/s390/char/defkeymap.c b/drivers/s390/char/defkeymap.c index 17027d918cf7..564baca01b7c 100644 --- a/drivers/s390/char/defkeymap.c +++ b/drivers/s390/char/defkeymap.c | |||
@@ -5,6 +5,8 @@ | |||
5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
6 | #include <linux/keyboard.h> | 6 | #include <linux/keyboard.h> |
7 | #include <linux/kd.h> | 7 | #include <linux/kd.h> |
8 | #include <linux/kbd_kern.h> | ||
9 | #include <linux/kbd_diacr.h> | ||
8 | 10 | ||
9 | u_short plain_map[NR_KEYS] = { | 11 | u_short plain_map[NR_KEYS] = { |
10 | 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, | 12 | 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, 0xf000, |
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 0893d306ae80..e1a746269c4c 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include "raw3270.h" | 23 | #include "raw3270.h" |
24 | #include "ctrlchar.h" | 24 | #include "ctrlchar.h" |
25 | 25 | ||
26 | struct raw3270_fn fs3270_fn; | 26 | static struct raw3270_fn fs3270_fn; |
27 | 27 | ||
28 | struct fs3270 { | 28 | struct fs3270 { |
29 | struct raw3270_view view; | 29 | struct raw3270_view view; |
@@ -401,7 +401,7 @@ fs3270_release(struct raw3270_view *view) | |||
401 | } | 401 | } |
402 | 402 | ||
403 | /* View to a 3270 device. Can be console, tty or fullscreen. */ | 403 | /* View to a 3270 device. Can be console, tty or fullscreen. */ |
404 | struct raw3270_fn fs3270_fn = { | 404 | static struct raw3270_fn fs3270_fn = { |
405 | .activate = fs3270_activate, | 405 | .activate = fs3270_activate, |
406 | .deactivate = fs3270_deactivate, | 406 | .deactivate = fs3270_deactivate, |
407 | .intv = (void *) fs3270_irq, | 407 | .intv = (void *) fs3270_irq, |
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index 3e86fd1756e5..f62f9a4e8950 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c | |||
@@ -148,6 +148,7 @@ kbd_ascebc(struct kbd_data *kbd, unsigned char *ascebc) | |||
148 | } | 148 | } |
149 | } | 149 | } |
150 | 150 | ||
151 | #if 0 | ||
151 | /* | 152 | /* |
152 | * Generate ebcdic -> ascii translation table from kbd_data. | 153 | * Generate ebcdic -> ascii translation table from kbd_data. |
153 | */ | 154 | */ |
@@ -173,6 +174,7 @@ kbd_ebcasc(struct kbd_data *kbd, unsigned char *ebcasc) | |||
173 | } | 174 | } |
174 | } | 175 | } |
175 | } | 176 | } |
177 | #endif | ||
176 | 178 | ||
177 | /* | 179 | /* |
178 | * We have a combining character DIACR here, followed by the character CH. | 180 | * We have a combining character DIACR here, followed by the character CH. |
diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c index cdb24f528112..9e451acc6491 100644 --- a/drivers/s390/char/monwriter.c +++ b/drivers/s390/char/monwriter.c | |||
@@ -67,8 +67,8 @@ static int monwrite_diag(struct monwrite_hdr *myhdr, char *buffer, int fcn) | |||
67 | return -EINVAL; | 67 | return -EINVAL; |
68 | } | 68 | } |
69 | 69 | ||
70 | static inline struct mon_buf *monwrite_find_hdr(struct mon_private *monpriv, | 70 | static struct mon_buf *monwrite_find_hdr(struct mon_private *monpriv, |
71 | struct monwrite_hdr *monhdr) | 71 | struct monwrite_hdr *monhdr) |
72 | { | 72 | { |
73 | struct mon_buf *entry, *next; | 73 | struct mon_buf *entry, *next; |
74 | 74 | ||
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 7a84014f2037..8facd14adb7c 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include <linux/device.h> | 29 | #include <linux/device.h> |
30 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
31 | 31 | ||
32 | struct class *class3270; | 32 | static struct class *class3270; |
33 | 33 | ||
34 | /* The main 3270 data structure. */ | 34 | /* The main 3270 data structure. */ |
35 | struct raw3270 { | 35 | struct raw3270 { |
@@ -86,7 +86,7 @@ DECLARE_WAIT_QUEUE_HEAD(raw3270_wait_queue); | |||
86 | /* | 86 | /* |
87 | * Encode array for 12 bit 3270 addresses. | 87 | * Encode array for 12 bit 3270 addresses. |
88 | */ | 88 | */ |
89 | unsigned char raw3270_ebcgraf[64] = { | 89 | static unsigned char raw3270_ebcgraf[64] = { |
90 | 0x40, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, | 90 | 0x40, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, |
91 | 0xc8, 0xc9, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, | 91 | 0xc8, 0xc9, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, |
92 | 0x50, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, | 92 | 0x50, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, |
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 8a056df09d6b..f171de3b0b11 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c | |||
@@ -59,7 +59,8 @@ static volatile enum sclp_init_state_t { | |||
59 | /* Internal state: is a request active at the sclp? */ | 59 | /* Internal state: is a request active at the sclp? */ |
60 | static volatile enum sclp_running_state_t { | 60 | static volatile enum sclp_running_state_t { |
61 | sclp_running_state_idle, | 61 | sclp_running_state_idle, |
62 | sclp_running_state_running | 62 | sclp_running_state_running, |
63 | sclp_running_state_reset_pending | ||
63 | } sclp_running_state = sclp_running_state_idle; | 64 | } sclp_running_state = sclp_running_state_idle; |
64 | 65 | ||
65 | /* Internal state: is a read request pending? */ | 66 | /* Internal state: is a read request pending? */ |
@@ -88,15 +89,15 @@ static volatile enum sclp_mask_state_t { | |||
88 | 89 | ||
89 | /* Timeout intervals in seconds.*/ | 90 | /* Timeout intervals in seconds.*/ |
90 | #define SCLP_BUSY_INTERVAL 10 | 91 | #define SCLP_BUSY_INTERVAL 10 |
91 | #define SCLP_RETRY_INTERVAL 15 | 92 | #define SCLP_RETRY_INTERVAL 30 |
92 | 93 | ||
93 | static void sclp_process_queue(void); | 94 | static void sclp_process_queue(void); |
94 | static int sclp_init_mask(int calculate); | 95 | static int sclp_init_mask(int calculate); |
95 | static int sclp_init(void); | 96 | static int sclp_init(void); |
96 | 97 | ||
97 | /* Perform service call. Return 0 on success, non-zero otherwise. */ | 98 | /* Perform service call. Return 0 on success, non-zero otherwise. */ |
98 | static int | 99 | int |
99 | service_call(sclp_cmdw_t command, void *sccb) | 100 | sclp_service_call(sclp_cmdw_t command, void *sccb) |
100 | { | 101 | { |
101 | int cc; | 102 | int cc; |
102 | 103 | ||
@@ -113,19 +114,17 @@ service_call(sclp_cmdw_t command, void *sccb) | |||
113 | return 0; | 114 | return 0; |
114 | } | 115 | } |
115 | 116 | ||
116 | /* Request timeout handler. Restart the request queue. If DATA is non-zero, | 117 | static inline void __sclp_make_read_req(void); |
117 | * force restart of running request. */ | 118 | |
118 | static void | 119 | static void |
119 | sclp_request_timeout(unsigned long data) | 120 | __sclp_queue_read_req(void) |
120 | { | 121 | { |
121 | unsigned long flags; | 122 | if (sclp_reading_state == sclp_reading_state_idle) { |
122 | 123 | sclp_reading_state = sclp_reading_state_reading; | |
123 | if (data) { | 124 | __sclp_make_read_req(); |
124 | spin_lock_irqsave(&sclp_lock, flags); | 125 | /* Add request to head of queue */ |
125 | sclp_running_state = sclp_running_state_idle; | 126 | list_add(&sclp_read_req.list, &sclp_req_queue); |
126 | spin_unlock_irqrestore(&sclp_lock, flags); | ||
127 | } | 127 | } |
128 | sclp_process_queue(); | ||
129 | } | 128 | } |
130 | 129 | ||
131 | /* Set up request retry timer. Called while sclp_lock is locked. */ | 130 | /* Set up request retry timer. Called while sclp_lock is locked. */ |
@@ -140,6 +139,29 @@ __sclp_set_request_timer(unsigned long time, void (*function)(unsigned long), | |||
140 | add_timer(&sclp_request_timer); | 139 | add_timer(&sclp_request_timer); |
141 | } | 140 | } |
142 | 141 | ||
142 | /* Request timeout handler. Restart the request queue. If DATA is non-zero, | ||
143 | * force restart of running request. */ | ||
144 | static void | ||
145 | sclp_request_timeout(unsigned long data) | ||
146 | { | ||
147 | unsigned long flags; | ||
148 | |||
149 | spin_lock_irqsave(&sclp_lock, flags); | ||
150 | if (data) { | ||
151 | if (sclp_running_state == sclp_running_state_running) { | ||
152 | /* Break running state and queue NOP read event request | ||
153 | * to get a defined interface state. */ | ||
154 | __sclp_queue_read_req(); | ||
155 | sclp_running_state = sclp_running_state_idle; | ||
156 | } | ||
157 | } else { | ||
158 | __sclp_set_request_timer(SCLP_BUSY_INTERVAL * HZ, | ||
159 | sclp_request_timeout, 0); | ||
160 | } | ||
161 | spin_unlock_irqrestore(&sclp_lock, flags); | ||
162 | sclp_process_queue(); | ||
163 | } | ||
164 | |||
143 | /* Try to start a request. Return zero if the request was successfully | 165 | /* Try to start a request. Return zero if the request was successfully |
144 | * started or if it will be started at a later time. Return non-zero otherwise. | 166 | * started or if it will be started at a later time. Return non-zero otherwise. |
145 | * Called while sclp_lock is locked. */ | 167 | * Called while sclp_lock is locked. */ |
@@ -151,7 +173,7 @@ __sclp_start_request(struct sclp_req *req) | |||
151 | if (sclp_running_state != sclp_running_state_idle) | 173 | if (sclp_running_state != sclp_running_state_idle) |
152 | return 0; | 174 | return 0; |
153 | del_timer(&sclp_request_timer); | 175 | del_timer(&sclp_request_timer); |
154 | rc = service_call(req->command, req->sccb); | 176 | rc = sclp_service_call(req->command, req->sccb); |
155 | req->start_count++; | 177 | req->start_count++; |
156 | 178 | ||
157 | if (rc == 0) { | 179 | if (rc == 0) { |
@@ -191,7 +213,15 @@ sclp_process_queue(void) | |||
191 | rc = __sclp_start_request(req); | 213 | rc = __sclp_start_request(req); |
192 | if (rc == 0) | 214 | if (rc == 0) |
193 | break; | 215 | break; |
194 | /* Request failed. */ | 216 | /* Request failed */ |
217 | if (req->start_count > 1) { | ||
218 | /* Cannot abort already submitted request - could still | ||
219 | * be active at the SCLP */ | ||
220 | __sclp_set_request_timer(SCLP_BUSY_INTERVAL * HZ, | ||
221 | sclp_request_timeout, 0); | ||
222 | break; | ||
223 | } | ||
224 | /* Post-processing for aborted request */ | ||
195 | list_del(&req->list); | 225 | list_del(&req->list); |
196 | if (req->callback) { | 226 | if (req->callback) { |
197 | spin_unlock_irqrestore(&sclp_lock, flags); | 227 | spin_unlock_irqrestore(&sclp_lock, flags); |
@@ -221,7 +251,8 @@ sclp_add_request(struct sclp_req *req) | |||
221 | list_add_tail(&req->list, &sclp_req_queue); | 251 | list_add_tail(&req->list, &sclp_req_queue); |
222 | rc = 0; | 252 | rc = 0; |
223 | /* Start if request is first in list */ | 253 | /* Start if request is first in list */ |
224 | if (req->list.prev == &sclp_req_queue) { | 254 | if (sclp_running_state == sclp_running_state_idle && |
255 | req->list.prev == &sclp_req_queue) { | ||
225 | rc = __sclp_start_request(req); | 256 | rc = __sclp_start_request(req); |
226 | if (rc) | 257 | if (rc) |
227 | list_del(&req->list); | 258 | list_del(&req->list); |
@@ -294,7 +325,7 @@ __sclp_make_read_req(void) | |||
294 | sccb = (struct sccb_header *) sclp_read_sccb; | 325 | sccb = (struct sccb_header *) sclp_read_sccb; |
295 | clear_page(sccb); | 326 | clear_page(sccb); |
296 | memset(&sclp_read_req, 0, sizeof(struct sclp_req)); | 327 | memset(&sclp_read_req, 0, sizeof(struct sclp_req)); |
297 | sclp_read_req.command = SCLP_CMDW_READDATA; | 328 | sclp_read_req.command = SCLP_CMDW_READ_EVENT_DATA; |
298 | sclp_read_req.status = SCLP_REQ_QUEUED; | 329 | sclp_read_req.status = SCLP_REQ_QUEUED; |
299 | sclp_read_req.start_count = 0; | 330 | sclp_read_req.start_count = 0; |
300 | sclp_read_req.callback = sclp_read_cb; | 331 | sclp_read_req.callback = sclp_read_cb; |
@@ -334,6 +365,8 @@ sclp_interrupt_handler(__u16 code) | |||
334 | finished_sccb = S390_lowcore.ext_params & 0xfffffff8; | 365 | finished_sccb = S390_lowcore.ext_params & 0xfffffff8; |
335 | evbuf_pending = S390_lowcore.ext_params & 0x3; | 366 | evbuf_pending = S390_lowcore.ext_params & 0x3; |
336 | if (finished_sccb) { | 367 | if (finished_sccb) { |
368 | del_timer(&sclp_request_timer); | ||
369 | sclp_running_state = sclp_running_state_reset_pending; | ||
337 | req = __sclp_find_req(finished_sccb); | 370 | req = __sclp_find_req(finished_sccb); |
338 | if (req) { | 371 | if (req) { |
339 | /* Request post-processing */ | 372 | /* Request post-processing */ |
@@ -348,13 +381,8 @@ sclp_interrupt_handler(__u16 code) | |||
348 | sclp_running_state = sclp_running_state_idle; | 381 | sclp_running_state = sclp_running_state_idle; |
349 | } | 382 | } |
350 | if (evbuf_pending && sclp_receive_mask != 0 && | 383 | if (evbuf_pending && sclp_receive_mask != 0 && |
351 | sclp_reading_state == sclp_reading_state_idle && | 384 | sclp_activation_state == sclp_activation_state_active) |
352 | sclp_activation_state == sclp_activation_state_active ) { | 385 | __sclp_queue_read_req(); |
353 | sclp_reading_state = sclp_reading_state_reading; | ||
354 | __sclp_make_read_req(); | ||
355 | /* Add request to head of queue */ | ||
356 | list_add(&sclp_read_req.list, &sclp_req_queue); | ||
357 | } | ||
358 | spin_unlock(&sclp_lock); | 386 | spin_unlock(&sclp_lock); |
359 | sclp_process_queue(); | 387 | sclp_process_queue(); |
360 | } | 388 | } |
@@ -374,6 +402,7 @@ sclp_sync_wait(void) | |||
374 | unsigned long flags; | 402 | unsigned long flags; |
375 | unsigned long cr0, cr0_sync; | 403 | unsigned long cr0, cr0_sync; |
376 | u64 timeout; | 404 | u64 timeout; |
405 | int irq_context; | ||
377 | 406 | ||
378 | /* We'll be disabling timer interrupts, so we need a custom timeout | 407 | /* We'll be disabling timer interrupts, so we need a custom timeout |
379 | * mechanism */ | 408 | * mechanism */ |
@@ -386,7 +415,9 @@ sclp_sync_wait(void) | |||
386 | } | 415 | } |
387 | local_irq_save(flags); | 416 | local_irq_save(flags); |
388 | /* Prevent bottom half from executing once we force interrupts open */ | 417 | /* Prevent bottom half from executing once we force interrupts open */ |
389 | local_bh_disable(); | 418 | irq_context = in_interrupt(); |
419 | if (!irq_context) | ||
420 | local_bh_disable(); | ||
390 | /* Enable service-signal interruption, disable timer interrupts */ | 421 | /* Enable service-signal interruption, disable timer interrupts */ |
391 | trace_hardirqs_on(); | 422 | trace_hardirqs_on(); |
392 | __ctl_store(cr0, 0, 0); | 423 | __ctl_store(cr0, 0, 0); |
@@ -402,19 +433,19 @@ sclp_sync_wait(void) | |||
402 | get_clock() > timeout && | 433 | get_clock() > timeout && |
403 | del_timer(&sclp_request_timer)) | 434 | del_timer(&sclp_request_timer)) |
404 | sclp_request_timer.function(sclp_request_timer.data); | 435 | sclp_request_timer.function(sclp_request_timer.data); |
405 | barrier(); | ||
406 | cpu_relax(); | 436 | cpu_relax(); |
407 | } | 437 | } |
408 | local_irq_disable(); | 438 | local_irq_disable(); |
409 | __ctl_load(cr0, 0, 0); | 439 | __ctl_load(cr0, 0, 0); |
410 | _local_bh_enable(); | 440 | if (!irq_context) |
441 | _local_bh_enable(); | ||
411 | local_irq_restore(flags); | 442 | local_irq_restore(flags); |
412 | } | 443 | } |
413 | 444 | ||
414 | EXPORT_SYMBOL(sclp_sync_wait); | 445 | EXPORT_SYMBOL(sclp_sync_wait); |
415 | 446 | ||
416 | /* Dispatch changes in send and receive mask to registered listeners. */ | 447 | /* Dispatch changes in send and receive mask to registered listeners. */ |
417 | static inline void | 448 | static void |
418 | sclp_dispatch_state_change(void) | 449 | sclp_dispatch_state_change(void) |
419 | { | 450 | { |
420 | struct list_head *l; | 451 | struct list_head *l; |
@@ -597,7 +628,7 @@ __sclp_make_init_req(u32 receive_mask, u32 send_mask) | |||
597 | sccb = (struct init_sccb *) sclp_init_sccb; | 628 | sccb = (struct init_sccb *) sclp_init_sccb; |
598 | clear_page(sccb); | 629 | clear_page(sccb); |
599 | memset(&sclp_init_req, 0, sizeof(struct sclp_req)); | 630 | memset(&sclp_init_req, 0, sizeof(struct sclp_req)); |
600 | sclp_init_req.command = SCLP_CMDW_WRITEMASK; | 631 | sclp_init_req.command = SCLP_CMDW_WRITE_EVENT_MASK; |
601 | sclp_init_req.status = SCLP_REQ_FILLED; | 632 | sclp_init_req.status = SCLP_REQ_FILLED; |
602 | sclp_init_req.start_count = 0; | 633 | sclp_init_req.start_count = 0; |
603 | sclp_init_req.callback = NULL; | 634 | sclp_init_req.callback = NULL; |
@@ -800,7 +831,7 @@ sclp_check_interface(void) | |||
800 | for (retry = 0; retry <= SCLP_INIT_RETRY; retry++) { | 831 | for (retry = 0; retry <= SCLP_INIT_RETRY; retry++) { |
801 | __sclp_make_init_req(0, 0); | 832 | __sclp_make_init_req(0, 0); |
802 | sccb = (struct init_sccb *) sclp_init_req.sccb; | 833 | sccb = (struct init_sccb *) sclp_init_req.sccb; |
803 | rc = service_call(sclp_init_req.command, sccb); | 834 | rc = sclp_service_call(sclp_init_req.command, sccb); |
804 | if (rc == -EIO) | 835 | if (rc == -EIO) |
805 | break; | 836 | break; |
806 | sclp_init_req.status = SCLP_REQ_RUNNING; | 837 | sclp_init_req.status = SCLP_REQ_RUNNING; |
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 2c71d6ee7b5b..7d29ab45a6ed 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h | |||
@@ -12,7 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/list.h> | 14 | #include <linux/list.h> |
15 | 15 | #include <asm/sclp.h> | |
16 | #include <asm/ebcdic.h> | 16 | #include <asm/ebcdic.h> |
17 | 17 | ||
18 | /* maximum number of pages concerning our own memory management */ | 18 | /* maximum number of pages concerning our own memory management */ |
@@ -49,9 +49,11 @@ | |||
49 | 49 | ||
50 | typedef unsigned int sclp_cmdw_t; | 50 | typedef unsigned int sclp_cmdw_t; |
51 | 51 | ||
52 | #define SCLP_CMDW_READDATA 0x00770005 | 52 | #define SCLP_CMDW_READ_EVENT_DATA 0x00770005 |
53 | #define SCLP_CMDW_WRITEDATA 0x00760005 | 53 | #define SCLP_CMDW_WRITE_EVENT_DATA 0x00760005 |
54 | #define SCLP_CMDW_WRITEMASK 0x00780005 | 54 | #define SCLP_CMDW_WRITE_EVENT_MASK 0x00780005 |
55 | #define SCLP_CMDW_READ_SCP_INFO 0x00020001 | ||
56 | #define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 | ||
55 | 57 | ||
56 | #define GDS_ID_MDSMU 0x1310 | 58 | #define GDS_ID_MDSMU 0x1310 |
57 | #define GDS_ID_MDSRouteInfo 0x1311 | 59 | #define GDS_ID_MDSRouteInfo 0x1311 |
@@ -66,13 +68,6 @@ typedef unsigned int sclp_cmdw_t; | |||
66 | 68 | ||
67 | typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ | 69 | typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ |
68 | 70 | ||
69 | struct sccb_header { | ||
70 | u16 length; | ||
71 | u8 function_code; | ||
72 | u8 control_mask[3]; | ||
73 | u16 response_code; | ||
74 | } __attribute__((packed)); | ||
75 | |||
76 | struct gds_subvector { | 71 | struct gds_subvector { |
77 | u8 length; | 72 | u8 length; |
78 | u8 key; | 73 | u8 key; |
@@ -131,6 +126,7 @@ void sclp_unregister(struct sclp_register *reg); | |||
131 | int sclp_remove_processed(struct sccb_header *sccb); | 126 | int sclp_remove_processed(struct sccb_header *sccb); |
132 | int sclp_deactivate(void); | 127 | int sclp_deactivate(void); |
133 | int sclp_reactivate(void); | 128 | int sclp_reactivate(void); |
129 | int sclp_service_call(sclp_cmdw_t command, void *sccb); | ||
134 | 130 | ||
135 | /* useful inlines */ | 131 | /* useful inlines */ |
136 | 132 | ||
diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c index 86864f641716..ead1043d788e 100644 --- a/drivers/s390/char/sclp_con.c +++ b/drivers/s390/char/sclp_con.c | |||
@@ -66,7 +66,7 @@ sclp_conbuf_callback(struct sclp_buffer *buffer, int rc) | |||
66 | } while (buffer && sclp_emit_buffer(buffer, sclp_conbuf_callback)); | 66 | } while (buffer && sclp_emit_buffer(buffer, sclp_conbuf_callback)); |
67 | } | 67 | } |
68 | 68 | ||
69 | static inline void | 69 | static void |
70 | sclp_conbuf_emit(void) | 70 | sclp_conbuf_emit(void) |
71 | { | 71 | { |
72 | struct sclp_buffer* buffer; | 72 | struct sclp_buffer* buffer; |
diff --git a/drivers/s390/char/sclp_cpi.c b/drivers/s390/char/sclp_cpi.c index 4f873ae148b7..65aa2c85737f 100644 --- a/drivers/s390/char/sclp_cpi.c +++ b/drivers/s390/char/sclp_cpi.c | |||
@@ -169,7 +169,7 @@ cpi_prepare_req(void) | |||
169 | } | 169 | } |
170 | 170 | ||
171 | /* prepare request data structure presented to SCLP driver */ | 171 | /* prepare request data structure presented to SCLP driver */ |
172 | req->command = SCLP_CMDW_WRITEDATA; | 172 | req->command = SCLP_CMDW_WRITE_EVENT_DATA; |
173 | req->sccb = sccb; | 173 | req->sccb = sccb; |
174 | req->status = SCLP_REQ_FILLED; | 174 | req->status = SCLP_REQ_FILLED; |
175 | req->callback = cpi_callback; | 175 | req->callback = cpi_callback; |
diff --git a/drivers/s390/char/sclp_info.c b/drivers/s390/char/sclp_info.c new file mode 100644 index 000000000000..7bcbe643b087 --- /dev/null +++ b/drivers/s390/char/sclp_info.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * drivers/s390/char/sclp_info.c | ||
3 | * | ||
4 | * Copyright IBM Corp. 2007 | ||
5 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> | ||
6 | */ | ||
7 | |||
8 | #include <linux/init.h> | ||
9 | #include <linux/errno.h> | ||
10 | #include <linux/string.h> | ||
11 | #include <asm/sclp.h> | ||
12 | #include "sclp.h" | ||
13 | |||
14 | struct sclp_readinfo_sccb s390_readinfo_sccb; | ||
15 | |||
16 | void __init sclp_readinfo_early(void) | ||
17 | { | ||
18 | sclp_cmdw_t command; | ||
19 | struct sccb_header *sccb; | ||
20 | int ret; | ||
21 | |||
22 | __ctl_set_bit(0, 9); /* enable service signal subclass mask */ | ||
23 | |||
24 | sccb = &s390_readinfo_sccb.header; | ||
25 | command = SCLP_CMDW_READ_SCP_INFO_FORCED; | ||
26 | while (1) { | ||
27 | u16 response; | ||
28 | |||
29 | memset(&s390_readinfo_sccb, 0, sizeof(s390_readinfo_sccb)); | ||
30 | sccb->length = sizeof(s390_readinfo_sccb); | ||
31 | sccb->control_mask[2] = 0x80; | ||
32 | |||
33 | ret = sclp_service_call(command, &s390_readinfo_sccb); | ||
34 | |||
35 | if (ret == -EIO) | ||
36 | goto out; | ||
37 | if (ret == -EBUSY) | ||
38 | continue; | ||
39 | |||
40 | __load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT | | ||
41 | PSW_MASK_WAIT | PSW_DEFAULT_KEY); | ||
42 | local_irq_disable(); | ||
43 | barrier(); | ||
44 | |||
45 | response = sccb->response_code; | ||
46 | |||
47 | if (response == 0x10) | ||
48 | break; | ||
49 | |||
50 | if (response != 0x1f0 || command == SCLP_CMDW_READ_SCP_INFO) | ||
51 | break; | ||
52 | |||
53 | command = SCLP_CMDW_READ_SCP_INFO; | ||
54 | } | ||
55 | out: | ||
56 | __ctl_clear_bit(0, 9); /* disable service signal subclass mask */ | ||
57 | } | ||
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c index 0c92d3909cca..2486783ea58e 100644 --- a/drivers/s390/char/sclp_rw.c +++ b/drivers/s390/char/sclp_rw.c | |||
@@ -460,7 +460,7 @@ sclp_emit_buffer(struct sclp_buffer *buffer, | |||
460 | sccb->msg_buf.header.type = EvTyp_PMsgCmd; | 460 | sccb->msg_buf.header.type = EvTyp_PMsgCmd; |
461 | else | 461 | else |
462 | return -ENOSYS; | 462 | return -ENOSYS; |
463 | buffer->request.command = SCLP_CMDW_WRITEDATA; | 463 | buffer->request.command = SCLP_CMDW_WRITE_EVENT_DATA; |
464 | buffer->request.status = SCLP_REQ_FILLED; | 464 | buffer->request.status = SCLP_REQ_FILLED; |
465 | buffer->request.callback = sclp_writedata_callback; | 465 | buffer->request.callback = sclp_writedata_callback; |
466 | buffer->request.callback_data = buffer; | 466 | buffer->request.callback_data = buffer; |
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index 2d173e5c8a09..90536f60bf50 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c | |||
@@ -721,7 +721,7 @@ static const struct tty_operations sclp_ops = { | |||
721 | .ioctl = sclp_tty_ioctl, | 721 | .ioctl = sclp_tty_ioctl, |
722 | }; | 722 | }; |
723 | 723 | ||
724 | int __init | 724 | static int __init |
725 | sclp_tty_init(void) | 725 | sclp_tty_init(void) |
726 | { | 726 | { |
727 | struct tty_driver *driver; | 727 | struct tty_driver *driver; |
diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 723bf4191bfe..544f137d70d7 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c | |||
@@ -207,7 +207,7 @@ __sclp_vt220_emit(struct sclp_vt220_request *request) | |||
207 | request->sclp_req.status = SCLP_REQ_FAILED; | 207 | request->sclp_req.status = SCLP_REQ_FAILED; |
208 | return -EIO; | 208 | return -EIO; |
209 | } | 209 | } |
210 | request->sclp_req.command = SCLP_CMDW_WRITEDATA; | 210 | request->sclp_req.command = SCLP_CMDW_WRITE_EVENT_DATA; |
211 | request->sclp_req.status = SCLP_REQ_FILLED; | 211 | request->sclp_req.status = SCLP_REQ_FILLED; |
212 | request->sclp_req.callback = sclp_vt220_callback; | 212 | request->sclp_req.callback = sclp_vt220_callback; |
213 | request->sclp_req.callback_data = (void *) request; | 213 | request->sclp_req.callback_data = (void *) request; |
@@ -669,7 +669,7 @@ static const struct tty_operations sclp_vt220_ops = { | |||
669 | /* | 669 | /* |
670 | * Register driver with SCLP and Linux and initialize internal tty structures. | 670 | * Register driver with SCLP and Linux and initialize internal tty structures. |
671 | */ | 671 | */ |
672 | int __init | 672 | static int __init |
673 | sclp_vt220_tty_init(void) | 673 | sclp_vt220_tty_init(void) |
674 | { | 674 | { |
675 | struct tty_driver *driver; | 675 | struct tty_driver *driver; |
diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h index c9f1c4c8bb13..bb4ff537729d 100644 --- a/drivers/s390/char/tape.h +++ b/drivers/s390/char/tape.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * tape device driver for 3480/3490E/3590 tapes. | 3 | * tape device driver for 3480/3490E/3590 tapes. |
4 | * | 4 | * |
5 | * S390 and zSeries version | 5 | * S390 and zSeries version |
6 | * Copyright (C) 2001,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation | 6 | * Copyright IBM Corp. 2001,2006 |
7 | * Author(s): Carsten Otte <cotte@de.ibm.com> | 7 | * Author(s): Carsten Otte <cotte@de.ibm.com> |
8 | * Tuan Ngo-Anh <ngoanh@de.ibm.com> | 8 | * Tuan Ngo-Anh <ngoanh@de.ibm.com> |
9 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 9 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
@@ -99,7 +99,11 @@ enum tape_op { | |||
99 | TO_DIS, /* Tape display */ | 99 | TO_DIS, /* Tape display */ |
100 | TO_ASSIGN, /* Assign tape to channel path */ | 100 | TO_ASSIGN, /* Assign tape to channel path */ |
101 | TO_UNASSIGN, /* Unassign tape from channel path */ | 101 | TO_UNASSIGN, /* Unassign tape from channel path */ |
102 | TO_SIZE /* #entries in tape_op_t */ | 102 | TO_CRYPT_ON, /* Enable encrpytion */ |
103 | TO_CRYPT_OFF, /* Disable encrpytion */ | ||
104 | TO_KEKL_SET, /* Set KEK label */ | ||
105 | TO_KEKL_QUERY, /* Query KEK label */ | ||
106 | TO_SIZE, /* #entries in tape_op_t */ | ||
103 | }; | 107 | }; |
104 | 108 | ||
105 | /* Forward declaration */ | 109 | /* Forward declaration */ |
@@ -112,6 +116,7 @@ enum tape_request_status { | |||
112 | TAPE_REQUEST_IN_IO, /* request is currently in IO */ | 116 | TAPE_REQUEST_IN_IO, /* request is currently in IO */ |
113 | TAPE_REQUEST_DONE, /* request is completed. */ | 117 | TAPE_REQUEST_DONE, /* request is completed. */ |
114 | TAPE_REQUEST_CANCEL, /* request should be canceled. */ | 118 | TAPE_REQUEST_CANCEL, /* request should be canceled. */ |
119 | TAPE_REQUEST_LONG_BUSY, /* request has to be restarted after long busy */ | ||
115 | }; | 120 | }; |
116 | 121 | ||
117 | /* Tape CCW request */ | 122 | /* Tape CCW request */ |
@@ -164,10 +169,11 @@ struct tape_discipline { | |||
164 | * The discipline irq function either returns an error code (<0) which | 169 | * The discipline irq function either returns an error code (<0) which |
165 | * means that the request has failed with an error or one of the following: | 170 | * means that the request has failed with an error or one of the following: |
166 | */ | 171 | */ |
167 | #define TAPE_IO_SUCCESS 0 /* request successful */ | 172 | #define TAPE_IO_SUCCESS 0 /* request successful */ |
168 | #define TAPE_IO_PENDING 1 /* request still running */ | 173 | #define TAPE_IO_PENDING 1 /* request still running */ |
169 | #define TAPE_IO_RETRY 2 /* retry to current request */ | 174 | #define TAPE_IO_RETRY 2 /* retry to current request */ |
170 | #define TAPE_IO_STOP 3 /* stop the running request */ | 175 | #define TAPE_IO_STOP 3 /* stop the running request */ |
176 | #define TAPE_IO_LONG_BUSY 4 /* delay the running request */ | ||
171 | 177 | ||
172 | /* Char Frontend Data */ | 178 | /* Char Frontend Data */ |
173 | struct tape_char_data { | 179 | struct tape_char_data { |
@@ -242,6 +248,10 @@ struct tape_device { | |||
242 | 248 | ||
243 | /* Function to start or stop the next request later. */ | 249 | /* Function to start or stop the next request later. */ |
244 | struct delayed_work tape_dnr; | 250 | struct delayed_work tape_dnr; |
251 | |||
252 | /* Timer for long busy */ | ||
253 | struct timer_list lb_timeout; | ||
254 | |||
245 | }; | 255 | }; |
246 | 256 | ||
247 | /* Externals from tape_core.c */ | 257 | /* Externals from tape_core.c */ |
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 9df912f63188..50f5edab83d7 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * drivers/s390/char/tape_3590.c | 2 | * drivers/s390/char/tape_3590.c |
3 | * tape device discipline for 3590 tapes. | 3 | * tape device discipline for 3590 tapes. |
4 | * | 4 | * |
5 | * Copyright (C) IBM Corp. 2001,2006 | 5 | * Copyright IBM Corp. 2001,2006 |
6 | * Author(s): Stefan Bader <shbader@de.ibm.com> | 6 | * Author(s): Stefan Bader <shbader@de.ibm.com> |
7 | * Michael Holzheu <holzheu@de.ibm.com> | 7 | * Michael Holzheu <holzheu@de.ibm.com> |
8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/bio.h> | 13 | #include <linux/bio.h> |
14 | #include <asm/ebcdic.h> | ||
14 | 15 | ||
15 | #define TAPE_DBF_AREA tape_3590_dbf | 16 | #define TAPE_DBF_AREA tape_3590_dbf |
16 | 17 | ||
@@ -30,7 +31,7 @@ EXPORT_SYMBOL(TAPE_DBF_AREA); | |||
30 | * - Read Device (buffered) log: BRA | 31 | * - Read Device (buffered) log: BRA |
31 | * - Read Library log: BRA | 32 | * - Read Library log: BRA |
32 | * - Swap Devices: BRA | 33 | * - Swap Devices: BRA |
33 | * - Long Busy: BRA | 34 | * - Long Busy: implemented |
34 | * - Special Intercept: BRA | 35 | * - Special Intercept: BRA |
35 | * - Read Alternate: implemented | 36 | * - Read Alternate: implemented |
36 | *******************************************************************/ | 37 | *******************************************************************/ |
@@ -94,6 +95,332 @@ static const char *tape_3590_msg[TAPE_3590_MAX_MSG] = { | |||
94 | [0xae] = "Subsystem environmental alert", | 95 | [0xae] = "Subsystem environmental alert", |
95 | }; | 96 | }; |
96 | 97 | ||
98 | static int crypt_supported(struct tape_device *device) | ||
99 | { | ||
100 | return TAPE390_CRYPT_SUPPORTED(TAPE_3590_CRYPT_INFO(device)); | ||
101 | } | ||
102 | |||
103 | static int crypt_enabled(struct tape_device *device) | ||
104 | { | ||
105 | return TAPE390_CRYPT_ON(TAPE_3590_CRYPT_INFO(device)); | ||
106 | } | ||
107 | |||
108 | static void ext_to_int_kekl(struct tape390_kekl *in, | ||
109 | struct tape3592_kekl *out) | ||
110 | { | ||
111 | int i; | ||
112 | |||
113 | memset(out, 0, sizeof(*out)); | ||
114 | if (in->type == TAPE390_KEKL_TYPE_HASH) | ||
115 | out->flags |= 0x40; | ||
116 | if (in->type_on_tape == TAPE390_KEKL_TYPE_HASH) | ||
117 | out->flags |= 0x80; | ||
118 | strncpy(out->label, in->label, 64); | ||
119 | for (i = strlen(in->label); i < sizeof(out->label); i++) | ||
120 | out->label[i] = ' '; | ||
121 | ASCEBC(out->label, sizeof(out->label)); | ||
122 | } | ||
123 | |||
124 | static void int_to_ext_kekl(struct tape3592_kekl *in, | ||
125 | struct tape390_kekl *out) | ||
126 | { | ||
127 | memset(out, 0, sizeof(*out)); | ||
128 | if(in->flags & 0x40) | ||
129 | out->type = TAPE390_KEKL_TYPE_HASH; | ||
130 | else | ||
131 | out->type = TAPE390_KEKL_TYPE_LABEL; | ||
132 | if(in->flags & 0x80) | ||
133 | out->type_on_tape = TAPE390_KEKL_TYPE_HASH; | ||
134 | else | ||
135 | out->type_on_tape = TAPE390_KEKL_TYPE_LABEL; | ||
136 | memcpy(out->label, in->label, sizeof(in->label)); | ||
137 | EBCASC(out->label, sizeof(in->label)); | ||
138 | strstrip(out->label); | ||
139 | } | ||
140 | |||
141 | static void int_to_ext_kekl_pair(struct tape3592_kekl_pair *in, | ||
142 | struct tape390_kekl_pair *out) | ||
143 | { | ||
144 | if (in->count == 0) { | ||
145 | out->kekl[0].type = TAPE390_KEKL_TYPE_NONE; | ||
146 | out->kekl[0].type_on_tape = TAPE390_KEKL_TYPE_NONE; | ||
147 | out->kekl[1].type = TAPE390_KEKL_TYPE_NONE; | ||
148 | out->kekl[1].type_on_tape = TAPE390_KEKL_TYPE_NONE; | ||
149 | } else if (in->count == 1) { | ||
150 | int_to_ext_kekl(&in->kekl[0], &out->kekl[0]); | ||
151 | out->kekl[1].type = TAPE390_KEKL_TYPE_NONE; | ||
152 | out->kekl[1].type_on_tape = TAPE390_KEKL_TYPE_NONE; | ||
153 | } else if (in->count == 2) { | ||
154 | int_to_ext_kekl(&in->kekl[0], &out->kekl[0]); | ||
155 | int_to_ext_kekl(&in->kekl[1], &out->kekl[1]); | ||
156 | } else { | ||
157 | printk("Invalid KEKL number: %d\n", in->count); | ||
158 | BUG(); | ||
159 | } | ||
160 | } | ||
161 | |||
162 | static int check_ext_kekl(struct tape390_kekl *kekl) | ||
163 | { | ||
164 | if (kekl->type == TAPE390_KEKL_TYPE_NONE) | ||
165 | goto invalid; | ||
166 | if (kekl->type > TAPE390_KEKL_TYPE_HASH) | ||
167 | goto invalid; | ||
168 | if (kekl->type_on_tape == TAPE390_KEKL_TYPE_NONE) | ||
169 | goto invalid; | ||
170 | if (kekl->type_on_tape > TAPE390_KEKL_TYPE_HASH) | ||
171 | goto invalid; | ||
172 | if ((kekl->type == TAPE390_KEKL_TYPE_HASH) && | ||
173 | (kekl->type_on_tape == TAPE390_KEKL_TYPE_LABEL)) | ||
174 | goto invalid; | ||
175 | |||
176 | return 0; | ||
177 | invalid: | ||
178 | return -EINVAL; | ||
179 | } | ||
180 | |||
181 | static int check_ext_kekl_pair(struct tape390_kekl_pair *kekls) | ||
182 | { | ||
183 | if (check_ext_kekl(&kekls->kekl[0])) | ||
184 | goto invalid; | ||
185 | if (check_ext_kekl(&kekls->kekl[1])) | ||
186 | goto invalid; | ||
187 | |||
188 | return 0; | ||
189 | invalid: | ||
190 | return -EINVAL; | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * Query KEKLs | ||
195 | */ | ||
196 | static int tape_3592_kekl_query(struct tape_device *device, | ||
197 | struct tape390_kekl_pair *ext_kekls) | ||
198 | { | ||
199 | struct tape_request *request; | ||
200 | struct tape3592_kekl_query_order *order; | ||
201 | struct tape3592_kekl_query_data *int_kekls; | ||
202 | int rc; | ||
203 | |||
204 | DBF_EVENT(6, "tape3592_kekl_query\n"); | ||
205 | int_kekls = kmalloc(sizeof(*int_kekls), GFP_KERNEL|GFP_DMA); | ||
206 | if (!int_kekls) | ||
207 | return -ENOMEM; | ||
208 | request = tape_alloc_request(2, sizeof(*order)); | ||
209 | if (IS_ERR(request)) { | ||
210 | rc = PTR_ERR(request); | ||
211 | goto fail_malloc; | ||
212 | } | ||
213 | order = request->cpdata; | ||
214 | memset(order,0,sizeof(*order)); | ||
215 | order->code = 0xe2; | ||
216 | order->max_count = 2; | ||
217 | request->op = TO_KEKL_QUERY; | ||
218 | tape_ccw_cc(request->cpaddr, PERF_SUBSYS_FUNC, sizeof(*order), order); | ||
219 | tape_ccw_end(request->cpaddr + 1, READ_SS_DATA, sizeof(*int_kekls), | ||
220 | int_kekls); | ||
221 | rc = tape_do_io(device, request); | ||
222 | if (rc) | ||
223 | goto fail_request; | ||
224 | int_to_ext_kekl_pair(&int_kekls->kekls, ext_kekls); | ||
225 | |||
226 | rc = 0; | ||
227 | fail_request: | ||
228 | tape_free_request(request); | ||
229 | fail_malloc: | ||
230 | kfree(int_kekls); | ||
231 | return rc; | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * IOCTL: Query KEKLs | ||
236 | */ | ||
237 | static int tape_3592_ioctl_kekl_query(struct tape_device *device, | ||
238 | unsigned long arg) | ||
239 | { | ||
240 | int rc; | ||
241 | struct tape390_kekl_pair *ext_kekls; | ||
242 | |||
243 | DBF_EVENT(6, "tape_3592_ioctl_kekl_query\n"); | ||
244 | if (!crypt_supported(device)) | ||
245 | return -ENOSYS; | ||
246 | if (!crypt_enabled(device)) | ||
247 | return -EUNATCH; | ||
248 | ext_kekls = kmalloc(sizeof(*ext_kekls), GFP_KERNEL); | ||
249 | if (!ext_kekls) | ||
250 | return -ENOMEM; | ||
251 | rc = tape_3592_kekl_query(device, ext_kekls); | ||
252 | if (rc != 0) | ||
253 | goto fail; | ||
254 | if (copy_to_user((char __user *) arg, ext_kekls, sizeof(*ext_kekls))) { | ||
255 | rc = -EFAULT; | ||
256 | goto fail; | ||
257 | } | ||
258 | rc = 0; | ||
259 | fail: | ||
260 | kfree(ext_kekls); | ||
261 | return rc; | ||
262 | } | ||
263 | |||
264 | static int tape_3590_mttell(struct tape_device *device, int mt_count); | ||
265 | |||
266 | /* | ||
267 | * Set KEKLs | ||
268 | */ | ||
269 | static int tape_3592_kekl_set(struct tape_device *device, | ||
270 | struct tape390_kekl_pair *ext_kekls) | ||
271 | { | ||
272 | struct tape_request *request; | ||
273 | struct tape3592_kekl_set_order *order; | ||
274 | |||
275 | DBF_EVENT(6, "tape3592_kekl_set\n"); | ||
276 | if (check_ext_kekl_pair(ext_kekls)) { | ||
277 | DBF_EVENT(6, "invalid kekls\n"); | ||
278 | return -EINVAL; | ||
279 | } | ||
280 | if (tape_3590_mttell(device, 0) != 0) | ||
281 | return -EBADSLT; | ||
282 | request = tape_alloc_request(1, sizeof(*order)); | ||
283 | if (IS_ERR(request)) | ||
284 | return PTR_ERR(request); | ||
285 | order = request->cpdata; | ||
286 | memset(order, 0, sizeof(*order)); | ||
287 | order->code = 0xe3; | ||
288 | order->kekls.count = 2; | ||
289 | ext_to_int_kekl(&ext_kekls->kekl[0], &order->kekls.kekl[0]); | ||
290 | ext_to_int_kekl(&ext_kekls->kekl[1], &order->kekls.kekl[1]); | ||
291 | request->op = TO_KEKL_SET; | ||
292 | tape_ccw_end(request->cpaddr, PERF_SUBSYS_FUNC, sizeof(*order), order); | ||
293 | |||
294 | return tape_do_io_free(device, request); | ||
295 | } | ||
296 | |||
297 | /* | ||
298 | * IOCTL: Set KEKLs | ||
299 | */ | ||
300 | static int tape_3592_ioctl_kekl_set(struct tape_device *device, | ||
301 | unsigned long arg) | ||
302 | { | ||
303 | int rc; | ||
304 | struct tape390_kekl_pair *ext_kekls; | ||
305 | |||
306 | DBF_EVENT(6, "tape_3592_ioctl_kekl_set\n"); | ||
307 | if (!crypt_supported(device)) | ||
308 | return -ENOSYS; | ||
309 | if (!crypt_enabled(device)) | ||
310 | return -EUNATCH; | ||
311 | ext_kekls = kmalloc(sizeof(*ext_kekls), GFP_KERNEL); | ||
312 | if (!ext_kekls) | ||
313 | return -ENOMEM; | ||
314 | if (copy_from_user(ext_kekls, (char __user *)arg, sizeof(*ext_kekls))) { | ||
315 | rc = -EFAULT; | ||
316 | goto out; | ||
317 | } | ||
318 | rc = tape_3592_kekl_set(device, ext_kekls); | ||
319 | out: | ||
320 | kfree(ext_kekls); | ||
321 | return rc; | ||
322 | } | ||
323 | |||
324 | /* | ||
325 | * Enable encryption | ||
326 | */ | ||
327 | static int tape_3592_enable_crypt(struct tape_device *device) | ||
328 | { | ||
329 | struct tape_request *request; | ||
330 | char *data; | ||
331 | |||
332 | DBF_EVENT(6, "tape_3592_enable_crypt\n"); | ||
333 | if (!crypt_supported(device)) | ||
334 | return -ENOSYS; | ||
335 | request = tape_alloc_request(2, 72); | ||
336 | if (IS_ERR(request)) | ||
337 | return PTR_ERR(request); | ||
338 | data = request->cpdata; | ||
339 | memset(data,0,72); | ||
340 | |||
341 | data[0] = 0x05; | ||
342 | data[36 + 0] = 0x03; | ||
343 | data[36 + 1] = 0x03; | ||
344 | data[36 + 4] = 0x40; | ||
345 | data[36 + 6] = 0x01; | ||
346 | data[36 + 14] = 0x2f; | ||
347 | data[36 + 18] = 0xc3; | ||
348 | data[36 + 35] = 0x72; | ||
349 | request->op = TO_CRYPT_ON; | ||
350 | tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data); | ||
351 | tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36); | ||
352 | return tape_do_io_free(device, request); | ||
353 | } | ||
354 | |||
355 | /* | ||
356 | * Disable encryption | ||
357 | */ | ||
358 | static int tape_3592_disable_crypt(struct tape_device *device) | ||
359 | { | ||
360 | struct tape_request *request; | ||
361 | char *data; | ||
362 | |||
363 | DBF_EVENT(6, "tape_3592_disable_crypt\n"); | ||
364 | if (!crypt_supported(device)) | ||
365 | return -ENOSYS; | ||
366 | request = tape_alloc_request(2, 72); | ||
367 | if (IS_ERR(request)) | ||
368 | return PTR_ERR(request); | ||
369 | data = request->cpdata; | ||
370 | memset(data,0,72); | ||
371 | |||
372 | data[0] = 0x05; | ||
373 | data[36 + 0] = 0x03; | ||
374 | data[36 + 1] = 0x03; | ||
375 | data[36 + 35] = 0x32; | ||
376 | |||
377 | request->op = TO_CRYPT_OFF; | ||
378 | tape_ccw_cc(request->cpaddr, MODE_SET_CB, 36, data); | ||
379 | tape_ccw_end(request->cpaddr + 1, MODE_SET_CB, 36, data + 36); | ||
380 | |||
381 | return tape_do_io_free(device, request); | ||
382 | } | ||
383 | |||
384 | /* | ||
385 | * IOCTL: Set encryption status | ||
386 | */ | ||
387 | static int tape_3592_ioctl_crypt_set(struct tape_device *device, | ||
388 | unsigned long arg) | ||
389 | { | ||
390 | struct tape390_crypt_info info; | ||
391 | |||
392 | DBF_EVENT(6, "tape_3592_ioctl_crypt_set\n"); | ||
393 | if (!crypt_supported(device)) | ||
394 | return -ENOSYS; | ||
395 | if (copy_from_user(&info, (char __user *)arg, sizeof(info))) | ||
396 | return -EFAULT; | ||
397 | if (info.status & ~TAPE390_CRYPT_ON_MASK) | ||
398 | return -EINVAL; | ||
399 | if (info.status & TAPE390_CRYPT_ON_MASK) | ||
400 | return tape_3592_enable_crypt(device); | ||
401 | else | ||
402 | return tape_3592_disable_crypt(device); | ||
403 | } | ||
404 | |||
405 | static int tape_3590_sense_medium(struct tape_device *device); | ||
406 | |||
407 | /* | ||
408 | * IOCTL: Query enryption status | ||
409 | */ | ||
410 | static int tape_3592_ioctl_crypt_query(struct tape_device *device, | ||
411 | unsigned long arg) | ||
412 | { | ||
413 | DBF_EVENT(6, "tape_3592_ioctl_crypt_query\n"); | ||
414 | if (!crypt_supported(device)) | ||
415 | return -ENOSYS; | ||
416 | tape_3590_sense_medium(device); | ||
417 | if (copy_to_user((char __user *) arg, &TAPE_3590_CRYPT_INFO(device), | ||
418 | sizeof(TAPE_3590_CRYPT_INFO(device)))) | ||
419 | return -EFAULT; | ||
420 | else | ||
421 | return 0; | ||
422 | } | ||
423 | |||
97 | /* | 424 | /* |
98 | * 3590 IOCTL Overload | 425 | * 3590 IOCTL Overload |
99 | */ | 426 | */ |
@@ -109,6 +436,14 @@ tape_3590_ioctl(struct tape_device *device, unsigned int cmd, unsigned long arg) | |||
109 | 436 | ||
110 | return tape_std_display(device, &disp); | 437 | return tape_std_display(device, &disp); |
111 | } | 438 | } |
439 | case TAPE390_KEKL_SET: | ||
440 | return tape_3592_ioctl_kekl_set(device, arg); | ||
441 | case TAPE390_KEKL_QUERY: | ||
442 | return tape_3592_ioctl_kekl_query(device, arg); | ||
443 | case TAPE390_CRYPT_SET: | ||
444 | return tape_3592_ioctl_crypt_set(device, arg); | ||
445 | case TAPE390_CRYPT_QUERY: | ||
446 | return tape_3592_ioctl_crypt_query(device, arg); | ||
112 | default: | 447 | default: |
113 | return -EINVAL; /* no additional ioctls */ | 448 | return -EINVAL; /* no additional ioctls */ |
114 | } | 449 | } |
@@ -248,6 +583,12 @@ tape_3590_work_handler(struct work_struct *work) | |||
248 | case TO_READ_ATTMSG: | 583 | case TO_READ_ATTMSG: |
249 | tape_3590_read_attmsg(p->device); | 584 | tape_3590_read_attmsg(p->device); |
250 | break; | 585 | break; |
586 | case TO_CRYPT_ON: | ||
587 | tape_3592_enable_crypt(p->device); | ||
588 | break; | ||
589 | case TO_CRYPT_OFF: | ||
590 | tape_3592_disable_crypt(p->device); | ||
591 | break; | ||
251 | default: | 592 | default: |
252 | DBF_EVENT(3, "T3590: work handler undefined for " | 593 | DBF_EVENT(3, "T3590: work handler undefined for " |
253 | "operation 0x%02x\n", p->op); | 594 | "operation 0x%02x\n", p->op); |
@@ -365,6 +706,33 @@ tape_3590_check_locate(struct tape_device *device, struct tape_request *request) | |||
365 | } | 706 | } |
366 | #endif | 707 | #endif |
367 | 708 | ||
709 | static void tape_3590_med_state_set(struct tape_device *device, | ||
710 | struct tape_3590_med_sense *sense) | ||
711 | { | ||
712 | struct tape390_crypt_info *c_info; | ||
713 | |||
714 | c_info = &TAPE_3590_CRYPT_INFO(device); | ||
715 | |||
716 | if (sense->masst == MSENSE_UNASSOCIATED) { | ||
717 | tape_med_state_set(device, MS_UNLOADED); | ||
718 | TAPE_3590_CRYPT_INFO(device).medium_status = 0; | ||
719 | return; | ||
720 | } | ||
721 | if (sense->masst != MSENSE_ASSOCIATED_MOUNT) { | ||
722 | PRINT_ERR("Unknown medium state: %x\n", sense->masst); | ||
723 | return; | ||
724 | } | ||
725 | tape_med_state_set(device, MS_LOADED); | ||
726 | c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK; | ||
727 | if (sense->flags & MSENSE_CRYPT_MASK) { | ||
728 | PRINT_INFO("Medium is encrypted (%04x)\n", sense->flags); | ||
729 | c_info->medium_status |= TAPE390_MEDIUM_ENCRYPTED_MASK; | ||
730 | } else { | ||
731 | DBF_EVENT(6, "Medium is not encrypted %04x\n", sense->flags); | ||
732 | c_info->medium_status &= ~TAPE390_MEDIUM_ENCRYPTED_MASK; | ||
733 | } | ||
734 | } | ||
735 | |||
368 | /* | 736 | /* |
369 | * The done handler is called at device/channel end and wakes up the sleeping | 737 | * The done handler is called at device/channel end and wakes up the sleeping |
370 | * process | 738 | * process |
@@ -372,9 +740,10 @@ tape_3590_check_locate(struct tape_device *device, struct tape_request *request) | |||
372 | static int | 740 | static int |
373 | tape_3590_done(struct tape_device *device, struct tape_request *request) | 741 | tape_3590_done(struct tape_device *device, struct tape_request *request) |
374 | { | 742 | { |
375 | struct tape_3590_med_sense *sense; | 743 | struct tape_3590_disc_data *disc_data; |
376 | 744 | ||
377 | DBF_EVENT(6, "%s done\n", tape_op_verbose[request->op]); | 745 | DBF_EVENT(6, "%s done\n", tape_op_verbose[request->op]); |
746 | disc_data = device->discdata; | ||
378 | 747 | ||
379 | switch (request->op) { | 748 | switch (request->op) { |
380 | case TO_BSB: | 749 | case TO_BSB: |
@@ -394,13 +763,20 @@ tape_3590_done(struct tape_device *device, struct tape_request *request) | |||
394 | break; | 763 | break; |
395 | case TO_RUN: | 764 | case TO_RUN: |
396 | tape_med_state_set(device, MS_UNLOADED); | 765 | tape_med_state_set(device, MS_UNLOADED); |
766 | tape_3590_schedule_work(device, TO_CRYPT_OFF); | ||
397 | break; | 767 | break; |
398 | case TO_MSEN: | 768 | case TO_MSEN: |
399 | sense = (struct tape_3590_med_sense *) request->cpdata; | 769 | tape_3590_med_state_set(device, request->cpdata); |
400 | if (sense->masst == MSENSE_UNASSOCIATED) | 770 | break; |
401 | tape_med_state_set(device, MS_UNLOADED); | 771 | case TO_CRYPT_ON: |
402 | if (sense->masst == MSENSE_ASSOCIATED_MOUNT) | 772 | TAPE_3590_CRYPT_INFO(device).status |
403 | tape_med_state_set(device, MS_LOADED); | 773 | |= TAPE390_CRYPT_ON_MASK; |
774 | *(device->modeset_byte) |= 0x03; | ||
775 | break; | ||
776 | case TO_CRYPT_OFF: | ||
777 | TAPE_3590_CRYPT_INFO(device).status | ||
778 | &= ~TAPE390_CRYPT_ON_MASK; | ||
779 | *(device->modeset_byte) &= ~0x03; | ||
404 | break; | 780 | break; |
405 | case TO_RBI: /* RBI seems to succeed even without medium loaded. */ | 781 | case TO_RBI: /* RBI seems to succeed even without medium loaded. */ |
406 | case TO_NOP: /* Same to NOP. */ | 782 | case TO_NOP: /* Same to NOP. */ |
@@ -409,8 +785,9 @@ tape_3590_done(struct tape_device *device, struct tape_request *request) | |||
409 | case TO_DIS: | 785 | case TO_DIS: |
410 | case TO_ASSIGN: | 786 | case TO_ASSIGN: |
411 | case TO_UNASSIGN: | 787 | case TO_UNASSIGN: |
412 | break; | ||
413 | case TO_SIZE: | 788 | case TO_SIZE: |
789 | case TO_KEKL_SET: | ||
790 | case TO_KEKL_QUERY: | ||
414 | break; | 791 | break; |
415 | } | 792 | } |
416 | return TAPE_IO_SUCCESS; | 793 | return TAPE_IO_SUCCESS; |
@@ -540,10 +917,8 @@ static int | |||
540 | tape_3590_erp_long_busy(struct tape_device *device, | 917 | tape_3590_erp_long_busy(struct tape_device *device, |
541 | struct tape_request *request, struct irb *irb) | 918 | struct tape_request *request, struct irb *irb) |
542 | { | 919 | { |
543 | /* FIXME: how about WAITING for a minute ? */ | 920 | DBF_EVENT(6, "Device is busy\n"); |
544 | PRINT_WARN("(%s): Device is busy! Please wait a minute!\n", | 921 | return TAPE_IO_LONG_BUSY; |
545 | device->cdev->dev.bus_id); | ||
546 | return tape_3590_erp_basic(device, request, irb, -EBUSY); | ||
547 | } | 922 | } |
548 | 923 | ||
549 | /* | 924 | /* |
@@ -951,6 +1326,34 @@ tape_3590_print_era_msg(struct tape_device *device, struct irb *irb) | |||
951 | device->cdev->dev.bus_id, sense->mc); | 1326 | device->cdev->dev.bus_id, sense->mc); |
952 | } | 1327 | } |
953 | 1328 | ||
1329 | static int tape_3590_crypt_error(struct tape_device *device, | ||
1330 | struct tape_request *request, struct irb *irb) | ||
1331 | { | ||
1332 | u8 cu_rc, ekm_rc1; | ||
1333 | u16 ekm_rc2; | ||
1334 | u32 drv_rc; | ||
1335 | char *bus_id, *sense; | ||
1336 | |||
1337 | sense = ((struct tape_3590_sense *) irb->ecw)->fmt.data; | ||
1338 | bus_id = device->cdev->dev.bus_id; | ||
1339 | cu_rc = sense[0]; | ||
1340 | drv_rc = *((u32*) &sense[5]) & 0xffffff; | ||
1341 | ekm_rc1 = sense[9]; | ||
1342 | ekm_rc2 = *((u16*) &sense[10]); | ||
1343 | if ((cu_rc == 0) && (ekm_rc2 == 0xee31)) | ||
1344 | /* key not defined on EKM */ | ||
1345 | return tape_3590_erp_basic(device, request, irb, -EKEYREJECTED); | ||
1346 | if ((cu_rc == 1) || (cu_rc == 2)) | ||
1347 | /* No connection to EKM */ | ||
1348 | return tape_3590_erp_basic(device, request, irb, -ENOTCONN); | ||
1349 | |||
1350 | PRINT_ERR("(%s): Unable to get encryption key from EKM\n", bus_id); | ||
1351 | PRINT_ERR("(%s): CU=%02X DRIVE=%06X EKM=%02X:%04X\n", bus_id, cu_rc, | ||
1352 | drv_rc, ekm_rc1, ekm_rc2); | ||
1353 | |||
1354 | return tape_3590_erp_basic(device, request, irb, -ENOKEY); | ||
1355 | } | ||
1356 | |||
954 | /* | 1357 | /* |
955 | * 3590 error Recovery routine: | 1358 | * 3590 error Recovery routine: |
956 | * If possible, it tries to recover from the error. If this is not possible, | 1359 | * If possible, it tries to recover from the error. If this is not possible, |
@@ -979,6 +1382,8 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, | |||
979 | 1382 | ||
980 | sense = (struct tape_3590_sense *) irb->ecw; | 1383 | sense = (struct tape_3590_sense *) irb->ecw; |
981 | 1384 | ||
1385 | DBF_EVENT(6, "Unit Check: RQC = %x\n", sense->rc_rqc); | ||
1386 | |||
982 | /* | 1387 | /* |
983 | * First check all RC-QRCs where we want to do something special | 1388 | * First check all RC-QRCs where we want to do something special |
984 | * - "break": basic error recovery is done | 1389 | * - "break": basic error recovery is done |
@@ -999,6 +1404,8 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, | |||
999 | case 0x2231: | 1404 | case 0x2231: |
1000 | tape_3590_print_era_msg(device, irb); | 1405 | tape_3590_print_era_msg(device, irb); |
1001 | return tape_3590_erp_special_interrupt(device, request, irb); | 1406 | return tape_3590_erp_special_interrupt(device, request, irb); |
1407 | case 0x2240: | ||
1408 | return tape_3590_crypt_error(device, request, irb); | ||
1002 | 1409 | ||
1003 | case 0x3010: | 1410 | case 0x3010: |
1004 | DBF_EVENT(2, "(%08x): Backward at Beginning of Partition\n", | 1411 | DBF_EVENT(2, "(%08x): Backward at Beginning of Partition\n", |
@@ -1020,6 +1427,7 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, | |||
1020 | DBF_EVENT(2, "(%08x): Rewind Unload complete\n", | 1427 | DBF_EVENT(2, "(%08x): Rewind Unload complete\n", |
1021 | device->cdev_id); | 1428 | device->cdev_id); |
1022 | tape_med_state_set(device, MS_UNLOADED); | 1429 | tape_med_state_set(device, MS_UNLOADED); |
1430 | tape_3590_schedule_work(device, TO_CRYPT_OFF); | ||
1023 | return tape_3590_erp_basic(device, request, irb, 0); | 1431 | return tape_3590_erp_basic(device, request, irb, 0); |
1024 | 1432 | ||
1025 | case 0x4010: | 1433 | case 0x4010: |
@@ -1030,9 +1438,15 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, | |||
1030 | PRINT_WARN("(%s): Tape operation when medium not loaded\n", | 1438 | PRINT_WARN("(%s): Tape operation when medium not loaded\n", |
1031 | device->cdev->dev.bus_id); | 1439 | device->cdev->dev.bus_id); |
1032 | tape_med_state_set(device, MS_UNLOADED); | 1440 | tape_med_state_set(device, MS_UNLOADED); |
1441 | tape_3590_schedule_work(device, TO_CRYPT_OFF); | ||
1033 | return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); | 1442 | return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); |
1034 | case 0x4012: /* Device Long Busy */ | 1443 | case 0x4012: /* Device Long Busy */ |
1444 | /* XXX: Also use long busy handling here? */ | ||
1445 | DBF_EVENT(6, "(%08x): LONG BUSY\n", device->cdev_id); | ||
1035 | tape_3590_print_era_msg(device, irb); | 1446 | tape_3590_print_era_msg(device, irb); |
1447 | return tape_3590_erp_basic(device, request, irb, -EBUSY); | ||
1448 | case 0x4014: | ||
1449 | DBF_EVENT(6, "(%08x): Crypto LONG BUSY\n", device->cdev_id); | ||
1036 | return tape_3590_erp_long_busy(device, request, irb); | 1450 | return tape_3590_erp_long_busy(device, request, irb); |
1037 | 1451 | ||
1038 | case 0x5010: | 1452 | case 0x5010: |
@@ -1064,6 +1478,7 @@ tape_3590_unit_check(struct tape_device *device, struct tape_request *request, | |||
1064 | case 0x5120: | 1478 | case 0x5120: |
1065 | case 0x1120: | 1479 | case 0x1120: |
1066 | tape_med_state_set(device, MS_UNLOADED); | 1480 | tape_med_state_set(device, MS_UNLOADED); |
1481 | tape_3590_schedule_work(device, TO_CRYPT_OFF); | ||
1067 | return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); | 1482 | return tape_3590_erp_basic(device, request, irb, -ENOMEDIUM); |
1068 | 1483 | ||
1069 | case 0x6020: | 1484 | case 0x6020: |
@@ -1142,21 +1557,47 @@ tape_3590_setup_device(struct tape_device *device) | |||
1142 | { | 1557 | { |
1143 | int rc; | 1558 | int rc; |
1144 | struct tape_3590_disc_data *data; | 1559 | struct tape_3590_disc_data *data; |
1560 | char *rdc_data; | ||
1145 | 1561 | ||
1146 | DBF_EVENT(6, "3590 device setup\n"); | 1562 | DBF_EVENT(6, "3590 device setup\n"); |
1147 | data = kmalloc(sizeof(struct tape_3590_disc_data), | 1563 | data = kzalloc(sizeof(struct tape_3590_disc_data), GFP_KERNEL | GFP_DMA); |
1148 | GFP_KERNEL | GFP_DMA); | ||
1149 | if (data == NULL) | 1564 | if (data == NULL) |
1150 | return -ENOMEM; | 1565 | return -ENOMEM; |
1151 | data->read_back_op = READ_PREVIOUS; | 1566 | data->read_back_op = READ_PREVIOUS; |
1152 | device->discdata = data; | 1567 | device->discdata = data; |
1153 | 1568 | ||
1154 | if ((rc = tape_std_assign(device)) == 0) { | 1569 | rdc_data = kmalloc(64, GFP_KERNEL | GFP_DMA); |
1155 | /* Try to find out if medium is loaded */ | 1570 | if (!rdc_data) { |
1156 | if ((rc = tape_3590_sense_medium(device)) != 0) | 1571 | rc = -ENOMEM; |
1157 | DBF_LH(3, "3590 medium sense returned %d\n", rc); | 1572 | goto fail_kmalloc; |
1573 | } | ||
1574 | rc = read_dev_chars(device->cdev, (void**)&rdc_data, 64); | ||
1575 | if (rc) { | ||
1576 | DBF_LH(3, "Read device characteristics failed!\n"); | ||
1577 | goto fail_kmalloc; | ||
1578 | } | ||
1579 | rc = tape_std_assign(device); | ||
1580 | if (rc) | ||
1581 | goto fail_rdc_data; | ||
1582 | if (rdc_data[31] == 0x13) { | ||
1583 | PRINT_INFO("Device has crypto support\n"); | ||
1584 | data->crypt_info.capability |= TAPE390_CRYPT_SUPPORTED_MASK; | ||
1585 | tape_3592_disable_crypt(device); | ||
1586 | } else { | ||
1587 | DBF_EVENT(6, "Device has NO crypto support\n"); | ||
1158 | } | 1588 | } |
1589 | /* Try to find out if medium is loaded */ | ||
1590 | rc = tape_3590_sense_medium(device); | ||
1591 | if (rc) { | ||
1592 | DBF_LH(3, "3590 medium sense returned %d\n", rc); | ||
1593 | goto fail_rdc_data; | ||
1594 | } | ||
1595 | return 0; | ||
1159 | 1596 | ||
1597 | fail_rdc_data: | ||
1598 | kfree(rdc_data); | ||
1599 | fail_kmalloc: | ||
1600 | kfree(data); | ||
1160 | return rc; | 1601 | return rc; |
1161 | } | 1602 | } |
1162 | 1603 | ||
diff --git a/drivers/s390/char/tape_3590.h b/drivers/s390/char/tape_3590.h index cf274b9445a6..aa5138807af1 100644 --- a/drivers/s390/char/tape_3590.h +++ b/drivers/s390/char/tape_3590.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * drivers/s390/char/tape_3590.h | 2 | * drivers/s390/char/tape_3590.h |
3 | * tape device discipline for 3590 tapes. | 3 | * tape device discipline for 3590 tapes. |
4 | * | 4 | * |
5 | * Copyright (C) IBM Corp. 2001,2006 | 5 | * Copyright IBM Corp. 2001,2006 |
6 | * Author(s): Stefan Bader <shbader@de.ibm.com> | 6 | * Author(s): Stefan Bader <shbader@de.ibm.com> |
7 | * Michael Holzheu <holzheu@de.ibm.com> | 7 | * Michael Holzheu <holzheu@de.ibm.com> |
8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
@@ -38,16 +38,22 @@ | |||
38 | #define MSENSE_UNASSOCIATED 0x00 | 38 | #define MSENSE_UNASSOCIATED 0x00 |
39 | #define MSENSE_ASSOCIATED_MOUNT 0x01 | 39 | #define MSENSE_ASSOCIATED_MOUNT 0x01 |
40 | #define MSENSE_ASSOCIATED_UMOUNT 0x02 | 40 | #define MSENSE_ASSOCIATED_UMOUNT 0x02 |
41 | #define MSENSE_CRYPT_MASK 0x00000010 | ||
41 | 42 | ||
42 | #define TAPE_3590_MAX_MSG 0xb0 | 43 | #define TAPE_3590_MAX_MSG 0xb0 |
43 | 44 | ||
44 | /* Datatypes */ | 45 | /* Datatypes */ |
45 | 46 | ||
46 | struct tape_3590_disc_data { | 47 | struct tape_3590_disc_data { |
47 | unsigned char modeset_byte; | 48 | struct tape390_crypt_info crypt_info; |
48 | int read_back_op; | 49 | int read_back_op; |
49 | }; | 50 | }; |
50 | 51 | ||
52 | #define TAPE_3590_CRYPT_INFO(device) \ | ||
53 | ((struct tape_3590_disc_data*)(device->discdata))->crypt_info | ||
54 | #define TAPE_3590_READ_BACK_OP(device) \ | ||
55 | ((struct tape_3590_disc_data*)(device->discdata))->read_back_op | ||
56 | |||
51 | struct tape_3590_sense { | 57 | struct tape_3590_sense { |
52 | 58 | ||
53 | unsigned int command_rej:1; | 59 | unsigned int command_rej:1; |
@@ -118,7 +124,48 @@ struct tape_3590_sense { | |||
118 | struct tape_3590_med_sense { | 124 | struct tape_3590_med_sense { |
119 | unsigned int macst:4; | 125 | unsigned int macst:4; |
120 | unsigned int masst:4; | 126 | unsigned int masst:4; |
121 | char pad[127]; | 127 | char pad1[7]; |
128 | unsigned int flags; | ||
129 | char pad2[116]; | ||
130 | } __attribute__ ((packed)); | ||
131 | |||
132 | /* Datastructures for 3592 encryption support */ | ||
133 | |||
134 | struct tape3592_kekl { | ||
135 | __u8 flags; | ||
136 | char label[64]; | ||
137 | } __attribute__ ((packed)); | ||
138 | |||
139 | struct tape3592_kekl_pair { | ||
140 | __u8 count; | ||
141 | struct tape3592_kekl kekl[2]; | ||
142 | } __attribute__ ((packed)); | ||
143 | |||
144 | struct tape3592_kekl_query_data { | ||
145 | __u16 len; | ||
146 | __u8 fmt; | ||
147 | __u8 mc; | ||
148 | __u32 id; | ||
149 | __u8 flags; | ||
150 | struct tape3592_kekl_pair kekls; | ||
151 | char reserved[116]; | ||
152 | } __attribute__ ((packed)); | ||
153 | |||
154 | struct tape3592_kekl_query_order { | ||
155 | __u8 code; | ||
156 | __u8 flags; | ||
157 | char reserved1[2]; | ||
158 | __u8 max_count; | ||
159 | char reserved2[35]; | ||
160 | } __attribute__ ((packed)); | ||
161 | |||
162 | struct tape3592_kekl_set_order { | ||
163 | __u8 code; | ||
164 | __u8 flags; | ||
165 | char reserved1[2]; | ||
166 | __u8 op; | ||
167 | struct tape3592_kekl_pair kekls; | ||
168 | char reserved2[120]; | ||
122 | } __attribute__ ((packed)); | 169 | } __attribute__ ((packed)); |
123 | 170 | ||
124 | #endif /* _TAPE_3590_H */ | 171 | #endif /* _TAPE_3590_H */ |
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index c8a89b3b87d4..dd0ecaed592e 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c | |||
@@ -73,7 +73,7 @@ tapeblock_trigger_requeue(struct tape_device *device) | |||
73 | /* | 73 | /* |
74 | * Post finished request. | 74 | * Post finished request. |
75 | */ | 75 | */ |
76 | static inline void | 76 | static void |
77 | tapeblock_end_request(struct request *req, int uptodate) | 77 | tapeblock_end_request(struct request *req, int uptodate) |
78 | { | 78 | { |
79 | if (end_that_request_first(req, uptodate, req->hard_nr_sectors)) | 79 | if (end_that_request_first(req, uptodate, req->hard_nr_sectors)) |
@@ -108,7 +108,7 @@ __tapeblock_end_request(struct tape_request *ccw_req, void *data) | |||
108 | /* | 108 | /* |
109 | * Feed the tape device CCW queue with requests supplied in a list. | 109 | * Feed the tape device CCW queue with requests supplied in a list. |
110 | */ | 110 | */ |
111 | static inline int | 111 | static int |
112 | tapeblock_start_request(struct tape_device *device, struct request *req) | 112 | tapeblock_start_request(struct tape_device *device, struct request *req) |
113 | { | 113 | { |
114 | struct tape_request * ccw_req; | 114 | struct tape_request * ccw_req; |
diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c index 31198c8f2718..9faea04e11e9 100644 --- a/drivers/s390/char/tape_char.c +++ b/drivers/s390/char/tape_char.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * character device frontend for tape device driver | 3 | * character device frontend for tape device driver |
4 | * | 4 | * |
5 | * S390 and zSeries version | 5 | * S390 and zSeries version |
6 | * Copyright (C) 2001,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation | 6 | * Copyright IBM Corp. 2001,2006 |
7 | * Author(s): Carsten Otte <cotte@de.ibm.com> | 7 | * Author(s): Carsten Otte <cotte@de.ibm.com> |
8 | * Michael Holzheu <holzheu@de.ibm.com> | 8 | * Michael Holzheu <holzheu@de.ibm.com> |
9 | * Tuan Ngo-Anh <ngoanh@de.ibm.com> | 9 | * Tuan Ngo-Anh <ngoanh@de.ibm.com> |
@@ -89,22 +89,7 @@ tapechar_cleanup_device(struct tape_device *device) | |||
89 | device->nt = NULL; | 89 | device->nt = NULL; |
90 | } | 90 | } |
91 | 91 | ||
92 | /* | 92 | static int |
93 | * Terminate write command (we write two TMs and skip backward over last) | ||
94 | * This ensures that the tape is always correctly terminated. | ||
95 | * When the user writes afterwards a new file, he will overwrite the | ||
96 | * second TM and therefore one TM will remain to separate the | ||
97 | * two files on the tape... | ||
98 | */ | ||
99 | static inline void | ||
100 | tapechar_terminate_write(struct tape_device *device) | ||
101 | { | ||
102 | if (tape_mtop(device, MTWEOF, 1) == 0 && | ||
103 | tape_mtop(device, MTWEOF, 1) == 0) | ||
104 | tape_mtop(device, MTBSR, 1); | ||
105 | } | ||
106 | |||
107 | static inline int | ||
108 | tapechar_check_idalbuffer(struct tape_device *device, size_t block_size) | 93 | tapechar_check_idalbuffer(struct tape_device *device, size_t block_size) |
109 | { | 94 | { |
110 | struct idal_buffer *new; | 95 | struct idal_buffer *new; |
@@ -137,7 +122,7 @@ tapechar_check_idalbuffer(struct tape_device *device, size_t block_size) | |||
137 | /* | 122 | /* |
138 | * Tape device read function | 123 | * Tape device read function |
139 | */ | 124 | */ |
140 | ssize_t | 125 | static ssize_t |
141 | tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) | 126 | tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) |
142 | { | 127 | { |
143 | struct tape_device *device; | 128 | struct tape_device *device; |
@@ -201,7 +186,7 @@ tapechar_read(struct file *filp, char __user *data, size_t count, loff_t *ppos) | |||
201 | /* | 186 | /* |
202 | * Tape device write function | 187 | * Tape device write function |
203 | */ | 188 | */ |
204 | ssize_t | 189 | static ssize_t |
205 | tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t *ppos) | 190 | tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t *ppos) |
206 | { | 191 | { |
207 | struct tape_device *device; | 192 | struct tape_device *device; |
@@ -291,7 +276,7 @@ tapechar_write(struct file *filp, const char __user *data, size_t count, loff_t | |||
291 | /* | 276 | /* |
292 | * Character frontend tape device open function. | 277 | * Character frontend tape device open function. |
293 | */ | 278 | */ |
294 | int | 279 | static int |
295 | tapechar_open (struct inode *inode, struct file *filp) | 280 | tapechar_open (struct inode *inode, struct file *filp) |
296 | { | 281 | { |
297 | struct tape_device *device; | 282 | struct tape_device *device; |
@@ -326,7 +311,7 @@ tapechar_open (struct inode *inode, struct file *filp) | |||
326 | * Character frontend tape device release function. | 311 | * Character frontend tape device release function. |
327 | */ | 312 | */ |
328 | 313 | ||
329 | int | 314 | static int |
330 | tapechar_release(struct inode *inode, struct file *filp) | 315 | tapechar_release(struct inode *inode, struct file *filp) |
331 | { | 316 | { |
332 | struct tape_device *device; | 317 | struct tape_device *device; |
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index c6c2e918b990..e2a8a1a04bab 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * basic function of the tape device driver | 3 | * basic function of the tape device driver |
4 | * | 4 | * |
5 | * S390 and zSeries version | 5 | * S390 and zSeries version |
6 | * Copyright (C) 2001,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation | 6 | * Copyright IBM Corp. 2001,2006 |
7 | * Author(s): Carsten Otte <cotte@de.ibm.com> | 7 | * Author(s): Carsten Otte <cotte@de.ibm.com> |
8 | * Michael Holzheu <holzheu@de.ibm.com> | 8 | * Michael Holzheu <holzheu@de.ibm.com> |
9 | * Tuan Ngo-Anh <ngoanh@de.ibm.com> | 9 | * Tuan Ngo-Anh <ngoanh@de.ibm.com> |
@@ -26,9 +26,11 @@ | |||
26 | #include "tape_std.h" | 26 | #include "tape_std.h" |
27 | 27 | ||
28 | #define PRINTK_HEADER "TAPE_CORE: " | 28 | #define PRINTK_HEADER "TAPE_CORE: " |
29 | #define LONG_BUSY_TIMEOUT 180 /* seconds */ | ||
29 | 30 | ||
30 | static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *); | 31 | static void __tape_do_irq (struct ccw_device *, unsigned long, struct irb *); |
31 | static void tape_delayed_next_request(struct work_struct *); | 32 | static void tape_delayed_next_request(struct work_struct *); |
33 | static void tape_long_busy_timeout(unsigned long data); | ||
32 | 34 | ||
33 | /* | 35 | /* |
34 | * One list to contain all tape devices of all disciplines, so | 36 | * One list to contain all tape devices of all disciplines, so |
@@ -69,10 +71,12 @@ const char *tape_op_verbose[TO_SIZE] = | |||
69 | [TO_LOAD] = "LOA", [TO_READ_CONFIG] = "RCF", | 71 | [TO_LOAD] = "LOA", [TO_READ_CONFIG] = "RCF", |
70 | [TO_READ_ATTMSG] = "RAT", | 72 | [TO_READ_ATTMSG] = "RAT", |
71 | [TO_DIS] = "DIS", [TO_ASSIGN] = "ASS", | 73 | [TO_DIS] = "DIS", [TO_ASSIGN] = "ASS", |
72 | [TO_UNASSIGN] = "UAS" | 74 | [TO_UNASSIGN] = "UAS", [TO_CRYPT_ON] = "CON", |
75 | [TO_CRYPT_OFF] = "COF", [TO_KEKL_SET] = "KLS", | ||
76 | [TO_KEKL_QUERY] = "KLQ", | ||
73 | }; | 77 | }; |
74 | 78 | ||
75 | static inline int | 79 | static int |
76 | busid_to_int(char *bus_id) | 80 | busid_to_int(char *bus_id) |
77 | { | 81 | { |
78 | int dec; | 82 | int dec; |
@@ -252,7 +256,7 @@ tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate) | |||
252 | /* | 256 | /* |
253 | * Stop running ccw. Has to be called with the device lock held. | 257 | * Stop running ccw. Has to be called with the device lock held. |
254 | */ | 258 | */ |
255 | static inline int | 259 | static int |
256 | __tape_cancel_io(struct tape_device *device, struct tape_request *request) | 260 | __tape_cancel_io(struct tape_device *device, struct tape_request *request) |
257 | { | 261 | { |
258 | int retries; | 262 | int retries; |
@@ -346,6 +350,9 @@ tape_generic_online(struct tape_device *device, | |||
346 | return -EINVAL; | 350 | return -EINVAL; |
347 | } | 351 | } |
348 | 352 | ||
353 | init_timer(&device->lb_timeout); | ||
354 | device->lb_timeout.function = tape_long_busy_timeout; | ||
355 | |||
349 | /* Let the discipline have a go at the device. */ | 356 | /* Let the discipline have a go at the device. */ |
350 | device->discipline = discipline; | 357 | device->discipline = discipline; |
351 | if (!try_module_get(discipline->owner)) { | 358 | if (!try_module_get(discipline->owner)) { |
@@ -385,7 +392,7 @@ out: | |||
385 | return rc; | 392 | return rc; |
386 | } | 393 | } |
387 | 394 | ||
388 | static inline void | 395 | static void |
389 | tape_cleanup_device(struct tape_device *device) | 396 | tape_cleanup_device(struct tape_device *device) |
390 | { | 397 | { |
391 | tapeblock_cleanup_device(device); | 398 | tapeblock_cleanup_device(device); |
@@ -563,7 +570,7 @@ tape_generic_probe(struct ccw_device *cdev) | |||
563 | return ret; | 570 | return ret; |
564 | } | 571 | } |
565 | 572 | ||
566 | static inline void | 573 | static void |
567 | __tape_discard_requests(struct tape_device *device) | 574 | __tape_discard_requests(struct tape_device *device) |
568 | { | 575 | { |
569 | struct tape_request * request; | 576 | struct tape_request * request; |
@@ -703,7 +710,7 @@ tape_free_request (struct tape_request * request) | |||
703 | kfree(request); | 710 | kfree(request); |
704 | } | 711 | } |
705 | 712 | ||
706 | static inline int | 713 | static int |
707 | __tape_start_io(struct tape_device *device, struct tape_request *request) | 714 | __tape_start_io(struct tape_device *device, struct tape_request *request) |
708 | { | 715 | { |
709 | int rc; | 716 | int rc; |
@@ -733,7 +740,7 @@ __tape_start_io(struct tape_device *device, struct tape_request *request) | |||
733 | return rc; | 740 | return rc; |
734 | } | 741 | } |
735 | 742 | ||
736 | static inline void | 743 | static void |
737 | __tape_start_next_request(struct tape_device *device) | 744 | __tape_start_next_request(struct tape_device *device) |
738 | { | 745 | { |
739 | struct list_head *l, *n; | 746 | struct list_head *l, *n; |
@@ -801,7 +808,23 @@ tape_delayed_next_request(struct work_struct *work) | |||
801 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); | 808 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); |
802 | } | 809 | } |
803 | 810 | ||
804 | static inline void | 811 | static void tape_long_busy_timeout(unsigned long data) |
812 | { | ||
813 | struct tape_request *request; | ||
814 | struct tape_device *device; | ||
815 | |||
816 | device = (struct tape_device *) data; | ||
817 | spin_lock_irq(get_ccwdev_lock(device->cdev)); | ||
818 | request = list_entry(device->req_queue.next, struct tape_request, list); | ||
819 | if (request->status != TAPE_REQUEST_LONG_BUSY) | ||
820 | BUG(); | ||
821 | DBF_LH(6, "%08x: Long busy timeout.\n", device->cdev_id); | ||
822 | __tape_start_next_request(device); | ||
823 | device->lb_timeout.data = (unsigned long) tape_put_device(device); | ||
824 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); | ||
825 | } | ||
826 | |||
827 | static void | ||
805 | __tape_end_request( | 828 | __tape_end_request( |
806 | struct tape_device * device, | 829 | struct tape_device * device, |
807 | struct tape_request * request, | 830 | struct tape_request * request, |
@@ -878,7 +901,7 @@ tape_dump_sense_dbf(struct tape_device *device, struct tape_request *request, | |||
878 | * and starts it if the tape is idle. Has to be called with | 901 | * and starts it if the tape is idle. Has to be called with |
879 | * the device lock held. | 902 | * the device lock held. |
880 | */ | 903 | */ |
881 | static inline int | 904 | static int |
882 | __tape_start_request(struct tape_device *device, struct tape_request *request) | 905 | __tape_start_request(struct tape_device *device, struct tape_request *request) |
883 | { | 906 | { |
884 | int rc; | 907 | int rc; |
@@ -1094,7 +1117,22 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
1094 | /* May be an unsolicited irq */ | 1117 | /* May be an unsolicited irq */ |
1095 | if(request != NULL) | 1118 | if(request != NULL) |
1096 | request->rescnt = irb->scsw.count; | 1119 | request->rescnt = irb->scsw.count; |
1097 | 1120 | else if ((irb->scsw.dstat == 0x85 || irb->scsw.dstat == 0x80) && | |
1121 | !list_empty(&device->req_queue)) { | ||
1122 | /* Not Ready to Ready after long busy ? */ | ||
1123 | struct tape_request *req; | ||
1124 | req = list_entry(device->req_queue.next, | ||
1125 | struct tape_request, list); | ||
1126 | if (req->status == TAPE_REQUEST_LONG_BUSY) { | ||
1127 | DBF_EVENT(3, "(%08x): del timer\n", device->cdev_id); | ||
1128 | if (del_timer(&device->lb_timeout)) { | ||
1129 | device->lb_timeout.data = (unsigned long) | ||
1130 | tape_put_device(device); | ||
1131 | __tape_start_next_request(device); | ||
1132 | } | ||
1133 | return; | ||
1134 | } | ||
1135 | } | ||
1098 | if (irb->scsw.dstat != 0x0c) { | 1136 | if (irb->scsw.dstat != 0x0c) { |
1099 | /* Set the 'ONLINE' flag depending on sense byte 1 */ | 1137 | /* Set the 'ONLINE' flag depending on sense byte 1 */ |
1100 | if(*(((__u8 *) irb->ecw) + 1) & SENSE_DRIVE_ONLINE) | 1138 | if(*(((__u8 *) irb->ecw) + 1) & SENSE_DRIVE_ONLINE) |
@@ -1142,6 +1180,15 @@ __tape_do_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
1142 | break; | 1180 | break; |
1143 | case TAPE_IO_PENDING: | 1181 | case TAPE_IO_PENDING: |
1144 | break; | 1182 | break; |
1183 | case TAPE_IO_LONG_BUSY: | ||
1184 | device->lb_timeout.data = | ||
1185 | (unsigned long)tape_get_device_reference(device); | ||
1186 | device->lb_timeout.expires = jiffies + | ||
1187 | LONG_BUSY_TIMEOUT * HZ; | ||
1188 | DBF_EVENT(3, "(%08x): add timer\n", device->cdev_id); | ||
1189 | add_timer(&device->lb_timeout); | ||
1190 | request->status = TAPE_REQUEST_LONG_BUSY; | ||
1191 | break; | ||
1145 | case TAPE_IO_RETRY: | 1192 | case TAPE_IO_RETRY: |
1146 | rc = __tape_start_io(device, request); | 1193 | rc = __tape_start_io(device, request); |
1147 | if (rc) | 1194 | if (rc) |
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 09844621edc0..bc33068b9ce2 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c | |||
@@ -36,7 +36,7 @@ | |||
36 | struct tty_driver *tty3270_driver; | 36 | struct tty_driver *tty3270_driver; |
37 | static int tty3270_max_index; | 37 | static int tty3270_max_index; |
38 | 38 | ||
39 | struct raw3270_fn tty3270_fn; | 39 | static struct raw3270_fn tty3270_fn; |
40 | 40 | ||
41 | struct tty3270_cell { | 41 | struct tty3270_cell { |
42 | unsigned char character; | 42 | unsigned char character; |
@@ -119,8 +119,7 @@ static void tty3270_update(struct tty3270 *); | |||
119 | /* | 119 | /* |
120 | * Setup timeout for a device. On timeout trigger an update. | 120 | * Setup timeout for a device. On timeout trigger an update. |
121 | */ | 121 | */ |
122 | void | 122 | static void tty3270_set_timer(struct tty3270 *tp, int expires) |
123 | tty3270_set_timer(struct tty3270 *tp, int expires) | ||
124 | { | 123 | { |
125 | if (expires == 0) { | 124 | if (expires == 0) { |
126 | if (timer_pending(&tp->timer) && del_timer(&tp->timer)) | 125 | if (timer_pending(&tp->timer) && del_timer(&tp->timer)) |
@@ -841,7 +840,7 @@ tty3270_del_views(void) | |||
841 | } | 840 | } |
842 | } | 841 | } |
843 | 842 | ||
844 | struct raw3270_fn tty3270_fn = { | 843 | static struct raw3270_fn tty3270_fn = { |
845 | .activate = tty3270_activate, | 844 | .activate = tty3270_activate, |
846 | .deactivate = tty3270_deactivate, | 845 | .deactivate = tty3270_deactivate, |
847 | .intv = (void *) tty3270_irq, | 846 | .intv = (void *) tty3270_irq, |
@@ -1754,8 +1753,7 @@ static const struct tty_operations tty3270_ops = { | |||
1754 | .set_termios = tty3270_set_termios | 1753 | .set_termios = tty3270_set_termios |
1755 | }; | 1754 | }; |
1756 | 1755 | ||
1757 | void | 1756 | static void tty3270_notifier(int index, int active) |
1758 | tty3270_notifier(int index, int active) | ||
1759 | { | 1757 | { |
1760 | if (active) | 1758 | if (active) |
1761 | tty_register_device(tty3270_driver, index, NULL); | 1759 | tty_register_device(tty3270_driver, index, NULL); |
@@ -1767,8 +1765,7 @@ tty3270_notifier(int index, int active) | |||
1767 | * 3270 tty registration code called from tty_init(). | 1765 | * 3270 tty registration code called from tty_init(). |
1768 | * Most kernel services (incl. kmalloc) are available at this poimt. | 1766 | * Most kernel services (incl. kmalloc) are available at this poimt. |
1769 | */ | 1767 | */ |
1770 | int __init | 1768 | static int __init tty3270_init(void) |
1771 | tty3270_init(void) | ||
1772 | { | 1769 | { |
1773 | struct tty_driver *driver; | 1770 | struct tty_driver *driver; |
1774 | int ret; | 1771 | int ret; |
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index 6cb23040954b..4f894dc2373b 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c | |||
@@ -128,9 +128,8 @@ static iucv_interrupt_ops_t vmlogrdr_iucvops = { | |||
128 | .MessagePending = vmlogrdr_iucv_MessagePending, | 128 | .MessagePending = vmlogrdr_iucv_MessagePending, |
129 | }; | 129 | }; |
130 | 130 | ||
131 | 131 | static DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue); | |
132 | DECLARE_WAIT_QUEUE_HEAD(conn_wait_queue); | 132 | static DECLARE_WAIT_QUEUE_HEAD(read_wait_queue); |
133 | DECLARE_WAIT_QUEUE_HEAD(read_wait_queue); | ||
134 | 133 | ||
135 | /* | 134 | /* |
136 | * pointer to system service private structure | 135 | * pointer to system service private structure |
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index 12c2d6b746e6..aa65df4dfced 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c | |||
@@ -43,7 +43,7 @@ typedef enum {add, free} range_action; | |||
43 | * Function: blacklist_range | 43 | * Function: blacklist_range |
44 | * (Un-)blacklist the devices from-to | 44 | * (Un-)blacklist the devices from-to |
45 | */ | 45 | */ |
46 | static inline void | 46 | static void |
47 | blacklist_range (range_action action, unsigned int from, unsigned int to, | 47 | blacklist_range (range_action action, unsigned int from, unsigned int to, |
48 | unsigned int ssid) | 48 | unsigned int ssid) |
49 | { | 49 | { |
@@ -69,7 +69,7 @@ blacklist_range (range_action action, unsigned int from, unsigned int to, | |||
69 | * Get devno/busid from given string. | 69 | * Get devno/busid from given string. |
70 | * Shamelessly grabbed from dasd_devmap.c. | 70 | * Shamelessly grabbed from dasd_devmap.c. |
71 | */ | 71 | */ |
72 | static inline int | 72 | static int |
73 | blacklist_busid(char **str, int *id0, int *ssid, int *devno) | 73 | blacklist_busid(char **str, int *id0, int *ssid, int *devno) |
74 | { | 74 | { |
75 | int val, old_style; | 75 | int val, old_style; |
@@ -123,10 +123,10 @@ confused: | |||
123 | return 1; | 123 | return 1; |
124 | } | 124 | } |
125 | 125 | ||
126 | static inline int | 126 | static int |
127 | blacklist_parse_parameters (char *str, range_action action) | 127 | blacklist_parse_parameters (char *str, range_action action) |
128 | { | 128 | { |
129 | unsigned int from, to, from_id0, to_id0, from_ssid, to_ssid; | 129 | int from, to, from_id0, to_id0, from_ssid, to_ssid; |
130 | 130 | ||
131 | while (*str != 0 && *str != '\n') { | 131 | while (*str != 0 && *str != '\n') { |
132 | range_action ra = action; | 132 | range_action ra = action; |
@@ -227,7 +227,7 @@ is_blacklisted (int ssid, int devno) | |||
227 | * Function: blacklist_parse_proc_parameters | 227 | * Function: blacklist_parse_proc_parameters |
228 | * parse the stuff which is piped to /proc/cio_ignore | 228 | * parse the stuff which is piped to /proc/cio_ignore |
229 | */ | 229 | */ |
230 | static inline void | 230 | static void |
231 | blacklist_parse_proc_parameters (char *buf) | 231 | blacklist_parse_proc_parameters (char *buf) |
232 | { | 232 | { |
233 | if (strncmp (buf, "free ", 5) == 0) { | 233 | if (strncmp (buf, "free ", 5) == 0) { |
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 38954f5cd14c..d48e3ca4752c 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -53,7 +53,7 @@ ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer, | |||
53 | 53 | ||
54 | static struct bus_type ccwgroup_bus_type; | 54 | static struct bus_type ccwgroup_bus_type; |
55 | 55 | ||
56 | static inline void | 56 | static void |
57 | __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) | 57 | __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) |
58 | { | 58 | { |
59 | int i; | 59 | int i; |
@@ -104,7 +104,7 @@ ccwgroup_release (struct device *dev) | |||
104 | kfree(gdev); | 104 | kfree(gdev); |
105 | } | 105 | } |
106 | 106 | ||
107 | static inline int | 107 | static int |
108 | __ccwgroup_create_symlinks(struct ccwgroup_device *gdev) | 108 | __ccwgroup_create_symlinks(struct ccwgroup_device *gdev) |
109 | { | 109 | { |
110 | char str[8]; | 110 | char str[8]; |
@@ -424,7 +424,7 @@ ccwgroup_probe_ccwdev(struct ccw_device *cdev) | |||
424 | return 0; | 424 | return 0; |
425 | } | 425 | } |
426 | 426 | ||
427 | static inline struct ccwgroup_device * | 427 | static struct ccwgroup_device * |
428 | __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev) | 428 | __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev) |
429 | { | 429 | { |
430 | struct ccwgroup_device *gdev; | 430 | struct ccwgroup_device *gdev; |
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index cbab8d2ce5cf..6f05a44e3817 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -93,7 +93,7 @@ chsc_get_sch_desc_irq(struct subchannel *sch, void *page) | |||
93 | u16 sch; /* subchannel */ | 93 | u16 sch; /* subchannel */ |
94 | u8 chpid[8]; /* chpids 0-7 */ | 94 | u8 chpid[8]; /* chpids 0-7 */ |
95 | u16 fla[8]; /* full link addresses 0-7 */ | 95 | u16 fla[8]; /* full link addresses 0-7 */ |
96 | } *ssd_area; | 96 | } __attribute__ ((packed)) *ssd_area; |
97 | 97 | ||
98 | ssd_area = page; | 98 | ssd_area = page; |
99 | 99 | ||
@@ -277,7 +277,7 @@ out_unreg: | |||
277 | return 0; | 277 | return 0; |
278 | } | 278 | } |
279 | 279 | ||
280 | static inline void | 280 | static void |
281 | s390_set_chpid_offline( __u8 chpid) | 281 | s390_set_chpid_offline( __u8 chpid) |
282 | { | 282 | { |
283 | char dbf_txt[15]; | 283 | char dbf_txt[15]; |
@@ -338,7 +338,7 @@ s390_process_res_acc_sch(struct res_acc_data *res_data, struct subchannel *sch) | |||
338 | return 0x80 >> chp; | 338 | return 0x80 >> chp; |
339 | } | 339 | } |
340 | 340 | ||
341 | static inline int | 341 | static int |
342 | s390_process_res_acc_new_sch(struct subchannel_id schid) | 342 | s390_process_res_acc_new_sch(struct subchannel_id schid) |
343 | { | 343 | { |
344 | struct schib schib; | 344 | struct schib schib; |
@@ -444,7 +444,7 @@ __get_chpid_from_lir(void *data) | |||
444 | u32 andesc[28]; | 444 | u32 andesc[28]; |
445 | /* incident-specific information */ | 445 | /* incident-specific information */ |
446 | u32 isinfo[28]; | 446 | u32 isinfo[28]; |
447 | } *lir; | 447 | } __attribute__ ((packed)) *lir; |
448 | 448 | ||
449 | lir = data; | 449 | lir = data; |
450 | if (!(lir->iq&0x80)) | 450 | if (!(lir->iq&0x80)) |
@@ -461,154 +461,146 @@ __get_chpid_from_lir(void *data) | |||
461 | return (u16) (lir->indesc[0]&0x000000ff); | 461 | return (u16) (lir->indesc[0]&0x000000ff); |
462 | } | 462 | } |
463 | 463 | ||
464 | int | 464 | struct chsc_sei_area { |
465 | chsc_process_crw(void) | 465 | struct chsc_header request; |
466 | u32 reserved1; | ||
467 | u32 reserved2; | ||
468 | u32 reserved3; | ||
469 | struct chsc_header response; | ||
470 | u32 reserved4; | ||
471 | u8 flags; | ||
472 | u8 vf; /* validity flags */ | ||
473 | u8 rs; /* reporting source */ | ||
474 | u8 cc; /* content code */ | ||
475 | u16 fla; /* full link address */ | ||
476 | u16 rsid; /* reporting source id */ | ||
477 | u32 reserved5; | ||
478 | u32 reserved6; | ||
479 | u8 ccdf[4096 - 16 - 24]; /* content-code dependent field */ | ||
480 | /* ccdf has to be big enough for a link-incident record */ | ||
481 | } __attribute__ ((packed)); | ||
482 | |||
483 | static int chsc_process_sei_link_incident(struct chsc_sei_area *sei_area) | ||
484 | { | ||
485 | int chpid; | ||
486 | |||
487 | CIO_CRW_EVENT(4, "chsc: link incident (rs=%02x, rs_id=%04x)\n", | ||
488 | sei_area->rs, sei_area->rsid); | ||
489 | if (sei_area->rs != 4) | ||
490 | return 0; | ||
491 | chpid = __get_chpid_from_lir(sei_area->ccdf); | ||
492 | if (chpid < 0) | ||
493 | CIO_CRW_EVENT(4, "chsc: link incident - invalid LIR\n"); | ||
494 | else | ||
495 | s390_set_chpid_offline(chpid); | ||
496 | |||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | static int chsc_process_sei_res_acc(struct chsc_sei_area *sei_area) | ||
466 | { | 501 | { |
467 | int chpid, ret; | ||
468 | struct res_acc_data res_data; | 502 | struct res_acc_data res_data; |
469 | struct { | 503 | struct device *dev; |
470 | struct chsc_header request; | 504 | int status; |
471 | u32 reserved1; | 505 | int rc; |
472 | u32 reserved2; | 506 | |
473 | u32 reserved3; | 507 | CIO_CRW_EVENT(4, "chsc: resource accessibility event (rs=%02x, " |
474 | struct chsc_header response; | 508 | "rs_id=%04x)\n", sei_area->rs, sei_area->rsid); |
475 | u32 reserved4; | 509 | if (sei_area->rs != 4) |
476 | u8 flags; | 510 | return 0; |
477 | u8 vf; /* validity flags */ | 511 | /* allocate a new channel path structure, if needed */ |
478 | u8 rs; /* reporting source */ | 512 | status = get_chp_status(sei_area->rsid); |
479 | u8 cc; /* content code */ | 513 | if (status < 0) |
480 | u16 fla; /* full link address */ | 514 | new_channel_path(sei_area->rsid); |
481 | u16 rsid; /* reporting source id */ | 515 | else if (!status) |
482 | u32 reserved5; | 516 | return 0; |
483 | u32 reserved6; | 517 | dev = get_device(&css[0]->chps[sei_area->rsid]->dev); |
484 | u32 ccdf[96]; /* content-code dependent field */ | 518 | memset(&res_data, 0, sizeof(struct res_acc_data)); |
485 | /* ccdf has to be big enough for a link-incident record */ | 519 | res_data.chp = to_channelpath(dev); |
486 | } *sei_area; | 520 | if ((sei_area->vf & 0xc0) != 0) { |
521 | res_data.fla = sei_area->fla; | ||
522 | if ((sei_area->vf & 0xc0) == 0xc0) | ||
523 | /* full link address */ | ||
524 | res_data.fla_mask = 0xffff; | ||
525 | else | ||
526 | /* link address */ | ||
527 | res_data.fla_mask = 0xff00; | ||
528 | } | ||
529 | rc = s390_process_res_acc(&res_data); | ||
530 | put_device(dev); | ||
531 | |||
532 | return rc; | ||
533 | } | ||
534 | |||
535 | static int chsc_process_sei(struct chsc_sei_area *sei_area) | ||
536 | { | ||
537 | int rc; | ||
538 | |||
539 | /* Check if we might have lost some information. */ | ||
540 | if (sei_area->flags & 0x40) | ||
541 | CIO_CRW_EVENT(2, "chsc: event overflow\n"); | ||
542 | /* which kind of information was stored? */ | ||
543 | rc = 0; | ||
544 | switch (sei_area->cc) { | ||
545 | case 1: /* link incident*/ | ||
546 | rc = chsc_process_sei_link_incident(sei_area); | ||
547 | break; | ||
548 | case 2: /* i/o resource accessibiliy */ | ||
549 | rc = chsc_process_sei_res_acc(sei_area); | ||
550 | break; | ||
551 | default: /* other stuff */ | ||
552 | CIO_CRW_EVENT(4, "chsc: unhandled sei content code %d\n", | ||
553 | sei_area->cc); | ||
554 | break; | ||
555 | } | ||
556 | |||
557 | return rc; | ||
558 | } | ||
559 | |||
560 | int chsc_process_crw(void) | ||
561 | { | ||
562 | struct chsc_sei_area *sei_area; | ||
563 | int ret; | ||
564 | int rc; | ||
487 | 565 | ||
488 | if (!sei_page) | 566 | if (!sei_page) |
489 | return 0; | 567 | return 0; |
490 | /* | 568 | /* Access to sei_page is serialized through machine check handler |
491 | * build the chsc request block for store event information | 569 | * thread, so no need for locking. */ |
492 | * and do the call | ||
493 | * This function is only called by the machine check handler thread, | ||
494 | * so we don't need locking for the sei_page. | ||
495 | */ | ||
496 | sei_area = sei_page; | 570 | sei_area = sei_page; |
497 | 571 | ||
498 | CIO_TRACE_EVENT( 2, "prcss"); | 572 | CIO_TRACE_EVENT( 2, "prcss"); |
499 | ret = 0; | 573 | ret = 0; |
500 | do { | 574 | do { |
501 | int ccode, status; | ||
502 | struct device *dev; | ||
503 | memset(sei_area, 0, sizeof(*sei_area)); | 575 | memset(sei_area, 0, sizeof(*sei_area)); |
504 | memset(&res_data, 0, sizeof(struct res_acc_data)); | ||
505 | sei_area->request.length = 0x0010; | 576 | sei_area->request.length = 0x0010; |
506 | sei_area->request.code = 0x000e; | 577 | sei_area->request.code = 0x000e; |
578 | if (chsc(sei_area)) | ||
579 | break; | ||
507 | 580 | ||
508 | ccode = chsc(sei_area); | 581 | if (sei_area->response.code == 0x0001) { |
509 | if (ccode > 0) | 582 | CIO_CRW_EVENT(4, "chsc: sei successful\n"); |
510 | return 0; | 583 | rc = chsc_process_sei(sei_area); |
511 | 584 | if (rc) | |
512 | switch (sei_area->response.code) { | 585 | ret = rc; |
513 | /* for debug purposes, check for problems */ | 586 | } else { |
514 | case 0x0001: | 587 | CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n", |
515 | CIO_CRW_EVENT(4, "chsc_process_crw: event information " | ||
516 | "successfully stored\n"); | ||
517 | break; /* everything ok */ | ||
518 | case 0x0002: | ||
519 | CIO_CRW_EVENT(2, | ||
520 | "chsc_process_crw: invalid command!\n"); | ||
521 | return 0; | ||
522 | case 0x0003: | ||
523 | CIO_CRW_EVENT(2, "chsc_process_crw: error in chsc " | ||
524 | "request block!\n"); | ||
525 | return 0; | ||
526 | case 0x0005: | ||
527 | CIO_CRW_EVENT(2, "chsc_process_crw: no event " | ||
528 | "information stored\n"); | ||
529 | return 0; | ||
530 | default: | ||
531 | CIO_CRW_EVENT(2, "chsc_process_crw: chsc response %d\n", | ||
532 | sei_area->response.code); | 588 | sei_area->response.code); |
533 | return 0; | 589 | ret = 0; |
534 | } | ||
535 | |||
536 | /* Check if we might have lost some information. */ | ||
537 | if (sei_area->flags & 0x40) | ||
538 | CIO_CRW_EVENT(2, "chsc_process_crw: Event information " | ||
539 | "has been lost due to overflow!\n"); | ||
540 | |||
541 | if (sei_area->rs != 4) { | ||
542 | CIO_CRW_EVENT(2, "chsc_process_crw: reporting source " | ||
543 | "(%04X) isn't a chpid!\n", | ||
544 | sei_area->rsid); | ||
545 | continue; | ||
546 | } | ||
547 | |||
548 | /* which kind of information was stored? */ | ||
549 | switch (sei_area->cc) { | ||
550 | case 1: /* link incident*/ | ||
551 | CIO_CRW_EVENT(4, "chsc_process_crw: " | ||
552 | "channel subsystem reports link incident," | ||
553 | " reporting source is chpid %x\n", | ||
554 | sei_area->rsid); | ||
555 | chpid = __get_chpid_from_lir(sei_area->ccdf); | ||
556 | if (chpid < 0) | ||
557 | CIO_CRW_EVENT(4, "%s: Invalid LIR, skipping\n", | ||
558 | __FUNCTION__); | ||
559 | else | ||
560 | s390_set_chpid_offline(chpid); | ||
561 | break; | ||
562 | |||
563 | case 2: /* i/o resource accessibiliy */ | ||
564 | CIO_CRW_EVENT(4, "chsc_process_crw: " | ||
565 | "channel subsystem reports some I/O " | ||
566 | "devices may have become accessible\n"); | ||
567 | pr_debug("Data received after sei: \n"); | ||
568 | pr_debug("Validity flags: %x\n", sei_area->vf); | ||
569 | |||
570 | /* allocate a new channel path structure, if needed */ | ||
571 | status = get_chp_status(sei_area->rsid); | ||
572 | if (status < 0) | ||
573 | new_channel_path(sei_area->rsid); | ||
574 | else if (!status) | ||
575 | break; | ||
576 | dev = get_device(&css[0]->chps[sei_area->rsid]->dev); | ||
577 | res_data.chp = to_channelpath(dev); | ||
578 | pr_debug("chpid: %x", sei_area->rsid); | ||
579 | if ((sei_area->vf & 0xc0) != 0) { | ||
580 | res_data.fla = sei_area->fla; | ||
581 | if ((sei_area->vf & 0xc0) == 0xc0) { | ||
582 | pr_debug(" full link addr: %x", | ||
583 | sei_area->fla); | ||
584 | res_data.fla_mask = 0xffff; | ||
585 | } else { | ||
586 | pr_debug(" link addr: %x", | ||
587 | sei_area->fla); | ||
588 | res_data.fla_mask = 0xff00; | ||
589 | } | ||
590 | } | ||
591 | ret = s390_process_res_acc(&res_data); | ||
592 | pr_debug("\n\n"); | ||
593 | put_device(dev); | ||
594 | break; | ||
595 | |||
596 | default: /* other stuff */ | ||
597 | CIO_CRW_EVENT(4, "chsc_process_crw: event %d\n", | ||
598 | sei_area->cc); | ||
599 | break; | 590 | break; |
600 | } | 591 | } |
601 | } while (sei_area->flags & 0x80); | 592 | } while (sei_area->flags & 0x80); |
593 | |||
602 | return ret; | 594 | return ret; |
603 | } | 595 | } |
604 | 596 | ||
605 | static inline int | 597 | static int |
606 | __chp_add_new_sch(struct subchannel_id schid) | 598 | __chp_add_new_sch(struct subchannel_id schid) |
607 | { | 599 | { |
608 | struct schib schib; | 600 | struct schib schib; |
609 | int ret; | 601 | int ret; |
610 | 602 | ||
611 | if (stsch(schid, &schib)) | 603 | if (stsch_err(schid, &schib)) |
612 | /* We're through */ | 604 | /* We're through */ |
613 | return need_rescan ? -EAGAIN : -ENXIO; | 605 | return need_rescan ? -EAGAIN : -ENXIO; |
614 | 606 | ||
@@ -709,7 +701,7 @@ chp_process_crw(int chpid, int on) | |||
709 | return chp_add(chpid); | 701 | return chp_add(chpid); |
710 | } | 702 | } |
711 | 703 | ||
712 | static inline int check_for_io_on_path(struct subchannel *sch, int index) | 704 | static int check_for_io_on_path(struct subchannel *sch, int index) |
713 | { | 705 | { |
714 | int cc; | 706 | int cc; |
715 | 707 | ||
@@ -741,7 +733,7 @@ static void terminate_internal_io(struct subchannel *sch) | |||
741 | sch->driver->termination(&sch->dev); | 733 | sch->driver->termination(&sch->dev); |
742 | } | 734 | } |
743 | 735 | ||
744 | static inline void | 736 | static void |
745 | __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) | 737 | __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on) |
746 | { | 738 | { |
747 | int chp, old_lpm; | 739 | int chp, old_lpm; |
@@ -967,8 +959,8 @@ static struct bin_attribute chp_measurement_attr = { | |||
967 | static void | 959 | static void |
968 | chsc_remove_chp_cmg_attr(struct channel_path *chp) | 960 | chsc_remove_chp_cmg_attr(struct channel_path *chp) |
969 | { | 961 | { |
970 | sysfs_remove_bin_file(&chp->dev.kobj, &chp_measurement_chars_attr); | 962 | device_remove_bin_file(&chp->dev, &chp_measurement_chars_attr); |
971 | sysfs_remove_bin_file(&chp->dev.kobj, &chp_measurement_attr); | 963 | device_remove_bin_file(&chp->dev, &chp_measurement_attr); |
972 | } | 964 | } |
973 | 965 | ||
974 | static int | 966 | static int |
@@ -976,14 +968,12 @@ chsc_add_chp_cmg_attr(struct channel_path *chp) | |||
976 | { | 968 | { |
977 | int ret; | 969 | int ret; |
978 | 970 | ||
979 | ret = sysfs_create_bin_file(&chp->dev.kobj, | 971 | ret = device_create_bin_file(&chp->dev, &chp_measurement_chars_attr); |
980 | &chp_measurement_chars_attr); | ||
981 | if (ret) | 972 | if (ret) |
982 | return ret; | 973 | return ret; |
983 | ret = sysfs_create_bin_file(&chp->dev.kobj, &chp_measurement_attr); | 974 | ret = device_create_bin_file(&chp->dev, &chp_measurement_attr); |
984 | if (ret) | 975 | if (ret) |
985 | sysfs_remove_bin_file(&chp->dev.kobj, | 976 | device_remove_bin_file(&chp->dev, &chp_measurement_chars_attr); |
986 | &chp_measurement_chars_attr); | ||
987 | return ret; | 977 | return ret; |
988 | } | 978 | } |
989 | 979 | ||
@@ -1042,7 +1032,7 @@ __chsc_do_secm(struct channel_subsystem *css, int enable, void *page) | |||
1042 | u32 : 4; | 1032 | u32 : 4; |
1043 | u32 fmt : 4; | 1033 | u32 fmt : 4; |
1044 | u32 : 16; | 1034 | u32 : 16; |
1045 | } *secm_area; | 1035 | } __attribute__ ((packed)) *secm_area; |
1046 | int ret, ccode; | 1036 | int ret, ccode; |
1047 | 1037 | ||
1048 | secm_area = page; | 1038 | secm_area = page; |
@@ -1253,7 +1243,7 @@ chsc_determine_channel_path_description(int chpid, | |||
1253 | struct chsc_header response; | 1243 | struct chsc_header response; |
1254 | u32 zeroes2; | 1244 | u32 zeroes2; |
1255 | struct channel_path_desc desc; | 1245 | struct channel_path_desc desc; |
1256 | } *scpd_area; | 1246 | } __attribute__ ((packed)) *scpd_area; |
1257 | 1247 | ||
1258 | scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); | 1248 | scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); |
1259 | if (!scpd_area) | 1249 | if (!scpd_area) |
@@ -1350,7 +1340,7 @@ chsc_get_channel_measurement_chars(struct channel_path *chp) | |||
1350 | u32 cmg : 8; | 1340 | u32 cmg : 8; |
1351 | u32 zeroes3; | 1341 | u32 zeroes3; |
1352 | u32 data[NR_MEASUREMENT_CHARS]; | 1342 | u32 data[NR_MEASUREMENT_CHARS]; |
1353 | } *scmc_area; | 1343 | } __attribute__ ((packed)) *scmc_area; |
1354 | 1344 | ||
1355 | scmc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); | 1345 | scmc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); |
1356 | if (!scmc_area) | 1346 | if (!scmc_area) |
@@ -1517,7 +1507,7 @@ chsc_enable_facility(int operation_code) | |||
1517 | u32 reserved5:4; | 1507 | u32 reserved5:4; |
1518 | u32 format2:4; | 1508 | u32 format2:4; |
1519 | u32 reserved6:24; | 1509 | u32 reserved6:24; |
1520 | } *sda_area; | 1510 | } __attribute__ ((packed)) *sda_area; |
1521 | 1511 | ||
1522 | sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA); | 1512 | sda_area = (void *)get_zeroed_page(GFP_KERNEL|GFP_DMA); |
1523 | if (!sda_area) | 1513 | if (!sda_area) |
@@ -1569,7 +1559,7 @@ chsc_determine_css_characteristics(void) | |||
1569 | u32 reserved4; | 1559 | u32 reserved4; |
1570 | u32 general_char[510]; | 1560 | u32 general_char[510]; |
1571 | u32 chsc_char[518]; | 1561 | u32 chsc_char[518]; |
1572 | } *scsc_area; | 1562 | } __attribute__ ((packed)) *scsc_area; |
1573 | 1563 | ||
1574 | scsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); | 1564 | scsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); |
1575 | if (!scsc_area) { | 1565 | if (!scsc_area) { |
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index a259245780ae..0fb2b024208f 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h | |||
@@ -10,17 +10,17 @@ | |||
10 | struct chsc_header { | 10 | struct chsc_header { |
11 | u16 length; | 11 | u16 length; |
12 | u16 code; | 12 | u16 code; |
13 | }; | 13 | } __attribute__ ((packed)); |
14 | 14 | ||
15 | #define NR_MEASUREMENT_CHARS 5 | 15 | #define NR_MEASUREMENT_CHARS 5 |
16 | struct cmg_chars { | 16 | struct cmg_chars { |
17 | u32 values[NR_MEASUREMENT_CHARS]; | 17 | u32 values[NR_MEASUREMENT_CHARS]; |
18 | }; | 18 | } __attribute__ ((packed)); |
19 | 19 | ||
20 | #define NR_MEASUREMENT_ENTRIES 8 | 20 | #define NR_MEASUREMENT_ENTRIES 8 |
21 | struct cmg_entry { | 21 | struct cmg_entry { |
22 | u32 values[NR_MEASUREMENT_ENTRIES]; | 22 | u32 values[NR_MEASUREMENT_ENTRIES]; |
23 | }; | 23 | } __attribute__ ((packed)); |
24 | 24 | ||
25 | struct channel_path_desc { | 25 | struct channel_path_desc { |
26 | u8 flags; | 26 | u8 flags; |
@@ -31,7 +31,7 @@ struct channel_path_desc { | |||
31 | u8 zeroes; | 31 | u8 zeroes; |
32 | u8 chla; | 32 | u8 chla; |
33 | u8 chpp; | 33 | u8 chpp; |
34 | }; | 34 | } __attribute__ ((packed)); |
35 | 35 | ||
36 | struct channel_path { | 36 | struct channel_path { |
37 | int id; | 37 | int id; |
@@ -47,6 +47,9 @@ struct channel_path { | |||
47 | extern void s390_process_css( void ); | 47 | extern void s390_process_css( void ); |
48 | extern void chsc_validate_chpids(struct subchannel *); | 48 | extern void chsc_validate_chpids(struct subchannel *); |
49 | extern void chpid_is_actually_online(int); | 49 | extern void chpid_is_actually_online(int); |
50 | extern int css_get_ssd_info(struct subchannel *); | ||
51 | extern int chsc_process_crw(void); | ||
52 | extern int chp_process_crw(int, int); | ||
50 | 53 | ||
51 | struct css_general_char { | 54 | struct css_general_char { |
52 | u64 : 41; | 55 | u64 : 41; |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index ae1bf231d089..b3a56dc5f68a 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -122,7 +122,7 @@ cio_get_options (struct subchannel *sch) | |||
122 | * Use tpi to get a pending interrupt, call the interrupt handler and | 122 | * Use tpi to get a pending interrupt, call the interrupt handler and |
123 | * return a pointer to the subchannel structure. | 123 | * return a pointer to the subchannel structure. |
124 | */ | 124 | */ |
125 | static inline int | 125 | static int |
126 | cio_tpi(void) | 126 | cio_tpi(void) |
127 | { | 127 | { |
128 | struct tpi_info *tpi_info; | 128 | struct tpi_info *tpi_info; |
@@ -152,7 +152,7 @@ cio_tpi(void) | |||
152 | return 1; | 152 | return 1; |
153 | } | 153 | } |
154 | 154 | ||
155 | static inline int | 155 | static int |
156 | cio_start_handle_notoper(struct subchannel *sch, __u8 lpm) | 156 | cio_start_handle_notoper(struct subchannel *sch, __u8 lpm) |
157 | { | 157 | { |
158 | char dbf_text[15]; | 158 | char dbf_text[15]; |
@@ -585,7 +585,7 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) | |||
585 | * This device must not be known to Linux. So we simply | 585 | * This device must not be known to Linux. So we simply |
586 | * say that there is no device and return ENODEV. | 586 | * say that there is no device and return ENODEV. |
587 | */ | 587 | */ |
588 | CIO_MSG_EVENT(0, "Blacklisted device detected " | 588 | CIO_MSG_EVENT(4, "Blacklisted device detected " |
589 | "at devno %04X, subchannel set %x\n", | 589 | "at devno %04X, subchannel set %x\n", |
590 | sch->schib.pmcw.dev, sch->schid.ssid); | 590 | sch->schib.pmcw.dev, sch->schid.ssid); |
591 | err = -ENODEV; | 591 | err = -ENODEV; |
@@ -646,7 +646,7 @@ do_IRQ (struct pt_regs *regs) | |||
646 | * Make sure that the i/o interrupt did not "overtake" | 646 | * Make sure that the i/o interrupt did not "overtake" |
647 | * the last HZ timer interrupt. | 647 | * the last HZ timer interrupt. |
648 | */ | 648 | */ |
649 | account_ticks(); | 649 | account_ticks(S390_lowcore.int_clock); |
650 | /* | 650 | /* |
651 | * Get interrupt information from lowcore | 651 | * Get interrupt information from lowcore |
652 | */ | 652 | */ |
@@ -832,7 +832,7 @@ cio_get_console_subchannel(void) | |||
832 | } | 832 | } |
833 | 833 | ||
834 | #endif | 834 | #endif |
835 | static inline int | 835 | static int |
836 | __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) | 836 | __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) |
837 | { | 837 | { |
838 | int retry, cc; | 838 | int retry, cc; |
@@ -850,7 +850,20 @@ __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) | |||
850 | return -EBUSY; /* uhm... */ | 850 | return -EBUSY; /* uhm... */ |
851 | } | 851 | } |
852 | 852 | ||
853 | static inline int | 853 | /* we can't use the normal udelay here, since it enables external interrupts */ |
854 | |||
855 | static void udelay_reset(unsigned long usecs) | ||
856 | { | ||
857 | uint64_t start_cc, end_cc; | ||
858 | |||
859 | asm volatile ("STCK %0" : "=m" (start_cc)); | ||
860 | do { | ||
861 | cpu_relax(); | ||
862 | asm volatile ("STCK %0" : "=m" (end_cc)); | ||
863 | } while (((end_cc - start_cc)/4096) < usecs); | ||
864 | } | ||
865 | |||
866 | static int | ||
854 | __clear_subchannel_easy(struct subchannel_id schid) | 867 | __clear_subchannel_easy(struct subchannel_id schid) |
855 | { | 868 | { |
856 | int retry; | 869 | int retry; |
@@ -865,7 +878,7 @@ __clear_subchannel_easy(struct subchannel_id schid) | |||
865 | if (schid_equal(&ti.schid, &schid)) | 878 | if (schid_equal(&ti.schid, &schid)) |
866 | return 0; | 879 | return 0; |
867 | } | 880 | } |
868 | udelay(100); | 881 | udelay_reset(100); |
869 | } | 882 | } |
870 | return -EBUSY; | 883 | return -EBUSY; |
871 | } | 884 | } |
@@ -882,11 +895,11 @@ static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr) | |||
882 | int rc; | 895 | int rc; |
883 | 896 | ||
884 | pgm_check_occured = 0; | 897 | pgm_check_occured = 0; |
885 | s390_reset_pgm_handler = cio_reset_pgm_check_handler; | 898 | s390_base_pgm_handler_fn = cio_reset_pgm_check_handler; |
886 | rc = stsch(schid, addr); | 899 | rc = stsch(schid, addr); |
887 | s390_reset_pgm_handler = NULL; | 900 | s390_base_pgm_handler_fn = NULL; |
888 | 901 | ||
889 | /* The program check handler could have changed pgm_check_occured */ | 902 | /* The program check handler could have changed pgm_check_occured. */ |
890 | barrier(); | 903 | barrier(); |
891 | 904 | ||
892 | if (pgm_check_occured) | 905 | if (pgm_check_occured) |
@@ -944,7 +957,7 @@ static void css_reset(void) | |||
944 | /* Reset subchannels. */ | 957 | /* Reset subchannels. */ |
945 | for_each_subchannel(__shutdown_subchannel_easy, NULL); | 958 | for_each_subchannel(__shutdown_subchannel_easy, NULL); |
946 | /* Reset channel paths. */ | 959 | /* Reset channel paths. */ |
947 | s390_reset_mcck_handler = s390_reset_chpids_mcck_handler; | 960 | s390_base_mcck_handler_fn = s390_reset_chpids_mcck_handler; |
948 | /* Enable channel report machine checks. */ | 961 | /* Enable channel report machine checks. */ |
949 | __ctl_set_bit(14, 28); | 962 | __ctl_set_bit(14, 28); |
950 | /* Temporarily reenable machine checks. */ | 963 | /* Temporarily reenable machine checks. */ |
@@ -969,7 +982,7 @@ static void css_reset(void) | |||
969 | local_mcck_disable(); | 982 | local_mcck_disable(); |
970 | /* Disable channel report machine checks. */ | 983 | /* Disable channel report machine checks. */ |
971 | __ctl_clear_bit(14, 28); | 984 | __ctl_clear_bit(14, 28); |
972 | s390_reset_mcck_handler = NULL; | 985 | s390_base_mcck_handler_fn = NULL; |
973 | } | 986 | } |
974 | 987 | ||
975 | static struct reset_call css_reset_call = { | 988 | static struct reset_call css_reset_call = { |
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 828b2d334f0a..90b22faabbf7 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c | |||
@@ -519,8 +519,8 @@ struct cmb { | |||
519 | /* insert a single device into the cmb_area list | 519 | /* insert a single device into the cmb_area list |
520 | * called with cmb_area.lock held from alloc_cmb | 520 | * called with cmb_area.lock held from alloc_cmb |
521 | */ | 521 | */ |
522 | static inline int alloc_cmb_single (struct ccw_device *cdev, | 522 | static int alloc_cmb_single(struct ccw_device *cdev, |
523 | struct cmb_data *cmb_data) | 523 | struct cmb_data *cmb_data) |
524 | { | 524 | { |
525 | struct cmb *cmb; | 525 | struct cmb *cmb; |
526 | struct ccw_device_private *node; | 526 | struct ccw_device_private *node; |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 9d6c02446863..fe0ace7aece8 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -30,7 +30,7 @@ struct channel_subsystem *css[__MAX_CSSID + 1]; | |||
30 | 30 | ||
31 | int css_characteristics_avail = 0; | 31 | int css_characteristics_avail = 0; |
32 | 32 | ||
33 | inline int | 33 | int |
34 | for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data) | 34 | for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data) |
35 | { | 35 | { |
36 | struct subchannel_id schid; | 36 | struct subchannel_id schid; |
@@ -108,9 +108,6 @@ css_subchannel_release(struct device *dev) | |||
108 | } | 108 | } |
109 | } | 109 | } |
110 | 110 | ||
111 | extern int css_get_ssd_info(struct subchannel *sch); | ||
112 | |||
113 | |||
114 | int css_sch_device_register(struct subchannel *sch) | 111 | int css_sch_device_register(struct subchannel *sch) |
115 | { | 112 | { |
116 | int ret; | 113 | int ret; |
@@ -187,7 +184,7 @@ get_subchannel_by_schid(struct subchannel_id schid) | |||
187 | return dev ? to_subchannel(dev) : NULL; | 184 | return dev ? to_subchannel(dev) : NULL; |
188 | } | 185 | } |
189 | 186 | ||
190 | static inline int css_get_subchannel_status(struct subchannel *sch) | 187 | static int css_get_subchannel_status(struct subchannel *sch) |
191 | { | 188 | { |
192 | struct schib schib; | 189 | struct schib schib; |
193 | 190 | ||
@@ -299,7 +296,7 @@ static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow) | |||
299 | /* Will be done on the slow path. */ | 296 | /* Will be done on the slow path. */ |
300 | return -EAGAIN; | 297 | return -EAGAIN; |
301 | } | 298 | } |
302 | if (stsch(schid, &schib) || !schib.pmcw.dnv) { | 299 | if (stsch_err(schid, &schib) || !schib.pmcw.dnv) { |
303 | /* Unusable - ignore. */ | 300 | /* Unusable - ignore. */ |
304 | return 0; | 301 | return 0; |
305 | } | 302 | } |
@@ -417,7 +414,7 @@ static void reprobe_all(struct work_struct *unused) | |||
417 | need_reprobe); | 414 | need_reprobe); |
418 | } | 415 | } |
419 | 416 | ||
420 | DECLARE_WORK(css_reprobe_work, reprobe_all); | 417 | static DECLARE_WORK(css_reprobe_work, reprobe_all); |
421 | 418 | ||
422 | /* Schedule reprobing of all unregistered subchannels. */ | 419 | /* Schedule reprobing of all unregistered subchannels. */ |
423 | void css_schedule_reprobe(void) | 420 | void css_schedule_reprobe(void) |
@@ -578,7 +575,7 @@ css_cm_enable_store(struct device *dev, struct device_attribute *attr, | |||
578 | 575 | ||
579 | static DEVICE_ATTR(cm_enable, 0644, css_cm_enable_show, css_cm_enable_store); | 576 | static DEVICE_ATTR(cm_enable, 0644, css_cm_enable_show, css_cm_enable_store); |
580 | 577 | ||
581 | static inline int __init setup_css(int nr) | 578 | static int __init setup_css(int nr) |
582 | { | 579 | { |
583 | u32 tod_high; | 580 | u32 tod_high; |
584 | int ret; | 581 | int ret; |
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 3464c5b875c4..ca2bab932a8a 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
@@ -143,6 +143,8 @@ extern void css_sch_device_unregister(struct subchannel *); | |||
143 | extern struct subchannel * get_subchannel_by_schid(struct subchannel_id); | 143 | extern struct subchannel * get_subchannel_by_schid(struct subchannel_id); |
144 | extern int css_init_done; | 144 | extern int css_init_done; |
145 | extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); | 145 | extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); |
146 | extern int css_process_crw(int, int); | ||
147 | extern void css_reiterate_subchannels(void); | ||
146 | 148 | ||
147 | #define __MAX_SUBCHANNEL 65535 | 149 | #define __MAX_SUBCHANNEL 65535 |
148 | #define __MAX_SSID 3 | 150 | #define __MAX_SSID 3 |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 803579053c2f..e322111fb369 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -138,7 +138,6 @@ struct bus_type ccw_bus_type; | |||
138 | 138 | ||
139 | static int io_subchannel_probe (struct subchannel *); | 139 | static int io_subchannel_probe (struct subchannel *); |
140 | static int io_subchannel_remove (struct subchannel *); | 140 | static int io_subchannel_remove (struct subchannel *); |
141 | void io_subchannel_irq (struct device *); | ||
142 | static int io_subchannel_notify(struct device *, int); | 141 | static int io_subchannel_notify(struct device *, int); |
143 | static void io_subchannel_verify(struct device *); | 142 | static void io_subchannel_verify(struct device *); |
144 | static void io_subchannel_ioterm(struct device *); | 143 | static void io_subchannel_ioterm(struct device *); |
@@ -235,11 +234,8 @@ chpids_show (struct device * dev, struct device_attribute *attr, char * buf) | |||
235 | ssize_t ret = 0; | 234 | ssize_t ret = 0; |
236 | int chp; | 235 | int chp; |
237 | 236 | ||
238 | if (ssd) | 237 | for (chp = 0; chp < 8; chp++) |
239 | for (chp = 0; chp < 8; chp++) | 238 | ret += sprintf (buf+ret, "%02x ", ssd->chpid[chp]); |
240 | ret += sprintf (buf+ret, "%02x ", ssd->chpid[chp]); | ||
241 | else | ||
242 | ret += sprintf (buf, "n/a"); | ||
243 | ret += sprintf (buf+ret, "\n"); | 239 | ret += sprintf (buf+ret, "\n"); |
244 | return min((ssize_t)PAGE_SIZE, ret); | 240 | return min((ssize_t)PAGE_SIZE, ret); |
245 | } | 241 | } |
@@ -552,13 +548,13 @@ static struct attribute_group ccwdev_attr_group = { | |||
552 | .attrs = ccwdev_attrs, | 548 | .attrs = ccwdev_attrs, |
553 | }; | 549 | }; |
554 | 550 | ||
555 | static inline int | 551 | static int |
556 | device_add_files (struct device *dev) | 552 | device_add_files (struct device *dev) |
557 | { | 553 | { |
558 | return sysfs_create_group(&dev->kobj, &ccwdev_attr_group); | 554 | return sysfs_create_group(&dev->kobj, &ccwdev_attr_group); |
559 | } | 555 | } |
560 | 556 | ||
561 | static inline void | 557 | static void |
562 | device_remove_files(struct device *dev) | 558 | device_remove_files(struct device *dev) |
563 | { | 559 | { |
564 | sysfs_remove_group(&dev->kobj, &ccwdev_attr_group); | 560 | sysfs_remove_group(&dev->kobj, &ccwdev_attr_group); |
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 29db6341d632..b66338b76579 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h | |||
@@ -74,6 +74,7 @@ extern struct workqueue_struct *ccw_device_notify_work; | |||
74 | extern wait_queue_head_t ccw_device_init_wq; | 74 | extern wait_queue_head_t ccw_device_init_wq; |
75 | extern atomic_t ccw_device_init_count; | 75 | extern atomic_t ccw_device_init_count; |
76 | 76 | ||
77 | void io_subchannel_irq (struct device *pdev); | ||
77 | void io_subchannel_recog_done(struct ccw_device *cdev); | 78 | void io_subchannel_recog_done(struct ccw_device *cdev); |
78 | 79 | ||
79 | int ccw_device_cancel_halt_clear(struct ccw_device *); | 80 | int ccw_device_cancel_halt_clear(struct ccw_device *); |
@@ -118,6 +119,7 @@ int ccw_device_stlck(struct ccw_device *); | |||
118 | /* qdio needs this. */ | 119 | /* qdio needs this. */ |
119 | void ccw_device_set_timeout(struct ccw_device *, int); | 120 | void ccw_device_set_timeout(struct ccw_device *, int); |
120 | extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *); | 121 | extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *); |
122 | extern struct bus_type ccw_bus_type; | ||
121 | 123 | ||
122 | /* Channel measurement facility related */ | 124 | /* Channel measurement facility related */ |
123 | void retry_set_schib(struct ccw_device *cdev); | 125 | void retry_set_schib(struct ccw_device *cdev); |
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index eed14572fc3b..51238e7555bb 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -206,7 +206,7 @@ ccw_device_handle_oper(struct ccw_device *cdev) | |||
206 | * been varied online on the SE so we have to find out by magic (i. e. driving | 206 | * been varied online on the SE so we have to find out by magic (i. e. driving |
207 | * the channel subsystem to device selection and updating our path masks). | 207 | * the channel subsystem to device selection and updating our path masks). |
208 | */ | 208 | */ |
209 | static inline void | 209 | static void |
210 | __recover_lost_chpids(struct subchannel *sch, int old_lpm) | 210 | __recover_lost_chpids(struct subchannel *sch, int old_lpm) |
211 | { | 211 | { |
212 | int mask, i; | 212 | int mask, i; |
@@ -387,7 +387,7 @@ ccw_device_done(struct ccw_device *cdev, int state) | |||
387 | put_device (&cdev->dev); | 387 | put_device (&cdev->dev); |
388 | } | 388 | } |
389 | 389 | ||
390 | static inline int cmp_pgid(struct pgid *p1, struct pgid *p2) | 390 | static int cmp_pgid(struct pgid *p1, struct pgid *p2) |
391 | { | 391 | { |
392 | char *c1; | 392 | char *c1; |
393 | char *c2; | 393 | char *c2; |
@@ -842,6 +842,8 @@ ccw_device_irq(struct ccw_device *cdev, enum dev_event dev_event) | |||
842 | call_handler_unsol: | 842 | call_handler_unsol: |
843 | if (cdev->handler) | 843 | if (cdev->handler) |
844 | cdev->handler (cdev, 0, irb); | 844 | cdev->handler (cdev, 0, irb); |
845 | if (cdev->private->flags.doverify) | ||
846 | ccw_device_online_verify(cdev, 0); | ||
845 | return; | 847 | return; |
846 | } | 848 | } |
847 | /* Accumulate status and find out if a basic sense is needed. */ | 849 | /* Accumulate status and find out if a basic sense is needed. */ |
@@ -892,7 +894,7 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event) | |||
892 | /* | 894 | /* |
893 | * Got an interrupt for a basic sense. | 895 | * Got an interrupt for a basic sense. |
894 | */ | 896 | */ |
895 | void | 897 | static void |
896 | ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event) | 898 | ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event) |
897 | { | 899 | { |
898 | struct irb *irb; | 900 | struct irb *irb; |
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index d269607336ec..d7b25b8f71d2 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c | |||
@@ -302,7 +302,7 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb) | |||
302 | wake_up(&cdev->private->wait_q); | 302 | wake_up(&cdev->private->wait_q); |
303 | } | 303 | } |
304 | 304 | ||
305 | static inline int | 305 | static int |
306 | __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, __u8 lpm) | 306 | __ccw_device_retry_loop(struct ccw_device *cdev, struct ccw1 *ccw, long magic, __u8 lpm) |
307 | { | 307 | { |
308 | int ret; | 308 | int ret; |
diff --git a/drivers/s390/cio/device_status.c b/drivers/s390/cio/device_status.c index bdcf930f7beb..6b1caea622ea 100644 --- a/drivers/s390/cio/device_status.c +++ b/drivers/s390/cio/device_status.c | |||
@@ -25,7 +25,7 @@ | |||
25 | * Check for any kind of channel or interface control check but don't | 25 | * Check for any kind of channel or interface control check but don't |
26 | * issue the message for the console device | 26 | * issue the message for the console device |
27 | */ | 27 | */ |
28 | static inline void | 28 | static void |
29 | ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb) | 29 | ccw_device_msg_control_check(struct ccw_device *cdev, struct irb *irb) |
30 | { | 30 | { |
31 | if (!(irb->scsw.cstat & (SCHN_STAT_CHN_DATA_CHK | | 31 | if (!(irb->scsw.cstat & (SCHN_STAT_CHN_DATA_CHK | |
@@ -72,7 +72,7 @@ ccw_device_path_notoper(struct ccw_device *cdev) | |||
72 | /* | 72 | /* |
73 | * Copy valid bits from the extended control word to device irb. | 73 | * Copy valid bits from the extended control word to device irb. |
74 | */ | 74 | */ |
75 | static inline void | 75 | static void |
76 | ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb) | 76 | ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb) |
77 | { | 77 | { |
78 | /* | 78 | /* |
@@ -94,7 +94,7 @@ ccw_device_accumulate_ecw(struct ccw_device *cdev, struct irb *irb) | |||
94 | /* | 94 | /* |
95 | * Check if extended status word is valid. | 95 | * Check if extended status word is valid. |
96 | */ | 96 | */ |
97 | static inline int | 97 | static int |
98 | ccw_device_accumulate_esw_valid(struct irb *irb) | 98 | ccw_device_accumulate_esw_valid(struct irb *irb) |
99 | { | 99 | { |
100 | if (!irb->scsw.eswf && irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) | 100 | if (!irb->scsw.eswf && irb->scsw.stctl == SCSW_STCTL_STATUS_PEND) |
@@ -109,7 +109,7 @@ ccw_device_accumulate_esw_valid(struct irb *irb) | |||
109 | /* | 109 | /* |
110 | * Copy valid bits from the extended status word to device irb. | 110 | * Copy valid bits from the extended status word to device irb. |
111 | */ | 111 | */ |
112 | static inline void | 112 | static void |
113 | ccw_device_accumulate_esw(struct ccw_device *cdev, struct irb *irb) | 113 | ccw_device_accumulate_esw(struct ccw_device *cdev, struct irb *irb) |
114 | { | 114 | { |
115 | struct irb *cdev_irb; | 115 | struct irb *cdev_irb; |
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 6fd1940842eb..d726cd5777de 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c | |||
@@ -66,7 +66,6 @@ MODULE_LICENSE("GPL"); | |||
66 | /******************** HERE WE GO ***********************************/ | 66 | /******************** HERE WE GO ***********************************/ |
67 | 67 | ||
68 | static const char version[] = "QDIO base support version 2"; | 68 | static const char version[] = "QDIO base support version 2"; |
69 | extern struct bus_type ccw_bus_type; | ||
70 | 69 | ||
71 | static int qdio_performance_stats = 0; | 70 | static int qdio_performance_stats = 0; |
72 | static int proc_perf_file_registration; | 71 | static int proc_perf_file_registration; |
@@ -138,7 +137,7 @@ qdio_release_q(struct qdio_q *q) | |||
138 | } | 137 | } |
139 | 138 | ||
140 | /*check ccq */ | 139 | /*check ccq */ |
141 | static inline int | 140 | static int |
142 | qdio_check_ccq(struct qdio_q *q, unsigned int ccq) | 141 | qdio_check_ccq(struct qdio_q *q, unsigned int ccq) |
143 | { | 142 | { |
144 | char dbf_text[15]; | 143 | char dbf_text[15]; |
@@ -153,7 +152,7 @@ qdio_check_ccq(struct qdio_q *q, unsigned int ccq) | |||
153 | return -EIO; | 152 | return -EIO; |
154 | } | 153 | } |
155 | /* EQBS: extract buffer states */ | 154 | /* EQBS: extract buffer states */ |
156 | static inline int | 155 | static int |
157 | qdio_do_eqbs(struct qdio_q *q, unsigned char *state, | 156 | qdio_do_eqbs(struct qdio_q *q, unsigned char *state, |
158 | unsigned int *start, unsigned int *cnt) | 157 | unsigned int *start, unsigned int *cnt) |
159 | { | 158 | { |
@@ -188,7 +187,7 @@ again: | |||
188 | } | 187 | } |
189 | 188 | ||
190 | /* SQBS: set buffer states */ | 189 | /* SQBS: set buffer states */ |
191 | static inline int | 190 | static int |
192 | qdio_do_sqbs(struct qdio_q *q, unsigned char state, | 191 | qdio_do_sqbs(struct qdio_q *q, unsigned char state, |
193 | unsigned int *start, unsigned int *cnt) | 192 | unsigned int *start, unsigned int *cnt) |
194 | { | 193 | { |
@@ -315,7 +314,7 @@ __do_siga_output(struct qdio_q *q, unsigned int *busy_bit) | |||
315 | * returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns | 314 | * returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns |
316 | * an access exception | 315 | * an access exception |
317 | */ | 316 | */ |
318 | static inline int | 317 | static int |
319 | qdio_siga_output(struct qdio_q *q) | 318 | qdio_siga_output(struct qdio_q *q) |
320 | { | 319 | { |
321 | int cc; | 320 | int cc; |
@@ -349,7 +348,7 @@ qdio_siga_output(struct qdio_q *q) | |||
349 | return cc; | 348 | return cc; |
350 | } | 349 | } |
351 | 350 | ||
352 | static inline int | 351 | static int |
353 | qdio_siga_input(struct qdio_q *q) | 352 | qdio_siga_input(struct qdio_q *q) |
354 | { | 353 | { |
355 | int cc; | 354 | int cc; |
@@ -421,7 +420,7 @@ tiqdio_sched_tl(void) | |||
421 | tasklet_hi_schedule(&tiqdio_tasklet); | 420 | tasklet_hi_schedule(&tiqdio_tasklet); |
422 | } | 421 | } |
423 | 422 | ||
424 | static inline void | 423 | static void |
425 | qdio_mark_tiq(struct qdio_q *q) | 424 | qdio_mark_tiq(struct qdio_q *q) |
426 | { | 425 | { |
427 | unsigned long flags; | 426 | unsigned long flags; |
@@ -471,7 +470,7 @@ qdio_mark_q(struct qdio_q *q) | |||
471 | tasklet_schedule(&q->tasklet); | 470 | tasklet_schedule(&q->tasklet); |
472 | } | 471 | } |
473 | 472 | ||
474 | static inline int | 473 | static int |
475 | qdio_stop_polling(struct qdio_q *q) | 474 | qdio_stop_polling(struct qdio_q *q) |
476 | { | 475 | { |
477 | #ifdef QDIO_USE_PROCESSING_STATE | 476 | #ifdef QDIO_USE_PROCESSING_STATE |
@@ -525,7 +524,7 @@ qdio_stop_polling(struct qdio_q *q) | |||
525 | * sophisticated locking outside of unmark_q, so that we don't need to | 524 | * sophisticated locking outside of unmark_q, so that we don't need to |
526 | * disable the interrupts :-) | 525 | * disable the interrupts :-) |
527 | */ | 526 | */ |
528 | static inline void | 527 | static void |
529 | qdio_unmark_q(struct qdio_q *q) | 528 | qdio_unmark_q(struct qdio_q *q) |
530 | { | 529 | { |
531 | unsigned long flags; | 530 | unsigned long flags; |
@@ -691,7 +690,7 @@ qdio_qebsm_get_inbound_buffer_frontier(struct qdio_q *q) | |||
691 | return q->first_to_check; | 690 | return q->first_to_check; |
692 | } | 691 | } |
693 | 692 | ||
694 | static inline int | 693 | static int |
695 | qdio_get_outbound_buffer_frontier(struct qdio_q *q) | 694 | qdio_get_outbound_buffer_frontier(struct qdio_q *q) |
696 | { | 695 | { |
697 | struct qdio_irq *irq; | 696 | struct qdio_irq *irq; |
@@ -774,7 +773,7 @@ out: | |||
774 | } | 773 | } |
775 | 774 | ||
776 | /* all buffers are processed */ | 775 | /* all buffers are processed */ |
777 | static inline int | 776 | static int |
778 | qdio_is_outbound_q_done(struct qdio_q *q) | 777 | qdio_is_outbound_q_done(struct qdio_q *q) |
779 | { | 778 | { |
780 | int no_used; | 779 | int no_used; |
@@ -796,7 +795,7 @@ qdio_is_outbound_q_done(struct qdio_q *q) | |||
796 | return (no_used==0); | 795 | return (no_used==0); |
797 | } | 796 | } |
798 | 797 | ||
799 | static inline int | 798 | static int |
800 | qdio_has_outbound_q_moved(struct qdio_q *q) | 799 | qdio_has_outbound_q_moved(struct qdio_q *q) |
801 | { | 800 | { |
802 | int i; | 801 | int i; |
@@ -816,7 +815,7 @@ qdio_has_outbound_q_moved(struct qdio_q *q) | |||
816 | } | 815 | } |
817 | } | 816 | } |
818 | 817 | ||
819 | static inline void | 818 | static void |
820 | qdio_kick_outbound_q(struct qdio_q *q) | 819 | qdio_kick_outbound_q(struct qdio_q *q) |
821 | { | 820 | { |
822 | int result; | 821 | int result; |
@@ -905,7 +904,7 @@ qdio_kick_outbound_q(struct qdio_q *q) | |||
905 | } | 904 | } |
906 | } | 905 | } |
907 | 906 | ||
908 | static inline void | 907 | static void |
909 | qdio_kick_outbound_handler(struct qdio_q *q) | 908 | qdio_kick_outbound_handler(struct qdio_q *q) |
910 | { | 909 | { |
911 | int start, end, real_end, count; | 910 | int start, end, real_end, count; |
@@ -942,7 +941,7 @@ qdio_kick_outbound_handler(struct qdio_q *q) | |||
942 | q->error_status_flags=0; | 941 | q->error_status_flags=0; |
943 | } | 942 | } |
944 | 943 | ||
945 | static inline void | 944 | static void |
946 | __qdio_outbound_processing(struct qdio_q *q) | 945 | __qdio_outbound_processing(struct qdio_q *q) |
947 | { | 946 | { |
948 | int siga_attempts; | 947 | int siga_attempts; |
@@ -1002,7 +1001,7 @@ qdio_outbound_processing(struct qdio_q *q) | |||
1002 | /************************* INBOUND ROUTINES *******************************/ | 1001 | /************************* INBOUND ROUTINES *******************************/ |
1003 | 1002 | ||
1004 | 1003 | ||
1005 | static inline int | 1004 | static int |
1006 | qdio_get_inbound_buffer_frontier(struct qdio_q *q) | 1005 | qdio_get_inbound_buffer_frontier(struct qdio_q *q) |
1007 | { | 1006 | { |
1008 | struct qdio_irq *irq; | 1007 | struct qdio_irq *irq; |
@@ -1133,7 +1132,7 @@ out: | |||
1133 | return q->first_to_check; | 1132 | return q->first_to_check; |
1134 | } | 1133 | } |
1135 | 1134 | ||
1136 | static inline int | 1135 | static int |
1137 | qdio_has_inbound_q_moved(struct qdio_q *q) | 1136 | qdio_has_inbound_q_moved(struct qdio_q *q) |
1138 | { | 1137 | { |
1139 | int i; | 1138 | int i; |
@@ -1167,7 +1166,7 @@ qdio_has_inbound_q_moved(struct qdio_q *q) | |||
1167 | } | 1166 | } |
1168 | 1167 | ||
1169 | /* means, no more buffers to be filled */ | 1168 | /* means, no more buffers to be filled */ |
1170 | static inline int | 1169 | static int |
1171 | tiqdio_is_inbound_q_done(struct qdio_q *q) | 1170 | tiqdio_is_inbound_q_done(struct qdio_q *q) |
1172 | { | 1171 | { |
1173 | int no_used; | 1172 | int no_used; |
@@ -1228,7 +1227,7 @@ tiqdio_is_inbound_q_done(struct qdio_q *q) | |||
1228 | return 0; | 1227 | return 0; |
1229 | } | 1228 | } |
1230 | 1229 | ||
1231 | static inline int | 1230 | static int |
1232 | qdio_is_inbound_q_done(struct qdio_q *q) | 1231 | qdio_is_inbound_q_done(struct qdio_q *q) |
1233 | { | 1232 | { |
1234 | int no_used; | 1233 | int no_used; |
@@ -1296,7 +1295,7 @@ qdio_is_inbound_q_done(struct qdio_q *q) | |||
1296 | } | 1295 | } |
1297 | } | 1296 | } |
1298 | 1297 | ||
1299 | static inline void | 1298 | static void |
1300 | qdio_kick_inbound_handler(struct qdio_q *q) | 1299 | qdio_kick_inbound_handler(struct qdio_q *q) |
1301 | { | 1300 | { |
1302 | int count, start, end, real_end, i; | 1301 | int count, start, end, real_end, i; |
@@ -1343,7 +1342,7 @@ qdio_kick_inbound_handler(struct qdio_q *q) | |||
1343 | } | 1342 | } |
1344 | } | 1343 | } |
1345 | 1344 | ||
1346 | static inline void | 1345 | static void |
1347 | __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set) | 1346 | __tiqdio_inbound_processing(struct qdio_q *q, int spare_ind_was_set) |
1348 | { | 1347 | { |
1349 | struct qdio_irq *irq_ptr; | 1348 | struct qdio_irq *irq_ptr; |
@@ -1442,7 +1441,7 @@ tiqdio_inbound_processing(struct qdio_q *q) | |||
1442 | __tiqdio_inbound_processing(q, atomic_read(&spare_indicator_usecount)); | 1441 | __tiqdio_inbound_processing(q, atomic_read(&spare_indicator_usecount)); |
1443 | } | 1442 | } |
1444 | 1443 | ||
1445 | static inline void | 1444 | static void |
1446 | __qdio_inbound_processing(struct qdio_q *q) | 1445 | __qdio_inbound_processing(struct qdio_q *q) |
1447 | { | 1446 | { |
1448 | int q_laps=0; | 1447 | int q_laps=0; |
@@ -1493,7 +1492,7 @@ qdio_inbound_processing(struct qdio_q *q) | |||
1493 | /************************* MAIN ROUTINES *******************************/ | 1492 | /************************* MAIN ROUTINES *******************************/ |
1494 | 1493 | ||
1495 | #ifdef QDIO_USE_PROCESSING_STATE | 1494 | #ifdef QDIO_USE_PROCESSING_STATE |
1496 | static inline int | 1495 | static int |
1497 | tiqdio_reset_processing_state(struct qdio_q *q, int q_laps) | 1496 | tiqdio_reset_processing_state(struct qdio_q *q, int q_laps) |
1498 | { | 1497 | { |
1499 | if (!q) { | 1498 | if (!q) { |
@@ -1545,7 +1544,7 @@ tiqdio_reset_processing_state(struct qdio_q *q, int q_laps) | |||
1545 | } | 1544 | } |
1546 | #endif /* QDIO_USE_PROCESSING_STATE */ | 1545 | #endif /* QDIO_USE_PROCESSING_STATE */ |
1547 | 1546 | ||
1548 | static inline void | 1547 | static void |
1549 | tiqdio_inbound_checks(void) | 1548 | tiqdio_inbound_checks(void) |
1550 | { | 1549 | { |
1551 | struct qdio_q *q; | 1550 | struct qdio_q *q; |
@@ -1949,7 +1948,7 @@ qdio_set_state(struct qdio_irq *irq_ptr, enum qdio_irq_states state) | |||
1949 | mb(); | 1948 | mb(); |
1950 | } | 1949 | } |
1951 | 1950 | ||
1952 | static inline void | 1951 | static void |
1953 | qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb) | 1952 | qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb) |
1954 | { | 1953 | { |
1955 | char dbf_text[15]; | 1954 | char dbf_text[15]; |
@@ -1966,7 +1965,7 @@ qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb) | |||
1966 | 1965 | ||
1967 | } | 1966 | } |
1968 | 1967 | ||
1969 | static inline void | 1968 | static void |
1970 | qdio_handle_pci(struct qdio_irq *irq_ptr) | 1969 | qdio_handle_pci(struct qdio_irq *irq_ptr) |
1971 | { | 1970 | { |
1972 | int i; | 1971 | int i; |
@@ -2002,7 +2001,7 @@ qdio_handle_pci(struct qdio_irq *irq_ptr) | |||
2002 | 2001 | ||
2003 | static void qdio_establish_handle_irq(struct ccw_device*, int, int); | 2002 | static void qdio_establish_handle_irq(struct ccw_device*, int, int); |
2004 | 2003 | ||
2005 | static inline void | 2004 | static void |
2006 | qdio_handle_activate_check(struct ccw_device *cdev, unsigned long intparm, | 2005 | qdio_handle_activate_check(struct ccw_device *cdev, unsigned long intparm, |
2007 | int cstat, int dstat) | 2006 | int cstat, int dstat) |
2008 | { | 2007 | { |
@@ -2229,7 +2228,7 @@ qdio_synchronize(struct ccw_device *cdev, unsigned int flags, | |||
2229 | return cc; | 2228 | return cc; |
2230 | } | 2229 | } |
2231 | 2230 | ||
2232 | static inline void | 2231 | static void |
2233 | qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac, | 2232 | qdio_check_subchannel_qebsm(struct qdio_irq *irq_ptr, unsigned char qdioac, |
2234 | unsigned long token) | 2233 | unsigned long token) |
2235 | { | 2234 | { |
@@ -2740,7 +2739,7 @@ qdio_free(struct ccw_device *cdev) | |||
2740 | return 0; | 2739 | return 0; |
2741 | } | 2740 | } |
2742 | 2741 | ||
2743 | static inline void | 2742 | static void |
2744 | qdio_allocate_do_dbf(struct qdio_initialize *init_data) | 2743 | qdio_allocate_do_dbf(struct qdio_initialize *init_data) |
2745 | { | 2744 | { |
2746 | char dbf_text[20]; /* if a printf printed out more than 8 chars */ | 2745 | char dbf_text[20]; /* if a printf printed out more than 8 chars */ |
@@ -2773,7 +2772,7 @@ qdio_allocate_do_dbf(struct qdio_initialize *init_data) | |||
2773 | QDIO_DBF_HEX0(0,setup,&init_data->output_sbal_addr_array,sizeof(void*)); | 2772 | QDIO_DBF_HEX0(0,setup,&init_data->output_sbal_addr_array,sizeof(void*)); |
2774 | } | 2773 | } |
2775 | 2774 | ||
2776 | static inline void | 2775 | static void |
2777 | qdio_allocate_fill_input_desc(struct qdio_irq *irq_ptr, int i, int iqfmt) | 2776 | qdio_allocate_fill_input_desc(struct qdio_irq *irq_ptr, int i, int iqfmt) |
2778 | { | 2777 | { |
2779 | irq_ptr->input_qs[i]->is_iqdio_q = iqfmt; | 2778 | irq_ptr->input_qs[i]->is_iqdio_q = iqfmt; |
@@ -2792,7 +2791,7 @@ qdio_allocate_fill_input_desc(struct qdio_irq *irq_ptr, int i, int iqfmt) | |||
2792 | irq_ptr->qdr->qdf0[i].dkey=QDIO_STORAGE_KEY; | 2791 | irq_ptr->qdr->qdf0[i].dkey=QDIO_STORAGE_KEY; |
2793 | } | 2792 | } |
2794 | 2793 | ||
2795 | static inline void | 2794 | static void |
2796 | qdio_allocate_fill_output_desc(struct qdio_irq *irq_ptr, int i, | 2795 | qdio_allocate_fill_output_desc(struct qdio_irq *irq_ptr, int i, |
2797 | int j, int iqfmt) | 2796 | int j, int iqfmt) |
2798 | { | 2797 | { |
@@ -2813,7 +2812,7 @@ qdio_allocate_fill_output_desc(struct qdio_irq *irq_ptr, int i, | |||
2813 | } | 2812 | } |
2814 | 2813 | ||
2815 | 2814 | ||
2816 | static inline void | 2815 | static void |
2817 | qdio_initialize_set_siga_flags_input(struct qdio_irq *irq_ptr) | 2816 | qdio_initialize_set_siga_flags_input(struct qdio_irq *irq_ptr) |
2818 | { | 2817 | { |
2819 | int i; | 2818 | int i; |
@@ -2839,7 +2838,7 @@ qdio_initialize_set_siga_flags_input(struct qdio_irq *irq_ptr) | |||
2839 | } | 2838 | } |
2840 | } | 2839 | } |
2841 | 2840 | ||
2842 | static inline void | 2841 | static void |
2843 | qdio_initialize_set_siga_flags_output(struct qdio_irq *irq_ptr) | 2842 | qdio_initialize_set_siga_flags_output(struct qdio_irq *irq_ptr) |
2844 | { | 2843 | { |
2845 | int i; | 2844 | int i; |
@@ -2865,7 +2864,7 @@ qdio_initialize_set_siga_flags_output(struct qdio_irq *irq_ptr) | |||
2865 | } | 2864 | } |
2866 | } | 2865 | } |
2867 | 2866 | ||
2868 | static inline int | 2867 | static int |
2869 | qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat, | 2868 | qdio_establish_irq_check_for_errors(struct ccw_device *cdev, int cstat, |
2870 | int dstat) | 2869 | int dstat) |
2871 | { | 2870 | { |
@@ -3014,7 +3013,7 @@ qdio_allocate(struct qdio_initialize *init_data) | |||
3014 | return 0; | 3013 | return 0; |
3015 | } | 3014 | } |
3016 | 3015 | ||
3017 | int qdio_fill_irq(struct qdio_initialize *init_data) | 3016 | static int qdio_fill_irq(struct qdio_initialize *init_data) |
3018 | { | 3017 | { |
3019 | int i; | 3018 | int i; |
3020 | char dbf_text[15]; | 3019 | char dbf_text[15]; |
@@ -3367,7 +3366,7 @@ qdio_activate(struct ccw_device *cdev, int flags) | |||
3367 | } | 3366 | } |
3368 | 3367 | ||
3369 | /* buffers filled forwards again to make Rick happy */ | 3368 | /* buffers filled forwards again to make Rick happy */ |
3370 | static inline void | 3369 | static void |
3371 | qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx, | 3370 | qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx, |
3372 | unsigned int count, struct qdio_buffer *buffers) | 3371 | unsigned int count, struct qdio_buffer *buffers) |
3373 | { | 3372 | { |
@@ -3386,7 +3385,7 @@ qdio_do_qdio_fill_input(struct qdio_q *q, unsigned int qidx, | |||
3386 | } | 3385 | } |
3387 | } | 3386 | } |
3388 | 3387 | ||
3389 | static inline void | 3388 | static void |
3390 | qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx, | 3389 | qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx, |
3391 | unsigned int count, struct qdio_buffer *buffers) | 3390 | unsigned int count, struct qdio_buffer *buffers) |
3392 | { | 3391 | { |
@@ -3407,7 +3406,7 @@ qdio_do_qdio_fill_output(struct qdio_q *q, unsigned int qidx, | |||
3407 | } | 3406 | } |
3408 | } | 3407 | } |
3409 | 3408 | ||
3410 | static inline void | 3409 | static void |
3411 | do_qdio_handle_inbound(struct qdio_q *q, unsigned int callflags, | 3410 | do_qdio_handle_inbound(struct qdio_q *q, unsigned int callflags, |
3412 | unsigned int qidx, unsigned int count, | 3411 | unsigned int qidx, unsigned int count, |
3413 | struct qdio_buffer *buffers) | 3412 | struct qdio_buffer *buffers) |
@@ -3443,7 +3442,7 @@ do_qdio_handle_inbound(struct qdio_q *q, unsigned int callflags, | |||
3443 | qdio_mark_q(q); | 3442 | qdio_mark_q(q); |
3444 | } | 3443 | } |
3445 | 3444 | ||
3446 | static inline void | 3445 | static void |
3447 | do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, | 3446 | do_qdio_handle_outbound(struct qdio_q *q, unsigned int callflags, |
3448 | unsigned int qidx, unsigned int count, | 3447 | unsigned int qidx, unsigned int count, |
3449 | struct qdio_buffer *buffers) | 3448 | struct qdio_buffer *buffers) |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 81b5899f4010..c7d1355237b6 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -465,7 +465,7 @@ static int ap_device_probe(struct device *dev) | |||
465 | * Flush all requests from the request/pending queue of an AP device. | 465 | * Flush all requests from the request/pending queue of an AP device. |
466 | * @ap_dev: pointer to the AP device. | 466 | * @ap_dev: pointer to the AP device. |
467 | */ | 467 | */ |
468 | static inline void __ap_flush_queue(struct ap_device *ap_dev) | 468 | static void __ap_flush_queue(struct ap_device *ap_dev) |
469 | { | 469 | { |
470 | struct ap_message *ap_msg, *next; | 470 | struct ap_message *ap_msg, *next; |
471 | 471 | ||
@@ -587,7 +587,7 @@ static struct bus_attribute *const ap_bus_attrs[] = { | |||
587 | /** | 587 | /** |
588 | * Pick one of the 16 ap domains. | 588 | * Pick one of the 16 ap domains. |
589 | */ | 589 | */ |
590 | static inline int ap_select_domain(void) | 590 | static int ap_select_domain(void) |
591 | { | 591 | { |
592 | int queue_depth, device_type, count, max_count, best_domain; | 592 | int queue_depth, device_type, count, max_count, best_domain; |
593 | int rc, i, j; | 593 | int rc, i, j; |
@@ -825,7 +825,7 @@ static inline void ap_schedule_poll_timer(void) | |||
825 | * required, bit 2^1 is set if the poll timer needs to get armed | 825 | * required, bit 2^1 is set if the poll timer needs to get armed |
826 | * Returns 0 if the device is still present, -ENODEV if not. | 826 | * Returns 0 if the device is still present, -ENODEV if not. |
827 | */ | 827 | */ |
828 | static inline int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags) | 828 | static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags) |
829 | { | 829 | { |
830 | struct ap_queue_status status; | 830 | struct ap_queue_status status; |
831 | struct ap_message *ap_msg; | 831 | struct ap_message *ap_msg; |
@@ -872,7 +872,7 @@ static inline int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags) | |||
872 | * required, bit 2^1 is set if the poll timer needs to get armed | 872 | * required, bit 2^1 is set if the poll timer needs to get armed |
873 | * Returns 0 if the device is still present, -ENODEV if not. | 873 | * Returns 0 if the device is still present, -ENODEV if not. |
874 | */ | 874 | */ |
875 | static inline int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags) | 875 | static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags) |
876 | { | 876 | { |
877 | struct ap_queue_status status; | 877 | struct ap_queue_status status; |
878 | struct ap_message *ap_msg; | 878 | struct ap_message *ap_msg; |
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 1edc10a7a6f2..b9e59bc9435a 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c | |||
@@ -791,7 +791,7 @@ static long trans_xcRB32(struct file *filp, unsigned int cmd, | |||
791 | return rc; | 791 | return rc; |
792 | } | 792 | } |
793 | 793 | ||
794 | long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd, | 794 | static long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd, |
795 | unsigned long arg) | 795 | unsigned long arg) |
796 | { | 796 | { |
797 | if (cmd == ICARSAMODEXPO) | 797 | if (cmd == ICARSAMODEXPO) |
@@ -833,8 +833,8 @@ static struct miscdevice zcrypt_misc_device = { | |||
833 | */ | 833 | */ |
834 | static struct proc_dir_entry *zcrypt_entry; | 834 | static struct proc_dir_entry *zcrypt_entry; |
835 | 835 | ||
836 | static inline int sprintcl(unsigned char *outaddr, unsigned char *addr, | 836 | static int sprintcl(unsigned char *outaddr, unsigned char *addr, |
837 | unsigned int len) | 837 | unsigned int len) |
838 | { | 838 | { |
839 | int hl, i; | 839 | int hl, i; |
840 | 840 | ||
@@ -845,8 +845,8 @@ static inline int sprintcl(unsigned char *outaddr, unsigned char *addr, | |||
845 | return hl; | 845 | return hl; |
846 | } | 846 | } |
847 | 847 | ||
848 | static inline int sprintrw(unsigned char *outaddr, unsigned char *addr, | 848 | static int sprintrw(unsigned char *outaddr, unsigned char *addr, |
849 | unsigned int len) | 849 | unsigned int len) |
850 | { | 850 | { |
851 | int hl, inl, c, cx; | 851 | int hl, inl, c, cx; |
852 | 852 | ||
@@ -865,8 +865,8 @@ static inline int sprintrw(unsigned char *outaddr, unsigned char *addr, | |||
865 | return hl; | 865 | return hl; |
866 | } | 866 | } |
867 | 867 | ||
868 | static inline int sprinthx(unsigned char *title, unsigned char *outaddr, | 868 | static int sprinthx(unsigned char *title, unsigned char *outaddr, |
869 | unsigned char *addr, unsigned int len) | 869 | unsigned char *addr, unsigned int len) |
870 | { | 870 | { |
871 | int hl, inl, r, rx; | 871 | int hl, inl, r, rx; |
872 | 872 | ||
@@ -885,8 +885,8 @@ static inline int sprinthx(unsigned char *title, unsigned char *outaddr, | |||
885 | return hl; | 885 | return hl; |
886 | } | 886 | } |
887 | 887 | ||
888 | static inline int sprinthx4(unsigned char *title, unsigned char *outaddr, | 888 | static int sprinthx4(unsigned char *title, unsigned char *outaddr, |
889 | unsigned int *array, unsigned int len) | 889 | unsigned int *array, unsigned int len) |
890 | { | 890 | { |
891 | int hl, r; | 891 | int hl, r; |
892 | 892 | ||
@@ -943,7 +943,7 @@ static int zcrypt_status_read(char *resp_buff, char **start, off_t offset, | |||
943 | zcrypt_qdepth_mask(workarea); | 943 | zcrypt_qdepth_mask(workarea); |
944 | len += sprinthx("Waiting work element counts", | 944 | len += sprinthx("Waiting work element counts", |
945 | resp_buff+len, workarea, AP_DEVICES); | 945 | resp_buff+len, workarea, AP_DEVICES); |
946 | zcrypt_perdev_reqcnt((unsigned int *) workarea); | 946 | zcrypt_perdev_reqcnt((int *) workarea); |
947 | len += sprinthx4("Per-device successfully completed request counts", | 947 | len += sprinthx4("Per-device successfully completed request counts", |
948 | resp_buff+len,(unsigned int *) workarea, AP_DEVICES); | 948 | resp_buff+len,(unsigned int *) workarea, AP_DEVICES); |
949 | *eof = 1; | 949 | *eof = 1; |
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c index 32e37014345c..818ffe05ac00 100644 --- a/drivers/s390/crypto/zcrypt_pcica.c +++ b/drivers/s390/crypto/zcrypt_pcica.c | |||
@@ -191,10 +191,10 @@ static int ICACRT_msg_to_type4CRT_msg(struct zcrypt_device *zdev, | |||
191 | * | 191 | * |
192 | * Returns 0 on success or -EFAULT. | 192 | * Returns 0 on success or -EFAULT. |
193 | */ | 193 | */ |
194 | static inline int convert_type84(struct zcrypt_device *zdev, | 194 | static int convert_type84(struct zcrypt_device *zdev, |
195 | struct ap_message *reply, | 195 | struct ap_message *reply, |
196 | char __user *outputdata, | 196 | char __user *outputdata, |
197 | unsigned int outputdatalength) | 197 | unsigned int outputdatalength) |
198 | { | 198 | { |
199 | struct type84_hdr *t84h = reply->message; | 199 | struct type84_hdr *t84h = reply->message; |
200 | char *data; | 200 | char *data; |
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c index b7153c1e15cd..252443b6bd1b 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/drivers/s390/crypto/zcrypt_pcixcc.c | |||
@@ -709,7 +709,8 @@ out_free: | |||
709 | * PCIXCC/CEX2C device to the request distributor | 709 | * PCIXCC/CEX2C device to the request distributor |
710 | * @xcRB: pointer to the send_cprb request buffer | 710 | * @xcRB: pointer to the send_cprb request buffer |
711 | */ | 711 | */ |
712 | long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, struct ica_xcRB *xcRB) | 712 | static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, |
713 | struct ica_xcRB *xcRB) | ||
713 | { | 714 | { |
714 | struct ap_message ap_msg; | 715 | struct ap_message ap_msg; |
715 | struct response_type resp_type = { | 716 | struct response_type resp_type = { |
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 95f4e105cb96..7809a79feec7 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c | |||
@@ -121,7 +121,7 @@ MODULE_LICENSE("GPL"); | |||
121 | #define DEBUG | 121 | #define DEBUG |
122 | #endif | 122 | #endif |
123 | 123 | ||
124 | char debug_buffer[255]; | 124 | static char debug_buffer[255]; |
125 | /** | 125 | /** |
126 | * Debug Facility Stuff | 126 | * Debug Facility Stuff |
127 | */ | 127 | */ |
@@ -223,16 +223,14 @@ static void claw_timer ( struct chbk * p_ch ); | |||
223 | /* Functions */ | 223 | /* Functions */ |
224 | static int add_claw_reads(struct net_device *dev, | 224 | static int add_claw_reads(struct net_device *dev, |
225 | struct ccwbk* p_first, struct ccwbk* p_last); | 225 | struct ccwbk* p_first, struct ccwbk* p_last); |
226 | static void inline ccw_check_return_code (struct ccw_device *cdev, | 226 | static void ccw_check_return_code (struct ccw_device *cdev, int return_code); |
227 | int return_code); | 227 | static void ccw_check_unit_check (struct chbk * p_ch, unsigned char sense ); |
228 | static void inline ccw_check_unit_check (struct chbk * p_ch, | ||
229 | unsigned char sense ); | ||
230 | static int find_link(struct net_device *dev, char *host_name, char *ws_name ); | 228 | static int find_link(struct net_device *dev, char *host_name, char *ws_name ); |
231 | static int claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid); | 229 | static int claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid); |
232 | static int init_ccw_bk(struct net_device *dev); | 230 | static int init_ccw_bk(struct net_device *dev); |
233 | static void probe_error( struct ccwgroup_device *cgdev); | 231 | static void probe_error( struct ccwgroup_device *cgdev); |
234 | static struct net_device_stats *claw_stats(struct net_device *dev); | 232 | static struct net_device_stats *claw_stats(struct net_device *dev); |
235 | static int inline pages_to_order_of_mag(int num_of_pages); | 233 | static int pages_to_order_of_mag(int num_of_pages); |
236 | static struct sk_buff *claw_pack_skb(struct claw_privbk *privptr); | 234 | static struct sk_buff *claw_pack_skb(struct claw_privbk *privptr); |
237 | #ifdef DEBUG | 235 | #ifdef DEBUG |
238 | static void dumpit (char *buf, int len); | 236 | static void dumpit (char *buf, int len); |
@@ -1310,7 +1308,7 @@ claw_timer ( struct chbk * p_ch ) | |||
1310 | * of magnitude get_free_pages() has an upper order of 9 * | 1308 | * of magnitude get_free_pages() has an upper order of 9 * |
1311 | *--------------------------------------------------------------------*/ | 1309 | *--------------------------------------------------------------------*/ |
1312 | 1310 | ||
1313 | static int inline | 1311 | static int |
1314 | pages_to_order_of_mag(int num_of_pages) | 1312 | pages_to_order_of_mag(int num_of_pages) |
1315 | { | 1313 | { |
1316 | int order_of_mag=1; /* assume 2 pages */ | 1314 | int order_of_mag=1; /* assume 2 pages */ |
@@ -1482,7 +1480,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first, | |||
1482 | * * | 1480 | * * |
1483 | *-------------------------------------------------------------------*/ | 1481 | *-------------------------------------------------------------------*/ |
1484 | 1482 | ||
1485 | static void inline | 1483 | static void |
1486 | ccw_check_return_code(struct ccw_device *cdev, int return_code) | 1484 | ccw_check_return_code(struct ccw_device *cdev, int return_code) |
1487 | { | 1485 | { |
1488 | #ifdef FUNCTRACE | 1486 | #ifdef FUNCTRACE |
@@ -1529,7 +1527,7 @@ ccw_check_return_code(struct ccw_device *cdev, int return_code) | |||
1529 | * ccw_check_unit_check * | 1527 | * ccw_check_unit_check * |
1530 | *--------------------------------------------------------------------*/ | 1528 | *--------------------------------------------------------------------*/ |
1531 | 1529 | ||
1532 | static void inline | 1530 | static void |
1533 | ccw_check_unit_check(struct chbk * p_ch, unsigned char sense ) | 1531 | ccw_check_unit_check(struct chbk * p_ch, unsigned char sense ) |
1534 | { | 1532 | { |
1535 | struct net_device *dev = p_ch->ndev; | 1533 | struct net_device *dev = p_ch->ndev; |
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 03cc263fe0da..5a84fbbc6611 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c | |||
@@ -369,7 +369,7 @@ ctc_dump_skb(struct sk_buff *skb, int offset) | |||
369 | * @param ch The channel where this skb has been received. | 369 | * @param ch The channel where this skb has been received. |
370 | * @param pskb The received skb. | 370 | * @param pskb The received skb. |
371 | */ | 371 | */ |
372 | static __inline__ void | 372 | static void |
373 | ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb) | 373 | ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb) |
374 | { | 374 | { |
375 | struct net_device *dev = ch->netdev; | 375 | struct net_device *dev = ch->netdev; |
@@ -512,7 +512,7 @@ ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb) | |||
512 | * @param ch The channel, the error belongs to. | 512 | * @param ch The channel, the error belongs to. |
513 | * @param return_code The error code to inspect. | 513 | * @param return_code The error code to inspect. |
514 | */ | 514 | */ |
515 | static void inline | 515 | static void |
516 | ccw_check_return_code(struct channel *ch, int return_code, char *msg) | 516 | ccw_check_return_code(struct channel *ch, int return_code, char *msg) |
517 | { | 517 | { |
518 | DBF_TEXT(trace, 5, __FUNCTION__); | 518 | DBF_TEXT(trace, 5, __FUNCTION__); |
@@ -547,7 +547,7 @@ ccw_check_return_code(struct channel *ch, int return_code, char *msg) | |||
547 | * @param ch The channel, the sense code belongs to. | 547 | * @param ch The channel, the sense code belongs to. |
548 | * @param sense The sense code to inspect. | 548 | * @param sense The sense code to inspect. |
549 | */ | 549 | */ |
550 | static void inline | 550 | static void |
551 | ccw_unit_check(struct channel *ch, unsigned char sense) | 551 | ccw_unit_check(struct channel *ch, unsigned char sense) |
552 | { | 552 | { |
553 | DBF_TEXT(trace, 5, __FUNCTION__); | 553 | DBF_TEXT(trace, 5, __FUNCTION__); |
@@ -603,7 +603,7 @@ ctc_purge_skb_queue(struct sk_buff_head *q) | |||
603 | } | 603 | } |
604 | } | 604 | } |
605 | 605 | ||
606 | static __inline__ int | 606 | static int |
607 | ctc_checkalloc_buffer(struct channel *ch, int warn) | 607 | ctc_checkalloc_buffer(struct channel *ch, int warn) |
608 | { | 608 | { |
609 | DBF_TEXT(trace, 5, __FUNCTION__); | 609 | DBF_TEXT(trace, 5, __FUNCTION__); |
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c index e965f03a7291..76728ae4b843 100644 --- a/drivers/s390/net/cu3088.c +++ b/drivers/s390/net/cu3088.c | |||
@@ -57,7 +57,7 @@ static struct ccw_device_id cu3088_ids[] = { | |||
57 | 57 | ||
58 | static struct ccw_driver cu3088_driver; | 58 | static struct ccw_driver cu3088_driver; |
59 | 59 | ||
60 | struct device *cu3088_root_dev; | 60 | static struct device *cu3088_root_dev; |
61 | 61 | ||
62 | static ssize_t | 62 | static ssize_t |
63 | group_write(struct device_driver *drv, const char *buf, size_t count) | 63 | group_write(struct device_driver *drv, const char *buf, size_t count) |
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index e5665b6743a1..b97dd15bdb9a 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c | |||
@@ -828,7 +828,7 @@ lcs_notify_lancmd_waiters(struct lcs_card *card, struct lcs_cmd *cmd) | |||
828 | /** | 828 | /** |
829 | * Emit buffer of a lan comand. | 829 | * Emit buffer of a lan comand. |
830 | */ | 830 | */ |
831 | void | 831 | static void |
832 | lcs_lancmd_timeout(unsigned long data) | 832 | lcs_lancmd_timeout(unsigned long data) |
833 | { | 833 | { |
834 | struct lcs_reply *reply, *list_reply, *r; | 834 | struct lcs_reply *reply, *list_reply, *r; |
@@ -1360,7 +1360,7 @@ lcs_get_problem(struct ccw_device *cdev, struct irb *irb) | |||
1360 | return 0; | 1360 | return 0; |
1361 | } | 1361 | } |
1362 | 1362 | ||
1363 | void | 1363 | static void |
1364 | lcs_schedule_recovery(struct lcs_card *card) | 1364 | lcs_schedule_recovery(struct lcs_card *card) |
1365 | { | 1365 | { |
1366 | LCS_DBF_TEXT(2, trace, "startrec"); | 1366 | LCS_DBF_TEXT(2, trace, "startrec"); |
@@ -1990,7 +1990,7 @@ lcs_timeout_store (struct device *dev, struct device_attribute *attr, const char | |||
1990 | 1990 | ||
1991 | } | 1991 | } |
1992 | 1992 | ||
1993 | DEVICE_ATTR(lancmd_timeout, 0644, lcs_timeout_show, lcs_timeout_store); | 1993 | static DEVICE_ATTR(lancmd_timeout, 0644, lcs_timeout_show, lcs_timeout_store); |
1994 | 1994 | ||
1995 | static ssize_t | 1995 | static ssize_t |
1996 | lcs_dev_recover_store(struct device *dev, struct device_attribute *attr, | 1996 | lcs_dev_recover_store(struct device *dev, struct device_attribute *attr, |
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index d7d1cc0a5c8e..3346088f47e0 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c | |||
@@ -2053,7 +2053,7 @@ out_free_ndev: | |||
2053 | return ret; | 2053 | return ret; |
2054 | } | 2054 | } |
2055 | 2055 | ||
2056 | DRIVER_ATTR(connection, 0200, NULL, conn_write); | 2056 | static DRIVER_ATTR(connection, 0200, NULL, conn_write); |
2057 | 2057 | ||
2058 | static ssize_t | 2058 | static ssize_t |
2059 | remove_write (struct device_driver *drv, const char *buf, size_t count) | 2059 | remove_write (struct device_driver *drv, const char *buf, size_t count) |
@@ -2112,7 +2112,7 @@ remove_write (struct device_driver *drv, const char *buf, size_t count) | |||
2112 | return -EINVAL; | 2112 | return -EINVAL; |
2113 | } | 2113 | } |
2114 | 2114 | ||
2115 | DRIVER_ATTR(remove, 0200, NULL, remove_write); | 2115 | static DRIVER_ATTR(remove, 0200, NULL, remove_write); |
2116 | 2116 | ||
2117 | static void | 2117 | static void |
2118 | netiucv_banner(void) | 2118 | netiucv_banner(void) |
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index 6bb558a9a032..7c735e1fe063 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c | |||
@@ -49,7 +49,7 @@ qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *queue, | |||
49 | return buffers_needed; | 49 | return buffers_needed; |
50 | } | 50 | } |
51 | 51 | ||
52 | static inline void | 52 | static void |
53 | qeth_eddp_free_context(struct qeth_eddp_context *ctx) | 53 | qeth_eddp_free_context(struct qeth_eddp_context *ctx) |
54 | { | 54 | { |
55 | int i; | 55 | int i; |
@@ -91,7 +91,7 @@ qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf) | |||
91 | } | 91 | } |
92 | } | 92 | } |
93 | 93 | ||
94 | static inline int | 94 | static int |
95 | qeth_eddp_buf_ref_context(struct qeth_qdio_out_buffer *buf, | 95 | qeth_eddp_buf_ref_context(struct qeth_qdio_out_buffer *buf, |
96 | struct qeth_eddp_context *ctx) | 96 | struct qeth_eddp_context *ctx) |
97 | { | 97 | { |
@@ -196,7 +196,7 @@ out: | |||
196 | return flush_cnt; | 196 | return flush_cnt; |
197 | } | 197 | } |
198 | 198 | ||
199 | static inline void | 199 | static void |
200 | qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, | 200 | qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, |
201 | struct qeth_eddp_data *eddp, int data_len) | 201 | struct qeth_eddp_data *eddp, int data_len) |
202 | { | 202 | { |
@@ -256,7 +256,7 @@ qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, | |||
256 | ctx->offset += eddp->thl; | 256 | ctx->offset += eddp->thl; |
257 | } | 257 | } |
258 | 258 | ||
259 | static inline void | 259 | static void |
260 | qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len, | 260 | qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len, |
261 | __wsum *hcsum) | 261 | __wsum *hcsum) |
262 | { | 262 | { |
@@ -302,7 +302,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len, | |||
302 | } | 302 | } |
303 | } | 303 | } |
304 | 304 | ||
305 | static inline void | 305 | static void |
306 | qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx, | 306 | qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx, |
307 | struct qeth_eddp_data *eddp, int data_len, | 307 | struct qeth_eddp_data *eddp, int data_len, |
308 | __wsum hcsum) | 308 | __wsum hcsum) |
@@ -349,7 +349,7 @@ qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx, | |||
349 | ((struct tcphdr *)eddp->th_in_ctx)->check = csum_fold(hcsum); | 349 | ((struct tcphdr *)eddp->th_in_ctx)->check = csum_fold(hcsum); |
350 | } | 350 | } |
351 | 351 | ||
352 | static inline __wsum | 352 | static __wsum |
353 | qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len) | 353 | qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len) |
354 | { | 354 | { |
355 | __wsum phcsum; /* pseudo header checksum */ | 355 | __wsum phcsum; /* pseudo header checksum */ |
@@ -363,7 +363,7 @@ qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len) | |||
363 | return csum_partial((u8 *)&eddp->th, eddp->thl, phcsum); | 363 | return csum_partial((u8 *)&eddp->th, eddp->thl, phcsum); |
364 | } | 364 | } |
365 | 365 | ||
366 | static inline __wsum | 366 | static __wsum |
367 | qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, int data_len) | 367 | qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, int data_len) |
368 | { | 368 | { |
369 | __be32 proto; | 369 | __be32 proto; |
@@ -381,7 +381,7 @@ qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, int data_len) | |||
381 | return phcsum; | 381 | return phcsum; |
382 | } | 382 | } |
383 | 383 | ||
384 | static inline struct qeth_eddp_data * | 384 | static struct qeth_eddp_data * |
385 | qeth_eddp_create_eddp_data(struct qeth_hdr *qh, u8 *nh, u8 nhl, u8 *th, u8 thl) | 385 | qeth_eddp_create_eddp_data(struct qeth_hdr *qh, u8 *nh, u8 nhl, u8 *th, u8 thl) |
386 | { | 386 | { |
387 | struct qeth_eddp_data *eddp; | 387 | struct qeth_eddp_data *eddp; |
@@ -399,7 +399,7 @@ qeth_eddp_create_eddp_data(struct qeth_hdr *qh, u8 *nh, u8 nhl, u8 *th, u8 thl) | |||
399 | return eddp; | 399 | return eddp; |
400 | } | 400 | } |
401 | 401 | ||
402 | static inline void | 402 | static void |
403 | __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, | 403 | __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, |
404 | struct qeth_eddp_data *eddp) | 404 | struct qeth_eddp_data *eddp) |
405 | { | 405 | { |
@@ -464,7 +464,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, | |||
464 | } | 464 | } |
465 | } | 465 | } |
466 | 466 | ||
467 | static inline int | 467 | static int |
468 | qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, | 468 | qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, |
469 | struct sk_buff *skb, struct qeth_hdr *qhdr) | 469 | struct sk_buff *skb, struct qeth_hdr *qhdr) |
470 | { | 470 | { |
@@ -505,7 +505,7 @@ qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, | |||
505 | return 0; | 505 | return 0; |
506 | } | 506 | } |
507 | 507 | ||
508 | static inline void | 508 | static void |
509 | qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb, | 509 | qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb, |
510 | int hdr_len) | 510 | int hdr_len) |
511 | { | 511 | { |
@@ -529,7 +529,7 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb, | |||
529 | (skb_shinfo(skb)->gso_segs + 1); | 529 | (skb_shinfo(skb)->gso_segs + 1); |
530 | } | 530 | } |
531 | 531 | ||
532 | static inline struct qeth_eddp_context * | 532 | static struct qeth_eddp_context * |
533 | qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb, | 533 | qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb, |
534 | int hdr_len) | 534 | int hdr_len) |
535 | { | 535 | { |
@@ -581,7 +581,7 @@ qeth_eddp_create_context_generic(struct qeth_card *card, struct sk_buff *skb, | |||
581 | return ctx; | 581 | return ctx; |
582 | } | 582 | } |
583 | 583 | ||
584 | static inline struct qeth_eddp_context * | 584 | static struct qeth_eddp_context * |
585 | qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb, | 585 | qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb, |
586 | struct qeth_hdr *qhdr) | 586 | struct qeth_hdr *qhdr) |
587 | { | 587 | { |
@@ -625,5 +625,3 @@ qeth_eddp_create_context(struct qeth_card *card, struct sk_buff *skb, | |||
625 | } | 625 | } |
626 | return NULL; | 626 | return NULL; |
627 | } | 627 | } |
628 | |||
629 | |||
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index d2efa5ff125d..2257e45594b3 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
@@ -651,7 +651,7 @@ __qeth_ref_ip_on_card(struct qeth_card *card, struct qeth_ipaddr *todo, | |||
651 | return 0; | 651 | return 0; |
652 | } | 652 | } |
653 | 653 | ||
654 | static inline int | 654 | static int |
655 | __qeth_address_exists_in_list(struct list_head *list, struct qeth_ipaddr *addr, | 655 | __qeth_address_exists_in_list(struct list_head *list, struct qeth_ipaddr *addr, |
656 | int same_type) | 656 | int same_type) |
657 | { | 657 | { |
@@ -795,7 +795,7 @@ qeth_add_ip(struct qeth_card *card, struct qeth_ipaddr *addr) | |||
795 | return rc; | 795 | return rc; |
796 | } | 796 | } |
797 | 797 | ||
798 | static inline void | 798 | static void |
799 | __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags) | 799 | __qeth_delete_all_mc(struct qeth_card *card, unsigned long *flags) |
800 | { | 800 | { |
801 | struct qeth_ipaddr *addr, *tmp; | 801 | struct qeth_ipaddr *addr, *tmp; |
@@ -882,7 +882,7 @@ static void qeth_layer2_add_multicast(struct qeth_card *); | |||
882 | static void qeth_add_multicast_ipv6(struct qeth_card *); | 882 | static void qeth_add_multicast_ipv6(struct qeth_card *); |
883 | #endif | 883 | #endif |
884 | 884 | ||
885 | static inline int | 885 | static int |
886 | qeth_set_thread_start_bit(struct qeth_card *card, unsigned long thread) | 886 | qeth_set_thread_start_bit(struct qeth_card *card, unsigned long thread) |
887 | { | 887 | { |
888 | unsigned long flags; | 888 | unsigned long flags; |
@@ -920,7 +920,7 @@ qeth_clear_thread_running_bit(struct qeth_card *card, unsigned long thread) | |||
920 | wake_up(&card->wait_q); | 920 | wake_up(&card->wait_q); |
921 | } | 921 | } |
922 | 922 | ||
923 | static inline int | 923 | static int |
924 | __qeth_do_run_thread(struct qeth_card *card, unsigned long thread) | 924 | __qeth_do_run_thread(struct qeth_card *card, unsigned long thread) |
925 | { | 925 | { |
926 | unsigned long flags; | 926 | unsigned long flags; |
@@ -1764,9 +1764,9 @@ out: | |||
1764 | qeth_release_buffer(channel,iob); | 1764 | qeth_release_buffer(channel,iob); |
1765 | } | 1765 | } |
1766 | 1766 | ||
1767 | static inline void | 1767 | static void |
1768 | qeth_prepare_control_data(struct qeth_card *card, int len, | 1768 | qeth_prepare_control_data(struct qeth_card *card, int len, |
1769 | struct qeth_cmd_buffer *iob) | 1769 | struct qeth_cmd_buffer *iob) |
1770 | { | 1770 | { |
1771 | qeth_setup_ccw(&card->write,iob->data,len); | 1771 | qeth_setup_ccw(&card->write,iob->data,len); |
1772 | iob->callback = qeth_release_buffer; | 1772 | iob->callback = qeth_release_buffer; |
@@ -2160,7 +2160,7 @@ qeth_check_qdio_errors(struct qdio_buffer *buf, unsigned int qdio_error, | |||
2160 | return 0; | 2160 | return 0; |
2161 | } | 2161 | } |
2162 | 2162 | ||
2163 | static inline struct sk_buff * | 2163 | static struct sk_buff * |
2164 | qeth_get_skb(unsigned int length, struct qeth_hdr *hdr) | 2164 | qeth_get_skb(unsigned int length, struct qeth_hdr *hdr) |
2165 | { | 2165 | { |
2166 | struct sk_buff* skb; | 2166 | struct sk_buff* skb; |
@@ -2179,7 +2179,7 @@ qeth_get_skb(unsigned int length, struct qeth_hdr *hdr) | |||
2179 | return skb; | 2179 | return skb; |
2180 | } | 2180 | } |
2181 | 2181 | ||
2182 | static inline struct sk_buff * | 2182 | static struct sk_buff * |
2183 | qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, | 2183 | qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer, |
2184 | struct qdio_buffer_element **__element, int *__offset, | 2184 | struct qdio_buffer_element **__element, int *__offset, |
2185 | struct qeth_hdr **hdr) | 2185 | struct qeth_hdr **hdr) |
@@ -2264,7 +2264,7 @@ no_mem: | |||
2264 | return NULL; | 2264 | return NULL; |
2265 | } | 2265 | } |
2266 | 2266 | ||
2267 | static inline __be16 | 2267 | static __be16 |
2268 | qeth_type_trans(struct sk_buff *skb, struct net_device *dev) | 2268 | qeth_type_trans(struct sk_buff *skb, struct net_device *dev) |
2269 | { | 2269 | { |
2270 | struct qeth_card *card; | 2270 | struct qeth_card *card; |
@@ -2297,7 +2297,7 @@ qeth_type_trans(struct sk_buff *skb, struct net_device *dev) | |||
2297 | return htons(ETH_P_802_2); | 2297 | return htons(ETH_P_802_2); |
2298 | } | 2298 | } |
2299 | 2299 | ||
2300 | static inline void | 2300 | static void |
2301 | qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb, | 2301 | qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb, |
2302 | struct qeth_hdr *hdr) | 2302 | struct qeth_hdr *hdr) |
2303 | { | 2303 | { |
@@ -2351,7 +2351,7 @@ qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb, | |||
2351 | fake_llc->ethertype = ETH_P_IP; | 2351 | fake_llc->ethertype = ETH_P_IP; |
2352 | } | 2352 | } |
2353 | 2353 | ||
2354 | static inline void | 2354 | static void |
2355 | qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb, | 2355 | qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb, |
2356 | struct qeth_hdr *hdr) | 2356 | struct qeth_hdr *hdr) |
2357 | { | 2357 | { |
@@ -2420,7 +2420,7 @@ qeth_layer2_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | |||
2420 | *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; | 2420 | *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; |
2421 | } | 2421 | } |
2422 | 2422 | ||
2423 | static inline __u16 | 2423 | static __u16 |
2424 | qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | 2424 | qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, |
2425 | struct qeth_hdr *hdr) | 2425 | struct qeth_hdr *hdr) |
2426 | { | 2426 | { |
@@ -2476,7 +2476,7 @@ qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, | |||
2476 | return vlan_id; | 2476 | return vlan_id; |
2477 | } | 2477 | } |
2478 | 2478 | ||
2479 | static inline void | 2479 | static void |
2480 | qeth_process_inbound_buffer(struct qeth_card *card, | 2480 | qeth_process_inbound_buffer(struct qeth_card *card, |
2481 | struct qeth_qdio_buffer *buf, int index) | 2481 | struct qeth_qdio_buffer *buf, int index) |
2482 | { | 2482 | { |
@@ -2528,7 +2528,7 @@ qeth_process_inbound_buffer(struct qeth_card *card, | |||
2528 | } | 2528 | } |
2529 | } | 2529 | } |
2530 | 2530 | ||
2531 | static inline struct qeth_buffer_pool_entry * | 2531 | static struct qeth_buffer_pool_entry * |
2532 | qeth_get_buffer_pool_entry(struct qeth_card *card) | 2532 | qeth_get_buffer_pool_entry(struct qeth_card *card) |
2533 | { | 2533 | { |
2534 | struct qeth_buffer_pool_entry *entry; | 2534 | struct qeth_buffer_pool_entry *entry; |
@@ -2543,7 +2543,7 @@ qeth_get_buffer_pool_entry(struct qeth_card *card) | |||
2543 | return NULL; | 2543 | return NULL; |
2544 | } | 2544 | } |
2545 | 2545 | ||
2546 | static inline void | 2546 | static void |
2547 | qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf) | 2547 | qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf) |
2548 | { | 2548 | { |
2549 | struct qeth_buffer_pool_entry *pool_entry; | 2549 | struct qeth_buffer_pool_entry *pool_entry; |
@@ -2570,7 +2570,7 @@ qeth_init_input_buffer(struct qeth_card *card, struct qeth_qdio_buffer *buf) | |||
2570 | buf->state = QETH_QDIO_BUF_EMPTY; | 2570 | buf->state = QETH_QDIO_BUF_EMPTY; |
2571 | } | 2571 | } |
2572 | 2572 | ||
2573 | static inline void | 2573 | static void |
2574 | qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, | 2574 | qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, |
2575 | struct qeth_qdio_out_buffer *buf) | 2575 | struct qeth_qdio_out_buffer *buf) |
2576 | { | 2576 | { |
@@ -2595,7 +2595,7 @@ qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, | |||
2595 | atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY); | 2595 | atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY); |
2596 | } | 2596 | } |
2597 | 2597 | ||
2598 | static inline void | 2598 | static void |
2599 | qeth_queue_input_buffer(struct qeth_card *card, int index) | 2599 | qeth_queue_input_buffer(struct qeth_card *card, int index) |
2600 | { | 2600 | { |
2601 | struct qeth_qdio_q *queue = card->qdio.in_q; | 2601 | struct qeth_qdio_q *queue = card->qdio.in_q; |
@@ -2699,7 +2699,7 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status, | |||
2699 | card->perf_stats.inbound_start_time; | 2699 | card->perf_stats.inbound_start_time; |
2700 | } | 2700 | } |
2701 | 2701 | ||
2702 | static inline int | 2702 | static int |
2703 | qeth_handle_send_error(struct qeth_card *card, | 2703 | qeth_handle_send_error(struct qeth_card *card, |
2704 | struct qeth_qdio_out_buffer *buffer, | 2704 | struct qeth_qdio_out_buffer *buffer, |
2705 | unsigned int qdio_err, unsigned int siga_err) | 2705 | unsigned int qdio_err, unsigned int siga_err) |
@@ -2821,7 +2821,7 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, | |||
2821 | * Switched to packing state if the number of used buffers on a queue | 2821 | * Switched to packing state if the number of used buffers on a queue |
2822 | * reaches a certain limit. | 2822 | * reaches a certain limit. |
2823 | */ | 2823 | */ |
2824 | static inline void | 2824 | static void |
2825 | qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue) | 2825 | qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue) |
2826 | { | 2826 | { |
2827 | if (!queue->do_pack) { | 2827 | if (!queue->do_pack) { |
@@ -2842,7 +2842,7 @@ qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue) | |||
2842 | * In that case 1 is returned to inform the caller. If no buffer | 2842 | * In that case 1 is returned to inform the caller. If no buffer |
2843 | * has to be flushed, zero is returned. | 2843 | * has to be flushed, zero is returned. |
2844 | */ | 2844 | */ |
2845 | static inline int | 2845 | static int |
2846 | qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) | 2846 | qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) |
2847 | { | 2847 | { |
2848 | struct qeth_qdio_out_buffer *buffer; | 2848 | struct qeth_qdio_out_buffer *buffer; |
@@ -2877,7 +2877,7 @@ qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue) | |||
2877 | * Checks if there is a packing buffer and prepares it to be flushed. | 2877 | * Checks if there is a packing buffer and prepares it to be flushed. |
2878 | * In that case returns 1, otherwise zero. | 2878 | * In that case returns 1, otherwise zero. |
2879 | */ | 2879 | */ |
2880 | static inline int | 2880 | static int |
2881 | qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue) | 2881 | qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue) |
2882 | { | 2882 | { |
2883 | struct qeth_qdio_out_buffer *buffer; | 2883 | struct qeth_qdio_out_buffer *buffer; |
@@ -2894,7 +2894,7 @@ qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue) | |||
2894 | return 0; | 2894 | return 0; |
2895 | } | 2895 | } |
2896 | 2896 | ||
2897 | static inline void | 2897 | static void |
2898 | qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) | 2898 | qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) |
2899 | { | 2899 | { |
2900 | int index; | 2900 | int index; |
@@ -3594,7 +3594,7 @@ qeth_fake_header(struct sk_buff *skb, struct net_device *dev, | |||
3594 | } | 3594 | } |
3595 | } | 3595 | } |
3596 | 3596 | ||
3597 | static inline int | 3597 | static int |
3598 | qeth_send_packet(struct qeth_card *, struct sk_buff *); | 3598 | qeth_send_packet(struct qeth_card *, struct sk_buff *); |
3599 | 3599 | ||
3600 | static int | 3600 | static int |
@@ -3759,7 +3759,7 @@ qeth_stop(struct net_device *dev) | |||
3759 | return 0; | 3759 | return 0; |
3760 | } | 3760 | } |
3761 | 3761 | ||
3762 | static inline int | 3762 | static int |
3763 | qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb) | 3763 | qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb) |
3764 | { | 3764 | { |
3765 | int cast_type = RTN_UNSPEC; | 3765 | int cast_type = RTN_UNSPEC; |
@@ -3806,7 +3806,7 @@ qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb) | |||
3806 | return cast_type; | 3806 | return cast_type; |
3807 | } | 3807 | } |
3808 | 3808 | ||
3809 | static inline int | 3809 | static int |
3810 | qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb, | 3810 | qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb, |
3811 | int ipv, int cast_type) | 3811 | int ipv, int cast_type) |
3812 | { | 3812 | { |
@@ -3853,7 +3853,7 @@ qeth_get_ip_version(struct sk_buff *skb) | |||
3853 | } | 3853 | } |
3854 | } | 3854 | } |
3855 | 3855 | ||
3856 | static inline struct qeth_hdr * | 3856 | static struct qeth_hdr * |
3857 | __qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv) | 3857 | __qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv) |
3858 | { | 3858 | { |
3859 | #ifdef CONFIG_QETH_VLAN | 3859 | #ifdef CONFIG_QETH_VLAN |
@@ -3882,14 +3882,14 @@ __qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, int ipv) | |||
3882 | qeth_push_skb(card, skb, sizeof(struct qeth_hdr))); | 3882 | qeth_push_skb(card, skb, sizeof(struct qeth_hdr))); |
3883 | } | 3883 | } |
3884 | 3884 | ||
3885 | static inline void | 3885 | static void |
3886 | __qeth_free_new_skb(struct sk_buff *orig_skb, struct sk_buff *new_skb) | 3886 | __qeth_free_new_skb(struct sk_buff *orig_skb, struct sk_buff *new_skb) |
3887 | { | 3887 | { |
3888 | if (orig_skb != new_skb) | 3888 | if (orig_skb != new_skb) |
3889 | dev_kfree_skb_any(new_skb); | 3889 | dev_kfree_skb_any(new_skb); |
3890 | } | 3890 | } |
3891 | 3891 | ||
3892 | static inline struct sk_buff * | 3892 | static struct sk_buff * |
3893 | qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, | 3893 | qeth_prepare_skb(struct qeth_card *card, struct sk_buff *skb, |
3894 | struct qeth_hdr **hdr, int ipv) | 3894 | struct qeth_hdr **hdr, int ipv) |
3895 | { | 3895 | { |
@@ -3940,7 +3940,7 @@ qeth_get_qeth_hdr_flags6(int cast_type) | |||
3940 | return ct | QETH_CAST_UNICAST; | 3940 | return ct | QETH_CAST_UNICAST; |
3941 | } | 3941 | } |
3942 | 3942 | ||
3943 | static inline void | 3943 | static void |
3944 | qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr, | 3944 | qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr, |
3945 | struct sk_buff *skb) | 3945 | struct sk_buff *skb) |
3946 | { | 3946 | { |
@@ -3977,7 +3977,7 @@ qeth_layer2_get_packet_type(struct qeth_card *card, struct qeth_hdr *hdr, | |||
3977 | } | 3977 | } |
3978 | } | 3978 | } |
3979 | 3979 | ||
3980 | static inline void | 3980 | static void |
3981 | qeth_layer2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, | 3981 | qeth_layer2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, |
3982 | struct sk_buff *skb, int cast_type) | 3982 | struct sk_buff *skb, int cast_type) |
3983 | { | 3983 | { |
@@ -4068,7 +4068,7 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, | |||
4068 | } | 4068 | } |
4069 | } | 4069 | } |
4070 | 4070 | ||
4071 | static inline void | 4071 | static void |
4072 | __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, | 4072 | __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, |
4073 | int is_tso, int *next_element_to_fill) | 4073 | int is_tso, int *next_element_to_fill) |
4074 | { | 4074 | { |
@@ -4112,7 +4112,7 @@ __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, | |||
4112 | *next_element_to_fill = element; | 4112 | *next_element_to_fill = element; |
4113 | } | 4113 | } |
4114 | 4114 | ||
4115 | static inline int | 4115 | static int |
4116 | qeth_fill_buffer(struct qeth_qdio_out_q *queue, | 4116 | qeth_fill_buffer(struct qeth_qdio_out_q *queue, |
4117 | struct qeth_qdio_out_buffer *buf, | 4117 | struct qeth_qdio_out_buffer *buf, |
4118 | struct sk_buff *skb) | 4118 | struct sk_buff *skb) |
@@ -4171,7 +4171,7 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue, | |||
4171 | return flush_cnt; | 4171 | return flush_cnt; |
4172 | } | 4172 | } |
4173 | 4173 | ||
4174 | static inline int | 4174 | static int |
4175 | qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue, | 4175 | qeth_do_send_packet_fast(struct qeth_card *card, struct qeth_qdio_out_q *queue, |
4176 | struct sk_buff *skb, struct qeth_hdr *hdr, | 4176 | struct sk_buff *skb, struct qeth_hdr *hdr, |
4177 | int elements_needed, | 4177 | int elements_needed, |
@@ -4222,7 +4222,7 @@ out: | |||
4222 | return -EBUSY; | 4222 | return -EBUSY; |
4223 | } | 4223 | } |
4224 | 4224 | ||
4225 | static inline int | 4225 | static int |
4226 | qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, | 4226 | qeth_do_send_packet(struct qeth_card *card, struct qeth_qdio_out_q *queue, |
4227 | struct sk_buff *skb, struct qeth_hdr *hdr, | 4227 | struct sk_buff *skb, struct qeth_hdr *hdr, |
4228 | int elements_needed, struct qeth_eddp_context *ctx) | 4228 | int elements_needed, struct qeth_eddp_context *ctx) |
@@ -4328,7 +4328,7 @@ out: | |||
4328 | return rc; | 4328 | return rc; |
4329 | } | 4329 | } |
4330 | 4330 | ||
4331 | static inline int | 4331 | static int |
4332 | qeth_get_elements_no(struct qeth_card *card, void *hdr, | 4332 | qeth_get_elements_no(struct qeth_card *card, void *hdr, |
4333 | struct sk_buff *skb, int elems) | 4333 | struct sk_buff *skb, int elems) |
4334 | { | 4334 | { |
@@ -4349,7 +4349,7 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, | |||
4349 | } | 4349 | } |
4350 | 4350 | ||
4351 | 4351 | ||
4352 | static inline int | 4352 | static int |
4353 | qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) | 4353 | qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) |
4354 | { | 4354 | { |
4355 | int ipv = 0; | 4355 | int ipv = 0; |
@@ -4536,7 +4536,7 @@ qeth_mdio_read(struct net_device *dev, int phy_id, int regnum) | |||
4536 | } | 4536 | } |
4537 | 4537 | ||
4538 | 4538 | ||
4539 | static inline const char * | 4539 | static const char * |
4540 | qeth_arp_get_error_cause(int *rc) | 4540 | qeth_arp_get_error_cause(int *rc) |
4541 | { | 4541 | { |
4542 | switch (*rc) { | 4542 | switch (*rc) { |
@@ -4597,7 +4597,7 @@ qeth_arp_set_no_entries(struct qeth_card *card, int no_entries) | |||
4597 | return rc; | 4597 | return rc; |
4598 | } | 4598 | } |
4599 | 4599 | ||
4600 | static inline void | 4600 | static void |
4601 | qeth_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo, | 4601 | qeth_copy_arp_entries_stripped(struct qeth_arp_query_info *qinfo, |
4602 | struct qeth_arp_query_data *qdata, | 4602 | struct qeth_arp_query_data *qdata, |
4603 | int entry_size, int uentry_size) | 4603 | int entry_size, int uentry_size) |
@@ -5214,7 +5214,7 @@ qeth_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) | |||
5214 | spin_unlock_irqrestore(&card->vlanlock, flags); | 5214 | spin_unlock_irqrestore(&card->vlanlock, flags); |
5215 | } | 5215 | } |
5216 | 5216 | ||
5217 | static inline void | 5217 | static void |
5218 | qeth_free_vlan_buffer(struct qeth_card *card, struct qeth_qdio_out_buffer *buf, | 5218 | qeth_free_vlan_buffer(struct qeth_card *card, struct qeth_qdio_out_buffer *buf, |
5219 | unsigned short vid) | 5219 | unsigned short vid) |
5220 | { | 5220 | { |
@@ -5625,7 +5625,7 @@ qeth_delete_mc_addresses(struct qeth_card *card) | |||
5625 | spin_unlock_irqrestore(&card->ip_lock, flags); | 5625 | spin_unlock_irqrestore(&card->ip_lock, flags); |
5626 | } | 5626 | } |
5627 | 5627 | ||
5628 | static inline void | 5628 | static void |
5629 | qeth_add_mc(struct qeth_card *card, struct in_device *in4_dev) | 5629 | qeth_add_mc(struct qeth_card *card, struct in_device *in4_dev) |
5630 | { | 5630 | { |
5631 | struct qeth_ipaddr *ipm; | 5631 | struct qeth_ipaddr *ipm; |
@@ -5711,7 +5711,7 @@ qeth_layer2_add_multicast(struct qeth_card *card) | |||
5711 | } | 5711 | } |
5712 | 5712 | ||
5713 | #ifdef CONFIG_QETH_IPV6 | 5713 | #ifdef CONFIG_QETH_IPV6 |
5714 | static inline void | 5714 | static void |
5715 | qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev) | 5715 | qeth_add_mc6(struct qeth_card *card, struct inet6_dev *in6_dev) |
5716 | { | 5716 | { |
5717 | struct qeth_ipaddr *ipm; | 5717 | struct qeth_ipaddr *ipm; |
@@ -6022,7 +6022,7 @@ qeth_send_setdelmc(struct qeth_card *card, struct qeth_ipaddr *addr, int ipacmd) | |||
6022 | 6022 | ||
6023 | return rc; | 6023 | return rc; |
6024 | } | 6024 | } |
6025 | static inline void | 6025 | static void |
6026 | qeth_fill_netmask(u8 *netmask, unsigned int len) | 6026 | qeth_fill_netmask(u8 *netmask, unsigned int len) |
6027 | { | 6027 | { |
6028 | int i,j; | 6028 | int i,j; |
@@ -6626,7 +6626,7 @@ qeth_send_setadp_mode(struct qeth_card *card, __u32 command, __u32 mode) | |||
6626 | return rc; | 6626 | return rc; |
6627 | } | 6627 | } |
6628 | 6628 | ||
6629 | static inline int | 6629 | static int |
6630 | qeth_setadapter_hstr(struct qeth_card *card) | 6630 | qeth_setadapter_hstr(struct qeth_card *card) |
6631 | { | 6631 | { |
6632 | int rc; | 6632 | int rc; |
@@ -6889,7 +6889,7 @@ qeth_send_simple_setassparms(struct qeth_card *card, | |||
6889 | return rc; | 6889 | return rc; |
6890 | } | 6890 | } |
6891 | 6891 | ||
6892 | static inline int | 6892 | static int |
6893 | qeth_start_ipa_arp_processing(struct qeth_card *card) | 6893 | qeth_start_ipa_arp_processing(struct qeth_card *card) |
6894 | { | 6894 | { |
6895 | int rc; | 6895 | int rc; |
@@ -7529,7 +7529,7 @@ qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads, | |||
7529 | wake_up(&card->wait_q); | 7529 | wake_up(&card->wait_q); |
7530 | } | 7530 | } |
7531 | 7531 | ||
7532 | static inline int | 7532 | static int |
7533 | qeth_threads_running(struct qeth_card *card, unsigned long threads) | 7533 | qeth_threads_running(struct qeth_card *card, unsigned long threads) |
7534 | { | 7534 | { |
7535 | unsigned long flags; | 7535 | unsigned long flags; |
@@ -8118,7 +8118,7 @@ qeth_del_ipato_entry(struct qeth_card *card, enum qeth_prot_versions proto, | |||
8118 | spin_unlock_irqrestore(&card->ip_lock, flags); | 8118 | spin_unlock_irqrestore(&card->ip_lock, flags); |
8119 | } | 8119 | } |
8120 | 8120 | ||
8121 | static inline void | 8121 | static void |
8122 | qeth_convert_addr_to_bits(u8 *addr, u8 *bits, int len) | 8122 | qeth_convert_addr_to_bits(u8 *addr, u8 *bits, int len) |
8123 | { | 8123 | { |
8124 | int i, j; | 8124 | int i, j; |
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index 5836737ac58f..d518419cd0c6 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c | |||
@@ -328,7 +328,7 @@ qeth_dev_bufcnt_store(struct device *dev, struct device_attribute *attr, const c | |||
328 | static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show, | 328 | static DEVICE_ATTR(buffer_count, 0644, qeth_dev_bufcnt_show, |
329 | qeth_dev_bufcnt_store); | 329 | qeth_dev_bufcnt_store); |
330 | 330 | ||
331 | static inline ssize_t | 331 | static ssize_t |
332 | qeth_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route, | 332 | qeth_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route, |
333 | char *buf) | 333 | char *buf) |
334 | { | 334 | { |
@@ -368,7 +368,7 @@ qeth_dev_route4_show(struct device *dev, struct device_attribute *attr, char *bu | |||
368 | return qeth_dev_route_show(card, &card->options.route4, buf); | 368 | return qeth_dev_route_show(card, &card->options.route4, buf); |
369 | } | 369 | } |
370 | 370 | ||
371 | static inline ssize_t | 371 | static ssize_t |
372 | qeth_dev_route_store(struct qeth_card *card, struct qeth_routing_info *route, | 372 | qeth_dev_route_store(struct qeth_card *card, struct qeth_routing_info *route, |
373 | enum qeth_prot_versions prot, const char *buf, size_t count) | 373 | enum qeth_prot_versions prot, const char *buf, size_t count) |
374 | { | 374 | { |
@@ -998,7 +998,7 @@ struct device_attribute dev_attr_##_id = { \ | |||
998 | .store = _store, \ | 998 | .store = _store, \ |
999 | }; | 999 | }; |
1000 | 1000 | ||
1001 | int | 1001 | static int |
1002 | qeth_check_layer2(struct qeth_card *card) | 1002 | qeth_check_layer2(struct qeth_card *card) |
1003 | { | 1003 | { |
1004 | if (card->options.layer2) | 1004 | if (card->options.layer2) |
@@ -1100,7 +1100,7 @@ static QETH_DEVICE_ATTR(ipato_invert4, invert4, 0644, | |||
1100 | qeth_dev_ipato_invert4_show, | 1100 | qeth_dev_ipato_invert4_show, |
1101 | qeth_dev_ipato_invert4_store); | 1101 | qeth_dev_ipato_invert4_store); |
1102 | 1102 | ||
1103 | static inline ssize_t | 1103 | static ssize_t |
1104 | qeth_dev_ipato_add_show(char *buf, struct qeth_card *card, | 1104 | qeth_dev_ipato_add_show(char *buf, struct qeth_card *card, |
1105 | enum qeth_prot_versions proto) | 1105 | enum qeth_prot_versions proto) |
1106 | { | 1106 | { |
@@ -1146,7 +1146,7 @@ qeth_dev_ipato_add4_show(struct device *dev, struct device_attribute *attr, char | |||
1146 | return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV4); | 1146 | return qeth_dev_ipato_add_show(buf, card, QETH_PROT_IPV4); |
1147 | } | 1147 | } |
1148 | 1148 | ||
1149 | static inline int | 1149 | static int |
1150 | qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, | 1150 | qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, |
1151 | u8 *addr, int *mask_bits) | 1151 | u8 *addr, int *mask_bits) |
1152 | { | 1152 | { |
@@ -1178,7 +1178,7 @@ qeth_parse_ipatoe(const char* buf, enum qeth_prot_versions proto, | |||
1178 | return 0; | 1178 | return 0; |
1179 | } | 1179 | } |
1180 | 1180 | ||
1181 | static inline ssize_t | 1181 | static ssize_t |
1182 | qeth_dev_ipato_add_store(const char *buf, size_t count, | 1182 | qeth_dev_ipato_add_store(const char *buf, size_t count, |
1183 | struct qeth_card *card, enum qeth_prot_versions proto) | 1183 | struct qeth_card *card, enum qeth_prot_versions proto) |
1184 | { | 1184 | { |
@@ -1223,7 +1223,7 @@ static QETH_DEVICE_ATTR(ipato_add4, add4, 0644, | |||
1223 | qeth_dev_ipato_add4_show, | 1223 | qeth_dev_ipato_add4_show, |
1224 | qeth_dev_ipato_add4_store); | 1224 | qeth_dev_ipato_add4_store); |
1225 | 1225 | ||
1226 | static inline ssize_t | 1226 | static ssize_t |
1227 | qeth_dev_ipato_del_store(const char *buf, size_t count, | 1227 | qeth_dev_ipato_del_store(const char *buf, size_t count, |
1228 | struct qeth_card *card, enum qeth_prot_versions proto) | 1228 | struct qeth_card *card, enum qeth_prot_versions proto) |
1229 | { | 1229 | { |
@@ -1361,7 +1361,7 @@ static struct attribute_group qeth_device_ipato_group = { | |||
1361 | .attrs = (struct attribute **)qeth_ipato_device_attrs, | 1361 | .attrs = (struct attribute **)qeth_ipato_device_attrs, |
1362 | }; | 1362 | }; |
1363 | 1363 | ||
1364 | static inline ssize_t | 1364 | static ssize_t |
1365 | qeth_dev_vipa_add_show(char *buf, struct qeth_card *card, | 1365 | qeth_dev_vipa_add_show(char *buf, struct qeth_card *card, |
1366 | enum qeth_prot_versions proto) | 1366 | enum qeth_prot_versions proto) |
1367 | { | 1367 | { |
@@ -1407,7 +1407,7 @@ qeth_dev_vipa_add4_show(struct device *dev, struct device_attribute *attr, char | |||
1407 | return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV4); | 1407 | return qeth_dev_vipa_add_show(buf, card, QETH_PROT_IPV4); |
1408 | } | 1408 | } |
1409 | 1409 | ||
1410 | static inline int | 1410 | static int |
1411 | qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto, | 1411 | qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto, |
1412 | u8 *addr) | 1412 | u8 *addr) |
1413 | { | 1413 | { |
@@ -1418,7 +1418,7 @@ qeth_parse_vipae(const char* buf, enum qeth_prot_versions proto, | |||
1418 | return 0; | 1418 | return 0; |
1419 | } | 1419 | } |
1420 | 1420 | ||
1421 | static inline ssize_t | 1421 | static ssize_t |
1422 | qeth_dev_vipa_add_store(const char *buf, size_t count, | 1422 | qeth_dev_vipa_add_store(const char *buf, size_t count, |
1423 | struct qeth_card *card, enum qeth_prot_versions proto) | 1423 | struct qeth_card *card, enum qeth_prot_versions proto) |
1424 | { | 1424 | { |
@@ -1451,7 +1451,7 @@ static QETH_DEVICE_ATTR(vipa_add4, add4, 0644, | |||
1451 | qeth_dev_vipa_add4_show, | 1451 | qeth_dev_vipa_add4_show, |
1452 | qeth_dev_vipa_add4_store); | 1452 | qeth_dev_vipa_add4_store); |
1453 | 1453 | ||
1454 | static inline ssize_t | 1454 | static ssize_t |
1455 | qeth_dev_vipa_del_store(const char *buf, size_t count, | 1455 | qeth_dev_vipa_del_store(const char *buf, size_t count, |
1456 | struct qeth_card *card, enum qeth_prot_versions proto) | 1456 | struct qeth_card *card, enum qeth_prot_versions proto) |
1457 | { | 1457 | { |
@@ -1542,7 +1542,7 @@ static struct attribute_group qeth_device_vipa_group = { | |||
1542 | .attrs = (struct attribute **)qeth_vipa_device_attrs, | 1542 | .attrs = (struct attribute **)qeth_vipa_device_attrs, |
1543 | }; | 1543 | }; |
1544 | 1544 | ||
1545 | static inline ssize_t | 1545 | static ssize_t |
1546 | qeth_dev_rxip_add_show(char *buf, struct qeth_card *card, | 1546 | qeth_dev_rxip_add_show(char *buf, struct qeth_card *card, |
1547 | enum qeth_prot_versions proto) | 1547 | enum qeth_prot_versions proto) |
1548 | { | 1548 | { |
@@ -1588,7 +1588,7 @@ qeth_dev_rxip_add4_show(struct device *dev, struct device_attribute *attr, char | |||
1588 | return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV4); | 1588 | return qeth_dev_rxip_add_show(buf, card, QETH_PROT_IPV4); |
1589 | } | 1589 | } |
1590 | 1590 | ||
1591 | static inline int | 1591 | static int |
1592 | qeth_parse_rxipe(const char* buf, enum qeth_prot_versions proto, | 1592 | qeth_parse_rxipe(const char* buf, enum qeth_prot_versions proto, |
1593 | u8 *addr) | 1593 | u8 *addr) |
1594 | { | 1594 | { |
@@ -1599,7 +1599,7 @@ qeth_parse_rxipe(const char* buf, enum qeth_prot_versions proto, | |||
1599 | return 0; | 1599 | return 0; |
1600 | } | 1600 | } |
1601 | 1601 | ||
1602 | static inline ssize_t | 1602 | static ssize_t |
1603 | qeth_dev_rxip_add_store(const char *buf, size_t count, | 1603 | qeth_dev_rxip_add_store(const char *buf, size_t count, |
1604 | struct qeth_card *card, enum qeth_prot_versions proto) | 1604 | struct qeth_card *card, enum qeth_prot_versions proto) |
1605 | { | 1605 | { |
@@ -1632,7 +1632,7 @@ static QETH_DEVICE_ATTR(rxip_add4, add4, 0644, | |||
1632 | qeth_dev_rxip_add4_show, | 1632 | qeth_dev_rxip_add4_show, |
1633 | qeth_dev_rxip_add4_store); | 1633 | qeth_dev_rxip_add4_store); |
1634 | 1634 | ||
1635 | static inline ssize_t | 1635 | static ssize_t |
1636 | qeth_dev_rxip_del_store(const char *buf, size_t count, | 1636 | qeth_dev_rxip_del_store(const char *buf, size_t count, |
1637 | struct qeth_card *card, enum qeth_prot_versions proto) | 1637 | struct qeth_card *card, enum qeth_prot_versions proto) |
1638 | { | 1638 | { |
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c index e088b5e28711..806bb1a921eb 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c | |||
@@ -13,22 +13,18 @@ | |||
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/workqueue.h> | 14 | #include <linux/workqueue.h> |
15 | #include <linux/time.h> | 15 | #include <linux/time.h> |
16 | #include <linux/device.h> | ||
16 | #include <linux/kthread.h> | 17 | #include <linux/kthread.h> |
17 | 18 | #include <asm/etr.h> | |
18 | #include <asm/lowcore.h> | 19 | #include <asm/lowcore.h> |
19 | 20 | #include <asm/cio.h> | |
21 | #include "cio/cio.h" | ||
22 | #include "cio/chsc.h" | ||
23 | #include "cio/css.h" | ||
20 | #include "s390mach.h" | 24 | #include "s390mach.h" |
21 | 25 | ||
22 | static struct semaphore m_sem; | 26 | static struct semaphore m_sem; |
23 | 27 | ||
24 | extern int css_process_crw(int, int); | ||
25 | extern int chsc_process_crw(void); | ||
26 | extern int chp_process_crw(int, int); | ||
27 | extern void css_reiterate_subchannels(void); | ||
28 | |||
29 | extern struct workqueue_struct *slow_path_wq; | ||
30 | extern struct work_struct slow_path_work; | ||
31 | |||
32 | static NORET_TYPE void | 28 | static NORET_TYPE void |
33 | s390_handle_damage(char *msg) | 29 | s390_handle_damage(char *msg) |
34 | { | 30 | { |
@@ -470,6 +466,19 @@ s390_do_machine_check(struct pt_regs *regs) | |||
470 | s390_handle_damage("unable to revalidate registers."); | 466 | s390_handle_damage("unable to revalidate registers."); |
471 | } | 467 | } |
472 | 468 | ||
469 | if (mci->cd) { | ||
470 | /* Timing facility damage */ | ||
471 | s390_handle_damage("TOD clock damaged"); | ||
472 | } | ||
473 | |||
474 | if (mci->ed && mci->ec) { | ||
475 | /* External damage */ | ||
476 | if (S390_lowcore.external_damage_code & (1U << ED_ETR_SYNC)) | ||
477 | etr_sync_check(); | ||
478 | if (S390_lowcore.external_damage_code & (1U << ED_ETR_SWITCH)) | ||
479 | etr_switch_to_local(); | ||
480 | } | ||
481 | |||
473 | if (mci->se) | 482 | if (mci->se) |
474 | /* Storage error uncorrected */ | 483 | /* Storage error uncorrected */ |
475 | s390_handle_damage("received storage error uncorrected " | 484 | s390_handle_damage("received storage error uncorrected " |
@@ -508,7 +517,7 @@ static int | |||
508 | machine_check_init(void) | 517 | machine_check_init(void) |
509 | { | 518 | { |
510 | init_MUTEX_LOCKED(&m_sem); | 519 | init_MUTEX_LOCKED(&m_sem); |
511 | ctl_clear_bit(14, 25); /* disable external damage MCH */ | 520 | ctl_set_bit(14, 25); /* enable external damage MCH */ |
512 | ctl_set_bit(14, 27); /* enable system recovery MCH */ | 521 | ctl_set_bit(14, 27); /* enable system recovery MCH */ |
513 | #ifdef CONFIG_MACHCHK_WARNING | 522 | #ifdef CONFIG_MACHCHK_WARNING |
514 | ctl_set_bit(14, 24); /* enable warning MCH */ | 523 | ctl_set_bit(14, 24); /* enable warning MCH */ |
@@ -529,7 +538,11 @@ arch_initcall(machine_check_init); | |||
529 | static int __init | 538 | static int __init |
530 | machine_check_crw_init (void) | 539 | machine_check_crw_init (void) |
531 | { | 540 | { |
532 | kthread_run(s390_collect_crw_info, &m_sem, "kmcheck"); | 541 | struct task_struct *task; |
542 | |||
543 | task = kthread_run(s390_collect_crw_info, &m_sem, "kmcheck"); | ||
544 | if (IS_ERR(task)) | ||
545 | return PTR_ERR(task); | ||
533 | ctl_set_bit(14, 28); /* enable channel report MCH */ | 546 | ctl_set_bit(14, 28); /* enable channel report MCH */ |
534 | return 0; | 547 | return 0; |
535 | } | 548 | } |
diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h index 7abb42a09ae2..d3ca4281a494 100644 --- a/drivers/s390/s390mach.h +++ b/drivers/s390/s390mach.h | |||
@@ -102,4 +102,7 @@ static inline int stcrw(struct crw *pcrw ) | |||
102 | return ccode; | 102 | return ccode; |
103 | } | 103 | } |
104 | 104 | ||
105 | #define ED_ETR_SYNC 12 /* External damage ETR sync check */ | ||
106 | #define ED_ETR_SWITCH 13 /* External damage ETR switch to local */ | ||
107 | |||
105 | #endif /* __s390mach */ | 108 | #endif /* __s390mach */ |
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 85093b71f9fa..39a885266790 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -47,13 +47,12 @@ static int __init zfcp_module_init(void); | |||
47 | static void zfcp_ns_gid_pn_handler(unsigned long); | 47 | static void zfcp_ns_gid_pn_handler(unsigned long); |
48 | 48 | ||
49 | /* miscellaneous */ | 49 | /* miscellaneous */ |
50 | static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t); | 50 | static int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t); |
51 | static inline void zfcp_sg_list_free(struct zfcp_sg_list *); | 51 | static void zfcp_sg_list_free(struct zfcp_sg_list *); |
52 | static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *, | 52 | static int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *, |
53 | void __user *, size_t); | 53 | void __user *, size_t); |
54 | static inline int zfcp_sg_list_copy_to_user(void __user *, | 54 | static int zfcp_sg_list_copy_to_user(void __user *, |
55 | struct zfcp_sg_list *, size_t); | 55 | struct zfcp_sg_list *, size_t); |
56 | |||
57 | static long zfcp_cfdc_dev_ioctl(struct file *, unsigned int, unsigned long); | 56 | static long zfcp_cfdc_dev_ioctl(struct file *, unsigned int, unsigned long); |
58 | 57 | ||
59 | #define ZFCP_CFDC_IOC_MAGIC 0xDD | 58 | #define ZFCP_CFDC_IOC_MAGIC 0xDD |
@@ -605,7 +604,7 @@ zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command, | |||
605 | * elements of the scatter-gather list. The maximum size of a single element | 604 | * elements of the scatter-gather list. The maximum size of a single element |
606 | * in the scatter-gather list is PAGE_SIZE. | 605 | * in the scatter-gather list is PAGE_SIZE. |
607 | */ | 606 | */ |
608 | static inline int | 607 | static int |
609 | zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) | 608 | zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) |
610 | { | 609 | { |
611 | struct scatterlist *sg; | 610 | struct scatterlist *sg; |
@@ -652,7 +651,7 @@ zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size) | |||
652 | * Memory for each element in the scatter-gather list is freed. | 651 | * Memory for each element in the scatter-gather list is freed. |
653 | * Finally sg_list->sg is freed itself and sg_list->count is reset. | 652 | * Finally sg_list->sg is freed itself and sg_list->count is reset. |
654 | */ | 653 | */ |
655 | static inline void | 654 | static void |
656 | zfcp_sg_list_free(struct zfcp_sg_list *sg_list) | 655 | zfcp_sg_list_free(struct zfcp_sg_list *sg_list) |
657 | { | 656 | { |
658 | struct scatterlist *sg; | 657 | struct scatterlist *sg; |
@@ -697,7 +696,7 @@ zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count) | |||
697 | * @size: number of bytes to be copied | 696 | * @size: number of bytes to be copied |
698 | * Return: 0 on success, -EFAULT if copy_from_user fails. | 697 | * Return: 0 on success, -EFAULT if copy_from_user fails. |
699 | */ | 698 | */ |
700 | static inline int | 699 | static int |
701 | zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, | 700 | zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, |
702 | void __user *user_buffer, | 701 | void __user *user_buffer, |
703 | size_t size) | 702 | size_t size) |
@@ -735,7 +734,7 @@ zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, | |||
735 | * @size: number of bytes to be copied | 734 | * @size: number of bytes to be copied |
736 | * Return: 0 on success, -EFAULT if copy_to_user fails | 735 | * Return: 0 on success, -EFAULT if copy_to_user fails |
737 | */ | 736 | */ |
738 | static inline int | 737 | static int |
739 | zfcp_sg_list_copy_to_user(void __user *user_buffer, | 738 | zfcp_sg_list_copy_to_user(void __user *user_buffer, |
740 | struct zfcp_sg_list *sg_list, | 739 | struct zfcp_sg_list *sg_list, |
741 | size_t size) | 740 | size_t size) |
@@ -1799,7 +1798,7 @@ static const struct zfcp_rc_entry zfcp_p_rjt_rc[] = { | |||
1799 | * @code: reason code | 1798 | * @code: reason code |
1800 | * @rc_table: table of reason codes and descriptions | 1799 | * @rc_table: table of reason codes and descriptions |
1801 | */ | 1800 | */ |
1802 | static inline const char * | 1801 | static const char * |
1803 | zfcp_rc_description(u8 code, const struct zfcp_rc_entry *rc_table) | 1802 | zfcp_rc_description(u8 code, const struct zfcp_rc_entry *rc_table) |
1804 | { | 1803 | { |
1805 | const char *descr = "unknown reason code"; | 1804 | const char *descr = "unknown reason code"; |
@@ -1847,7 +1846,7 @@ zfcp_check_ct_response(struct ct_hdr *rjt) | |||
1847 | * @rjt_par: reject parameter acc. to FC-PH/FC-FS | 1846 | * @rjt_par: reject parameter acc. to FC-PH/FC-FS |
1848 | * @rc_table: table of reason codes and descriptions | 1847 | * @rc_table: table of reason codes and descriptions |
1849 | */ | 1848 | */ |
1850 | static inline void | 1849 | static void |
1851 | zfcp_print_els_rjt(struct zfcp_ls_rjt_par *rjt_par, | 1850 | zfcp_print_els_rjt(struct zfcp_ls_rjt_par *rjt_par, |
1852 | const struct zfcp_rc_entry *rc_table) | 1851 | const struct zfcp_rc_entry *rc_table) |
1853 | { | 1852 | { |
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 0aa3b1ac76af..d8191d115c14 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c | |||
@@ -31,7 +31,7 @@ MODULE_PARM_DESC(dbfsize, | |||
31 | 31 | ||
32 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER | 32 | #define ZFCP_LOG_AREA ZFCP_LOG_AREA_OTHER |
33 | 33 | ||
34 | static inline int | 34 | static int |
35 | zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck) | 35 | zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck) |
36 | { | 36 | { |
37 | unsigned long long sec; | 37 | unsigned long long sec; |
@@ -106,7 +106,7 @@ zfcp_dbf_view_dump(char *out_buf, const char *label, | |||
106 | return len; | 106 | return len; |
107 | } | 107 | } |
108 | 108 | ||
109 | static inline int | 109 | static int |
110 | zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area, | 110 | zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area, |
111 | debug_entry_t * entry, char *out_buf) | 111 | debug_entry_t * entry, char *out_buf) |
112 | { | 112 | { |
@@ -130,7 +130,7 @@ zfcp_dbf_view_header(debug_info_t * id, struct debug_view *view, int area, | |||
130 | return len; | 130 | return len; |
131 | } | 131 | } |
132 | 132 | ||
133 | inline void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req) | 133 | void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req) |
134 | { | 134 | { |
135 | struct zfcp_adapter *adapter = fsf_req->adapter; | 135 | struct zfcp_adapter *adapter = fsf_req->adapter; |
136 | struct fsf_qtcb *qtcb = fsf_req->qtcb; | 136 | struct fsf_qtcb *qtcb = fsf_req->qtcb; |
@@ -241,7 +241,7 @@ inline void zfcp_hba_dbf_event_fsf_response(struct zfcp_fsf_req *fsf_req) | |||
241 | spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); | 241 | spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); |
242 | } | 242 | } |
243 | 243 | ||
244 | inline void | 244 | void |
245 | zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter, | 245 | zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter, |
246 | struct fsf_status_read_buffer *status_buffer) | 246 | struct fsf_status_read_buffer *status_buffer) |
247 | { | 247 | { |
@@ -295,7 +295,7 @@ zfcp_hba_dbf_event_fsf_unsol(const char *tag, struct zfcp_adapter *adapter, | |||
295 | spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); | 295 | spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); |
296 | } | 296 | } |
297 | 297 | ||
298 | inline void | 298 | void |
299 | zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status, | 299 | zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status, |
300 | unsigned int qdio_error, unsigned int siga_error, | 300 | unsigned int qdio_error, unsigned int siga_error, |
301 | int sbal_index, int sbal_count) | 301 | int sbal_index, int sbal_count) |
@@ -316,7 +316,7 @@ zfcp_hba_dbf_event_qdio(struct zfcp_adapter *adapter, unsigned int status, | |||
316 | spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); | 316 | spin_unlock_irqrestore(&adapter->hba_dbf_lock, flags); |
317 | } | 317 | } |
318 | 318 | ||
319 | static inline int | 319 | static int |
320 | zfcp_hba_dbf_view_response(char *out_buf, | 320 | zfcp_hba_dbf_view_response(char *out_buf, |
321 | struct zfcp_hba_dbf_record_response *rec) | 321 | struct zfcp_hba_dbf_record_response *rec) |
322 | { | 322 | { |
@@ -403,7 +403,7 @@ zfcp_hba_dbf_view_response(char *out_buf, | |||
403 | return len; | 403 | return len; |
404 | } | 404 | } |
405 | 405 | ||
406 | static inline int | 406 | static int |
407 | zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec) | 407 | zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec) |
408 | { | 408 | { |
409 | int len = 0; | 409 | int len = 0; |
@@ -424,7 +424,7 @@ zfcp_hba_dbf_view_status(char *out_buf, struct zfcp_hba_dbf_record_status *rec) | |||
424 | return len; | 424 | return len; |
425 | } | 425 | } |
426 | 426 | ||
427 | static inline int | 427 | static int |
428 | zfcp_hba_dbf_view_qdio(char *out_buf, struct zfcp_hba_dbf_record_qdio *rec) | 428 | zfcp_hba_dbf_view_qdio(char *out_buf, struct zfcp_hba_dbf_record_qdio *rec) |
429 | { | 429 | { |
430 | int len = 0; | 430 | int len = 0; |
@@ -469,7 +469,7 @@ zfcp_hba_dbf_view_format(debug_info_t * id, struct debug_view *view, | |||
469 | return len; | 469 | return len; |
470 | } | 470 | } |
471 | 471 | ||
472 | struct debug_view zfcp_hba_dbf_view = { | 472 | static struct debug_view zfcp_hba_dbf_view = { |
473 | "structured", | 473 | "structured", |
474 | NULL, | 474 | NULL, |
475 | &zfcp_dbf_view_header, | 475 | &zfcp_dbf_view_header, |
@@ -478,7 +478,7 @@ struct debug_view zfcp_hba_dbf_view = { | |||
478 | NULL | 478 | NULL |
479 | }; | 479 | }; |
480 | 480 | ||
481 | inline void | 481 | void |
482 | _zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req, | 482 | _zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req, |
483 | u32 s_id, u32 d_id, void *buffer, int buflen) | 483 | u32 s_id, u32 d_id, void *buffer, int buflen) |
484 | { | 484 | { |
@@ -519,7 +519,7 @@ _zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req, | |||
519 | spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); | 519 | spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); |
520 | } | 520 | } |
521 | 521 | ||
522 | inline void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) | 522 | void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) |
523 | { | 523 | { |
524 | struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; | 524 | struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; |
525 | struct zfcp_port *port = ct->port; | 525 | struct zfcp_port *port = ct->port; |
@@ -531,7 +531,7 @@ inline void zfcp_san_dbf_event_ct_request(struct zfcp_fsf_req *fsf_req) | |||
531 | ct->req->length); | 531 | ct->req->length); |
532 | } | 532 | } |
533 | 533 | ||
534 | inline void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) | 534 | void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) |
535 | { | 535 | { |
536 | struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; | 536 | struct zfcp_send_ct *ct = (struct zfcp_send_ct *)fsf_req->data; |
537 | struct zfcp_port *port = ct->port; | 537 | struct zfcp_port *port = ct->port; |
@@ -543,7 +543,7 @@ inline void zfcp_san_dbf_event_ct_response(struct zfcp_fsf_req *fsf_req) | |||
543 | ct->resp->length); | 543 | ct->resp->length); |
544 | } | 544 | } |
545 | 545 | ||
546 | static inline void | 546 | static void |
547 | _zfcp_san_dbf_event_common_els(const char *tag, int level, | 547 | _zfcp_san_dbf_event_common_els(const char *tag, int level, |
548 | struct zfcp_fsf_req *fsf_req, u32 s_id, | 548 | struct zfcp_fsf_req *fsf_req, u32 s_id, |
549 | u32 d_id, u8 ls_code, void *buffer, int buflen) | 549 | u32 d_id, u8 ls_code, void *buffer, int buflen) |
@@ -585,7 +585,7 @@ _zfcp_san_dbf_event_common_els(const char *tag, int level, | |||
585 | spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); | 585 | spin_unlock_irqrestore(&adapter->san_dbf_lock, flags); |
586 | } | 586 | } |
587 | 587 | ||
588 | inline void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req) | 588 | void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req) |
589 | { | 589 | { |
590 | struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data; | 590 | struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data; |
591 | 591 | ||
@@ -597,7 +597,7 @@ inline void zfcp_san_dbf_event_els_request(struct zfcp_fsf_req *fsf_req) | |||
597 | els->req->length); | 597 | els->req->length); |
598 | } | 598 | } |
599 | 599 | ||
600 | inline void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req) | 600 | void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req) |
601 | { | 601 | { |
602 | struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data; | 602 | struct zfcp_send_els *els = (struct zfcp_send_els *)fsf_req->data; |
603 | 603 | ||
@@ -608,7 +608,7 @@ inline void zfcp_san_dbf_event_els_response(struct zfcp_fsf_req *fsf_req) | |||
608 | els->resp->length); | 608 | els->resp->length); |
609 | } | 609 | } |
610 | 610 | ||
611 | inline void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req) | 611 | void zfcp_san_dbf_event_incoming_els(struct zfcp_fsf_req *fsf_req) |
612 | { | 612 | { |
613 | struct zfcp_adapter *adapter = fsf_req->adapter; | 613 | struct zfcp_adapter *adapter = fsf_req->adapter; |
614 | struct fsf_status_read_buffer *status_buffer = | 614 | struct fsf_status_read_buffer *status_buffer = |
@@ -693,7 +693,7 @@ zfcp_san_dbf_view_format(debug_info_t * id, struct debug_view *view, | |||
693 | return len; | 693 | return len; |
694 | } | 694 | } |
695 | 695 | ||
696 | struct debug_view zfcp_san_dbf_view = { | 696 | static struct debug_view zfcp_san_dbf_view = { |
697 | "structured", | 697 | "structured", |
698 | NULL, | 698 | NULL, |
699 | &zfcp_dbf_view_header, | 699 | &zfcp_dbf_view_header, |
@@ -702,7 +702,7 @@ struct debug_view zfcp_san_dbf_view = { | |||
702 | NULL | 702 | NULL |
703 | }; | 703 | }; |
704 | 704 | ||
705 | static inline void | 705 | static void |
706 | _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, | 706 | _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, |
707 | struct zfcp_adapter *adapter, | 707 | struct zfcp_adapter *adapter, |
708 | struct scsi_cmnd *scsi_cmnd, | 708 | struct scsi_cmnd *scsi_cmnd, |
@@ -786,7 +786,7 @@ _zfcp_scsi_dbf_event_common(const char *tag, const char *tag2, int level, | |||
786 | spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags); | 786 | spin_unlock_irqrestore(&adapter->scsi_dbf_lock, flags); |
787 | } | 787 | } |
788 | 788 | ||
789 | inline void | 789 | void |
790 | zfcp_scsi_dbf_event_result(const char *tag, int level, | 790 | zfcp_scsi_dbf_event_result(const char *tag, int level, |
791 | struct zfcp_adapter *adapter, | 791 | struct zfcp_adapter *adapter, |
792 | struct scsi_cmnd *scsi_cmnd, | 792 | struct scsi_cmnd *scsi_cmnd, |
@@ -796,7 +796,7 @@ zfcp_scsi_dbf_event_result(const char *tag, int level, | |||
796 | adapter, scsi_cmnd, fsf_req, 0); | 796 | adapter, scsi_cmnd, fsf_req, 0); |
797 | } | 797 | } |
798 | 798 | ||
799 | inline void | 799 | void |
800 | zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter, | 800 | zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter, |
801 | struct scsi_cmnd *scsi_cmnd, | 801 | struct scsi_cmnd *scsi_cmnd, |
802 | struct zfcp_fsf_req *new_fsf_req, | 802 | struct zfcp_fsf_req *new_fsf_req, |
@@ -806,7 +806,7 @@ zfcp_scsi_dbf_event_abort(const char *tag, struct zfcp_adapter *adapter, | |||
806 | adapter, scsi_cmnd, new_fsf_req, old_req_id); | 806 | adapter, scsi_cmnd, new_fsf_req, old_req_id); |
807 | } | 807 | } |
808 | 808 | ||
809 | inline void | 809 | void |
810 | zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit, | 810 | zfcp_scsi_dbf_event_devreset(const char *tag, u8 flag, struct zfcp_unit *unit, |
811 | struct scsi_cmnd *scsi_cmnd) | 811 | struct scsi_cmnd *scsi_cmnd) |
812 | { | 812 | { |
@@ -884,7 +884,7 @@ zfcp_scsi_dbf_view_format(debug_info_t * id, struct debug_view *view, | |||
884 | return len; | 884 | return len; |
885 | } | 885 | } |
886 | 886 | ||
887 | struct debug_view zfcp_scsi_dbf_view = { | 887 | static struct debug_view zfcp_scsi_dbf_view = { |
888 | "structured", | 888 | "structured", |
889 | NULL, | 889 | NULL, |
890 | &zfcp_dbf_view_header, | 890 | &zfcp_dbf_view_header, |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index c88babce9bca..88642dec080c 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -200,7 +200,7 @@ void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout) | |||
200 | * returns: 0 - initiated action successfully | 200 | * returns: 0 - initiated action successfully |
201 | * <0 - failed to initiate action | 201 | * <0 - failed to initiate action |
202 | */ | 202 | */ |
203 | int | 203 | static int |
204 | zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask) | 204 | zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask) |
205 | { | 205 | { |
206 | int retval; | 206 | int retval; |
@@ -295,7 +295,7 @@ zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask) | |||
295 | * zfcp_erp_adisc - send ADISC ELS command | 295 | * zfcp_erp_adisc - send ADISC ELS command |
296 | * @port: port structure | 296 | * @port: port structure |
297 | */ | 297 | */ |
298 | int | 298 | static int |
299 | zfcp_erp_adisc(struct zfcp_port *port) | 299 | zfcp_erp_adisc(struct zfcp_port *port) |
300 | { | 300 | { |
301 | struct zfcp_adapter *adapter = port->adapter; | 301 | struct zfcp_adapter *adapter = port->adapter; |
@@ -380,7 +380,7 @@ zfcp_erp_adisc(struct zfcp_port *port) | |||
380 | * | 380 | * |
381 | * If ADISC failed (LS_RJT or timed out) forced reopen of the port is triggered. | 381 | * If ADISC failed (LS_RJT or timed out) forced reopen of the port is triggered. |
382 | */ | 382 | */ |
383 | void | 383 | static void |
384 | zfcp_erp_adisc_handler(unsigned long data) | 384 | zfcp_erp_adisc_handler(unsigned long data) |
385 | { | 385 | { |
386 | struct zfcp_send_els *send_els; | 386 | struct zfcp_send_els *send_els; |
@@ -3141,7 +3141,6 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter, | |||
3141 | break; | 3141 | break; |
3142 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: | 3142 | case ZFCP_ERP_ACTION_REOPEN_ADAPTER: |
3143 | if (result != ZFCP_ERP_SUCCEEDED) { | 3143 | if (result != ZFCP_ERP_SUCCEEDED) { |
3144 | struct zfcp_port *port; | ||
3145 | list_for_each_entry(port, &adapter->port_list_head, list) | 3144 | list_for_each_entry(port, &adapter->port_list_head, list) |
3146 | if (port->rport && | 3145 | if (port->rport && |
3147 | !atomic_test_mask(ZFCP_STATUS_PORT_WKA, | 3146 | !atomic_test_mask(ZFCP_STATUS_PORT_WKA, |
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index b8794d77285d..cda0cc095ad1 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h | |||
@@ -119,8 +119,8 @@ extern int zfcp_adapter_scsi_register(struct zfcp_adapter *); | |||
119 | extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *); | 119 | extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *); |
120 | extern void zfcp_set_fcp_dl(struct fcp_cmnd_iu *, fcp_dl_t); | 120 | extern void zfcp_set_fcp_dl(struct fcp_cmnd_iu *, fcp_dl_t); |
121 | extern char *zfcp_get_fcp_rsp_info_ptr(struct fcp_rsp_iu *); | 121 | extern char *zfcp_get_fcp_rsp_info_ptr(struct fcp_rsp_iu *); |
122 | extern void set_host_byte(u32 *, char); | 122 | extern void set_host_byte(int *, char); |
123 | extern void set_driver_byte(u32 *, char); | 123 | extern void set_driver_byte(int *, char); |
124 | extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *); | 124 | extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *); |
125 | extern fcp_dl_t zfcp_get_fcp_dl(struct fcp_cmnd_iu *); | 125 | extern fcp_dl_t zfcp_get_fcp_dl(struct fcp_cmnd_iu *); |
126 | 126 | ||
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 067f1519eb04..4b3ae3f22e78 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -4563,7 +4563,7 @@ zfcp_fsf_req_sbal_check(unsigned long *flags, | |||
4563 | /* | 4563 | /* |
4564 | * set qtcb pointer in fsf_req and initialize QTCB | 4564 | * set qtcb pointer in fsf_req and initialize QTCB |
4565 | */ | 4565 | */ |
4566 | static inline void | 4566 | static void |
4567 | zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req) | 4567 | zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req) |
4568 | { | 4568 | { |
4569 | if (likely(fsf_req->qtcb != NULL)) { | 4569 | if (likely(fsf_req->qtcb != NULL)) { |
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index dbd9f48e863e..1e12a78e8edd 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c | |||
@@ -21,22 +21,22 @@ | |||
21 | 21 | ||
22 | #include "zfcp_ext.h" | 22 | #include "zfcp_ext.h" |
23 | 23 | ||
24 | static inline void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int); | 24 | static void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int); |
25 | static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_get | 25 | static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_get |
26 | (struct zfcp_qdio_queue *, int, int); | 26 | (struct zfcp_qdio_queue *, int, int); |
27 | static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_resp | 27 | static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_resp |
28 | (struct zfcp_fsf_req *, int, int); | 28 | (struct zfcp_fsf_req *, int, int); |
29 | static inline volatile struct qdio_buffer_element *zfcp_qdio_sbal_chain | 29 | static volatile struct qdio_buffer_element *zfcp_qdio_sbal_chain |
30 | (struct zfcp_fsf_req *, unsigned long); | 30 | (struct zfcp_fsf_req *, unsigned long); |
31 | static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_next | 31 | static volatile struct qdio_buffer_element *zfcp_qdio_sbale_next |
32 | (struct zfcp_fsf_req *, unsigned long); | 32 | (struct zfcp_fsf_req *, unsigned long); |
33 | static inline int zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *, int, int); | 33 | static int zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *, int, int); |
34 | static inline int zfcp_qdio_sbals_wipe(struct zfcp_fsf_req *); | 34 | static inline int zfcp_qdio_sbals_wipe(struct zfcp_fsf_req *); |
35 | static inline void zfcp_qdio_sbale_fill | 35 | static void zfcp_qdio_sbale_fill |
36 | (struct zfcp_fsf_req *, unsigned long, void *, int); | 36 | (struct zfcp_fsf_req *, unsigned long, void *, int); |
37 | static inline int zfcp_qdio_sbals_from_segment | 37 | static int zfcp_qdio_sbals_from_segment |
38 | (struct zfcp_fsf_req *, unsigned long, void *, unsigned long); | 38 | (struct zfcp_fsf_req *, unsigned long, void *, unsigned long); |
39 | static inline int zfcp_qdio_sbals_from_buffer | 39 | static int zfcp_qdio_sbals_from_buffer |
40 | (struct zfcp_fsf_req *, unsigned long, void *, unsigned long, int); | 40 | (struct zfcp_fsf_req *, unsigned long, void *, unsigned long, int); |
41 | 41 | ||
42 | static qdio_handler_t zfcp_qdio_request_handler; | 42 | static qdio_handler_t zfcp_qdio_request_handler; |
@@ -201,7 +201,7 @@ zfcp_qdio_allocate(struct zfcp_adapter *adapter) | |||
201 | * returns: error flag | 201 | * returns: error flag |
202 | * | 202 | * |
203 | */ | 203 | */ |
204 | static inline int | 204 | static int |
205 | zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status, | 205 | zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status, |
206 | unsigned int qdio_error, unsigned int siga_error, | 206 | unsigned int qdio_error, unsigned int siga_error, |
207 | int first_element, int elements_processed) | 207 | int first_element, int elements_processed) |
@@ -462,7 +462,7 @@ zfcp_qdio_sbale_get(struct zfcp_qdio_queue *queue, int sbal, int sbale) | |||
462 | * zfcp_qdio_sbale_req - return pointer to SBALE of request_queue for | 462 | * zfcp_qdio_sbale_req - return pointer to SBALE of request_queue for |
463 | * a struct zfcp_fsf_req | 463 | * a struct zfcp_fsf_req |
464 | */ | 464 | */ |
465 | inline volatile struct qdio_buffer_element * | 465 | volatile struct qdio_buffer_element * |
466 | zfcp_qdio_sbale_req(struct zfcp_fsf_req *fsf_req, int sbal, int sbale) | 466 | zfcp_qdio_sbale_req(struct zfcp_fsf_req *fsf_req, int sbal, int sbale) |
467 | { | 467 | { |
468 | return zfcp_qdio_sbale_get(&fsf_req->adapter->request_queue, | 468 | return zfcp_qdio_sbale_get(&fsf_req->adapter->request_queue, |
@@ -484,7 +484,7 @@ zfcp_qdio_sbale_resp(struct zfcp_fsf_req *fsf_req, int sbal, int sbale) | |||
484 | * zfcp_qdio_sbale_curr - return current SBALE on request_queue for | 484 | * zfcp_qdio_sbale_curr - return current SBALE on request_queue for |
485 | * a struct zfcp_fsf_req | 485 | * a struct zfcp_fsf_req |
486 | */ | 486 | */ |
487 | inline volatile struct qdio_buffer_element * | 487 | volatile struct qdio_buffer_element * |
488 | zfcp_qdio_sbale_curr(struct zfcp_fsf_req *fsf_req) | 488 | zfcp_qdio_sbale_curr(struct zfcp_fsf_req *fsf_req) |
489 | { | 489 | { |
490 | return zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, | 490 | return zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, |
@@ -499,7 +499,7 @@ zfcp_qdio_sbale_curr(struct zfcp_fsf_req *fsf_req) | |||
499 | * | 499 | * |
500 | * Note: We can assume at least one free SBAL in the request_queue when called. | 500 | * Note: We can assume at least one free SBAL in the request_queue when called. |
501 | */ | 501 | */ |
502 | static inline void | 502 | static void |
503 | zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals) | 503 | zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals) |
504 | { | 504 | { |
505 | int count = atomic_read(&fsf_req->adapter->request_queue.free_count); | 505 | int count = atomic_read(&fsf_req->adapter->request_queue.free_count); |
@@ -517,7 +517,7 @@ zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals) | |||
517 | * | 517 | * |
518 | * This function changes sbal_curr, sbale_curr, sbal_number of fsf_req. | 518 | * This function changes sbal_curr, sbale_curr, sbal_number of fsf_req. |
519 | */ | 519 | */ |
520 | static inline volatile struct qdio_buffer_element * | 520 | static volatile struct qdio_buffer_element * |
521 | zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) | 521 | zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) |
522 | { | 522 | { |
523 | volatile struct qdio_buffer_element *sbale; | 523 | volatile struct qdio_buffer_element *sbale; |
@@ -554,7 +554,7 @@ zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) | |||
554 | /** | 554 | /** |
555 | * zfcp_qdio_sbale_next - switch to next SBALE, chain SBALs if needed | 555 | * zfcp_qdio_sbale_next - switch to next SBALE, chain SBALs if needed |
556 | */ | 556 | */ |
557 | static inline volatile struct qdio_buffer_element * | 557 | static volatile struct qdio_buffer_element * |
558 | zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) | 558 | zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) |
559 | { | 559 | { |
560 | if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL) | 560 | if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL) |
@@ -569,7 +569,7 @@ zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype) | |||
569 | * zfcp_qdio_sbals_zero - initialize SBALs between first and last in queue | 569 | * zfcp_qdio_sbals_zero - initialize SBALs between first and last in queue |
570 | * with zero from | 570 | * with zero from |
571 | */ | 571 | */ |
572 | static inline int | 572 | static int |
573 | zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *queue, int first, int last) | 573 | zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *queue, int first, int last) |
574 | { | 574 | { |
575 | struct qdio_buffer **buf = queue->buffer; | 575 | struct qdio_buffer **buf = queue->buffer; |
@@ -603,7 +603,7 @@ zfcp_qdio_sbals_wipe(struct zfcp_fsf_req *fsf_req) | |||
603 | * zfcp_qdio_sbale_fill - set address and lenght in current SBALE | 603 | * zfcp_qdio_sbale_fill - set address and lenght in current SBALE |
604 | * on request_queue | 604 | * on request_queue |
605 | */ | 605 | */ |
606 | static inline void | 606 | static void |
607 | zfcp_qdio_sbale_fill(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, | 607 | zfcp_qdio_sbale_fill(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, |
608 | void *addr, int length) | 608 | void *addr, int length) |
609 | { | 609 | { |
@@ -624,7 +624,7 @@ zfcp_qdio_sbale_fill(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, | |||
624 | * Alignment and length of the segment determine how many SBALEs are needed | 624 | * Alignment and length of the segment determine how many SBALEs are needed |
625 | * for the memory segment. | 625 | * for the memory segment. |
626 | */ | 626 | */ |
627 | static inline int | 627 | static int |
628 | zfcp_qdio_sbals_from_segment(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, | 628 | zfcp_qdio_sbals_from_segment(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, |
629 | void *start_addr, unsigned long total_length) | 629 | void *start_addr, unsigned long total_length) |
630 | { | 630 | { |
@@ -659,7 +659,7 @@ zfcp_qdio_sbals_from_segment(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, | |||
659 | * @sg_count: number of elements in scatter-gather list | 659 | * @sg_count: number of elements in scatter-gather list |
660 | * @max_sbals: upper bound for number of SBALs to be used | 660 | * @max_sbals: upper bound for number of SBALs to be used |
661 | */ | 661 | */ |
662 | inline int | 662 | int |
663 | zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, | 663 | zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, |
664 | struct scatterlist *sg, int sg_count, int max_sbals) | 664 | struct scatterlist *sg, int sg_count, int max_sbals) |
665 | { | 665 | { |
@@ -707,7 +707,7 @@ out: | |||
707 | * @length: length of buffer | 707 | * @length: length of buffer |
708 | * @max_sbals: upper bound for number of SBALs to be used | 708 | * @max_sbals: upper bound for number of SBALs to be used |
709 | */ | 709 | */ |
710 | static inline int | 710 | static int |
711 | zfcp_qdio_sbals_from_buffer(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, | 711 | zfcp_qdio_sbals_from_buffer(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, |
712 | void *buffer, unsigned long length, int max_sbals) | 712 | void *buffer, unsigned long length, int max_sbals) |
713 | { | 713 | { |
@@ -728,7 +728,7 @@ zfcp_qdio_sbals_from_buffer(struct zfcp_fsf_req *fsf_req, unsigned long sbtype, | |||
728 | * @scsi_cmnd: either scatter-gather list or buffer contained herein is used | 728 | * @scsi_cmnd: either scatter-gather list or buffer contained herein is used |
729 | * to fill SBALs | 729 | * to fill SBALs |
730 | */ | 730 | */ |
731 | inline int | 731 | int |
732 | zfcp_qdio_sbals_from_scsicmnd(struct zfcp_fsf_req *fsf_req, | 732 | zfcp_qdio_sbals_from_scsicmnd(struct zfcp_fsf_req *fsf_req, |
733 | unsigned long sbtype, struct scsi_cmnd *scsi_cmnd) | 733 | unsigned long sbtype, struct scsi_cmnd *scsi_cmnd) |
734 | { | 734 | { |
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 452d96f92a14..99db02062c3b 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -90,7 +90,7 @@ zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *fcp_rsp_iu) | |||
90 | return fcp_sns_info_ptr; | 90 | return fcp_sns_info_ptr; |
91 | } | 91 | } |
92 | 92 | ||
93 | fcp_dl_t * | 93 | static fcp_dl_t * |
94 | zfcp_get_fcp_dl_ptr(struct fcp_cmnd_iu * fcp_cmd) | 94 | zfcp_get_fcp_dl_ptr(struct fcp_cmnd_iu * fcp_cmd) |
95 | { | 95 | { |
96 | int additional_length = fcp_cmd->add_fcp_cdb_length << 2; | 96 | int additional_length = fcp_cmd->add_fcp_cdb_length << 2; |
@@ -124,19 +124,19 @@ zfcp_set_fcp_dl(struct fcp_cmnd_iu *fcp_cmd, fcp_dl_t fcp_dl) | |||
124 | * regarding the specified byte | 124 | * regarding the specified byte |
125 | */ | 125 | */ |
126 | static inline void | 126 | static inline void |
127 | set_byte(u32 * result, char status, char pos) | 127 | set_byte(int *result, char status, char pos) |
128 | { | 128 | { |
129 | *result |= status << (pos * 8); | 129 | *result |= status << (pos * 8); |
130 | } | 130 | } |
131 | 131 | ||
132 | void | 132 | void |
133 | set_host_byte(u32 * result, char status) | 133 | set_host_byte(int *result, char status) |
134 | { | 134 | { |
135 | set_byte(result, status, 2); | 135 | set_byte(result, status, 2); |
136 | } | 136 | } |
137 | 137 | ||
138 | void | 138 | void |
139 | set_driver_byte(u32 * result, char status) | 139 | set_driver_byte(int *result, char status) |
140 | { | 140 | { |
141 | set_byte(result, status, 3); | 141 | set_byte(result, status, 3); |
142 | } | 142 | } |
@@ -280,7 +280,7 @@ out: | |||
280 | return retval; | 280 | return retval; |
281 | } | 281 | } |
282 | 282 | ||
283 | void | 283 | static void |
284 | zfcp_scsi_command_sync_handler(struct scsi_cmnd *scpnt) | 284 | zfcp_scsi_command_sync_handler(struct scsi_cmnd *scpnt) |
285 | { | 285 | { |
286 | struct completion *wait = (struct completion *) scpnt->SCp.ptr; | 286 | struct completion *wait = (struct completion *) scpnt->SCp.ptr; |
@@ -324,7 +324,7 @@ zfcp_scsi_command_sync(struct zfcp_unit *unit, struct scsi_cmnd *scpnt, | |||
324 | * returns: 0 - success, SCSI command enqueued | 324 | * returns: 0 - success, SCSI command enqueued |
325 | * !0 - failure | 325 | * !0 - failure |
326 | */ | 326 | */ |
327 | int | 327 | static int |
328 | zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, | 328 | zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, |
329 | void (*done) (struct scsi_cmnd *)) | 329 | void (*done) (struct scsi_cmnd *)) |
330 | { | 330 | { |
@@ -380,7 +380,7 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id, | |||
380 | * will handle late commands. (Usually, the normal completion of late | 380 | * will handle late commands. (Usually, the normal completion of late |
381 | * commands is ignored with respect to the running abort operation.) | 381 | * commands is ignored with respect to the running abort operation.) |
382 | */ | 382 | */ |
383 | int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | 383 | static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) |
384 | { | 384 | { |
385 | struct Scsi_Host *scsi_host; | 385 | struct Scsi_Host *scsi_host; |
386 | struct zfcp_adapter *adapter; | 386 | struct zfcp_adapter *adapter; |
@@ -445,7 +445,7 @@ int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) | |||
445 | return retval; | 445 | return retval; |
446 | } | 446 | } |
447 | 447 | ||
448 | int | 448 | static int |
449 | zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) | 449 | zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) |
450 | { | 450 | { |
451 | int retval; | 451 | int retval; |
@@ -541,7 +541,7 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags, | |||
541 | /** | 541 | /** |
542 | * zfcp_scsi_eh_host_reset_handler - handler for host and bus reset | 542 | * zfcp_scsi_eh_host_reset_handler - handler for host and bus reset |
543 | */ | 543 | */ |
544 | int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) | 544 | static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) |
545 | { | 545 | { |
546 | struct zfcp_unit *unit; | 546 | struct zfcp_unit *unit; |
547 | struct zfcp_adapter *adapter; | 547 | struct zfcp_adapter *adapter; |
diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c index 1e788e815ce7..090743d2f914 100644 --- a/drivers/s390/sysinfo.c +++ b/drivers/s390/sysinfo.c | |||
@@ -9,8 +9,14 @@ | |||
9 | #include <linux/mm.h> | 9 | #include <linux/mm.h> |
10 | #include <linux/proc_fs.h> | 10 | #include <linux/proc_fs.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/delay.h> | ||
12 | #include <asm/ebcdic.h> | 13 | #include <asm/ebcdic.h> |
13 | 14 | ||
15 | /* Sigh, math-emu. Don't ask. */ | ||
16 | #include <asm/sfp-util.h> | ||
17 | #include <math-emu/soft-fp.h> | ||
18 | #include <math-emu/single.h> | ||
19 | |||
14 | struct sysinfo_1_1_1 { | 20 | struct sysinfo_1_1_1 { |
15 | char reserved_0[32]; | 21 | char reserved_0[32]; |
16 | char manufacturer[16]; | 22 | char manufacturer[16]; |
@@ -198,7 +204,7 @@ static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) | |||
198 | * if the higher order 8 bits are not zero. Printing | 204 | * if the higher order 8 bits are not zero. Printing |
199 | * a floating point number in the kernel is a no-no, | 205 | * a floating point number in the kernel is a no-no, |
200 | * always print the number as 32 bit unsigned integer. | 206 | * always print the number as 32 bit unsigned integer. |
201 | * The user-space needs to know about the stange | 207 | * The user-space needs to know about the strange |
202 | * encoding of the alternate cpu capability. | 208 | * encoding of the alternate cpu capability. |
203 | */ | 209 | */ |
204 | len += sprintf(page + len, "Capability: %u %u\n", | 210 | len += sprintf(page + len, "Capability: %u %u\n", |
@@ -351,3 +357,58 @@ static __init int create_proc_sysinfo(void) | |||
351 | 357 | ||
352 | __initcall(create_proc_sysinfo); | 358 | __initcall(create_proc_sysinfo); |
353 | 359 | ||
360 | /* | ||
361 | * CPU capability might have changed. Therefore recalculate loops_per_jiffy. | ||
362 | */ | ||
363 | void s390_adjust_jiffies(void) | ||
364 | { | ||
365 | struct sysinfo_1_2_2 *info; | ||
366 | const unsigned int fmil = 0x4b189680; /* 1e7 as 32-bit float. */ | ||
367 | FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); | ||
368 | FP_DECL_EX; | ||
369 | unsigned int capability; | ||
370 | |||
371 | info = (void *) get_zeroed_page(GFP_KERNEL); | ||
372 | if (!info) | ||
373 | return; | ||
374 | |||
375 | if (stsi(info, 1, 2, 2) != -ENOSYS) { | ||
376 | /* | ||
377 | * Major sigh. The cpu capability encoding is "special". | ||
378 | * If the first 9 bits of info->capability are 0 then it | ||
379 | * is a 32 bit unsigned integer in the range 0 .. 2^23. | ||
380 | * If the first 9 bits are != 0 then it is a 32 bit float. | ||
381 | * In addition a lower value indicates a proportionally | ||
382 | * higher cpu capacity. Bogomips are the other way round. | ||
383 | * To get to a halfway suitable number we divide 1e7 | ||
384 | * by the cpu capability number. Yes, that means a floating | ||
385 | * point division .. math-emu here we come :-) | ||
386 | */ | ||
387 | FP_UNPACK_SP(SA, &fmil); | ||
388 | if ((info->capability >> 23) == 0) | ||
389 | FP_FROM_INT_S(SB, info->capability, 32, int); | ||
390 | else | ||
391 | FP_UNPACK_SP(SB, &info->capability); | ||
392 | FP_DIV_S(SR, SA, SB); | ||
393 | FP_TO_INT_S(capability, SR, 32, 0); | ||
394 | } else | ||
395 | /* | ||
396 | * Really old machine without stsi block for basic | ||
397 | * cpu information. Report 42.0 bogomips. | ||
398 | */ | ||
399 | capability = 42; | ||
400 | loops_per_jiffy = capability * (500000/HZ); | ||
401 | free_page((unsigned long) info); | ||
402 | } | ||
403 | |||
404 | /* | ||
405 | * calibrate the delay loop | ||
406 | */ | ||
407 | void __init calibrate_delay(void) | ||
408 | { | ||
409 | s390_adjust_jiffies(); | ||
410 | /* Print the good old Bogomips line .. */ | ||
411 | printk(KERN_DEBUG "Calibrating delay loop (skipped)... " | ||
412 | "%lu.%02lu BogoMIPS preset\n", loops_per_jiffy/(500000/HZ), | ||
413 | (loops_per_jiffy/(5000/HZ)) % 100); | ||
414 | } | ||
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index c7d887540d8d..aa6a620c162f 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig | |||
@@ -69,6 +69,14 @@ config LOGITECH_FF | |||
69 | Note: if you say N here, this device will still be supported, but without | 69 | Note: if you say N here, this device will still be supported, but without |
70 | force feedback. | 70 | force feedback. |
71 | 71 | ||
72 | config PANTHERLORD_FF | ||
73 | bool "PantherLord USB/PS2 2in1 Adapter support" | ||
74 | depends on HID_FF | ||
75 | select INPUT_FF_MEMLESS if USB_HID | ||
76 | help | ||
77 | Say Y here if you have a PantherLord USB/PS2 2in1 Adapter and want | ||
78 | to enable force feedback support for it. | ||
79 | |||
72 | config THRUSTMASTER_FF | 80 | config THRUSTMASTER_FF |
73 | bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)" | 81 | bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)" |
74 | depends on HID_FF && EXPERIMENTAL | 82 | depends on HID_FF && EXPERIMENTAL |
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index 1a24b5bfa05f..a06024e5cd56 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile | |||
@@ -17,6 +17,9 @@ endif | |||
17 | ifeq ($(CONFIG_LOGITECH_FF),y) | 17 | ifeq ($(CONFIG_LOGITECH_FF),y) |
18 | usbhid-objs += hid-lgff.o | 18 | usbhid-objs += hid-lgff.o |
19 | endif | 19 | endif |
20 | ifeq ($(CONFIG_PANTHERLORD_FF),y) | ||
21 | usbhid-objs += hid-plff.o | ||
22 | endif | ||
20 | ifeq ($(CONFIG_THRUSTMASTER_FF),y) | 23 | ifeq ($(CONFIG_THRUSTMASTER_FF),y) |
21 | usbhid-objs += hid-tmff.o | 24 | usbhid-objs += hid-tmff.o |
22 | endif | 25 | endif |
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index c6c9e72e5fd9..e07a30490726 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | #include <linux/hid.h> | 36 | #include <linux/hid.h> |
37 | #include <linux/hiddev.h> | 37 | #include <linux/hiddev.h> |
38 | #include <linux/hid-debug.h> | ||
38 | #include "usbhid.h" | 39 | #include "usbhid.h" |
39 | 40 | ||
40 | /* | 41 | /* |
@@ -220,23 +221,6 @@ static void hid_irq_in(struct urb *urb) | |||
220 | } | 221 | } |
221 | } | 222 | } |
222 | 223 | ||
223 | /* | ||
224 | * Find a report field with a specified HID usage. | ||
225 | */ | ||
226 | #if 0 | ||
227 | struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type) | ||
228 | { | ||
229 | struct hid_report *report; | ||
230 | int i; | ||
231 | |||
232 | list_for_each_entry(report, &hid->report_enum[type].report_list, list) | ||
233 | for (i = 0; i < report->maxfield; i++) | ||
234 | if (report->field[i]->logical == wanted_usage) | ||
235 | return report->field[i]; | ||
236 | return NULL; | ||
237 | } | ||
238 | #endif /* 0 */ | ||
239 | |||
240 | static int hid_submit_out(struct hid_device *hid) | 224 | static int hid_submit_out(struct hid_device *hid) |
241 | { | 225 | { |
242 | struct hid_report *report; | 226 | struct hid_report *report; |
@@ -501,7 +485,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, | |||
501 | { | 485 | { |
502 | int result, retries = 4; | 486 | int result, retries = 4; |
503 | 487 | ||
504 | memset(buf,0,size); // Make sure we parse really received data | 488 | memset(buf, 0, size); |
505 | 489 | ||
506 | do { | 490 | do { |
507 | result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), | 491 | result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), |
@@ -528,18 +512,6 @@ void usbhid_close(struct hid_device *hid) | |||
528 | usb_kill_urb(usbhid->urbin); | 512 | usb_kill_urb(usbhid->urbin); |
529 | } | 513 | } |
530 | 514 | ||
531 | static int hidinput_open(struct input_dev *dev) | ||
532 | { | ||
533 | struct hid_device *hid = dev->private; | ||
534 | return usbhid_open(hid); | ||
535 | } | ||
536 | |||
537 | static void hidinput_close(struct input_dev *dev) | ||
538 | { | ||
539 | struct hid_device *hid = dev->private; | ||
540 | usbhid_close(hid); | ||
541 | } | ||
542 | |||
543 | #define USB_VENDOR_ID_PANJIT 0x134c | 515 | #define USB_VENDOR_ID_PANJIT 0x134c |
544 | 516 | ||
545 | #define USB_VENDOR_ID_TURBOX 0x062a | 517 | #define USB_VENDOR_ID_TURBOX 0x062a |
@@ -770,6 +742,7 @@ void usbhid_init_reports(struct hid_device *hid) | |||
770 | #define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c | 742 | #define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c |
771 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a | 743 | #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a |
772 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b | 744 | #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b |
745 | #define USB_DEVICE_ID_APPLE_IR 0x8240 | ||
773 | 746 | ||
774 | #define USB_VENDOR_ID_CHERRY 0x046a | 747 | #define USB_VENDOR_ID_CHERRY 0x046a |
775 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 | 748 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 |
@@ -792,6 +765,9 @@ void usbhid_init_reports(struct hid_device *hid) | |||
792 | #define USB_VENDOR_ID_IMATION 0x0718 | 765 | #define USB_VENDOR_ID_IMATION 0x0718 |
793 | #define USB_DEVICE_ID_DISC_STAKKA 0xd000 | 766 | #define USB_DEVICE_ID_DISC_STAKKA 0xd000 |
794 | 767 | ||
768 | #define USB_VENDOR_ID_PANTHERLORD 0x0810 | ||
769 | #define USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK 0x0001 | ||
770 | |||
795 | /* | 771 | /* |
796 | * Alphabetically sorted blacklist by quirk type. | 772 | * Alphabetically sorted blacklist by quirk type. |
797 | */ | 773 | */ |
@@ -946,19 +922,21 @@ static const struct hid_blacklist { | |||
946 | 922 | ||
947 | { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, | 923 | { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, |
948 | 924 | ||
949 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, | 925 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
950 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN }, | 926 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
951 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, | 927 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
952 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, | 928 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, |
953 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN }, | 929 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
954 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, | 930 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
955 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, | 931 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, |
956 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN }, | 932 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
957 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, | 933 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
958 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, | 934 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, |
959 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN }, | 935 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
960 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN }, | 936 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
961 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN }, | 937 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE }, |
938 | |||
939 | { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IR, HID_QUIRK_IGNORE }, | ||
962 | 940 | ||
963 | { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE }, | 941 | { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE }, |
964 | { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE }, | 942 | { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE }, |
@@ -969,6 +947,8 @@ static const struct hid_blacklist { | |||
969 | 947 | ||
970 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS }, | 948 | { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS }, |
971 | 949 | ||
950 | { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, | ||
951 | |||
972 | { 0, 0 } | 952 | { 0, 0 } |
973 | }; | 953 | }; |
974 | 954 | ||
@@ -1064,6 +1044,11 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1064 | if (quirks & HID_QUIRK_IGNORE) | 1044 | if (quirks & HID_QUIRK_IGNORE) |
1065 | return NULL; | 1045 | return NULL; |
1066 | 1046 | ||
1047 | if ((quirks & HID_QUIRK_IGNORE_MOUSE) && | ||
1048 | (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)) | ||
1049 | return NULL; | ||
1050 | |||
1051 | |||
1067 | if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && | 1052 | if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && |
1068 | (!interface->desc.bNumEndpoints || | 1053 | (!interface->desc.bNumEndpoints || |
1069 | usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { | 1054 | usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) { |
@@ -1235,8 +1220,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1235 | usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma; | 1220 | usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma; |
1236 | usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); | 1221 | usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP); |
1237 | hid->hidinput_input_event = usb_hidinput_input_event; | 1222 | hid->hidinput_input_event = usb_hidinput_input_event; |
1238 | hid->hidinput_open = hidinput_open; | 1223 | hid->hid_open = usbhid_open; |
1239 | hid->hidinput_close = hidinput_close; | 1224 | hid->hid_close = usbhid_close; |
1240 | #ifdef CONFIG_USB_HIDDEV | 1225 | #ifdef CONFIG_USB_HIDDEV |
1241 | hid->hiddev_hid_event = hiddev_hid_event; | 1226 | hid->hiddev_hid_event = hiddev_hid_event; |
1242 | hid->hiddev_report_event = hiddev_report_event; | 1227 | hid->hiddev_report_event = hiddev_report_event; |
@@ -1315,11 +1300,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
1315 | return -ENODEV; | 1300 | return -ENODEV; |
1316 | } | 1301 | } |
1317 | 1302 | ||
1318 | /* This only gets called when we are a single-input (most of the | 1303 | if ((hid->claimed & HID_CLAIMED_INPUT)) |
1319 | * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is | ||
1320 | * only useful in this case, and not for multi-input quirks. */ | ||
1321 | if ((hid->claimed & HID_CLAIMED_INPUT) && | ||
1322 | !(hid->quirks & HID_QUIRK_MULTI_INPUT)) | ||
1323 | hid_ff_init(hid); | 1304 | hid_ff_init(hid); |
1324 | 1305 | ||
1325 | printk(KERN_INFO); | 1306 | printk(KERN_INFO); |
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c index 59ed65e7a621..5d145058a5cb 100644 --- a/drivers/usb/input/hid-ff.c +++ b/drivers/usb/input/hid-ff.c | |||
@@ -58,6 +58,9 @@ static struct hid_ff_initializer inits[] = { | |||
58 | { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */ | 58 | { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */ |
59 | { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */ | 59 | { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */ |
60 | #endif | 60 | #endif |
61 | #ifdef CONFIG_PANTHERLORD_FF | ||
62 | { 0x810, 0x0001, hid_plff_init }, | ||
63 | #endif | ||
61 | #ifdef CONFIG_THRUSTMASTER_FF | 64 | #ifdef CONFIG_THRUSTMASTER_FF |
62 | { 0x44f, 0xb304, hid_tmff_init }, | 65 | { 0x44f, 0xb304, hid_tmff_init }, |
63 | #endif | 66 | #endif |
diff --git a/drivers/usb/input/hid-plff.c b/drivers/usb/input/hid-plff.c new file mode 100644 index 000000000000..76d2e6e14db4 --- /dev/null +++ b/drivers/usb/input/hid-plff.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Force feedback support for PantherLord USB/PS2 2in1 Adapter devices | ||
3 | * | ||
4 | * Copyright (c) 2007 Anssi Hannula <anssi.hannula@gmail.com> | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | |||
24 | /* #define DEBUG */ | ||
25 | |||
26 | #define debug(format, arg...) pr_debug("hid-plff: " format "\n" , ## arg) | ||
27 | |||
28 | #include <linux/input.h> | ||
29 | #include <linux/usb.h> | ||
30 | #include <linux/hid.h> | ||
31 | #include "usbhid.h" | ||
32 | |||
33 | struct plff_device { | ||
34 | struct hid_report *report; | ||
35 | }; | ||
36 | |||
37 | static int hid_plff_play(struct input_dev *dev, void *data, | ||
38 | struct ff_effect *effect) | ||
39 | { | ||
40 | struct hid_device *hid = dev->private; | ||
41 | struct plff_device *plff = data; | ||
42 | int left, right; | ||
43 | |||
44 | left = effect->u.rumble.strong_magnitude; | ||
45 | right = effect->u.rumble.weak_magnitude; | ||
46 | debug("called with 0x%04x 0x%04x", left, right); | ||
47 | |||
48 | left = left * 0x7f / 0xffff; | ||
49 | right = right * 0x7f / 0xffff; | ||
50 | |||
51 | plff->report->field[0]->value[2] = left; | ||
52 | plff->report->field[0]->value[3] = right; | ||
53 | debug("running with 0x%02x 0x%02x", left, right); | ||
54 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | int hid_plff_init(struct hid_device *hid) | ||
60 | { | ||
61 | struct plff_device *plff; | ||
62 | struct hid_report *report; | ||
63 | struct hid_input *hidinput; | ||
64 | struct list_head *report_list = | ||
65 | &hid->report_enum[HID_OUTPUT_REPORT].report_list; | ||
66 | struct list_head *report_ptr = report_list; | ||
67 | struct input_dev *dev; | ||
68 | int error; | ||
69 | |||
70 | /* The device contains 2 output reports (one for each | ||
71 | HID_QUIRK_MULTI_INPUT device), both containing 1 field, which | ||
72 | contains 4 ff00.0002 usages and 4 16bit absolute values. | ||
73 | |||
74 | The 2 input reports also contain a field which contains | ||
75 | 8 ff00.0001 usages and 8 boolean values. Their meaning is | ||
76 | currently unknown. */ | ||
77 | |||
78 | if (list_empty(report_list)) { | ||
79 | printk(KERN_ERR "hid-plff: no output reports found\n"); | ||
80 | return -ENODEV; | ||
81 | } | ||
82 | |||
83 | list_for_each_entry(hidinput, &hid->inputs, list) { | ||
84 | |||
85 | report_ptr = report_ptr->next; | ||
86 | |||
87 | if (report_ptr == report_list) { | ||
88 | printk(KERN_ERR "hid-plff: required output report is missing\n"); | ||
89 | return -ENODEV; | ||
90 | } | ||
91 | |||
92 | report = list_entry(report_ptr, struct hid_report, list); | ||
93 | if (report->maxfield < 1) { | ||
94 | printk(KERN_ERR "hid-plff: no fields in the report\n"); | ||
95 | return -ENODEV; | ||
96 | } | ||
97 | |||
98 | if (report->field[0]->report_count < 4) { | ||
99 | printk(KERN_ERR "hid-plff: not enough values in the field\n"); | ||
100 | return -ENODEV; | ||
101 | } | ||
102 | |||
103 | plff = kzalloc(sizeof(struct plff_device), GFP_KERNEL); | ||
104 | if (!plff) | ||
105 | return -ENOMEM; | ||
106 | |||
107 | dev = hidinput->input; | ||
108 | |||
109 | set_bit(FF_RUMBLE, dev->ffbit); | ||
110 | |||
111 | error = input_ff_create_memless(dev, plff, hid_plff_play); | ||
112 | if (error) { | ||
113 | kfree(plff); | ||
114 | return error; | ||
115 | } | ||
116 | |||
117 | plff->report = report; | ||
118 | plff->report->field[0]->value[0] = 0x00; | ||
119 | plff->report->field[0]->value[1] = 0x00; | ||
120 | plff->report->field[0]->value[2] = 0x00; | ||
121 | plff->report->field[0]->value[3] = 0x00; | ||
122 | usbhid_submit_report(hid, plff->report, USB_DIR_OUT); | ||
123 | } | ||
124 | |||
125 | printk(KERN_INFO "hid-plff: Force feedback for PantherLord USB/PS2 " | ||
126 | "2in1 Adapters by Anssi Hannula <anssi.hannula@gmail.com>\n"); | ||
127 | |||
128 | return 0; | ||
129 | } | ||