diff options
author | Paul Mundt <lethal@linux-sh.org> | 2009-04-01 22:17:41 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-04-01 22:17:41 -0400 |
commit | c4361bb64b81f5b81a7a08d58654493385a2f2b2 (patch) | |
tree | 8741c0b60ddfbc3fc4e17c8d200f6aa6ff32cca0 /drivers | |
parent | 46368fa05164e1afdc1401294908cf30c6d8d981 (diff) | |
parent | 833bb3046b6cb320e775ea2160ddca87d53260d5 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers')
226 files changed, 8907 insertions, 6632 deletions
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 9b917dac7732..88e42abf5d88 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c | |||
@@ -191,7 +191,6 @@ static int acpi_ac_add_fs(struct acpi_device *device) | |||
191 | acpi_ac_dir); | 191 | acpi_ac_dir); |
192 | if (!acpi_device_dir(device)) | 192 | if (!acpi_device_dir(device)) |
193 | return -ENODEV; | 193 | return -ENODEV; |
194 | acpi_device_dir(device)->owner = THIS_MODULE; | ||
195 | } | 194 | } |
196 | 195 | ||
197 | /* 'state' [R] */ | 196 | /* 'state' [R] */ |
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 69cbc57c2d1c..3bcb5bfc45d3 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -760,7 +760,6 @@ static int acpi_battery_add_fs(struct acpi_device *device) | |||
760 | acpi_battery_dir); | 760 | acpi_battery_dir); |
761 | if (!acpi_device_dir(device)) | 761 | if (!acpi_device_dir(device)) |
762 | return -ENODEV; | 762 | return -ENODEV; |
763 | acpi_device_dir(device)->owner = THIS_MODULE; | ||
764 | } | 763 | } |
765 | 764 | ||
766 | for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { | 765 | for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { |
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index 171fd914f435..c2f06069dcd4 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c | |||
@@ -200,12 +200,10 @@ static int acpi_button_add_fs(struct acpi_device *device) | |||
200 | 200 | ||
201 | if (!entry) | 201 | if (!entry) |
202 | return -ENODEV; | 202 | return -ENODEV; |
203 | entry->owner = THIS_MODULE; | ||
204 | 203 | ||
205 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry); | 204 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry); |
206 | if (!acpi_device_dir(device)) | 205 | if (!acpi_device_dir(device)) |
207 | return -ENODEV; | 206 | return -ENODEV; |
208 | acpi_device_dir(device)->owner = THIS_MODULE; | ||
209 | 207 | ||
210 | /* 'info' [R] */ | 208 | /* 'info' [R] */ |
211 | entry = proc_create_data(ACPI_BUTTON_FILE_INFO, | 209 | entry = proc_create_data(ACPI_BUTTON_FILE_INFO, |
@@ -522,7 +520,6 @@ static int __init acpi_button_init(void) | |||
522 | acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); | 520 | acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); |
523 | if (!acpi_button_dir) | 521 | if (!acpi_button_dir) |
524 | return -ENODEV; | 522 | return -ENODEV; |
525 | acpi_button_dir->owner = THIS_MODULE; | ||
526 | result = acpi_bus_register_driver(&acpi_button_driver); | 523 | result = acpi_bus_register_driver(&acpi_button_driver); |
527 | if (result < 0) { | 524 | if (result < 0) { |
528 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); | 525 | remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); |
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index eaaee1660bdf..8a02944bf92d 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c | |||
@@ -193,7 +193,6 @@ static int acpi_fan_add_fs(struct acpi_device *device) | |||
193 | acpi_fan_dir); | 193 | acpi_fan_dir); |
194 | if (!acpi_device_dir(device)) | 194 | if (!acpi_device_dir(device)) |
195 | return -ENODEV; | 195 | return -ENODEV; |
196 | acpi_device_dir(device)->owner = THIS_MODULE; | ||
197 | } | 196 | } |
198 | 197 | ||
199 | /* 'status' [R/W] */ | 198 | /* 'status' [R/W] */ |
@@ -347,7 +346,6 @@ static int __init acpi_fan_init(void) | |||
347 | acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir); | 346 | acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir); |
348 | if (!acpi_fan_dir) | 347 | if (!acpi_fan_dir) |
349 | return -ENODEV; | 348 | return -ENODEV; |
350 | acpi_fan_dir->owner = THIS_MODULE; | ||
351 | #endif | 349 | #endif |
352 | 350 | ||
353 | result = acpi_bus_register_driver(&acpi_fan_driver); | 351 | result = acpi_bus_register_driver(&acpi_fan_driver); |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 5b38a026d122..196f97d00956 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -66,11 +66,18 @@ struct acpi_pci_root { | |||
66 | struct acpi_device * device; | 66 | struct acpi_device * device; |
67 | struct acpi_pci_id id; | 67 | struct acpi_pci_id id; |
68 | struct pci_bus *bus; | 68 | struct pci_bus *bus; |
69 | |||
70 | u32 osc_support_set; /* _OSC state of support bits */ | ||
71 | u32 osc_control_set; /* _OSC state of control bits */ | ||
72 | u32 osc_control_qry; /* the latest _OSC query result */ | ||
73 | |||
74 | u32 osc_queried:1; /* has _OSC control been queried? */ | ||
69 | }; | 75 | }; |
70 | 76 | ||
71 | static LIST_HEAD(acpi_pci_roots); | 77 | static LIST_HEAD(acpi_pci_roots); |
72 | 78 | ||
73 | static struct acpi_pci_driver *sub_driver; | 79 | static struct acpi_pci_driver *sub_driver; |
80 | static DEFINE_MUTEX(osc_lock); | ||
74 | 81 | ||
75 | int acpi_pci_register_driver(struct acpi_pci_driver *driver) | 82 | int acpi_pci_register_driver(struct acpi_pci_driver *driver) |
76 | { | 83 | { |
@@ -185,6 +192,175 @@ static void acpi_pci_bridge_scan(struct acpi_device *device) | |||
185 | } | 192 | } |
186 | } | 193 | } |
187 | 194 | ||
195 | static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, | ||
196 | 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; | ||
197 | |||
198 | static acpi_status acpi_pci_run_osc(acpi_handle handle, | ||
199 | const u32 *capbuf, u32 *retval) | ||
200 | { | ||
201 | acpi_status status; | ||
202 | struct acpi_object_list input; | ||
203 | union acpi_object in_params[4]; | ||
204 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
205 | union acpi_object *out_obj; | ||
206 | u32 errors; | ||
207 | |||
208 | /* Setting up input parameters */ | ||
209 | input.count = 4; | ||
210 | input.pointer = in_params; | ||
211 | in_params[0].type = ACPI_TYPE_BUFFER; | ||
212 | in_params[0].buffer.length = 16; | ||
213 | in_params[0].buffer.pointer = OSC_UUID; | ||
214 | in_params[1].type = ACPI_TYPE_INTEGER; | ||
215 | in_params[1].integer.value = 1; | ||
216 | in_params[2].type = ACPI_TYPE_INTEGER; | ||
217 | in_params[2].integer.value = 3; | ||
218 | in_params[3].type = ACPI_TYPE_BUFFER; | ||
219 | in_params[3].buffer.length = 12; | ||
220 | in_params[3].buffer.pointer = (u8 *)capbuf; | ||
221 | |||
222 | status = acpi_evaluate_object(handle, "_OSC", &input, &output); | ||
223 | if (ACPI_FAILURE(status)) | ||
224 | return status; | ||
225 | |||
226 | if (!output.length) | ||
227 | return AE_NULL_OBJECT; | ||
228 | |||
229 | out_obj = output.pointer; | ||
230 | if (out_obj->type != ACPI_TYPE_BUFFER) { | ||
231 | printk(KERN_DEBUG "_OSC evaluation returned wrong type\n"); | ||
232 | status = AE_TYPE; | ||
233 | goto out_kfree; | ||
234 | } | ||
235 | /* Need to ignore the bit0 in result code */ | ||
236 | errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); | ||
237 | if (errors) { | ||
238 | if (errors & OSC_REQUEST_ERROR) | ||
239 | printk(KERN_DEBUG "_OSC request failed\n"); | ||
240 | if (errors & OSC_INVALID_UUID_ERROR) | ||
241 | printk(KERN_DEBUG "_OSC invalid UUID\n"); | ||
242 | if (errors & OSC_INVALID_REVISION_ERROR) | ||
243 | printk(KERN_DEBUG "_OSC invalid revision\n"); | ||
244 | if (errors & OSC_CAPABILITIES_MASK_ERROR) { | ||
245 | if (capbuf[OSC_QUERY_TYPE] & OSC_QUERY_ENABLE) | ||
246 | goto out_success; | ||
247 | printk(KERN_DEBUG | ||
248 | "Firmware did not grant requested _OSC control\n"); | ||
249 | status = AE_SUPPORT; | ||
250 | goto out_kfree; | ||
251 | } | ||
252 | status = AE_ERROR; | ||
253 | goto out_kfree; | ||
254 | } | ||
255 | out_success: | ||
256 | *retval = *((u32 *)(out_obj->buffer.pointer + 8)); | ||
257 | status = AE_OK; | ||
258 | |||
259 | out_kfree: | ||
260 | kfree(output.pointer); | ||
261 | return status; | ||
262 | } | ||
263 | |||
264 | static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags) | ||
265 | { | ||
266 | acpi_status status; | ||
267 | u32 support_set, result, capbuf[3]; | ||
268 | |||
269 | /* do _OSC query for all possible controls */ | ||
270 | support_set = root->osc_support_set | (flags & OSC_SUPPORT_MASKS); | ||
271 | capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; | ||
272 | capbuf[OSC_SUPPORT_TYPE] = support_set; | ||
273 | capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; | ||
274 | |||
275 | status = acpi_pci_run_osc(root->device->handle, capbuf, &result); | ||
276 | if (ACPI_SUCCESS(status)) { | ||
277 | root->osc_support_set = support_set; | ||
278 | root->osc_control_qry = result; | ||
279 | root->osc_queried = 1; | ||
280 | } | ||
281 | return status; | ||
282 | } | ||
283 | |||
284 | static acpi_status acpi_pci_osc_support(struct acpi_pci_root *root, u32 flags) | ||
285 | { | ||
286 | acpi_status status; | ||
287 | acpi_handle tmp; | ||
288 | |||
289 | status = acpi_get_handle(root->device->handle, "_OSC", &tmp); | ||
290 | if (ACPI_FAILURE(status)) | ||
291 | return status; | ||
292 | mutex_lock(&osc_lock); | ||
293 | status = acpi_pci_query_osc(root, flags); | ||
294 | mutex_unlock(&osc_lock); | ||
295 | return status; | ||
296 | } | ||
297 | |||
298 | static struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) | ||
299 | { | ||
300 | struct acpi_pci_root *root; | ||
301 | list_for_each_entry(root, &acpi_pci_roots, node) { | ||
302 | if (root->device->handle == handle) | ||
303 | return root; | ||
304 | } | ||
305 | return NULL; | ||
306 | } | ||
307 | |||
308 | /** | ||
309 | * acpi_pci_osc_control_set - commit requested control to Firmware | ||
310 | * @handle: acpi_handle for the target ACPI object | ||
311 | * @flags: driver's requested control bits | ||
312 | * | ||
313 | * Attempt to take control from Firmware on requested control bits. | ||
314 | **/ | ||
315 | acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags) | ||
316 | { | ||
317 | acpi_status status; | ||
318 | u32 control_req, result, capbuf[3]; | ||
319 | acpi_handle tmp; | ||
320 | struct acpi_pci_root *root; | ||
321 | |||
322 | status = acpi_get_handle(handle, "_OSC", &tmp); | ||
323 | if (ACPI_FAILURE(status)) | ||
324 | return status; | ||
325 | |||
326 | control_req = (flags & OSC_CONTROL_MASKS); | ||
327 | if (!control_req) | ||
328 | return AE_TYPE; | ||
329 | |||
330 | root = acpi_pci_find_root(handle); | ||
331 | if (!root) | ||
332 | return AE_NOT_EXIST; | ||
333 | |||
334 | mutex_lock(&osc_lock); | ||
335 | /* No need to evaluate _OSC if the control was already granted. */ | ||
336 | if ((root->osc_control_set & control_req) == control_req) | ||
337 | goto out; | ||
338 | |||
339 | /* Need to query controls first before requesting them */ | ||
340 | if (!root->osc_queried) { | ||
341 | status = acpi_pci_query_osc(root, root->osc_support_set); | ||
342 | if (ACPI_FAILURE(status)) | ||
343 | goto out; | ||
344 | } | ||
345 | if ((root->osc_control_qry & control_req) != control_req) { | ||
346 | printk(KERN_DEBUG | ||
347 | "Firmware did not grant requested _OSC control\n"); | ||
348 | status = AE_SUPPORT; | ||
349 | goto out; | ||
350 | } | ||
351 | |||
352 | capbuf[OSC_QUERY_TYPE] = 0; | ||
353 | capbuf[OSC_SUPPORT_TYPE] = root->osc_support_set; | ||
354 | capbuf[OSC_CONTROL_TYPE] = root->osc_control_set | control_req; | ||
355 | status = acpi_pci_run_osc(handle, capbuf, &result); | ||
356 | if (ACPI_SUCCESS(status)) | ||
357 | root->osc_control_set = result; | ||
358 | out: | ||
359 | mutex_unlock(&osc_lock); | ||
360 | return status; | ||
361 | } | ||
362 | EXPORT_SYMBOL(acpi_pci_osc_control_set); | ||
363 | |||
188 | static int __devinit acpi_pci_root_add(struct acpi_device *device) | 364 | static int __devinit acpi_pci_root_add(struct acpi_device *device) |
189 | { | 365 | { |
190 | int result = 0; | 366 | int result = 0; |
@@ -217,7 +393,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
217 | * PCI domains, so we indicate this in _OSC support capabilities. | 393 | * PCI domains, so we indicate this in _OSC support capabilities. |
218 | */ | 394 | */ |
219 | flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; | 395 | flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT; |
220 | pci_acpi_osc_support(device->handle, flags); | 396 | acpi_pci_osc_support(root, flags); |
221 | 397 | ||
222 | /* | 398 | /* |
223 | * Segment | 399 | * Segment |
@@ -353,7 +529,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
353 | if (pci_msi_enabled()) | 529 | if (pci_msi_enabled()) |
354 | flags |= OSC_MSI_SUPPORT; | 530 | flags |= OSC_MSI_SUPPORT; |
355 | if (flags != base_flags) | 531 | if (flags != base_flags) |
356 | pci_acpi_osc_support(device->handle, flags); | 532 | acpi_pci_osc_support(root, flags); |
357 | 533 | ||
358 | end: | 534 | end: |
359 | if (result) { | 535 | if (result) { |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 0cc2fd31e376..fa2f7422d23d 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
@@ -359,7 +359,6 @@ static int acpi_processor_add_fs(struct acpi_device *device) | |||
359 | if (!acpi_device_dir(device)) | 359 | if (!acpi_device_dir(device)) |
360 | return -ENODEV; | 360 | return -ENODEV; |
361 | } | 361 | } |
362 | acpi_device_dir(device)->owner = THIS_MODULE; | ||
363 | 362 | ||
364 | /* 'info' [R] */ | 363 | /* 'info' [R] */ |
365 | entry = proc_create_data(ACPI_PROCESSOR_FILE_INFO, | 364 | entry = proc_create_data(ACPI_PROCESSOR_FILE_INFO, |
@@ -1137,7 +1136,6 @@ static int __init acpi_processor_init(void) | |||
1137 | acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); | 1136 | acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); |
1138 | if (!acpi_processor_dir) | 1137 | if (!acpi_processor_dir) |
1139 | return -ENOMEM; | 1138 | return -ENOMEM; |
1140 | acpi_processor_dir->owner = THIS_MODULE; | ||
1141 | 1139 | ||
1142 | /* | 1140 | /* |
1143 | * Check whether the system is DMI table. If yes, OSPM | 1141 | * Check whether the system is DMI table. If yes, OSPM |
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 6050ce481873..59afd52ccc12 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c | |||
@@ -488,7 +488,6 @@ acpi_sbs_add_fs(struct proc_dir_entry **dir, | |||
488 | if (!*dir) { | 488 | if (!*dir) { |
489 | return -ENODEV; | 489 | return -ENODEV; |
490 | } | 490 | } |
491 | (*dir)->owner = THIS_MODULE; | ||
492 | } | 491 | } |
493 | 492 | ||
494 | /* 'info' [R] */ | 493 | /* 'info' [R] */ |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 99e6f1f8ea45..c11f9aeca706 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -1506,7 +1506,6 @@ static int acpi_thermal_add_fs(struct acpi_device *device) | |||
1506 | acpi_thermal_dir); | 1506 | acpi_thermal_dir); |
1507 | if (!acpi_device_dir(device)) | 1507 | if (!acpi_device_dir(device)) |
1508 | return -ENODEV; | 1508 | return -ENODEV; |
1509 | acpi_device_dir(device)->owner = THIS_MODULE; | ||
1510 | } | 1509 | } |
1511 | 1510 | ||
1512 | /* 'state' [R] */ | 1511 | /* 'state' [R] */ |
@@ -1875,7 +1874,6 @@ static int __init acpi_thermal_init(void) | |||
1875 | acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir); | 1874 | acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir); |
1876 | if (!acpi_thermal_dir) | 1875 | if (!acpi_thermal_dir) |
1877 | return -ENODEV; | 1876 | return -ENODEV; |
1878 | acpi_thermal_dir->owner = THIS_MODULE; | ||
1879 | 1877 | ||
1880 | result = acpi_bus_register_driver(&acpi_thermal_driver); | 1878 | result = acpi_bus_register_driver(&acpi_thermal_driver); |
1881 | if (result < 0) { | 1879 | if (result < 0) { |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index bb5ed059114a..67cc36dc9b82 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -1125,8 +1125,6 @@ static int acpi_video_device_add_fs(struct acpi_device *device) | |||
1125 | if (!device_dir) | 1125 | if (!device_dir) |
1126 | return -ENOMEM; | 1126 | return -ENOMEM; |
1127 | 1127 | ||
1128 | device_dir->owner = THIS_MODULE; | ||
1129 | |||
1130 | /* 'info' [R] */ | 1128 | /* 'info' [R] */ |
1131 | entry = proc_create_data("info", S_IRUGO, device_dir, | 1129 | entry = proc_create_data("info", S_IRUGO, device_dir, |
1132 | &acpi_video_device_info_fops, acpi_driver_data(device)); | 1130 | &acpi_video_device_info_fops, acpi_driver_data(device)); |
@@ -1403,8 +1401,6 @@ static int acpi_video_bus_add_fs(struct acpi_device *device) | |||
1403 | if (!device_dir) | 1401 | if (!device_dir) |
1404 | return -ENOMEM; | 1402 | return -ENOMEM; |
1405 | 1403 | ||
1406 | device_dir->owner = THIS_MODULE; | ||
1407 | |||
1408 | /* 'info' [R] */ | 1404 | /* 'info' [R] */ |
1409 | entry = proc_create_data("info", S_IRUGO, device_dir, | 1405 | entry = proc_create_data("info", S_IRUGO, device_dir, |
1410 | &acpi_video_bus_info_fops, | 1406 | &acpi_video_bus_info_fops, |
@@ -2131,7 +2127,6 @@ static int __init acpi_video_init(void) | |||
2131 | acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); | 2127 | acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir); |
2132 | if (!acpi_video_dir) | 2128 | if (!acpi_video_dir) |
2133 | return -ENODEV; | 2129 | return -ENODEV; |
2134 | acpi_video_dir->owner = THIS_MODULE; | ||
2135 | 2130 | ||
2136 | result = acpi_bus_register_driver(&acpi_video_bus); | 2131 | result = acpi_bus_register_driver(&acpi_video_bus); |
2137 | if (result < 0) { | 2132 | if (result < 0) { |
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig index 14b9d5f4c203..c07e725ea93d 100644 --- a/drivers/auxdisplay/Kconfig +++ b/drivers/auxdisplay/Kconfig | |||
@@ -6,7 +6,6 @@ | |||
6 | # | 6 | # |
7 | 7 | ||
8 | menuconfig AUXDISPLAY | 8 | menuconfig AUXDISPLAY |
9 | depends on PARPORT | ||
10 | bool "Auxiliary Display support" | 9 | bool "Auxiliary Display support" |
11 | ---help--- | 10 | ---help--- |
12 | Say Y here to get to see options for auxiliary display drivers. | 11 | Say Y here to get to see options for auxiliary display drivers. |
@@ -14,7 +13,7 @@ menuconfig AUXDISPLAY | |||
14 | 13 | ||
15 | If you say N, all options in this submenu will be skipped and disabled. | 14 | If you say N, all options in this submenu will be skipped and disabled. |
16 | 15 | ||
17 | if AUXDISPLAY && PARPORT | 16 | if AUXDISPLAY |
18 | 17 | ||
19 | config KS0108 | 18 | config KS0108 |
20 | tristate "KS0108 LCD Controller" | 19 | tristate "KS0108 LCD Controller" |
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 5b257a57bc57..e62a4ccea54d 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -119,7 +119,7 @@ static ssize_t print_cpus_map(char *buf, const struct cpumask *map) | |||
119 | #define print_cpus_func(type) \ | 119 | #define print_cpus_func(type) \ |
120 | static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \ | 120 | static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \ |
121 | { \ | 121 | { \ |
122 | return print_cpus_map(buf, &cpu_##type##_map); \ | 122 | return print_cpus_map(buf, cpu_##type##_mask); \ |
123 | } \ | 123 | } \ |
124 | static struct sysdev_class_attribute attr_##type##_map = \ | 124 | static struct sysdev_class_attribute attr_##type##_map = \ |
125 | _SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL) | 125 | _SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL) |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 2621ed2ce6d2..40b17d3b55a1 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -1192,6 +1192,30 @@ loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg) { | |||
1192 | return err; | 1192 | return err; |
1193 | } | 1193 | } |
1194 | 1194 | ||
1195 | static int loop_set_capacity(struct loop_device *lo, struct block_device *bdev) | ||
1196 | { | ||
1197 | int err; | ||
1198 | sector_t sec; | ||
1199 | loff_t sz; | ||
1200 | |||
1201 | err = -ENXIO; | ||
1202 | if (unlikely(lo->lo_state != Lo_bound)) | ||
1203 | goto out; | ||
1204 | err = figure_loop_size(lo); | ||
1205 | if (unlikely(err)) | ||
1206 | goto out; | ||
1207 | sec = get_capacity(lo->lo_disk); | ||
1208 | /* the width of sector_t may be narrow for bit-shift */ | ||
1209 | sz = sec; | ||
1210 | sz <<= 9; | ||
1211 | mutex_lock(&bdev->bd_mutex); | ||
1212 | bd_set_size(bdev, sz); | ||
1213 | mutex_unlock(&bdev->bd_mutex); | ||
1214 | |||
1215 | out: | ||
1216 | return err; | ||
1217 | } | ||
1218 | |||
1195 | static int lo_ioctl(struct block_device *bdev, fmode_t mode, | 1219 | static int lo_ioctl(struct block_device *bdev, fmode_t mode, |
1196 | unsigned int cmd, unsigned long arg) | 1220 | unsigned int cmd, unsigned long arg) |
1197 | { | 1221 | { |
@@ -1224,6 +1248,11 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, | |||
1224 | case LOOP_GET_STATUS64: | 1248 | case LOOP_GET_STATUS64: |
1225 | err = loop_get_status64(lo, (struct loop_info64 __user *) arg); | 1249 | err = loop_get_status64(lo, (struct loop_info64 __user *) arg); |
1226 | break; | 1250 | break; |
1251 | case LOOP_SET_CAPACITY: | ||
1252 | err = -EPERM; | ||
1253 | if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) | ||
1254 | err = loop_set_capacity(lo, bdev); | ||
1255 | break; | ||
1227 | default: | 1256 | default: |
1228 | err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; | 1257 | err = lo->ioctl ? lo->ioctl(lo, cmd, arg) : -EINVAL; |
1229 | } | 1258 | } |
@@ -1371,6 +1400,7 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode, | |||
1371 | lo, (struct compat_loop_info __user *) arg); | 1400 | lo, (struct compat_loop_info __user *) arg); |
1372 | mutex_unlock(&lo->lo_ctl_mutex); | 1401 | mutex_unlock(&lo->lo_ctl_mutex); |
1373 | break; | 1402 | break; |
1403 | case LOOP_SET_CAPACITY: | ||
1374 | case LOOP_CLR_FD: | 1404 | case LOOP_CLR_FD: |
1375 | case LOOP_GET_STATUS64: | 1405 | case LOOP_GET_STATUS64: |
1376 | case LOOP_SET_STATUS64: | 1406 | case LOOP_SET_STATUS64: |
diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c index 393ed6760d78..8eddef373a91 100644 --- a/drivers/block/ps3vram.c +++ b/drivers/block/ps3vram.c | |||
@@ -551,8 +551,6 @@ static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev) | |||
551 | dev_warn(&dev->core, "failed to create /proc entry\n"); | 551 | dev_warn(&dev->core, "failed to create /proc entry\n"); |
552 | return; | 552 | return; |
553 | } | 553 | } |
554 | |||
555 | pde->owner = THIS_MODULE; | ||
556 | pde->data = priv; | 554 | pde->data = priv; |
557 | } | 555 | } |
558 | 556 | ||
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index a58869ea8513..fd3ebd1be570 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -79,6 +79,7 @@ static char *serial_version = "4.30"; | |||
79 | #include <linux/ptrace.h> | 79 | #include <linux/ptrace.h> |
80 | #include <linux/ioport.h> | 80 | #include <linux/ioport.h> |
81 | #include <linux/mm.h> | 81 | #include <linux/mm.h> |
82 | #include <linux/seq_file.h> | ||
82 | #include <linux/slab.h> | 83 | #include <linux/slab.h> |
83 | #include <linux/init.h> | 84 | #include <linux/init.h> |
84 | #include <linux/bitops.h> | 85 | #include <linux/bitops.h> |
@@ -1825,14 +1826,13 @@ static int rs_open(struct tty_struct *tty, struct file * filp) | |||
1825 | * /proc fs routines.... | 1826 | * /proc fs routines.... |
1826 | */ | 1827 | */ |
1827 | 1828 | ||
1828 | static inline int line_info(char *buf, struct serial_state *state) | 1829 | static inline void line_info(struct seq_file *m, struct serial_state *state) |
1829 | { | 1830 | { |
1830 | struct async_struct *info = state->info, scr_info; | 1831 | struct async_struct *info = state->info, scr_info; |
1831 | char stat_buf[30], control, status; | 1832 | char stat_buf[30], control, status; |
1832 | int ret; | ||
1833 | unsigned long flags; | 1833 | unsigned long flags; |
1834 | 1834 | ||
1835 | ret = sprintf(buf, "%d: uart:amiga_builtin",state->line); | 1835 | seq_printf(m, "%d: uart:amiga_builtin",state->line); |
1836 | 1836 | ||
1837 | /* | 1837 | /* |
1838 | * Figure out the current RS-232 lines | 1838 | * Figure out the current RS-232 lines |
@@ -1864,55 +1864,49 @@ static inline int line_info(char *buf, struct serial_state *state) | |||
1864 | strcat(stat_buf, "|CD"); | 1864 | strcat(stat_buf, "|CD"); |
1865 | 1865 | ||
1866 | if (info->quot) { | 1866 | if (info->quot) { |
1867 | ret += sprintf(buf+ret, " baud:%d", | 1867 | seq_printf(m, " baud:%d", state->baud_base / info->quot); |
1868 | state->baud_base / info->quot); | ||
1869 | } | 1868 | } |
1870 | 1869 | ||
1871 | ret += sprintf(buf+ret, " tx:%d rx:%d", | 1870 | seq_printf(m, " tx:%d rx:%d", state->icount.tx, state->icount.rx); |
1872 | state->icount.tx, state->icount.rx); | ||
1873 | 1871 | ||
1874 | if (state->icount.frame) | 1872 | if (state->icount.frame) |
1875 | ret += sprintf(buf+ret, " fe:%d", state->icount.frame); | 1873 | seq_printf(m, " fe:%d", state->icount.frame); |
1876 | 1874 | ||
1877 | if (state->icount.parity) | 1875 | if (state->icount.parity) |
1878 | ret += sprintf(buf+ret, " pe:%d", state->icount.parity); | 1876 | seq_printf(m, " pe:%d", state->icount.parity); |
1879 | 1877 | ||
1880 | if (state->icount.brk) | 1878 | if (state->icount.brk) |
1881 | ret += sprintf(buf+ret, " brk:%d", state->icount.brk); | 1879 | seq_printf(m, " brk:%d", state->icount.brk); |
1882 | 1880 | ||
1883 | if (state->icount.overrun) | 1881 | if (state->icount.overrun) |
1884 | ret += sprintf(buf+ret, " oe:%d", state->icount.overrun); | 1882 | seq_printf(m, " oe:%d", state->icount.overrun); |
1885 | 1883 | ||
1886 | /* | 1884 | /* |
1887 | * Last thing is the RS-232 status lines | 1885 | * Last thing is the RS-232 status lines |
1888 | */ | 1886 | */ |
1889 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 1887 | seq_printf(m, " %s\n", stat_buf+1); |
1890 | return ret; | ||
1891 | } | 1888 | } |
1892 | 1889 | ||
1893 | static int rs_read_proc(char *page, char **start, off_t off, int count, | 1890 | static int rs_proc_show(struct seq_file *m, void *v) |
1894 | int *eof, void *data) | ||
1895 | { | 1891 | { |
1896 | int len = 0, l; | 1892 | seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version); |
1897 | off_t begin = 0; | 1893 | line_info(m, &rs_table[0]); |
1898 | 1894 | return 0; | |
1899 | len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version); | ||
1900 | l = line_info(page + len, &rs_table[0]); | ||
1901 | len += l; | ||
1902 | if (len+begin > off+count) | ||
1903 | goto done; | ||
1904 | if (len+begin < off) { | ||
1905 | begin += len; | ||
1906 | len = 0; | ||
1907 | } | ||
1908 | *eof = 1; | ||
1909 | done: | ||
1910 | if (off >= len+begin) | ||
1911 | return 0; | ||
1912 | *start = page + (off-begin); | ||
1913 | return ((count < begin+len-off) ? count : begin+len-off); | ||
1914 | } | 1895 | } |
1915 | 1896 | ||
1897 | static int rs_proc_open(struct inode *inode, struct file *file) | ||
1898 | { | ||
1899 | return single_open(file, rs_proc_show, NULL); | ||
1900 | } | ||
1901 | |||
1902 | static const struct file_operations rs_proc_fops = { | ||
1903 | .owner = THIS_MODULE, | ||
1904 | .open = rs_proc_open, | ||
1905 | .read = seq_read, | ||
1906 | .llseek = seq_lseek, | ||
1907 | .release = single_release, | ||
1908 | }; | ||
1909 | |||
1916 | /* | 1910 | /* |
1917 | * --------------------------------------------------------------------- | 1911 | * --------------------------------------------------------------------- |
1918 | * rs_init() and friends | 1912 | * rs_init() and friends |
@@ -1951,9 +1945,9 @@ static const struct tty_operations serial_ops = { | |||
1951 | .break_ctl = rs_break, | 1945 | .break_ctl = rs_break, |
1952 | .send_xchar = rs_send_xchar, | 1946 | .send_xchar = rs_send_xchar, |
1953 | .wait_until_sent = rs_wait_until_sent, | 1947 | .wait_until_sent = rs_wait_until_sent, |
1954 | .read_proc = rs_read_proc, | ||
1955 | .tiocmget = rs_tiocmget, | 1948 | .tiocmget = rs_tiocmget, |
1956 | .tiocmset = rs_tiocmset, | 1949 | .tiocmset = rs_tiocmset, |
1950 | .proc_fops = &rs_proc_fops, | ||
1957 | }; | 1951 | }; |
1958 | 1952 | ||
1959 | /* | 1953 | /* |
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 6a59f72a9c21..272db0e2b491 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -657,6 +657,7 @@ | |||
657 | 657 | ||
658 | #include <linux/stat.h> | 658 | #include <linux/stat.h> |
659 | #include <linux/proc_fs.h> | 659 | #include <linux/proc_fs.h> |
660 | #include <linux/seq_file.h> | ||
660 | 661 | ||
661 | static void cy_throttle(struct tty_struct *tty); | 662 | static void cy_throttle(struct tty_struct *tty); |
662 | static void cy_send_xchar(struct tty_struct *tty, char ch); | 663 | static void cy_send_xchar(struct tty_struct *tty, char ch); |
@@ -868,8 +869,6 @@ static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32); | |||
868 | static unsigned detect_isa_irq(void __iomem *); | 869 | static unsigned detect_isa_irq(void __iomem *); |
869 | #endif /* CONFIG_ISA */ | 870 | #endif /* CONFIG_ISA */ |
870 | 871 | ||
871 | static int cyclades_get_proc_info(char *, char **, off_t, int, int *, void *); | ||
872 | |||
873 | #ifndef CONFIG_CYZ_INTR | 872 | #ifndef CONFIG_CYZ_INTR |
874 | static void cyz_poll(unsigned long); | 873 | static void cyz_poll(unsigned long); |
875 | 874 | ||
@@ -5216,31 +5215,22 @@ static struct pci_driver cy_pci_driver = { | |||
5216 | }; | 5215 | }; |
5217 | #endif | 5216 | #endif |
5218 | 5217 | ||
5219 | static int | 5218 | static int cyclades_proc_show(struct seq_file *m, void *v) |
5220 | cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, | ||
5221 | int *eof, void *data) | ||
5222 | { | 5219 | { |
5223 | struct cyclades_port *info; | 5220 | struct cyclades_port *info; |
5224 | unsigned int i, j; | 5221 | unsigned int i, j; |
5225 | int len = 0; | ||
5226 | off_t begin = 0; | ||
5227 | off_t pos = 0; | ||
5228 | int size; | ||
5229 | __u32 cur_jifs = jiffies; | 5222 | __u32 cur_jifs = jiffies; |
5230 | 5223 | ||
5231 | size = sprintf(buf, "Dev TimeOpen BytesOut IdleOut BytesIn " | 5224 | seq_puts(m, "Dev TimeOpen BytesOut IdleOut BytesIn " |
5232 | "IdleIn Overruns Ldisc\n"); | 5225 | "IdleIn Overruns Ldisc\n"); |
5233 | 5226 | ||
5234 | pos += size; | ||
5235 | len += size; | ||
5236 | |||
5237 | /* Output one line for each known port */ | 5227 | /* Output one line for each known port */ |
5238 | for (i = 0; i < NR_CARDS; i++) | 5228 | for (i = 0; i < NR_CARDS; i++) |
5239 | for (j = 0; j < cy_card[i].nports; j++) { | 5229 | for (j = 0; j < cy_card[i].nports; j++) { |
5240 | info = &cy_card[i].ports[j]; | 5230 | info = &cy_card[i].ports[j]; |
5241 | 5231 | ||
5242 | if (info->port.count) | 5232 | if (info->port.count) |
5243 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu " | 5233 | seq_printf(m, "%3d %8lu %10lu %8lu " |
5244 | "%10lu %8lu %9lu %6ld\n", info->line, | 5234 | "%10lu %8lu %9lu %6ld\n", info->line, |
5245 | (cur_jifs - info->idle_stats.in_use) / | 5235 | (cur_jifs - info->idle_stats.in_use) / |
5246 | HZ, info->idle_stats.xmit_bytes, | 5236 | HZ, info->idle_stats.xmit_bytes, |
@@ -5251,30 +5241,26 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, | |||
5251 | /* FIXME: double check locking */ | 5241 | /* FIXME: double check locking */ |
5252 | (long)info->port.tty->ldisc.ops->num); | 5242 | (long)info->port.tty->ldisc.ops->num); |
5253 | else | 5243 | else |
5254 | size = sprintf(buf + len, "%3d %8lu %10lu %8lu " | 5244 | seq_printf(m, "%3d %8lu %10lu %8lu " |
5255 | "%10lu %8lu %9lu %6ld\n", | 5245 | "%10lu %8lu %9lu %6ld\n", |
5256 | info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); | 5246 | info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); |
5257 | len += size; | ||
5258 | pos = begin + len; | ||
5259 | |||
5260 | if (pos < offset) { | ||
5261 | len = 0; | ||
5262 | begin = pos; | ||
5263 | } | ||
5264 | if (pos > offset + length) | ||
5265 | goto done; | ||
5266 | } | 5247 | } |
5267 | *eof = 1; | 5248 | return 0; |
5268 | done: | 5249 | } |
5269 | *start = buf + (offset - begin); /* Start of wanted data */ | 5250 | |
5270 | len -= (offset - begin); /* Start slop */ | 5251 | static int cyclades_proc_open(struct inode *inode, struct file *file) |
5271 | if (len > length) | 5252 | { |
5272 | len = length; /* Ending slop */ | 5253 | return single_open(file, cyclades_proc_show, NULL); |
5273 | if (len < 0) | ||
5274 | len = 0; | ||
5275 | return len; | ||
5276 | } | 5254 | } |
5277 | 5255 | ||
5256 | static const struct file_operations cyclades_proc_fops = { | ||
5257 | .owner = THIS_MODULE, | ||
5258 | .open = cyclades_proc_open, | ||
5259 | .read = seq_read, | ||
5260 | .llseek = seq_lseek, | ||
5261 | .release = single_release, | ||
5262 | }; | ||
5263 | |||
5278 | /* The serial driver boot-time initialization code! | 5264 | /* The serial driver boot-time initialization code! |
5279 | Hardware I/O ports are mapped to character special devices on a | 5265 | Hardware I/O ports are mapped to character special devices on a |
5280 | first found, first allocated manner. That is, this code searches | 5266 | first found, first allocated manner. That is, this code searches |
@@ -5311,9 +5297,9 @@ static const struct tty_operations cy_ops = { | |||
5311 | .hangup = cy_hangup, | 5297 | .hangup = cy_hangup, |
5312 | .break_ctl = cy_break, | 5298 | .break_ctl = cy_break, |
5313 | .wait_until_sent = cy_wait_until_sent, | 5299 | .wait_until_sent = cy_wait_until_sent, |
5314 | .read_proc = cyclades_get_proc_info, | ||
5315 | .tiocmget = cy_tiocmget, | 5300 | .tiocmget = cy_tiocmget, |
5316 | .tiocmset = cy_tiocmset, | 5301 | .tiocmset = cy_tiocmset, |
5302 | .proc_fops = &cyclades_proc_fops, | ||
5317 | }; | 5303 | }; |
5318 | 5304 | ||
5319 | static int __init cy_init(void) | 5305 | static int __init cy_init(void) |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 70e0ebc30bd0..afd9247cf082 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -139,7 +139,7 @@ | |||
139 | #include <linux/seq_file.h> | 139 | #include <linux/seq_file.h> |
140 | 140 | ||
141 | static const struct file_operations ip2mem_proc_fops; | 141 | static const struct file_operations ip2mem_proc_fops; |
142 | static int ip2_read_proc(char *, char **, off_t, int, int *, void * ); | 142 | static const struct file_operations ip2_proc_fops; |
143 | 143 | ||
144 | /********************/ | 144 | /********************/ |
145 | /* Type Definitions */ | 145 | /* Type Definitions */ |
@@ -446,9 +446,9 @@ static const struct tty_operations ip2_ops = { | |||
446 | .stop = ip2_stop, | 446 | .stop = ip2_stop, |
447 | .start = ip2_start, | 447 | .start = ip2_start, |
448 | .hangup = ip2_hangup, | 448 | .hangup = ip2_hangup, |
449 | .read_proc = ip2_read_proc, | ||
450 | .tiocmget = ip2_tiocmget, | 449 | .tiocmget = ip2_tiocmget, |
451 | .tiocmset = ip2_tiocmset, | 450 | .tiocmset = ip2_tiocmset, |
451 | .proc_fops = &ip2_proc_fops, | ||
452 | }; | 452 | }; |
453 | 453 | ||
454 | /******************************************************************************/ | 454 | /******************************************************************************/ |
@@ -3029,19 +3029,17 @@ static const struct file_operations ip2mem_proc_fops = { | |||
3029 | * different sources including ip2mkdev.c and a couple of other drivers. | 3029 | * different sources including ip2mkdev.c and a couple of other drivers. |
3030 | * The bugs are all mine. :-) =mhw= | 3030 | * The bugs are all mine. :-) =mhw= |
3031 | */ | 3031 | */ |
3032 | static int ip2_read_proc(char *page, char **start, off_t off, | 3032 | static int ip2_proc_show(struct seq_file *m, void *v) |
3033 | int count, int *eof, void *data) | ||
3034 | { | 3033 | { |
3035 | int i, j, box; | 3034 | int i, j, box; |
3036 | int len = 0; | ||
3037 | int boxes = 0; | 3035 | int boxes = 0; |
3038 | int ports = 0; | 3036 | int ports = 0; |
3039 | int tports = 0; | 3037 | int tports = 0; |
3040 | off_t begin = 0; | ||
3041 | i2eBordStrPtr pB; | 3038 | i2eBordStrPtr pB; |
3039 | char *sep; | ||
3042 | 3040 | ||
3043 | len += sprintf(page, "ip2info: 1.0 driver: %s\n", pcVersion ); | 3041 | seq_printf(m, "ip2info: 1.0 driver: %s\n", pcVersion); |
3044 | len += sprintf(page+len, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n", | 3042 | seq_printf(m, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n", |
3045 | IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR, | 3043 | IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR, |
3046 | IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX); | 3044 | IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX); |
3047 | 3045 | ||
@@ -3053,7 +3051,8 @@ static int ip2_read_proc(char *page, char **start, off_t off, | |||
3053 | switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) | 3051 | switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) |
3054 | { | 3052 | { |
3055 | case POR_ID_FIIEX: | 3053 | case POR_ID_FIIEX: |
3056 | len += sprintf( page+len, "Board %d: EX ports=", i ); | 3054 | seq_printf(m, "Board %d: EX ports=", i); |
3055 | sep = ""; | ||
3057 | for( box = 0; box < ABS_MAX_BOXES; ++box ) | 3056 | for( box = 0; box < ABS_MAX_BOXES; ++box ) |
3058 | { | 3057 | { |
3059 | ports = 0; | 3058 | ports = 0; |
@@ -3065,79 +3064,74 @@ static int ip2_read_proc(char *page, char **start, off_t off, | |||
3065 | ++ports; | 3064 | ++ports; |
3066 | } | 3065 | } |
3067 | } | 3066 | } |
3068 | len += sprintf( page+len, "%d,", ports ); | 3067 | seq_printf(m, "%s%d", sep, ports); |
3068 | sep = ","; | ||
3069 | tports += ports; | 3069 | tports += ports; |
3070 | } | 3070 | } |
3071 | 3071 | seq_printf(m, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8); | |
3072 | --len; /* Backup over that last comma */ | ||
3073 | |||
3074 | len += sprintf( page+len, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8 ); | ||
3075 | break; | 3072 | break; |
3076 | 3073 | ||
3077 | case POR_ID_II_4: | 3074 | case POR_ID_II_4: |
3078 | len += sprintf(page+len, "Board %d: ISA-4 ports=4 boxes=1", i ); | 3075 | seq_printf(m, "Board %d: ISA-4 ports=4 boxes=1", i); |
3079 | tports = ports = 4; | 3076 | tports = ports = 4; |
3080 | break; | 3077 | break; |
3081 | 3078 | ||
3082 | case POR_ID_II_8: | 3079 | case POR_ID_II_8: |
3083 | len += sprintf(page+len, "Board %d: ISA-8-std ports=8 boxes=1", i ); | 3080 | seq_printf(m, "Board %d: ISA-8-std ports=8 boxes=1", i); |
3084 | tports = ports = 8; | 3081 | tports = ports = 8; |
3085 | break; | 3082 | break; |
3086 | 3083 | ||
3087 | case POR_ID_II_8R: | 3084 | case POR_ID_II_8R: |
3088 | len += sprintf(page+len, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i ); | 3085 | seq_printf(m, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i); |
3089 | tports = ports = 8; | 3086 | tports = ports = 8; |
3090 | break; | 3087 | break; |
3091 | 3088 | ||
3092 | default: | 3089 | default: |
3093 | len += sprintf(page+len, "Board %d: unknown", i ); | 3090 | seq_printf(m, "Board %d: unknown", i); |
3094 | /* Don't try and probe for minor numbers */ | 3091 | /* Don't try and probe for minor numbers */ |
3095 | tports = ports = 0; | 3092 | tports = ports = 0; |
3096 | } | 3093 | } |
3097 | 3094 | ||
3098 | } else { | 3095 | } else { |
3099 | /* Don't try and probe for minor numbers */ | 3096 | /* Don't try and probe for minor numbers */ |
3100 | len += sprintf(page+len, "Board %d: vacant", i ); | 3097 | seq_printf(m, "Board %d: vacant", i); |
3101 | tports = ports = 0; | 3098 | tports = ports = 0; |
3102 | } | 3099 | } |
3103 | 3100 | ||
3104 | if( tports ) { | 3101 | if( tports ) { |
3105 | len += sprintf(page+len, " minors=" ); | 3102 | seq_puts(m, " minors="); |
3106 | 3103 | sep = ""; | |
3107 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) | 3104 | for ( box = 0; box < ABS_MAX_BOXES; ++box ) |
3108 | { | 3105 | { |
3109 | for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) | 3106 | for ( j = 0; j < ABS_BIGGEST_BOX; ++j ) |
3110 | { | 3107 | { |
3111 | if ( pB->i2eChannelMap[box] & (1 << j) ) | 3108 | if ( pB->i2eChannelMap[box] & (1 << j) ) |
3112 | { | 3109 | { |
3113 | len += sprintf (page+len,"%d,", | 3110 | seq_printf(m, "%s%d", sep, |
3114 | j + ABS_BIGGEST_BOX * | 3111 | j + ABS_BIGGEST_BOX * |
3115 | (box+i*ABS_MAX_BOXES)); | 3112 | (box+i*ABS_MAX_BOXES)); |
3113 | sep = ","; | ||
3116 | } | 3114 | } |
3117 | } | 3115 | } |
3118 | } | 3116 | } |
3119 | |||
3120 | page[ len - 1 ] = '\n'; /* Overwrite that last comma */ | ||
3121 | } else { | ||
3122 | len += sprintf (page+len,"\n" ); | ||
3123 | } | ||
3124 | |||
3125 | if (len+begin > off+count) | ||
3126 | break; | ||
3127 | if (len+begin < off) { | ||
3128 | begin += len; | ||
3129 | len = 0; | ||
3130 | } | 3117 | } |
3118 | seq_putc(m, '\n'); | ||
3131 | } | 3119 | } |
3120 | return 0; | ||
3121 | } | ||
3132 | 3122 | ||
3133 | if (i >= IP2_MAX_BOARDS) | 3123 | static int ip2_proc_open(struct inode *inode, struct file *file) |
3134 | *eof = 1; | 3124 | { |
3135 | if (off >= len+begin) | 3125 | return single_open(file, ip2_proc_show, NULL); |
3136 | return 0; | 3126 | } |
3137 | 3127 | ||
3138 | *start = page + (off-begin); | 3128 | static const struct file_operations ip2_proc_fops = { |
3139 | return ((count < begin+len-off) ? count : begin+len-off); | 3129 | .owner = THIS_MODULE, |
3140 | } | 3130 | .open = ip2_proc_open, |
3131 | .read = seq_read, | ||
3132 | .llseek = seq_lseek, | ||
3133 | .release = single_release, | ||
3134 | }; | ||
3141 | 3135 | ||
3142 | /******************************************************************************/ | 3136 | /******************************************************************************/ |
3143 | /* Function: ip2trace() */ | 3137 | /* Function: ip2trace() */ |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 7a88dfd4427b..e93fc8d22fb2 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -1944,7 +1944,7 @@ static int stat_file_read_proc(char *page, char **start, off_t off, | |||
1944 | 1944 | ||
1945 | int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, | 1945 | int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, |
1946 | read_proc_t *read_proc, | 1946 | read_proc_t *read_proc, |
1947 | void *data, struct module *owner) | 1947 | void *data) |
1948 | { | 1948 | { |
1949 | int rv = 0; | 1949 | int rv = 0; |
1950 | #ifdef CONFIG_PROC_FS | 1950 | #ifdef CONFIG_PROC_FS |
@@ -1970,7 +1970,6 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name, | |||
1970 | } else { | 1970 | } else { |
1971 | file->data = data; | 1971 | file->data = data; |
1972 | file->read_proc = read_proc; | 1972 | file->read_proc = read_proc; |
1973 | file->owner = owner; | ||
1974 | 1973 | ||
1975 | mutex_lock(&smi->proc_entry_lock); | 1974 | mutex_lock(&smi->proc_entry_lock); |
1976 | /* Stick it on the list. */ | 1975 | /* Stick it on the list. */ |
@@ -1993,23 +1992,21 @@ static int add_proc_entries(ipmi_smi_t smi, int num) | |||
1993 | smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root); | 1992 | smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root); |
1994 | if (!smi->proc_dir) | 1993 | if (!smi->proc_dir) |
1995 | rv = -ENOMEM; | 1994 | rv = -ENOMEM; |
1996 | else | ||
1997 | smi->proc_dir->owner = THIS_MODULE; | ||
1998 | 1995 | ||
1999 | if (rv == 0) | 1996 | if (rv == 0) |
2000 | rv = ipmi_smi_add_proc_entry(smi, "stats", | 1997 | rv = ipmi_smi_add_proc_entry(smi, "stats", |
2001 | stat_file_read_proc, | 1998 | stat_file_read_proc, |
2002 | smi, THIS_MODULE); | 1999 | smi); |
2003 | 2000 | ||
2004 | if (rv == 0) | 2001 | if (rv == 0) |
2005 | rv = ipmi_smi_add_proc_entry(smi, "ipmb", | 2002 | rv = ipmi_smi_add_proc_entry(smi, "ipmb", |
2006 | ipmb_file_read_proc, | 2003 | ipmb_file_read_proc, |
2007 | smi, THIS_MODULE); | 2004 | smi); |
2008 | 2005 | ||
2009 | if (rv == 0) | 2006 | if (rv == 0) |
2010 | rv = ipmi_smi_add_proc_entry(smi, "version", | 2007 | rv = ipmi_smi_add_proc_entry(smi, "version", |
2011 | version_file_read_proc, | 2008 | version_file_read_proc, |
2012 | smi, THIS_MODULE); | 2009 | smi); |
2013 | #endif /* CONFIG_PROC_FS */ | 2010 | #endif /* CONFIG_PROC_FS */ |
2014 | 2011 | ||
2015 | return rv; | 2012 | return rv; |
@@ -4265,7 +4262,6 @@ static int ipmi_init_msghandler(void) | |||
4265 | return -ENOMEM; | 4262 | return -ENOMEM; |
4266 | } | 4263 | } |
4267 | 4264 | ||
4268 | proc_ipmi_root->owner = THIS_MODULE; | ||
4269 | #endif /* CONFIG_PROC_FS */ | 4265 | #endif /* CONFIG_PROC_FS */ |
4270 | 4266 | ||
4271 | setup_timer(&ipmi_timer, ipmi_timeout, 0); | 4267 | setup_timer(&ipmi_timer, ipmi_timeout, 0); |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 3000135f2ead..e58ea4cd55ce 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -2899,7 +2899,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2899 | 2899 | ||
2900 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "type", | 2900 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "type", |
2901 | type_file_read_proc, | 2901 | type_file_read_proc, |
2902 | new_smi, THIS_MODULE); | 2902 | new_smi); |
2903 | if (rv) { | 2903 | if (rv) { |
2904 | printk(KERN_ERR | 2904 | printk(KERN_ERR |
2905 | "ipmi_si: Unable to create proc entry: %d\n", | 2905 | "ipmi_si: Unable to create proc entry: %d\n", |
@@ -2909,7 +2909,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2909 | 2909 | ||
2910 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats", | 2910 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "si_stats", |
2911 | stat_file_read_proc, | 2911 | stat_file_read_proc, |
2912 | new_smi, THIS_MODULE); | 2912 | new_smi); |
2913 | if (rv) { | 2913 | if (rv) { |
2914 | printk(KERN_ERR | 2914 | printk(KERN_ERR |
2915 | "ipmi_si: Unable to create proc entry: %d\n", | 2915 | "ipmi_si: Unable to create proc entry: %d\n", |
@@ -2919,7 +2919,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2919 | 2919 | ||
2920 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "params", | 2920 | rv = ipmi_smi_add_proc_entry(new_smi->intf, "params", |
2921 | param_read_proc, | 2921 | param_read_proc, |
2922 | new_smi, THIS_MODULE); | 2922 | new_smi); |
2923 | if (rv) { | 2923 | if (rv) { |
2924 | printk(KERN_ERR | 2924 | printk(KERN_ERR |
2925 | "ipmi_si: Unable to create proc entry: %d\n", | 2925 | "ipmi_si: Unable to create proc entry: %d\n", |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 5c3dc6b8411c..fff19f7e29d2 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/tty.h> | 24 | #include <linux/tty.h> |
25 | #include <linux/tty_flip.h> | 25 | #include <linux/tty_flip.h> |
26 | #include <linux/serial.h> | 26 | #include <linux/serial.h> |
27 | #include <linux/seq_file.h> | ||
27 | #include <linux/cdk.h> | 28 | #include <linux/cdk.h> |
28 | #include <linux/comstats.h> | 29 | #include <linux/comstats.h> |
29 | #include <linux/istallion.h> | 30 | #include <linux/istallion.h> |
@@ -613,7 +614,6 @@ static int stli_breakctl(struct tty_struct *tty, int state); | |||
613 | static void stli_waituntilsent(struct tty_struct *tty, int timeout); | 614 | static void stli_waituntilsent(struct tty_struct *tty, int timeout); |
614 | static void stli_sendxchar(struct tty_struct *tty, char ch); | 615 | static void stli_sendxchar(struct tty_struct *tty, char ch); |
615 | static void stli_hangup(struct tty_struct *tty); | 616 | static void stli_hangup(struct tty_struct *tty); |
616 | static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos); | ||
617 | 617 | ||
618 | static int stli_brdinit(struct stlibrd *brdp); | 618 | static int stli_brdinit(struct stlibrd *brdp); |
619 | static int stli_startbrd(struct stlibrd *brdp); | 619 | static int stli_startbrd(struct stlibrd *brdp); |
@@ -1893,20 +1893,10 @@ static void stli_sendxchar(struct tty_struct *tty, char ch) | |||
1893 | stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0); | 1893 | stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0); |
1894 | } | 1894 | } |
1895 | 1895 | ||
1896 | /*****************************************************************************/ | 1896 | static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stliport *portp, int portnr) |
1897 | |||
1898 | #define MAXLINE 80 | ||
1899 | |||
1900 | /* | ||
1901 | * Format info for a specified port. The line is deliberately limited | ||
1902 | * to 80 characters. (If it is too long it will be truncated, if too | ||
1903 | * short then padded with spaces). | ||
1904 | */ | ||
1905 | |||
1906 | static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos) | ||
1907 | { | 1897 | { |
1908 | char *sp, *uart; | 1898 | char *uart; |
1909 | int rc, cnt; | 1899 | int rc; |
1910 | 1900 | ||
1911 | rc = stli_portcmdstats(NULL, portp); | 1901 | rc = stli_portcmdstats(NULL, portp); |
1912 | 1902 | ||
@@ -1918,44 +1908,50 @@ static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portn | |||
1918 | default:uart = "CD1400"; break; | 1908 | default:uart = "CD1400"; break; |
1919 | } | 1909 | } |
1920 | } | 1910 | } |
1921 | 1911 | seq_printf(m, "%d: uart:%s ", portnr, uart); | |
1922 | sp = pos; | ||
1923 | sp += sprintf(sp, "%d: uart:%s ", portnr, uart); | ||
1924 | 1912 | ||
1925 | if ((brdp->state & BST_STARTED) && (rc >= 0)) { | 1913 | if ((brdp->state & BST_STARTED) && (rc >= 0)) { |
1926 | sp += sprintf(sp, "tx:%d rx:%d", (int) stli_comstats.txtotal, | 1914 | char sep; |
1915 | |||
1916 | seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal, | ||
1927 | (int) stli_comstats.rxtotal); | 1917 | (int) stli_comstats.rxtotal); |
1928 | 1918 | ||
1929 | if (stli_comstats.rxframing) | 1919 | if (stli_comstats.rxframing) |
1930 | sp += sprintf(sp, " fe:%d", | 1920 | seq_printf(m, " fe:%d", |
1931 | (int) stli_comstats.rxframing); | 1921 | (int) stli_comstats.rxframing); |
1932 | if (stli_comstats.rxparity) | 1922 | if (stli_comstats.rxparity) |
1933 | sp += sprintf(sp, " pe:%d", | 1923 | seq_printf(m, " pe:%d", |
1934 | (int) stli_comstats.rxparity); | 1924 | (int) stli_comstats.rxparity); |
1935 | if (stli_comstats.rxbreaks) | 1925 | if (stli_comstats.rxbreaks) |
1936 | sp += sprintf(sp, " brk:%d", | 1926 | seq_printf(m, " brk:%d", |
1937 | (int) stli_comstats.rxbreaks); | 1927 | (int) stli_comstats.rxbreaks); |
1938 | if (stli_comstats.rxoverrun) | 1928 | if (stli_comstats.rxoverrun) |
1939 | sp += sprintf(sp, " oe:%d", | 1929 | seq_printf(m, " oe:%d", |
1940 | (int) stli_comstats.rxoverrun); | 1930 | (int) stli_comstats.rxoverrun); |
1941 | 1931 | ||
1942 | cnt = sprintf(sp, "%s%s%s%s%s ", | 1932 | sep = ' '; |
1943 | (stli_comstats.signals & TIOCM_RTS) ? "|RTS" : "", | 1933 | if (stli_comstats.signals & TIOCM_RTS) { |
1944 | (stli_comstats.signals & TIOCM_CTS) ? "|CTS" : "", | 1934 | seq_printf(m, "%c%s", sep, "RTS"); |
1945 | (stli_comstats.signals & TIOCM_DTR) ? "|DTR" : "", | 1935 | sep = '|'; |
1946 | (stli_comstats.signals & TIOCM_CD) ? "|DCD" : "", | 1936 | } |
1947 | (stli_comstats.signals & TIOCM_DSR) ? "|DSR" : ""); | 1937 | if (stli_comstats.signals & TIOCM_CTS) { |
1948 | *sp = ' '; | 1938 | seq_printf(m, "%c%s", sep, "CTS"); |
1949 | sp += cnt; | 1939 | sep = '|'; |
1940 | } | ||
1941 | if (stli_comstats.signals & TIOCM_DTR) { | ||
1942 | seq_printf(m, "%c%s", sep, "DTR"); | ||
1943 | sep = '|'; | ||
1944 | } | ||
1945 | if (stli_comstats.signals & TIOCM_CD) { | ||
1946 | seq_printf(m, "%c%s", sep, "DCD"); | ||
1947 | sep = '|'; | ||
1948 | } | ||
1949 | if (stli_comstats.signals & TIOCM_DSR) { | ||
1950 | seq_printf(m, "%c%s", sep, "DSR"); | ||
1951 | sep = '|'; | ||
1952 | } | ||
1950 | } | 1953 | } |
1951 | 1954 | seq_putc(m, '\n'); | |
1952 | for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++) | ||
1953 | *sp++ = ' '; | ||
1954 | if (cnt >= MAXLINE) | ||
1955 | pos[(MAXLINE - 2)] = '+'; | ||
1956 | pos[(MAXLINE - 1)] = '\n'; | ||
1957 | |||
1958 | return(MAXLINE); | ||
1959 | } | 1955 | } |
1960 | 1956 | ||
1961 | /*****************************************************************************/ | 1957 | /*****************************************************************************/ |
@@ -1964,26 +1960,15 @@ static int stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portn | |||
1964 | * Port info, read from the /proc file system. | 1960 | * Port info, read from the /proc file system. |
1965 | */ | 1961 | */ |
1966 | 1962 | ||
1967 | static int stli_readproc(char *page, char **start, off_t off, int count, int *eof, void *data) | 1963 | static int stli_proc_show(struct seq_file *m, void *v) |
1968 | { | 1964 | { |
1969 | struct stlibrd *brdp; | 1965 | struct stlibrd *brdp; |
1970 | struct stliport *portp; | 1966 | struct stliport *portp; |
1971 | unsigned int brdnr, portnr, totalport; | 1967 | unsigned int brdnr, portnr, totalport; |
1972 | int curoff, maxoff; | ||
1973 | char *pos; | ||
1974 | 1968 | ||
1975 | pos = page; | ||
1976 | totalport = 0; | 1969 | totalport = 0; |
1977 | curoff = 0; | 1970 | |
1978 | 1971 | seq_printf(m, "%s: version %s\n", stli_drvtitle, stli_drvversion); | |
1979 | if (off == 0) { | ||
1980 | pos += sprintf(pos, "%s: version %s", stli_drvtitle, | ||
1981 | stli_drvversion); | ||
1982 | while (pos < (page + MAXLINE - 1)) | ||
1983 | *pos++ = ' '; | ||
1984 | *pos++ = '\n'; | ||
1985 | } | ||
1986 | curoff = MAXLINE; | ||
1987 | 1972 | ||
1988 | /* | 1973 | /* |
1989 | * We scan through for each board, panel and port. The offset is | 1974 | * We scan through for each board, panel and port. The offset is |
@@ -1996,33 +1981,31 @@ static int stli_readproc(char *page, char **start, off_t off, int count, int *eo | |||
1996 | if (brdp->state == 0) | 1981 | if (brdp->state == 0) |
1997 | continue; | 1982 | continue; |
1998 | 1983 | ||
1999 | maxoff = curoff + (brdp->nrports * MAXLINE); | ||
2000 | if (off >= maxoff) { | ||
2001 | curoff = maxoff; | ||
2002 | continue; | ||
2003 | } | ||
2004 | |||
2005 | totalport = brdnr * STL_MAXPORTS; | 1984 | totalport = brdnr * STL_MAXPORTS; |
2006 | for (portnr = 0; (portnr < brdp->nrports); portnr++, | 1985 | for (portnr = 0; (portnr < brdp->nrports); portnr++, |
2007 | totalport++) { | 1986 | totalport++) { |
2008 | portp = brdp->ports[portnr]; | 1987 | portp = brdp->ports[portnr]; |
2009 | if (portp == NULL) | 1988 | if (portp == NULL) |
2010 | continue; | 1989 | continue; |
2011 | if (off >= (curoff += MAXLINE)) | 1990 | stli_portinfo(m, brdp, portp, totalport); |
2012 | continue; | ||
2013 | if ((pos - page + MAXLINE) > count) | ||
2014 | goto stli_readdone; | ||
2015 | pos += stli_portinfo(brdp, portp, totalport, pos); | ||
2016 | } | 1991 | } |
2017 | } | 1992 | } |
1993 | return 0; | ||
1994 | } | ||
2018 | 1995 | ||
2019 | *eof = 1; | 1996 | static int stli_proc_open(struct inode *inode, struct file *file) |
2020 | 1997 | { | |
2021 | stli_readdone: | 1998 | return single_open(file, stli_proc_show, NULL); |
2022 | *start = page; | ||
2023 | return(pos - page); | ||
2024 | } | 1999 | } |
2025 | 2000 | ||
2001 | static const struct file_operations stli_proc_fops = { | ||
2002 | .owner = THIS_MODULE, | ||
2003 | .open = stli_proc_open, | ||
2004 | .read = seq_read, | ||
2005 | .llseek = seq_lseek, | ||
2006 | .release = single_release, | ||
2007 | }; | ||
2008 | |||
2026 | /*****************************************************************************/ | 2009 | /*****************************************************************************/ |
2027 | 2010 | ||
2028 | /* | 2011 | /* |
@@ -4427,9 +4410,9 @@ static const struct tty_operations stli_ops = { | |||
4427 | .break_ctl = stli_breakctl, | 4410 | .break_ctl = stli_breakctl, |
4428 | .wait_until_sent = stli_waituntilsent, | 4411 | .wait_until_sent = stli_waituntilsent, |
4429 | .send_xchar = stli_sendxchar, | 4412 | .send_xchar = stli_sendxchar, |
4430 | .read_proc = stli_readproc, | ||
4431 | .tiocmget = stli_tiocmget, | 4413 | .tiocmget = stli_tiocmget, |
4432 | .tiocmset = stli_tiocmset, | 4414 | .tiocmset = stli_tiocmset, |
4415 | .proc_fops = &stli_proc_fops, | ||
4433 | }; | 4416 | }; |
4434 | 4417 | ||
4435 | static const struct tty_port_operations stli_port_ops = { | 4418 | static const struct tty_port_operations stli_port_ops = { |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 5608a1e5a3b3..19d79fc54461 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/ptrace.h> | 51 | #include <linux/ptrace.h> |
52 | #include <linux/ioport.h> | 52 | #include <linux/ioport.h> |
53 | #include <linux/mm.h> | 53 | #include <linux/mm.h> |
54 | #include <linux/seq_file.h> | ||
54 | #include <linux/slab.h> | 55 | #include <linux/slab.h> |
55 | #include <linux/netdevice.h> | 56 | #include <linux/netdevice.h> |
56 | #include <linux/vmalloc.h> | 57 | #include <linux/vmalloc.h> |
@@ -2619,13 +2620,12 @@ cleanup: | |||
2619 | * /proc fs routines.... | 2620 | * /proc fs routines.... |
2620 | */ | 2621 | */ |
2621 | 2622 | ||
2622 | static inline int line_info(char *buf, MGSLPC_INFO *info) | 2623 | static inline void line_info(struct seq_file *m, MGSLPC_INFO *info) |
2623 | { | 2624 | { |
2624 | char stat_buf[30]; | 2625 | char stat_buf[30]; |
2625 | int ret; | ||
2626 | unsigned long flags; | 2626 | unsigned long flags; |
2627 | 2627 | ||
2628 | ret = sprintf(buf, "%s:io:%04X irq:%d", | 2628 | seq_printf(m, "%s:io:%04X irq:%d", |
2629 | info->device_name, info->io_base, info->irq_level); | 2629 | info->device_name, info->io_base, info->irq_level); |
2630 | 2630 | ||
2631 | /* output current serial signal states */ | 2631 | /* output current serial signal states */ |
@@ -2649,75 +2649,70 @@ static inline int line_info(char *buf, MGSLPC_INFO *info) | |||
2649 | strcat(stat_buf, "|RI"); | 2649 | strcat(stat_buf, "|RI"); |
2650 | 2650 | ||
2651 | if (info->params.mode == MGSL_MODE_HDLC) { | 2651 | if (info->params.mode == MGSL_MODE_HDLC) { |
2652 | ret += sprintf(buf+ret, " HDLC txok:%d rxok:%d", | 2652 | seq_printf(m, " HDLC txok:%d rxok:%d", |
2653 | info->icount.txok, info->icount.rxok); | 2653 | info->icount.txok, info->icount.rxok); |
2654 | if (info->icount.txunder) | 2654 | if (info->icount.txunder) |
2655 | ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); | 2655 | seq_printf(m, " txunder:%d", info->icount.txunder); |
2656 | if (info->icount.txabort) | 2656 | if (info->icount.txabort) |
2657 | ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); | 2657 | seq_printf(m, " txabort:%d", info->icount.txabort); |
2658 | if (info->icount.rxshort) | 2658 | if (info->icount.rxshort) |
2659 | ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); | 2659 | seq_printf(m, " rxshort:%d", info->icount.rxshort); |
2660 | if (info->icount.rxlong) | 2660 | if (info->icount.rxlong) |
2661 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); | 2661 | seq_printf(m, " rxlong:%d", info->icount.rxlong); |
2662 | if (info->icount.rxover) | 2662 | if (info->icount.rxover) |
2663 | ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); | 2663 | seq_printf(m, " rxover:%d", info->icount.rxover); |
2664 | if (info->icount.rxcrc) | 2664 | if (info->icount.rxcrc) |
2665 | ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); | 2665 | seq_printf(m, " rxcrc:%d", info->icount.rxcrc); |
2666 | } else { | 2666 | } else { |
2667 | ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d", | 2667 | seq_printf(m, " ASYNC tx:%d rx:%d", |
2668 | info->icount.tx, info->icount.rx); | 2668 | info->icount.tx, info->icount.rx); |
2669 | if (info->icount.frame) | 2669 | if (info->icount.frame) |
2670 | ret += sprintf(buf+ret, " fe:%d", info->icount.frame); | 2670 | seq_printf(m, " fe:%d", info->icount.frame); |
2671 | if (info->icount.parity) | 2671 | if (info->icount.parity) |
2672 | ret += sprintf(buf+ret, " pe:%d", info->icount.parity); | 2672 | seq_printf(m, " pe:%d", info->icount.parity); |
2673 | if (info->icount.brk) | 2673 | if (info->icount.brk) |
2674 | ret += sprintf(buf+ret, " brk:%d", info->icount.brk); | 2674 | seq_printf(m, " brk:%d", info->icount.brk); |
2675 | if (info->icount.overrun) | 2675 | if (info->icount.overrun) |
2676 | ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); | 2676 | seq_printf(m, " oe:%d", info->icount.overrun); |
2677 | } | 2677 | } |
2678 | 2678 | ||
2679 | /* Append serial signal status to end */ | 2679 | /* Append serial signal status to end */ |
2680 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 2680 | seq_printf(m, " %s\n", stat_buf+1); |
2681 | 2681 | ||
2682 | ret += sprintf(buf+ret, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", | 2682 | seq_printf(m, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", |
2683 | info->tx_active,info->bh_requested,info->bh_running, | 2683 | info->tx_active,info->bh_requested,info->bh_running, |
2684 | info->pending_bh); | 2684 | info->pending_bh); |
2685 | |||
2686 | return ret; | ||
2687 | } | 2685 | } |
2688 | 2686 | ||
2689 | /* Called to print information about devices | 2687 | /* Called to print information about devices |
2690 | */ | 2688 | */ |
2691 | static int mgslpc_read_proc(char *page, char **start, off_t off, int count, | 2689 | static int mgslpc_proc_show(struct seq_file *m, void *v) |
2692 | int *eof, void *data) | ||
2693 | { | 2690 | { |
2694 | int len = 0, l; | ||
2695 | off_t begin = 0; | ||
2696 | MGSLPC_INFO *info; | 2691 | MGSLPC_INFO *info; |
2697 | 2692 | ||
2698 | len += sprintf(page, "synclink driver:%s\n", driver_version); | 2693 | seq_printf(m, "synclink driver:%s\n", driver_version); |
2699 | 2694 | ||
2700 | info = mgslpc_device_list; | 2695 | info = mgslpc_device_list; |
2701 | while( info ) { | 2696 | while( info ) { |
2702 | l = line_info(page + len, info); | 2697 | line_info(m, info); |
2703 | len += l; | ||
2704 | if (len+begin > off+count) | ||
2705 | goto done; | ||
2706 | if (len+begin < off) { | ||
2707 | begin += len; | ||
2708 | len = 0; | ||
2709 | } | ||
2710 | info = info->next_device; | 2698 | info = info->next_device; |
2711 | } | 2699 | } |
2700 | return 0; | ||
2701 | } | ||
2712 | 2702 | ||
2713 | *eof = 1; | 2703 | static int mgslpc_proc_open(struct inode *inode, struct file *file) |
2714 | done: | 2704 | { |
2715 | if (off >= len+begin) | 2705 | return single_open(file, mgslpc_proc_show, NULL); |
2716 | return 0; | ||
2717 | *start = page + (off-begin); | ||
2718 | return ((count < begin+len-off) ? count : begin+len-off); | ||
2719 | } | 2706 | } |
2720 | 2707 | ||
2708 | static const struct file_operations mgslpc_proc_fops = { | ||
2709 | .owner = THIS_MODULE, | ||
2710 | .open = mgslpc_proc_open, | ||
2711 | .read = seq_read, | ||
2712 | .llseek = seq_lseek, | ||
2713 | .release = single_release, | ||
2714 | }; | ||
2715 | |||
2721 | static int rx_alloc_buffers(MGSLPC_INFO *info) | 2716 | static int rx_alloc_buffers(MGSLPC_INFO *info) |
2722 | { | 2717 | { |
2723 | /* each buffer has header and data */ | 2718 | /* each buffer has header and data */ |
@@ -2861,13 +2856,13 @@ static const struct tty_operations mgslpc_ops = { | |||
2861 | .send_xchar = mgslpc_send_xchar, | 2856 | .send_xchar = mgslpc_send_xchar, |
2862 | .break_ctl = mgslpc_break, | 2857 | .break_ctl = mgslpc_break, |
2863 | .wait_until_sent = mgslpc_wait_until_sent, | 2858 | .wait_until_sent = mgslpc_wait_until_sent, |
2864 | .read_proc = mgslpc_read_proc, | ||
2865 | .set_termios = mgslpc_set_termios, | 2859 | .set_termios = mgslpc_set_termios, |
2866 | .stop = tx_pause, | 2860 | .stop = tx_pause, |
2867 | .start = tx_release, | 2861 | .start = tx_release, |
2868 | .hangup = mgslpc_hangup, | 2862 | .hangup = mgslpc_hangup, |
2869 | .tiocmget = tiocmget, | 2863 | .tiocmget = tiocmget, |
2870 | .tiocmset = tiocmset, | 2864 | .tiocmset = tiocmset, |
2865 | .proc_fops = &mgslpc_proc_fops, | ||
2871 | }; | 2866 | }; |
2872 | 2867 | ||
2873 | static void synclink_cs_cleanup(void) | 2868 | static void synclink_cs_cleanup(void) |
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index e1e0dd89ac9a..2ad813a801dc 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/tty.h> | 32 | #include <linux/tty.h> |
33 | #include <linux/tty_flip.h> | 33 | #include <linux/tty_flip.h> |
34 | #include <linux/serial.h> | 34 | #include <linux/serial.h> |
35 | #include <linux/seq_file.h> | ||
35 | #include <linux/cd1400.h> | 36 | #include <linux/cd1400.h> |
36 | #include <linux/sc26198.h> | 37 | #include <linux/sc26198.h> |
37 | #include <linux/comstats.h> | 38 | #include <linux/comstats.h> |
@@ -1379,52 +1380,47 @@ static void stl_sendxchar(struct tty_struct *tty, char ch) | |||
1379 | stl_putchar(tty, ch); | 1380 | stl_putchar(tty, ch); |
1380 | } | 1381 | } |
1381 | 1382 | ||
1382 | /*****************************************************************************/ | 1383 | static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr) |
1383 | |||
1384 | #define MAXLINE 80 | ||
1385 | |||
1386 | /* | ||
1387 | * Format info for a specified port. The line is deliberately limited | ||
1388 | * to 80 characters. (If it is too long it will be truncated, if too | ||
1389 | * short then padded with spaces). | ||
1390 | */ | ||
1391 | |||
1392 | static int stl_portinfo(struct stlport *portp, int portnr, char *pos) | ||
1393 | { | 1384 | { |
1394 | char *sp; | 1385 | int sigs; |
1395 | int sigs, cnt; | 1386 | char sep; |
1396 | 1387 | ||
1397 | sp = pos; | 1388 | seq_printf(m, "%d: uart:%s tx:%d rx:%d", |
1398 | sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d", | ||
1399 | portnr, (portp->hwid == 1) ? "SC26198" : "CD1400", | 1389 | portnr, (portp->hwid == 1) ? "SC26198" : "CD1400", |
1400 | (int) portp->stats.txtotal, (int) portp->stats.rxtotal); | 1390 | (int) portp->stats.txtotal, (int) portp->stats.rxtotal); |
1401 | 1391 | ||
1402 | if (portp->stats.rxframing) | 1392 | if (portp->stats.rxframing) |
1403 | sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing); | 1393 | seq_printf(m, " fe:%d", (int) portp->stats.rxframing); |
1404 | if (portp->stats.rxparity) | 1394 | if (portp->stats.rxparity) |
1405 | sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity); | 1395 | seq_printf(m, " pe:%d", (int) portp->stats.rxparity); |
1406 | if (portp->stats.rxbreaks) | 1396 | if (portp->stats.rxbreaks) |
1407 | sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks); | 1397 | seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks); |
1408 | if (portp->stats.rxoverrun) | 1398 | if (portp->stats.rxoverrun) |
1409 | sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun); | 1399 | seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun); |
1410 | 1400 | ||
1411 | sigs = stl_getsignals(portp); | 1401 | sigs = stl_getsignals(portp); |
1412 | cnt = sprintf(sp, "%s%s%s%s%s ", | 1402 | sep = ' '; |
1413 | (sigs & TIOCM_RTS) ? "|RTS" : "", | 1403 | if (sigs & TIOCM_RTS) { |
1414 | (sigs & TIOCM_CTS) ? "|CTS" : "", | 1404 | seq_printf(m, "%c%s", sep, "RTS"); |
1415 | (sigs & TIOCM_DTR) ? "|DTR" : "", | 1405 | sep = '|'; |
1416 | (sigs & TIOCM_CD) ? "|DCD" : "", | 1406 | } |
1417 | (sigs & TIOCM_DSR) ? "|DSR" : ""); | 1407 | if (sigs & TIOCM_CTS) { |
1418 | *sp = ' '; | 1408 | seq_printf(m, "%c%s", sep, "CTS"); |
1419 | sp += cnt; | 1409 | sep = '|'; |
1420 | 1410 | } | |
1421 | for (cnt = sp - pos; cnt < (MAXLINE - 1); cnt++) | 1411 | if (sigs & TIOCM_DTR) { |
1422 | *sp++ = ' '; | 1412 | seq_printf(m, "%c%s", sep, "DTR"); |
1423 | if (cnt >= MAXLINE) | 1413 | sep = '|'; |
1424 | pos[(MAXLINE - 2)] = '+'; | 1414 | } |
1425 | pos[(MAXLINE - 1)] = '\n'; | 1415 | if (sigs & TIOCM_CD) { |
1426 | 1416 | seq_printf(m, "%c%s", sep, "DCD"); | |
1427 | return MAXLINE; | 1417 | sep = '|'; |
1418 | } | ||
1419 | if (sigs & TIOCM_DSR) { | ||
1420 | seq_printf(m, "%c%s", sep, "DSR"); | ||
1421 | sep = '|'; | ||
1422 | } | ||
1423 | seq_putc(m, '\n'); | ||
1428 | } | 1424 | } |
1429 | 1425 | ||
1430 | /*****************************************************************************/ | 1426 | /*****************************************************************************/ |
@@ -1433,30 +1429,17 @@ static int stl_portinfo(struct stlport *portp, int portnr, char *pos) | |||
1433 | * Port info, read from the /proc file system. | 1429 | * Port info, read from the /proc file system. |
1434 | */ | 1430 | */ |
1435 | 1431 | ||
1436 | static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data) | 1432 | static int stl_proc_show(struct seq_file *m, void *v) |
1437 | { | 1433 | { |
1438 | struct stlbrd *brdp; | 1434 | struct stlbrd *brdp; |
1439 | struct stlpanel *panelp; | 1435 | struct stlpanel *panelp; |
1440 | struct stlport *portp; | 1436 | struct stlport *portp; |
1441 | unsigned int brdnr, panelnr, portnr; | 1437 | unsigned int brdnr, panelnr, portnr; |
1442 | int totalport, curoff, maxoff; | 1438 | int totalport; |
1443 | char *pos; | ||
1444 | 1439 | ||
1445 | pr_debug("stl_readproc(page=%p,start=%p,off=%lx,count=%d,eof=%p," | ||
1446 | "data=%p\n", page, start, off, count, eof, data); | ||
1447 | |||
1448 | pos = page; | ||
1449 | totalport = 0; | 1440 | totalport = 0; |
1450 | curoff = 0; | 1441 | |
1451 | 1442 | seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion); | |
1452 | if (off == 0) { | ||
1453 | pos += sprintf(pos, "%s: version %s", stl_drvtitle, | ||
1454 | stl_drvversion); | ||
1455 | while (pos < (page + MAXLINE - 1)) | ||
1456 | *pos++ = ' '; | ||
1457 | *pos++ = '\n'; | ||
1458 | } | ||
1459 | curoff = MAXLINE; | ||
1460 | 1443 | ||
1461 | /* | 1444 | /* |
1462 | * We scan through for each board, panel and port. The offset is | 1445 | * We scan through for each board, panel and port. The offset is |
@@ -1469,46 +1452,37 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof | |||
1469 | if (brdp->state == 0) | 1452 | if (brdp->state == 0) |
1470 | continue; | 1453 | continue; |
1471 | 1454 | ||
1472 | maxoff = curoff + (brdp->nrports * MAXLINE); | ||
1473 | if (off >= maxoff) { | ||
1474 | curoff = maxoff; | ||
1475 | continue; | ||
1476 | } | ||
1477 | |||
1478 | totalport = brdnr * STL_MAXPORTS; | 1455 | totalport = brdnr * STL_MAXPORTS; |
1479 | for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) { | 1456 | for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) { |
1480 | panelp = brdp->panels[panelnr]; | 1457 | panelp = brdp->panels[panelnr]; |
1481 | if (panelp == NULL) | 1458 | if (panelp == NULL) |
1482 | continue; | 1459 | continue; |
1483 | 1460 | ||
1484 | maxoff = curoff + (panelp->nrports * MAXLINE); | ||
1485 | if (off >= maxoff) { | ||
1486 | curoff = maxoff; | ||
1487 | totalport += panelp->nrports; | ||
1488 | continue; | ||
1489 | } | ||
1490 | |||
1491 | for (portnr = 0; portnr < panelp->nrports; portnr++, | 1461 | for (portnr = 0; portnr < panelp->nrports; portnr++, |
1492 | totalport++) { | 1462 | totalport++) { |
1493 | portp = panelp->ports[portnr]; | 1463 | portp = panelp->ports[portnr]; |
1494 | if (portp == NULL) | 1464 | if (portp == NULL) |
1495 | continue; | 1465 | continue; |
1496 | if (off >= (curoff += MAXLINE)) | 1466 | stl_portinfo(m, portp, totalport); |
1497 | continue; | ||
1498 | if ((pos - page + MAXLINE) > count) | ||
1499 | goto stl_readdone; | ||
1500 | pos += stl_portinfo(portp, totalport, pos); | ||
1501 | } | 1467 | } |
1502 | } | 1468 | } |
1503 | } | 1469 | } |
1470 | return 0; | ||
1471 | } | ||
1504 | 1472 | ||
1505 | *eof = 1; | 1473 | static int stl_proc_open(struct inode *inode, struct file *file) |
1506 | 1474 | { | |
1507 | stl_readdone: | 1475 | return single_open(file, stl_proc_show, NULL); |
1508 | *start = page; | ||
1509 | return pos - page; | ||
1510 | } | 1476 | } |
1511 | 1477 | ||
1478 | static const struct file_operations stl_proc_fops = { | ||
1479 | .owner = THIS_MODULE, | ||
1480 | .open = stl_proc_open, | ||
1481 | .read = seq_read, | ||
1482 | .llseek = seq_lseek, | ||
1483 | .release = single_release, | ||
1484 | }; | ||
1485 | |||
1512 | /*****************************************************************************/ | 1486 | /*****************************************************************************/ |
1513 | 1487 | ||
1514 | /* | 1488 | /* |
@@ -2566,9 +2540,9 @@ static const struct tty_operations stl_ops = { | |||
2566 | .break_ctl = stl_breakctl, | 2540 | .break_ctl = stl_breakctl, |
2567 | .wait_until_sent = stl_waituntilsent, | 2541 | .wait_until_sent = stl_waituntilsent, |
2568 | .send_xchar = stl_sendxchar, | 2542 | .send_xchar = stl_sendxchar, |
2569 | .read_proc = stl_readproc, | ||
2570 | .tiocmget = stl_tiocmget, | 2543 | .tiocmget = stl_tiocmget, |
2571 | .tiocmset = stl_tiocmset, | 2544 | .tiocmset = stl_tiocmset, |
2545 | .proc_fops = &stl_proc_fops, | ||
2572 | }; | 2546 | }; |
2573 | 2547 | ||
2574 | static const struct tty_port_operations stl_port_ops = { | 2548 | static const struct tty_port_operations stl_port_ops = { |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 0057a8f58cb1..afd0b26ca056 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -79,6 +79,7 @@ | |||
79 | #include <linux/ptrace.h> | 79 | #include <linux/ptrace.h> |
80 | #include <linux/ioport.h> | 80 | #include <linux/ioport.h> |
81 | #include <linux/mm.h> | 81 | #include <linux/mm.h> |
82 | #include <linux/seq_file.h> | ||
82 | #include <linux/slab.h> | 83 | #include <linux/slab.h> |
83 | #include <linux/delay.h> | 84 | #include <linux/delay.h> |
84 | #include <linux/netdevice.h> | 85 | #include <linux/netdevice.h> |
@@ -3459,18 +3460,17 @@ cleanup: | |||
3459 | * /proc fs routines.... | 3460 | * /proc fs routines.... |
3460 | */ | 3461 | */ |
3461 | 3462 | ||
3462 | static inline int line_info(char *buf, struct mgsl_struct *info) | 3463 | static inline void line_info(struct seq_file *m, struct mgsl_struct *info) |
3463 | { | 3464 | { |
3464 | char stat_buf[30]; | 3465 | char stat_buf[30]; |
3465 | int ret; | ||
3466 | unsigned long flags; | 3466 | unsigned long flags; |
3467 | 3467 | ||
3468 | if (info->bus_type == MGSL_BUS_TYPE_PCI) { | 3468 | if (info->bus_type == MGSL_BUS_TYPE_PCI) { |
3469 | ret = sprintf(buf, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X", | 3469 | seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X", |
3470 | info->device_name, info->io_base, info->irq_level, | 3470 | info->device_name, info->io_base, info->irq_level, |
3471 | info->phys_memory_base, info->phys_lcr_base); | 3471 | info->phys_memory_base, info->phys_lcr_base); |
3472 | } else { | 3472 | } else { |
3473 | ret = sprintf(buf, "%s:(E)ISA io:%04X irq:%d dma:%d", | 3473 | seq_printf(m, "%s:(E)ISA io:%04X irq:%d dma:%d", |
3474 | info->device_name, info->io_base, | 3474 | info->device_name, info->io_base, |
3475 | info->irq_level, info->dma_level); | 3475 | info->irq_level, info->dma_level); |
3476 | } | 3476 | } |
@@ -3497,37 +3497,37 @@ static inline int line_info(char *buf, struct mgsl_struct *info) | |||
3497 | 3497 | ||
3498 | if (info->params.mode == MGSL_MODE_HDLC || | 3498 | if (info->params.mode == MGSL_MODE_HDLC || |
3499 | info->params.mode == MGSL_MODE_RAW ) { | 3499 | info->params.mode == MGSL_MODE_RAW ) { |
3500 | ret += sprintf(buf+ret, " HDLC txok:%d rxok:%d", | 3500 | seq_printf(m, " HDLC txok:%d rxok:%d", |
3501 | info->icount.txok, info->icount.rxok); | 3501 | info->icount.txok, info->icount.rxok); |
3502 | if (info->icount.txunder) | 3502 | if (info->icount.txunder) |
3503 | ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); | 3503 | seq_printf(m, " txunder:%d", info->icount.txunder); |
3504 | if (info->icount.txabort) | 3504 | if (info->icount.txabort) |
3505 | ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); | 3505 | seq_printf(m, " txabort:%d", info->icount.txabort); |
3506 | if (info->icount.rxshort) | 3506 | if (info->icount.rxshort) |
3507 | ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); | 3507 | seq_printf(m, " rxshort:%d", info->icount.rxshort); |
3508 | if (info->icount.rxlong) | 3508 | if (info->icount.rxlong) |
3509 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); | 3509 | seq_printf(m, " rxlong:%d", info->icount.rxlong); |
3510 | if (info->icount.rxover) | 3510 | if (info->icount.rxover) |
3511 | ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); | 3511 | seq_printf(m, " rxover:%d", info->icount.rxover); |
3512 | if (info->icount.rxcrc) | 3512 | if (info->icount.rxcrc) |
3513 | ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); | 3513 | seq_printf(m, " rxcrc:%d", info->icount.rxcrc); |
3514 | } else { | 3514 | } else { |
3515 | ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d", | 3515 | seq_printf(m, " ASYNC tx:%d rx:%d", |
3516 | info->icount.tx, info->icount.rx); | 3516 | info->icount.tx, info->icount.rx); |
3517 | if (info->icount.frame) | 3517 | if (info->icount.frame) |
3518 | ret += sprintf(buf+ret, " fe:%d", info->icount.frame); | 3518 | seq_printf(m, " fe:%d", info->icount.frame); |
3519 | if (info->icount.parity) | 3519 | if (info->icount.parity) |
3520 | ret += sprintf(buf+ret, " pe:%d", info->icount.parity); | 3520 | seq_printf(m, " pe:%d", info->icount.parity); |
3521 | if (info->icount.brk) | 3521 | if (info->icount.brk) |
3522 | ret += sprintf(buf+ret, " brk:%d", info->icount.brk); | 3522 | seq_printf(m, " brk:%d", info->icount.brk); |
3523 | if (info->icount.overrun) | 3523 | if (info->icount.overrun) |
3524 | ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); | 3524 | seq_printf(m, " oe:%d", info->icount.overrun); |
3525 | } | 3525 | } |
3526 | 3526 | ||
3527 | /* Append serial signal status to end */ | 3527 | /* Append serial signal status to end */ |
3528 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 3528 | seq_printf(m, " %s\n", stat_buf+1); |
3529 | 3529 | ||
3530 | ret += sprintf(buf+ret, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", | 3530 | seq_printf(m, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", |
3531 | info->tx_active,info->bh_requested,info->bh_running, | 3531 | info->tx_active,info->bh_requested,info->bh_running, |
3532 | info->pending_bh); | 3532 | info->pending_bh); |
3533 | 3533 | ||
@@ -3544,60 +3544,40 @@ static inline int line_info(char *buf, struct mgsl_struct *info) | |||
3544 | u16 Tmr = usc_InReg( info, TMR ); | 3544 | u16 Tmr = usc_InReg( info, TMR ); |
3545 | u16 Tccr = usc_InReg( info, TCCR ); | 3545 | u16 Tccr = usc_InReg( info, TCCR ); |
3546 | u16 Ccar = inw( info->io_base + CCAR ); | 3546 | u16 Ccar = inw( info->io_base + CCAR ); |
3547 | ret += sprintf(buf+ret, "tcsr=%04X tdmr=%04X ticr=%04X rcsr=%04X rdmr=%04X\n" | 3547 | seq_printf(m, "tcsr=%04X tdmr=%04X ticr=%04X rcsr=%04X rdmr=%04X\n" |
3548 | "ricr=%04X icr =%04X dccr=%04X tmr=%04X tccr=%04X ccar=%04X\n", | 3548 | "ricr=%04X icr =%04X dccr=%04X tmr=%04X tccr=%04X ccar=%04X\n", |
3549 | Tcsr,Tdmr,Ticr,Rscr,Rdmr,Ricr,Icr,Dccr,Tmr,Tccr,Ccar ); | 3549 | Tcsr,Tdmr,Ticr,Rscr,Rdmr,Ricr,Icr,Dccr,Tmr,Tccr,Ccar ); |
3550 | } | 3550 | } |
3551 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | 3551 | spin_unlock_irqrestore(&info->irq_spinlock,flags); |
3552 | 3552 | } | |
3553 | return ret; | ||
3554 | |||
3555 | } /* end of line_info() */ | ||
3556 | 3553 | ||
3557 | /* mgsl_read_proc() | 3554 | /* Called to print information about devices */ |
3558 | * | 3555 | static int mgsl_proc_show(struct seq_file *m, void *v) |
3559 | * Called to print information about devices | ||
3560 | * | ||
3561 | * Arguments: | ||
3562 | * page page of memory to hold returned info | ||
3563 | * start | ||
3564 | * off | ||
3565 | * count | ||
3566 | * eof | ||
3567 | * data | ||
3568 | * | ||
3569 | * Return Value: | ||
3570 | */ | ||
3571 | static int mgsl_read_proc(char *page, char **start, off_t off, int count, | ||
3572 | int *eof, void *data) | ||
3573 | { | 3556 | { |
3574 | int len = 0, l; | ||
3575 | off_t begin = 0; | ||
3576 | struct mgsl_struct *info; | 3557 | struct mgsl_struct *info; |
3577 | 3558 | ||
3578 | len += sprintf(page, "synclink driver:%s\n", driver_version); | 3559 | seq_printf(m, "synclink driver:%s\n", driver_version); |
3579 | 3560 | ||
3580 | info = mgsl_device_list; | 3561 | info = mgsl_device_list; |
3581 | while( info ) { | 3562 | while( info ) { |
3582 | l = line_info(page + len, info); | 3563 | line_info(m, info); |
3583 | len += l; | ||
3584 | if (len+begin > off+count) | ||
3585 | goto done; | ||
3586 | if (len+begin < off) { | ||
3587 | begin += len; | ||
3588 | len = 0; | ||
3589 | } | ||
3590 | info = info->next_device; | 3564 | info = info->next_device; |
3591 | } | 3565 | } |
3566 | return 0; | ||
3567 | } | ||
3592 | 3568 | ||
3593 | *eof = 1; | 3569 | static int mgsl_proc_open(struct inode *inode, struct file *file) |
3594 | done: | 3570 | { |
3595 | if (off >= len+begin) | 3571 | return single_open(file, mgsl_proc_show, NULL); |
3596 | return 0; | 3572 | } |
3597 | *start = page + (off-begin); | 3573 | |
3598 | return ((count < begin+len-off) ? count : begin+len-off); | 3574 | static const struct file_operations mgsl_proc_fops = { |
3599 | 3575 | .owner = THIS_MODULE, | |
3600 | } /* end of mgsl_read_proc() */ | 3576 | .open = mgsl_proc_open, |
3577 | .read = seq_read, | ||
3578 | .llseek = seq_lseek, | ||
3579 | .release = single_release, | ||
3580 | }; | ||
3601 | 3581 | ||
3602 | /* mgsl_allocate_dma_buffers() | 3582 | /* mgsl_allocate_dma_buffers() |
3603 | * | 3583 | * |
@@ -4335,13 +4315,13 @@ static const struct tty_operations mgsl_ops = { | |||
4335 | .send_xchar = mgsl_send_xchar, | 4315 | .send_xchar = mgsl_send_xchar, |
4336 | .break_ctl = mgsl_break, | 4316 | .break_ctl = mgsl_break, |
4337 | .wait_until_sent = mgsl_wait_until_sent, | 4317 | .wait_until_sent = mgsl_wait_until_sent, |
4338 | .read_proc = mgsl_read_proc, | ||
4339 | .set_termios = mgsl_set_termios, | 4318 | .set_termios = mgsl_set_termios, |
4340 | .stop = mgsl_stop, | 4319 | .stop = mgsl_stop, |
4341 | .start = mgsl_start, | 4320 | .start = mgsl_start, |
4342 | .hangup = mgsl_hangup, | 4321 | .hangup = mgsl_hangup, |
4343 | .tiocmget = tiocmget, | 4322 | .tiocmget = tiocmget, |
4344 | .tiocmset = tiocmset, | 4323 | .tiocmset = tiocmset, |
4324 | .proc_fops = &mgsl_proc_fops, | ||
4345 | }; | 4325 | }; |
4346 | 4326 | ||
4347 | /* | 4327 | /* |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index efb3dc928a43..6ec6e13d47d7 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #include <linux/ptrace.h> | 60 | #include <linux/ptrace.h> |
61 | #include <linux/ioport.h> | 61 | #include <linux/ioport.h> |
62 | #include <linux/mm.h> | 62 | #include <linux/mm.h> |
63 | #include <linux/seq_file.h> | ||
63 | #include <linux/slab.h> | 64 | #include <linux/slab.h> |
64 | #include <linux/netdevice.h> | 65 | #include <linux/netdevice.h> |
65 | #include <linux/vmalloc.h> | 66 | #include <linux/vmalloc.h> |
@@ -154,7 +155,6 @@ static void tx_hold(struct tty_struct *tty); | |||
154 | static void tx_release(struct tty_struct *tty); | 155 | static void tx_release(struct tty_struct *tty); |
155 | 156 | ||
156 | static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); | 157 | static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); |
157 | static int read_proc(char *page, char **start, off_t off, int count,int *eof, void *data); | ||
158 | static int chars_in_buffer(struct tty_struct *tty); | 158 | static int chars_in_buffer(struct tty_struct *tty); |
159 | static void throttle(struct tty_struct * tty); | 159 | static void throttle(struct tty_struct * tty); |
160 | static void unthrottle(struct tty_struct * tty); | 160 | static void unthrottle(struct tty_struct * tty); |
@@ -1229,13 +1229,12 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file, | |||
1229 | /* | 1229 | /* |
1230 | * proc fs support | 1230 | * proc fs support |
1231 | */ | 1231 | */ |
1232 | static inline int line_info(char *buf, struct slgt_info *info) | 1232 | static inline void line_info(struct seq_file *m, struct slgt_info *info) |
1233 | { | 1233 | { |
1234 | char stat_buf[30]; | 1234 | char stat_buf[30]; |
1235 | int ret; | ||
1236 | unsigned long flags; | 1235 | unsigned long flags; |
1237 | 1236 | ||
1238 | ret = sprintf(buf, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n", | 1237 | seq_printf(m, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n", |
1239 | info->device_name, info->phys_reg_addr, | 1238 | info->device_name, info->phys_reg_addr, |
1240 | info->irq_level, info->max_frame_size); | 1239 | info->irq_level, info->max_frame_size); |
1241 | 1240 | ||
@@ -1260,75 +1259,70 @@ static inline int line_info(char *buf, struct slgt_info *info) | |||
1260 | strcat(stat_buf, "|RI"); | 1259 | strcat(stat_buf, "|RI"); |
1261 | 1260 | ||
1262 | if (info->params.mode != MGSL_MODE_ASYNC) { | 1261 | if (info->params.mode != MGSL_MODE_ASYNC) { |
1263 | ret += sprintf(buf+ret, "\tHDLC txok:%d rxok:%d", | 1262 | seq_printf(m, "\tHDLC txok:%d rxok:%d", |
1264 | info->icount.txok, info->icount.rxok); | 1263 | info->icount.txok, info->icount.rxok); |
1265 | if (info->icount.txunder) | 1264 | if (info->icount.txunder) |
1266 | ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); | 1265 | seq_printf(m, " txunder:%d", info->icount.txunder); |
1267 | if (info->icount.txabort) | 1266 | if (info->icount.txabort) |
1268 | ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); | 1267 | seq_printf(m, " txabort:%d", info->icount.txabort); |
1269 | if (info->icount.rxshort) | 1268 | if (info->icount.rxshort) |
1270 | ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); | 1269 | seq_printf(m, " rxshort:%d", info->icount.rxshort); |
1271 | if (info->icount.rxlong) | 1270 | if (info->icount.rxlong) |
1272 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); | 1271 | seq_printf(m, " rxlong:%d", info->icount.rxlong); |
1273 | if (info->icount.rxover) | 1272 | if (info->icount.rxover) |
1274 | ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); | 1273 | seq_printf(m, " rxover:%d", info->icount.rxover); |
1275 | if (info->icount.rxcrc) | 1274 | if (info->icount.rxcrc) |
1276 | ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); | 1275 | seq_printf(m, " rxcrc:%d", info->icount.rxcrc); |
1277 | } else { | 1276 | } else { |
1278 | ret += sprintf(buf+ret, "\tASYNC tx:%d rx:%d", | 1277 | seq_printf(m, "\tASYNC tx:%d rx:%d", |
1279 | info->icount.tx, info->icount.rx); | 1278 | info->icount.tx, info->icount.rx); |
1280 | if (info->icount.frame) | 1279 | if (info->icount.frame) |
1281 | ret += sprintf(buf+ret, " fe:%d", info->icount.frame); | 1280 | seq_printf(m, " fe:%d", info->icount.frame); |
1282 | if (info->icount.parity) | 1281 | if (info->icount.parity) |
1283 | ret += sprintf(buf+ret, " pe:%d", info->icount.parity); | 1282 | seq_printf(m, " pe:%d", info->icount.parity); |
1284 | if (info->icount.brk) | 1283 | if (info->icount.brk) |
1285 | ret += sprintf(buf+ret, " brk:%d", info->icount.brk); | 1284 | seq_printf(m, " brk:%d", info->icount.brk); |
1286 | if (info->icount.overrun) | 1285 | if (info->icount.overrun) |
1287 | ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); | 1286 | seq_printf(m, " oe:%d", info->icount.overrun); |
1288 | } | 1287 | } |
1289 | 1288 | ||
1290 | /* Append serial signal status to end */ | 1289 | /* Append serial signal status to end */ |
1291 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 1290 | seq_printf(m, " %s\n", stat_buf+1); |
1292 | 1291 | ||
1293 | ret += sprintf(buf+ret, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", | 1292 | seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", |
1294 | info->tx_active,info->bh_requested,info->bh_running, | 1293 | info->tx_active,info->bh_requested,info->bh_running, |
1295 | info->pending_bh); | 1294 | info->pending_bh); |
1296 | |||
1297 | return ret; | ||
1298 | } | 1295 | } |
1299 | 1296 | ||
1300 | /* Called to print information about devices | 1297 | /* Called to print information about devices |
1301 | */ | 1298 | */ |
1302 | static int read_proc(char *page, char **start, off_t off, int count, | 1299 | static int synclink_gt_proc_show(struct seq_file *m, void *v) |
1303 | int *eof, void *data) | ||
1304 | { | 1300 | { |
1305 | int len = 0, l; | ||
1306 | off_t begin = 0; | ||
1307 | struct slgt_info *info; | 1301 | struct slgt_info *info; |
1308 | 1302 | ||
1309 | len += sprintf(page, "synclink_gt driver\n"); | 1303 | seq_puts(m, "synclink_gt driver\n"); |
1310 | 1304 | ||
1311 | info = slgt_device_list; | 1305 | info = slgt_device_list; |
1312 | while( info ) { | 1306 | while( info ) { |
1313 | l = line_info(page + len, info); | 1307 | line_info(m, info); |
1314 | len += l; | ||
1315 | if (len+begin > off+count) | ||
1316 | goto done; | ||
1317 | if (len+begin < off) { | ||
1318 | begin += len; | ||
1319 | len = 0; | ||
1320 | } | ||
1321 | info = info->next_device; | 1308 | info = info->next_device; |
1322 | } | 1309 | } |
1310 | return 0; | ||
1311 | } | ||
1323 | 1312 | ||
1324 | *eof = 1; | 1313 | static int synclink_gt_proc_open(struct inode *inode, struct file *file) |
1325 | done: | 1314 | { |
1326 | if (off >= len+begin) | 1315 | return single_open(file, synclink_gt_proc_show, NULL); |
1327 | return 0; | ||
1328 | *start = page + (off-begin); | ||
1329 | return ((count < begin+len-off) ? count : begin+len-off); | ||
1330 | } | 1316 | } |
1331 | 1317 | ||
1318 | static const struct file_operations synclink_gt_proc_fops = { | ||
1319 | .owner = THIS_MODULE, | ||
1320 | .open = synclink_gt_proc_open, | ||
1321 | .read = seq_read, | ||
1322 | .llseek = seq_lseek, | ||
1323 | .release = single_release, | ||
1324 | }; | ||
1325 | |||
1332 | /* | 1326 | /* |
1333 | * return count of bytes in transmit buffer | 1327 | * return count of bytes in transmit buffer |
1334 | */ | 1328 | */ |
@@ -3562,13 +3556,13 @@ static const struct tty_operations ops = { | |||
3562 | .send_xchar = send_xchar, | 3556 | .send_xchar = send_xchar, |
3563 | .break_ctl = set_break, | 3557 | .break_ctl = set_break, |
3564 | .wait_until_sent = wait_until_sent, | 3558 | .wait_until_sent = wait_until_sent, |
3565 | .read_proc = read_proc, | ||
3566 | .set_termios = set_termios, | 3559 | .set_termios = set_termios, |
3567 | .stop = tx_hold, | 3560 | .stop = tx_hold, |
3568 | .start = tx_release, | 3561 | .start = tx_release, |
3569 | .hangup = hangup, | 3562 | .hangup = hangup, |
3570 | .tiocmget = tiocmget, | 3563 | .tiocmget = tiocmget, |
3571 | .tiocmset = tiocmset, | 3564 | .tiocmset = tiocmset, |
3565 | .proc_fops = &synclink_gt_proc_fops, | ||
3572 | }; | 3566 | }; |
3573 | 3567 | ||
3574 | static void slgt_cleanup(void) | 3568 | static void slgt_cleanup(void) |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 8eb6c89a980e..26de60efe4b2 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/ptrace.h> | 50 | #include <linux/ptrace.h> |
51 | #include <linux/ioport.h> | 51 | #include <linux/ioport.h> |
52 | #include <linux/mm.h> | 52 | #include <linux/mm.h> |
53 | #include <linux/seq_file.h> | ||
53 | #include <linux/slab.h> | 54 | #include <linux/slab.h> |
54 | #include <linux/netdevice.h> | 55 | #include <linux/netdevice.h> |
55 | #include <linux/vmalloc.h> | 56 | #include <linux/vmalloc.h> |
@@ -520,7 +521,6 @@ static void tx_hold(struct tty_struct *tty); | |||
520 | static void tx_release(struct tty_struct *tty); | 521 | static void tx_release(struct tty_struct *tty); |
521 | 522 | ||
522 | static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); | 523 | static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); |
523 | static int read_proc(char *page, char **start, off_t off, int count,int *eof, void *data); | ||
524 | static int chars_in_buffer(struct tty_struct *tty); | 524 | static int chars_in_buffer(struct tty_struct *tty); |
525 | static void throttle(struct tty_struct * tty); | 525 | static void throttle(struct tty_struct * tty); |
526 | static void unthrottle(struct tty_struct * tty); | 526 | static void unthrottle(struct tty_struct * tty); |
@@ -1354,13 +1354,12 @@ static int ioctl(struct tty_struct *tty, struct file *file, | |||
1354 | * /proc fs routines.... | 1354 | * /proc fs routines.... |
1355 | */ | 1355 | */ |
1356 | 1356 | ||
1357 | static inline int line_info(char *buf, SLMP_INFO *info) | 1357 | static inline void line_info(struct seq_file *m, SLMP_INFO *info) |
1358 | { | 1358 | { |
1359 | char stat_buf[30]; | 1359 | char stat_buf[30]; |
1360 | int ret; | ||
1361 | unsigned long flags; | 1360 | unsigned long flags; |
1362 | 1361 | ||
1363 | ret = sprintf(buf, "%s: SCABase=%08x Mem=%08X StatusControl=%08x LCR=%08X\n" | 1362 | seq_printf(m, "%s: SCABase=%08x Mem=%08X StatusControl=%08x LCR=%08X\n" |
1364 | "\tIRQ=%d MaxFrameSize=%u\n", | 1363 | "\tIRQ=%d MaxFrameSize=%u\n", |
1365 | info->device_name, | 1364 | info->device_name, |
1366 | info->phys_sca_base, | 1365 | info->phys_sca_base, |
@@ -1391,75 +1390,70 @@ static inline int line_info(char *buf, SLMP_INFO *info) | |||
1391 | strcat(stat_buf, "|RI"); | 1390 | strcat(stat_buf, "|RI"); |
1392 | 1391 | ||
1393 | if (info->params.mode == MGSL_MODE_HDLC) { | 1392 | if (info->params.mode == MGSL_MODE_HDLC) { |
1394 | ret += sprintf(buf+ret, "\tHDLC txok:%d rxok:%d", | 1393 | seq_printf(m, "\tHDLC txok:%d rxok:%d", |
1395 | info->icount.txok, info->icount.rxok); | 1394 | info->icount.txok, info->icount.rxok); |
1396 | if (info->icount.txunder) | 1395 | if (info->icount.txunder) |
1397 | ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); | 1396 | seq_printf(m, " txunder:%d", info->icount.txunder); |
1398 | if (info->icount.txabort) | 1397 | if (info->icount.txabort) |
1399 | ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); | 1398 | seq_printf(m, " txabort:%d", info->icount.txabort); |
1400 | if (info->icount.rxshort) | 1399 | if (info->icount.rxshort) |
1401 | ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); | 1400 | seq_printf(m, " rxshort:%d", info->icount.rxshort); |
1402 | if (info->icount.rxlong) | 1401 | if (info->icount.rxlong) |
1403 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); | 1402 | seq_printf(m, " rxlong:%d", info->icount.rxlong); |
1404 | if (info->icount.rxover) | 1403 | if (info->icount.rxover) |
1405 | ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); | 1404 | seq_printf(m, " rxover:%d", info->icount.rxover); |
1406 | if (info->icount.rxcrc) | 1405 | if (info->icount.rxcrc) |
1407 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxcrc); | 1406 | seq_printf(m, " rxlong:%d", info->icount.rxcrc); |
1408 | } else { | 1407 | } else { |
1409 | ret += sprintf(buf+ret, "\tASYNC tx:%d rx:%d", | 1408 | seq_printf(m, "\tASYNC tx:%d rx:%d", |
1410 | info->icount.tx, info->icount.rx); | 1409 | info->icount.tx, info->icount.rx); |
1411 | if (info->icount.frame) | 1410 | if (info->icount.frame) |
1412 | ret += sprintf(buf+ret, " fe:%d", info->icount.frame); | 1411 | seq_printf(m, " fe:%d", info->icount.frame); |
1413 | if (info->icount.parity) | 1412 | if (info->icount.parity) |
1414 | ret += sprintf(buf+ret, " pe:%d", info->icount.parity); | 1413 | seq_printf(m, " pe:%d", info->icount.parity); |
1415 | if (info->icount.brk) | 1414 | if (info->icount.brk) |
1416 | ret += sprintf(buf+ret, " brk:%d", info->icount.brk); | 1415 | seq_printf(m, " brk:%d", info->icount.brk); |
1417 | if (info->icount.overrun) | 1416 | if (info->icount.overrun) |
1418 | ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); | 1417 | seq_printf(m, " oe:%d", info->icount.overrun); |
1419 | } | 1418 | } |
1420 | 1419 | ||
1421 | /* Append serial signal status to end */ | 1420 | /* Append serial signal status to end */ |
1422 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | 1421 | seq_printf(m, " %s\n", stat_buf+1); |
1423 | 1422 | ||
1424 | ret += sprintf(buf+ret, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", | 1423 | seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", |
1425 | info->tx_active,info->bh_requested,info->bh_running, | 1424 | info->tx_active,info->bh_requested,info->bh_running, |
1426 | info->pending_bh); | 1425 | info->pending_bh); |
1427 | |||
1428 | return ret; | ||
1429 | } | 1426 | } |
1430 | 1427 | ||
1431 | /* Called to print information about devices | 1428 | /* Called to print information about devices |
1432 | */ | 1429 | */ |
1433 | static int read_proc(char *page, char **start, off_t off, int count, | 1430 | static int synclinkmp_proc_show(struct seq_file *m, void *v) |
1434 | int *eof, void *data) | ||
1435 | { | 1431 | { |
1436 | int len = 0, l; | ||
1437 | off_t begin = 0; | ||
1438 | SLMP_INFO *info; | 1432 | SLMP_INFO *info; |
1439 | 1433 | ||
1440 | len += sprintf(page, "synclinkmp driver:%s\n", driver_version); | 1434 | seq_printf(m, "synclinkmp driver:%s\n", driver_version); |
1441 | 1435 | ||
1442 | info = synclinkmp_device_list; | 1436 | info = synclinkmp_device_list; |
1443 | while( info ) { | 1437 | while( info ) { |
1444 | l = line_info(page + len, info); | 1438 | line_info(m, info); |
1445 | len += l; | ||
1446 | if (len+begin > off+count) | ||
1447 | goto done; | ||
1448 | if (len+begin < off) { | ||
1449 | begin += len; | ||
1450 | len = 0; | ||
1451 | } | ||
1452 | info = info->next_device; | 1439 | info = info->next_device; |
1453 | } | 1440 | } |
1441 | return 0; | ||
1442 | } | ||
1454 | 1443 | ||
1455 | *eof = 1; | 1444 | static int synclinkmp_proc_open(struct inode *inode, struct file *file) |
1456 | done: | 1445 | { |
1457 | if (off >= len+begin) | 1446 | return single_open(file, synclinkmp_proc_show, NULL); |
1458 | return 0; | ||
1459 | *start = page + (off-begin); | ||
1460 | return ((count < begin+len-off) ? count : begin+len-off); | ||
1461 | } | 1447 | } |
1462 | 1448 | ||
1449 | static const struct file_operations synclinkmp_proc_fops = { | ||
1450 | .owner = THIS_MODULE, | ||
1451 | .open = synclinkmp_proc_open, | ||
1452 | .read = seq_read, | ||
1453 | .llseek = seq_lseek, | ||
1454 | .release = single_release, | ||
1455 | }; | ||
1456 | |||
1463 | /* Return the count of bytes in transmit buffer | 1457 | /* Return the count of bytes in transmit buffer |
1464 | */ | 1458 | */ |
1465 | static int chars_in_buffer(struct tty_struct *tty) | 1459 | static int chars_in_buffer(struct tty_struct *tty) |
@@ -3905,13 +3899,13 @@ static const struct tty_operations ops = { | |||
3905 | .send_xchar = send_xchar, | 3899 | .send_xchar = send_xchar, |
3906 | .break_ctl = set_break, | 3900 | .break_ctl = set_break, |
3907 | .wait_until_sent = wait_until_sent, | 3901 | .wait_until_sent = wait_until_sent, |
3908 | .read_proc = read_proc, | ||
3909 | .set_termios = set_termios, | 3902 | .set_termios = set_termios, |
3910 | .stop = tx_hold, | 3903 | .stop = tx_hold, |
3911 | .start = tx_release, | 3904 | .start = tx_release, |
3912 | .hangup = hangup, | 3905 | .hangup = hangup, |
3913 | .tiocmget = tiocmget, | 3906 | .tiocmget = tiocmget, |
3914 | .tiocmset = tiocmset, | 3907 | .tiocmset = tiocmset, |
3908 | .proc_fops = &synclinkmp_proc_fops, | ||
3915 | }; | 3909 | }; |
3916 | 3910 | ||
3917 | 3911 | ||
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 33a9351c896d..ebea9b2c30a5 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include <linux/vt_kern.h> | 35 | #include <linux/vt_kern.h> |
36 | #include <linux/workqueue.h> | 36 | #include <linux/workqueue.h> |
37 | #include <linux/kexec.h> | 37 | #include <linux/kexec.h> |
38 | #include <linux/irq.h> | 38 | #include <linux/interrupt.h> |
39 | #include <linux/hrtimer.h> | 39 | #include <linux/hrtimer.h> |
40 | #include <linux/oom.h> | 40 | #include <linux/oom.h> |
41 | 41 | ||
@@ -346,6 +346,19 @@ static struct sysrq_key_op sysrq_moom_op = { | |||
346 | .enable_mask = SYSRQ_ENABLE_SIGNAL, | 346 | .enable_mask = SYSRQ_ENABLE_SIGNAL, |
347 | }; | 347 | }; |
348 | 348 | ||
349 | #ifdef CONFIG_BLOCK | ||
350 | static void sysrq_handle_thaw(int key, struct tty_struct *tty) | ||
351 | { | ||
352 | emergency_thaw_all(); | ||
353 | } | ||
354 | static struct sysrq_key_op sysrq_thaw_op = { | ||
355 | .handler = sysrq_handle_thaw, | ||
356 | .help_msg = "thaw-filesystems(J)", | ||
357 | .action_msg = "Emergency Thaw of all frozen filesystems", | ||
358 | .enable_mask = SYSRQ_ENABLE_SIGNAL, | ||
359 | }; | ||
360 | #endif | ||
361 | |||
349 | static void sysrq_handle_kill(int key, struct tty_struct *tty) | 362 | static void sysrq_handle_kill(int key, struct tty_struct *tty) |
350 | { | 363 | { |
351 | send_sig_all(SIGKILL); | 364 | send_sig_all(SIGKILL); |
@@ -396,9 +409,13 @@ static struct sysrq_key_op *sysrq_key_table[36] = { | |||
396 | &sysrq_moom_op, /* f */ | 409 | &sysrq_moom_op, /* f */ |
397 | /* g: May be registered by ppc for kgdb */ | 410 | /* g: May be registered by ppc for kgdb */ |
398 | NULL, /* g */ | 411 | NULL, /* g */ |
399 | NULL, /* h */ | 412 | NULL, /* h - reserved for help */ |
400 | &sysrq_kill_op, /* i */ | 413 | &sysrq_kill_op, /* i */ |
414 | #ifdef CONFIG_BLOCK | ||
415 | &sysrq_thaw_op, /* j */ | ||
416 | #else | ||
401 | NULL, /* j */ | 417 | NULL, /* j */ |
418 | #endif | ||
402 | &sysrq_SAK_op, /* k */ | 419 | &sysrq_SAK_op, /* k */ |
403 | #ifdef CONFIG_SMP | 420 | #ifdef CONFIG_SMP |
404 | &sysrq_showallcpus_op, /* l */ | 421 | &sysrq_showallcpus_op, /* l */ |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 224f271d8cbe..33dac94922a7 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -464,7 +464,7 @@ void tty_wakeup(struct tty_struct *tty) | |||
464 | tty_ldisc_deref(ld); | 464 | tty_ldisc_deref(ld); |
465 | } | 465 | } |
466 | } | 466 | } |
467 | wake_up_interruptible(&tty->write_wait); | 467 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); |
468 | } | 468 | } |
469 | 469 | ||
470 | EXPORT_SYMBOL_GPL(tty_wakeup); | 470 | EXPORT_SYMBOL_GPL(tty_wakeup); |
@@ -587,8 +587,8 @@ static void do_tty_hangup(struct work_struct *work) | |||
587 | * FIXME: Once we trust the LDISC code better we can wait here for | 587 | * FIXME: Once we trust the LDISC code better we can wait here for |
588 | * ldisc completion and fix the driver call race | 588 | * ldisc completion and fix the driver call race |
589 | */ | 589 | */ |
590 | wake_up_interruptible(&tty->write_wait); | 590 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); |
591 | wake_up_interruptible(&tty->read_wait); | 591 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); |
592 | /* | 592 | /* |
593 | * Shutdown the current line discipline, and reset it to | 593 | * Shutdown the current line discipline, and reset it to |
594 | * N_TTY. | 594 | * N_TTY. |
@@ -879,7 +879,7 @@ void stop_tty(struct tty_struct *tty) | |||
879 | if (tty->link && tty->link->packet) { | 879 | if (tty->link && tty->link->packet) { |
880 | tty->ctrl_status &= ~TIOCPKT_START; | 880 | tty->ctrl_status &= ~TIOCPKT_START; |
881 | tty->ctrl_status |= TIOCPKT_STOP; | 881 | tty->ctrl_status |= TIOCPKT_STOP; |
882 | wake_up_interruptible(&tty->link->read_wait); | 882 | wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); |
883 | } | 883 | } |
884 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 884 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
885 | if (tty->ops->stop) | 885 | if (tty->ops->stop) |
@@ -913,7 +913,7 @@ void start_tty(struct tty_struct *tty) | |||
913 | if (tty->link && tty->link->packet) { | 913 | if (tty->link && tty->link->packet) { |
914 | tty->ctrl_status &= ~TIOCPKT_STOP; | 914 | tty->ctrl_status &= ~TIOCPKT_STOP; |
915 | tty->ctrl_status |= TIOCPKT_START; | 915 | tty->ctrl_status |= TIOCPKT_START; |
916 | wake_up_interruptible(&tty->link->read_wait); | 916 | wake_up_interruptible_poll(&tty->link->read_wait, POLLIN); |
917 | } | 917 | } |
918 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 918 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
919 | if (tty->ops->start) | 919 | if (tty->ops->start) |
@@ -970,7 +970,7 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, | |||
970 | void tty_write_unlock(struct tty_struct *tty) | 970 | void tty_write_unlock(struct tty_struct *tty) |
971 | { | 971 | { |
972 | mutex_unlock(&tty->atomic_write_lock); | 972 | mutex_unlock(&tty->atomic_write_lock); |
973 | wake_up_interruptible(&tty->write_wait); | 973 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); |
974 | } | 974 | } |
975 | 975 | ||
976 | int tty_write_lock(struct tty_struct *tty, int ndelay) | 976 | int tty_write_lock(struct tty_struct *tty, int ndelay) |
@@ -1623,21 +1623,21 @@ void tty_release_dev(struct file *filp) | |||
1623 | 1623 | ||
1624 | if (tty_closing) { | 1624 | if (tty_closing) { |
1625 | if (waitqueue_active(&tty->read_wait)) { | 1625 | if (waitqueue_active(&tty->read_wait)) { |
1626 | wake_up(&tty->read_wait); | 1626 | wake_up_poll(&tty->read_wait, POLLIN); |
1627 | do_sleep++; | 1627 | do_sleep++; |
1628 | } | 1628 | } |
1629 | if (waitqueue_active(&tty->write_wait)) { | 1629 | if (waitqueue_active(&tty->write_wait)) { |
1630 | wake_up(&tty->write_wait); | 1630 | wake_up_poll(&tty->write_wait, POLLOUT); |
1631 | do_sleep++; | 1631 | do_sleep++; |
1632 | } | 1632 | } |
1633 | } | 1633 | } |
1634 | if (o_tty_closing) { | 1634 | if (o_tty_closing) { |
1635 | if (waitqueue_active(&o_tty->read_wait)) { | 1635 | if (waitqueue_active(&o_tty->read_wait)) { |
1636 | wake_up(&o_tty->read_wait); | 1636 | wake_up_poll(&o_tty->read_wait, POLLIN); |
1637 | do_sleep++; | 1637 | do_sleep++; |
1638 | } | 1638 | } |
1639 | if (waitqueue_active(&o_tty->write_wait)) { | 1639 | if (waitqueue_active(&o_tty->write_wait)) { |
1640 | wake_up(&o_tty->write_wait); | 1640 | wake_up_poll(&o_tty->write_wait, POLLOUT); |
1641 | do_sleep++; | 1641 | do_sleep++; |
1642 | } | 1642 | } |
1643 | } | 1643 | } |
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 8f0f7c449305..5f1b5400d96a 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c | |||
@@ -68,7 +68,8 @@ static char * __init dmi_string(const struct dmi_header *dm, u8 s) | |||
68 | * pointing to completely the wrong place for example | 68 | * pointing to completely the wrong place for example |
69 | */ | 69 | */ |
70 | static void dmi_table(u8 *buf, int len, int num, | 70 | static void dmi_table(u8 *buf, int len, int num, |
71 | void (*decode)(const struct dmi_header *)) | 71 | void (*decode)(const struct dmi_header *, void *), |
72 | void *private_data) | ||
72 | { | 73 | { |
73 | u8 *data = buf; | 74 | u8 *data = buf; |
74 | int i = 0; | 75 | int i = 0; |
@@ -89,7 +90,7 @@ static void dmi_table(u8 *buf, int len, int num, | |||
89 | while ((data - buf < len - 1) && (data[0] || data[1])) | 90 | while ((data - buf < len - 1) && (data[0] || data[1])) |
90 | data++; | 91 | data++; |
91 | if (data - buf < len - 1) | 92 | if (data - buf < len - 1) |
92 | decode(dm); | 93 | decode(dm, private_data); |
93 | data += 2; | 94 | data += 2; |
94 | i++; | 95 | i++; |
95 | } | 96 | } |
@@ -99,7 +100,8 @@ static u32 dmi_base; | |||
99 | static u16 dmi_len; | 100 | static u16 dmi_len; |
100 | static u16 dmi_num; | 101 | static u16 dmi_num; |
101 | 102 | ||
102 | static int __init dmi_walk_early(void (*decode)(const struct dmi_header *)) | 103 | static int __init dmi_walk_early(void (*decode)(const struct dmi_header *, |
104 | void *)) | ||
103 | { | 105 | { |
104 | u8 *buf; | 106 | u8 *buf; |
105 | 107 | ||
@@ -107,7 +109,7 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *)) | |||
107 | if (buf == NULL) | 109 | if (buf == NULL) |
108 | return -1; | 110 | return -1; |
109 | 111 | ||
110 | dmi_table(buf, dmi_len, dmi_num, decode); | 112 | dmi_table(buf, dmi_len, dmi_num, decode, NULL); |
111 | 113 | ||
112 | dmi_iounmap(buf, dmi_len); | 114 | dmi_iounmap(buf, dmi_len); |
113 | return 0; | 115 | return 0; |
@@ -295,7 +297,7 @@ static void __init dmi_save_extended_devices(const struct dmi_header *dm) | |||
295 | * and machine entries. For 2.5 we should pull the smbus controller info | 297 | * and machine entries. For 2.5 we should pull the smbus controller info |
296 | * out of here. | 298 | * out of here. |
297 | */ | 299 | */ |
298 | static void __init dmi_decode(const struct dmi_header *dm) | 300 | static void __init dmi_decode(const struct dmi_header *dm, void *dummy) |
299 | { | 301 | { |
300 | switch(dm->type) { | 302 | switch(dm->type) { |
301 | case 0: /* BIOS Information */ | 303 | case 0: /* BIOS Information */ |
@@ -598,10 +600,12 @@ int dmi_get_year(int field) | |||
598 | /** | 600 | /** |
599 | * dmi_walk - Walk the DMI table and get called back for every record | 601 | * dmi_walk - Walk the DMI table and get called back for every record |
600 | * @decode: Callback function | 602 | * @decode: Callback function |
603 | * @private_data: Private data to be passed to the callback function | ||
601 | * | 604 | * |
602 | * Returns -1 when the DMI table can't be reached, 0 on success. | 605 | * Returns -1 when the DMI table can't be reached, 0 on success. |
603 | */ | 606 | */ |
604 | int dmi_walk(void (*decode)(const struct dmi_header *)) | 607 | int dmi_walk(void (*decode)(const struct dmi_header *, void *), |
608 | void *private_data) | ||
605 | { | 609 | { |
606 | u8 *buf; | 610 | u8 *buf; |
607 | 611 | ||
@@ -612,7 +616,7 @@ int dmi_walk(void (*decode)(const struct dmi_header *)) | |||
612 | if (buf == NULL) | 616 | if (buf == NULL) |
613 | return -1; | 617 | return -1; |
614 | 618 | ||
615 | dmi_table(buf, dmi_len, dmi_num, decode); | 619 | dmi_table(buf, dmi_len, dmi_num, decode, private_data); |
616 | 620 | ||
617 | iounmap(buf); | 621 | iounmap(buf); |
618 | return 0; | 622 | return 0; |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index b4eea0292c1a..ce52bf2f235e 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -343,12 +343,13 @@ config SENSORS_FSCPOS | |||
343 | will be called fscpos. | 343 | will be called fscpos. |
344 | 344 | ||
345 | config SENSORS_FSCHMD | 345 | config SENSORS_FSCHMD |
346 | tristate "FSC Poseidon, Scylla, Hermes, Heimdall and Heracles" | 346 | tristate "Fujitsu Siemens Computers sensor chips" |
347 | depends on X86 && I2C | 347 | depends on X86 && I2C |
348 | help | 348 | help |
349 | If you say yes here you get support for various Fujitsu Siemens | 349 | If you say yes here you get support for the following Fujitsu |
350 | Computers sensor chips, including support for the integrated | 350 | Siemens Computers (FSC) sensor chips: Poseidon, Scylla, Hermes, |
351 | watchdog. | 351 | Heimdall, Heracles, Hades and Syleus including support for the |
352 | integrated watchdog. | ||
352 | 353 | ||
353 | This is a merged driver for FSC sensor chips replacing the fscpos, | 354 | This is a merged driver for FSC sensor chips replacing the fscpos, |
354 | fscscy and fscher drivers and adding support for several other FSC | 355 | fscscy and fscher drivers and adding support for several other FSC |
@@ -570,6 +571,17 @@ config SENSORS_LM93 | |||
570 | This driver can also be built as a module. If so, the module | 571 | This driver can also be built as a module. If so, the module |
571 | will be called lm93. | 572 | will be called lm93. |
572 | 573 | ||
574 | config SENSORS_LTC4215 | ||
575 | tristate "Linear Technology LTC4215" | ||
576 | depends on I2C && EXPERIMENTAL | ||
577 | default n | ||
578 | help | ||
579 | If you say yes here you get support for Linear Technology LTC4215 | ||
580 | Hot Swap Controller I2C interface. | ||
581 | |||
582 | This driver can also be built as a module. If so, the module will | ||
583 | be called ltc4215. | ||
584 | |||
573 | config SENSORS_LTC4245 | 585 | config SENSORS_LTC4245 |
574 | tristate "Linear Technology LTC4245" | 586 | tristate "Linear Technology LTC4245" |
575 | depends on I2C && EXPERIMENTAL | 587 | depends on I2C && EXPERIMENTAL |
@@ -581,6 +593,15 @@ config SENSORS_LTC4245 | |||
581 | This driver can also be built as a module. If so, the module will | 593 | This driver can also be built as a module. If so, the module will |
582 | be called ltc4245. | 594 | be called ltc4245. |
583 | 595 | ||
596 | config SENSORS_LM95241 | ||
597 | tristate "National Semiconductor LM95241 sensor chip" | ||
598 | depends on I2C | ||
599 | help | ||
600 | If you say yes here you get support for LM95241 sensor chip. | ||
601 | |||
602 | This driver can also be built as a module. If so, the module | ||
603 | will be called lm95241. | ||
604 | |||
584 | config SENSORS_MAX1111 | 605 | config SENSORS_MAX1111 |
585 | tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" | 606 | tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" |
586 | depends on SPI_MASTER | 607 | depends on SPI_MASTER |
@@ -635,6 +656,20 @@ config SENSORS_PC87427 | |||
635 | This driver can also be built as a module. If so, the module | 656 | This driver can also be built as a module. If so, the module |
636 | will be called pc87427. | 657 | will be called pc87427. |
637 | 658 | ||
659 | config SENSORS_PCF8591 | ||
660 | tristate "Philips PCF8591 ADC/DAC" | ||
661 | depends on I2C | ||
662 | default n | ||
663 | help | ||
664 | If you say yes here you get support for Philips PCF8591 4-channel | ||
665 | ADC, 1-channel DAC chips. | ||
666 | |||
667 | This driver can also be built as a module. If so, the module | ||
668 | will be called pcf8591. | ||
669 | |||
670 | These devices are hard to detect and rarely found on mainstream | ||
671 | hardware. If unsure, say N. | ||
672 | |||
638 | config SENSORS_SIS5595 | 673 | config SENSORS_SIS5595 |
639 | tristate "Silicon Integrated Systems Corp. SiS5595" | 674 | tristate "Silicon Integrated Systems Corp. SiS5595" |
640 | depends on PCI | 675 | depends on PCI |
@@ -827,7 +862,7 @@ config SENSORS_W83627HF | |||
827 | will be called w83627hf. | 862 | will be called w83627hf. |
828 | 863 | ||
829 | config SENSORS_W83627EHF | 864 | config SENSORS_W83627EHF |
830 | tristate "Winbond W83627EHF/DHG" | 865 | tristate "Winbond W83627EHF/EHG/DHG, W83667HG" |
831 | select HWMON_VID | 866 | select HWMON_VID |
832 | help | 867 | help |
833 | If you say yes here you get support for the hardware | 868 | If you say yes here you get support for the hardware |
@@ -838,6 +873,8 @@ config SENSORS_W83627EHF | |||
838 | chip suited for specific Intel processors that use PECI such as | 873 | chip suited for specific Intel processors that use PECI such as |
839 | the Core 2 Duo. | 874 | the Core 2 Duo. |
840 | 875 | ||
876 | This driver also supports the W83667HG chip. | ||
877 | |||
841 | This driver can also be built as a module. If so, the module | 878 | This driver can also be built as a module. If so, the module |
842 | will be called w83627ehf. | 879 | will be called w83627ehf. |
843 | 880 | ||
@@ -895,6 +932,22 @@ config SENSORS_LIS3LV02D | |||
895 | Say Y here if you have an applicable laptop and want to experience | 932 | Say Y here if you have an applicable laptop and want to experience |
896 | the awesome power of lis3lv02d. | 933 | the awesome power of lis3lv02d. |
897 | 934 | ||
935 | config SENSORS_LIS3_SPI | ||
936 | tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)" | ||
937 | depends on !ACPI && SPI_MASTER && INPUT | ||
938 | default n | ||
939 | help | ||
940 | This driver provides support for the LIS3LV02Dx accelerometer connected | ||
941 | via SPI. The accelerometer data is readable via | ||
942 | /sys/devices/platform/lis3lv02d. | ||
943 | |||
944 | This driver also provides an absolute input class device, allowing | ||
945 | the laptop to act as a pinball machine-esque joystick. | ||
946 | |||
947 | This driver can also be built as modules. If so, the core module | ||
948 | will be called lis3lv02d and a specific module for the SPI transport | ||
949 | is called lis3lv02d_spi. | ||
950 | |||
898 | config SENSORS_APPLESMC | 951 | config SENSORS_APPLESMC |
899 | tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)" | 952 | tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)" |
900 | depends on INPUT && X86 | 953 | depends on INPUT && X86 |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 2e80f37f39eb..3a6b1f06f8f4 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -52,6 +52,7 @@ obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o | |||
52 | obj-$(CONFIG_SENSORS_IT87) += it87.o | 52 | obj-$(CONFIG_SENSORS_IT87) += it87.o |
53 | obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o | 53 | obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o |
54 | obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o | 54 | obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o |
55 | obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o | ||
55 | obj-$(CONFIG_SENSORS_LM63) += lm63.o | 56 | obj-$(CONFIG_SENSORS_LM63) += lm63.o |
56 | obj-$(CONFIG_SENSORS_LM70) += lm70.o | 57 | obj-$(CONFIG_SENSORS_LM70) += lm70.o |
57 | obj-$(CONFIG_SENSORS_LM75) += lm75.o | 58 | obj-$(CONFIG_SENSORS_LM75) += lm75.o |
@@ -64,12 +65,15 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o | |||
64 | obj-$(CONFIG_SENSORS_LM90) += lm90.o | 65 | obj-$(CONFIG_SENSORS_LM90) += lm90.o |
65 | obj-$(CONFIG_SENSORS_LM92) += lm92.o | 66 | obj-$(CONFIG_SENSORS_LM92) += lm92.o |
66 | obj-$(CONFIG_SENSORS_LM93) += lm93.o | 67 | obj-$(CONFIG_SENSORS_LM93) += lm93.o |
68 | obj-$(CONFIG_SENSORS_LM95241) += lm95241.o | ||
69 | obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o | ||
67 | obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o | 70 | obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o |
68 | obj-$(CONFIG_SENSORS_MAX1111) += max1111.o | 71 | obj-$(CONFIG_SENSORS_MAX1111) += max1111.o |
69 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o | 72 | obj-$(CONFIG_SENSORS_MAX1619) += max1619.o |
70 | obj-$(CONFIG_SENSORS_MAX6650) += max6650.o | 73 | obj-$(CONFIG_SENSORS_MAX6650) += max6650.o |
71 | obj-$(CONFIG_SENSORS_PC87360) += pc87360.o | 74 | obj-$(CONFIG_SENSORS_PC87360) += pc87360.o |
72 | obj-$(CONFIG_SENSORS_PC87427) += pc87427.o | 75 | obj-$(CONFIG_SENSORS_PC87427) += pc87427.o |
76 | obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o | ||
73 | obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o | 77 | obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o |
74 | obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o | 78 | obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o |
75 | obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o | 79 | obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o |
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c index 7415381601c3..53f88f511816 100644 --- a/drivers/hwmon/ds1621.c +++ b/drivers/hwmon/ds1621.c | |||
@@ -81,71 +81,84 @@ struct ds1621_data { | |||
81 | u8 conf; /* Register encoding, combined */ | 81 | u8 conf; /* Register encoding, combined */ |
82 | }; | 82 | }; |
83 | 83 | ||
84 | static int ds1621_probe(struct i2c_client *client, | 84 | /* Temperature registers are word-sized. |
85 | const struct i2c_device_id *id); | ||
86 | static int ds1621_detect(struct i2c_client *client, int kind, | ||
87 | struct i2c_board_info *info); | ||
88 | static void ds1621_init_client(struct i2c_client *client); | ||
89 | static int ds1621_remove(struct i2c_client *client); | ||
90 | static struct ds1621_data *ds1621_update_client(struct device *dev); | ||
91 | |||
92 | static const struct i2c_device_id ds1621_id[] = { | ||
93 | { "ds1621", ds1621 }, | ||
94 | { "ds1625", ds1621 }, | ||
95 | { } | ||
96 | }; | ||
97 | MODULE_DEVICE_TABLE(i2c, ds1621_id); | ||
98 | |||
99 | /* This is the driver that will be inserted */ | ||
100 | static struct i2c_driver ds1621_driver = { | ||
101 | .class = I2C_CLASS_HWMON, | ||
102 | .driver = { | ||
103 | .name = "ds1621", | ||
104 | }, | ||
105 | .probe = ds1621_probe, | ||
106 | .remove = ds1621_remove, | ||
107 | .id_table = ds1621_id, | ||
108 | .detect = ds1621_detect, | ||
109 | .address_data = &addr_data, | ||
110 | }; | ||
111 | |||
112 | /* All registers are word-sized, except for the configuration register. | ||
113 | DS1621 uses a high-byte first convention, which is exactly opposite to | 85 | DS1621 uses a high-byte first convention, which is exactly opposite to |
114 | the SMBus standard. */ | 86 | the SMBus standard. */ |
115 | static int ds1621_read_value(struct i2c_client *client, u8 reg) | 87 | static int ds1621_read_temp(struct i2c_client *client, u8 reg) |
116 | { | 88 | { |
117 | if (reg == DS1621_REG_CONF) | 89 | int ret; |
118 | return i2c_smbus_read_byte_data(client, reg); | 90 | |
119 | else | 91 | ret = i2c_smbus_read_word_data(client, reg); |
120 | return swab16(i2c_smbus_read_word_data(client, reg)); | 92 | if (ret < 0) |
93 | return ret; | ||
94 | return swab16(ret); | ||
121 | } | 95 | } |
122 | 96 | ||
123 | static int ds1621_write_value(struct i2c_client *client, u8 reg, u16 value) | 97 | static int ds1621_write_temp(struct i2c_client *client, u8 reg, u16 value) |
124 | { | 98 | { |
125 | if (reg == DS1621_REG_CONF) | 99 | return i2c_smbus_write_word_data(client, reg, swab16(value)); |
126 | return i2c_smbus_write_byte_data(client, reg, value); | ||
127 | else | ||
128 | return i2c_smbus_write_word_data(client, reg, swab16(value)); | ||
129 | } | 100 | } |
130 | 101 | ||
131 | static void ds1621_init_client(struct i2c_client *client) | 102 | static void ds1621_init_client(struct i2c_client *client) |
132 | { | 103 | { |
133 | int reg = ds1621_read_value(client, DS1621_REG_CONF); | 104 | u8 conf, new_conf; |
105 | |||
106 | new_conf = conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); | ||
134 | /* switch to continuous conversion mode */ | 107 | /* switch to continuous conversion mode */ |
135 | reg &= ~ DS1621_REG_CONFIG_1SHOT; | 108 | new_conf &= ~DS1621_REG_CONFIG_1SHOT; |
136 | 109 | ||
137 | /* setup output polarity */ | 110 | /* setup output polarity */ |
138 | if (polarity == 0) | 111 | if (polarity == 0) |
139 | reg &= ~DS1621_REG_CONFIG_POLARITY; | 112 | new_conf &= ~DS1621_REG_CONFIG_POLARITY; |
140 | else if (polarity == 1) | 113 | else if (polarity == 1) |
141 | reg |= DS1621_REG_CONFIG_POLARITY; | 114 | new_conf |= DS1621_REG_CONFIG_POLARITY; |
142 | 115 | ||
143 | ds1621_write_value(client, DS1621_REG_CONF, reg); | 116 | if (conf != new_conf) |
117 | i2c_smbus_write_byte_data(client, DS1621_REG_CONF, new_conf); | ||
144 | 118 | ||
145 | /* start conversion */ | 119 | /* start conversion */ |
146 | i2c_smbus_write_byte(client, DS1621_COM_START); | 120 | i2c_smbus_write_byte(client, DS1621_COM_START); |
147 | } | 121 | } |
148 | 122 | ||
123 | static struct ds1621_data *ds1621_update_client(struct device *dev) | ||
124 | { | ||
125 | struct i2c_client *client = to_i2c_client(dev); | ||
126 | struct ds1621_data *data = i2c_get_clientdata(client); | ||
127 | u8 new_conf; | ||
128 | |||
129 | mutex_lock(&data->update_lock); | ||
130 | |||
131 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | ||
132 | || !data->valid) { | ||
133 | int i; | ||
134 | |||
135 | dev_dbg(&client->dev, "Starting ds1621 update\n"); | ||
136 | |||
137 | data->conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); | ||
138 | |||
139 | for (i = 0; i < ARRAY_SIZE(data->temp); i++) | ||
140 | data->temp[i] = ds1621_read_temp(client, | ||
141 | DS1621_REG_TEMP[i]); | ||
142 | |||
143 | /* reset alarms if necessary */ | ||
144 | new_conf = data->conf; | ||
145 | if (data->temp[0] > data->temp[1]) /* input > min */ | ||
146 | new_conf &= ~DS1621_ALARM_TEMP_LOW; | ||
147 | if (data->temp[0] < data->temp[2]) /* input < max */ | ||
148 | new_conf &= ~DS1621_ALARM_TEMP_HIGH; | ||
149 | if (data->conf != new_conf) | ||
150 | i2c_smbus_write_byte_data(client, DS1621_REG_CONF, | ||
151 | new_conf); | ||
152 | |||
153 | data->last_updated = jiffies; | ||
154 | data->valid = 1; | ||
155 | } | ||
156 | |||
157 | mutex_unlock(&data->update_lock); | ||
158 | |||
159 | return data; | ||
160 | } | ||
161 | |||
149 | static ssize_t show_temp(struct device *dev, struct device_attribute *da, | 162 | static ssize_t show_temp(struct device *dev, struct device_attribute *da, |
150 | char *buf) | 163 | char *buf) |
151 | { | 164 | { |
@@ -160,13 +173,13 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, | |||
160 | { | 173 | { |
161 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | 174 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); |
162 | struct i2c_client *client = to_i2c_client(dev); | 175 | struct i2c_client *client = to_i2c_client(dev); |
163 | struct ds1621_data *data = ds1621_update_client(dev); | 176 | struct ds1621_data *data = i2c_get_clientdata(client); |
164 | u16 val = LM75_TEMP_TO_REG(simple_strtol(buf, NULL, 10)); | 177 | u16 val = LM75_TEMP_TO_REG(simple_strtol(buf, NULL, 10)); |
165 | 178 | ||
166 | mutex_lock(&data->update_lock); | 179 | mutex_lock(&data->update_lock); |
167 | data->temp[attr->index] = val; | 180 | data->temp[attr->index] = val; |
168 | ds1621_write_value(client, DS1621_REG_TEMP[attr->index], | 181 | ds1621_write_temp(client, DS1621_REG_TEMP[attr->index], |
169 | data->temp[attr->index]); | 182 | data->temp[attr->index]); |
170 | mutex_unlock(&data->update_lock); | 183 | mutex_unlock(&data->update_lock); |
171 | return count; | 184 | return count; |
172 | } | 185 | } |
@@ -228,13 +241,14 @@ static int ds1621_detect(struct i2c_client *client, int kind, | |||
228 | /* The NVB bit should be low if no EEPROM write has been | 241 | /* The NVB bit should be low if no EEPROM write has been |
229 | requested during the latest 10ms, which is highly | 242 | requested during the latest 10ms, which is highly |
230 | improbable in our case. */ | 243 | improbable in our case. */ |
231 | conf = ds1621_read_value(client, DS1621_REG_CONF); | 244 | conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); |
232 | if (conf & DS1621_REG_CONFIG_NVB) | 245 | if (conf < 0 || conf & DS1621_REG_CONFIG_NVB) |
233 | return -ENODEV; | 246 | return -ENODEV; |
234 | /* The 7 lowest bits of a temperature should always be 0. */ | 247 | /* The 7 lowest bits of a temperature should always be 0. */ |
235 | for (i = 0; i < ARRAY_SIZE(DS1621_REG_TEMP); i++) { | 248 | for (i = 0; i < ARRAY_SIZE(DS1621_REG_TEMP); i++) { |
236 | temp = ds1621_read_value(client, DS1621_REG_TEMP[i]); | 249 | temp = i2c_smbus_read_word_data(client, |
237 | if (temp & 0x007f) | 250 | DS1621_REG_TEMP[i]); |
251 | if (temp < 0 || (temp & 0x7f00)) | ||
238 | return -ENODEV; | 252 | return -ENODEV; |
239 | } | 253 | } |
240 | } | 254 | } |
@@ -294,45 +308,25 @@ static int ds1621_remove(struct i2c_client *client) | |||
294 | return 0; | 308 | return 0; |
295 | } | 309 | } |
296 | 310 | ||
311 | static const struct i2c_device_id ds1621_id[] = { | ||
312 | { "ds1621", ds1621 }, | ||
313 | { "ds1625", ds1621 }, | ||
314 | { } | ||
315 | }; | ||
316 | MODULE_DEVICE_TABLE(i2c, ds1621_id); | ||
297 | 317 | ||
298 | static struct ds1621_data *ds1621_update_client(struct device *dev) | 318 | /* This is the driver that will be inserted */ |
299 | { | 319 | static struct i2c_driver ds1621_driver = { |
300 | struct i2c_client *client = to_i2c_client(dev); | 320 | .class = I2C_CLASS_HWMON, |
301 | struct ds1621_data *data = i2c_get_clientdata(client); | 321 | .driver = { |
302 | u8 new_conf; | 322 | .name = "ds1621", |
303 | 323 | }, | |
304 | mutex_lock(&data->update_lock); | 324 | .probe = ds1621_probe, |
305 | 325 | .remove = ds1621_remove, | |
306 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | 326 | .id_table = ds1621_id, |
307 | || !data->valid) { | 327 | .detect = ds1621_detect, |
308 | int i; | 328 | .address_data = &addr_data, |
309 | 329 | }; | |
310 | dev_dbg(&client->dev, "Starting ds1621 update\n"); | ||
311 | |||
312 | data->conf = ds1621_read_value(client, DS1621_REG_CONF); | ||
313 | |||
314 | for (i = 0; i < ARRAY_SIZE(data->temp); i++) | ||
315 | data->temp[i] = ds1621_read_value(client, | ||
316 | DS1621_REG_TEMP[i]); | ||
317 | |||
318 | /* reset alarms if necessary */ | ||
319 | new_conf = data->conf; | ||
320 | if (data->temp[0] > data->temp[1]) /* input > min */ | ||
321 | new_conf &= ~DS1621_ALARM_TEMP_LOW; | ||
322 | if (data->temp[0] < data->temp[2]) /* input < max */ | ||
323 | new_conf &= ~DS1621_ALARM_TEMP_HIGH; | ||
324 | if (data->conf != new_conf) | ||
325 | ds1621_write_value(client, DS1621_REG_CONF, | ||
326 | new_conf); | ||
327 | |||
328 | data->last_updated = jiffies; | ||
329 | data->valid = 1; | ||
330 | } | ||
331 | |||
332 | mutex_unlock(&data->update_lock); | ||
333 | |||
334 | return data; | ||
335 | } | ||
336 | 330 | ||
337 | static int __init ds1621_init(void) | 331 | static int __init ds1621_init(void) |
338 | { | 332 | { |
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index d07f4ef75092..ea955edde87e 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* fschmd.c | 1 | /* fschmd.c |
2 | * | 2 | * |
3 | * Copyright (C) 2007,2008 Hans de Goede <hdegoede@redhat.com> | 3 | * Copyright (C) 2007 - 2009 Hans de Goede <hdegoede@redhat.com> |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | /* | 20 | /* |
21 | * Merged Fujitsu Siemens hwmon driver, supporting the Poseidon, Hermes, | 21 | * Merged Fujitsu Siemens hwmon driver, supporting the Poseidon, Hermes, |
22 | * Scylla, Heracles and Heimdall chips | 22 | * Scylla, Heracles, Heimdall, Hades and Syleus chips |
23 | * | 23 | * |
24 | * Based on the original 2.4 fscscy, 2.6 fscpos, 2.6 fscher and 2.6 | 24 | * Based on the original 2.4 fscscy, 2.6 fscpos, 2.6 fscher and 2.6 |
25 | * (candidate) fschmd drivers: | 25 | * (candidate) fschmd drivers: |
@@ -56,7 +56,7 @@ static int nowayout = WATCHDOG_NOWAYOUT; | |||
56 | module_param(nowayout, int, 0); | 56 | module_param(nowayout, int, 0); |
57 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | 57 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" |
58 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 58 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); |
59 | I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd); | 59 | I2C_CLIENT_INSMOD_7(fscpos, fscher, fscscy, fschrc, fschmd, fschds, fscsyl); |
60 | 60 | ||
61 | /* | 61 | /* |
62 | * The FSCHMD registers and other defines | 62 | * The FSCHMD registers and other defines |
@@ -75,9 +75,12 @@ I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd); | |||
75 | #define FSCHMD_CONTROL_ALERT_LED 0x01 | 75 | #define FSCHMD_CONTROL_ALERT_LED 0x01 |
76 | 76 | ||
77 | /* watchdog */ | 77 | /* watchdog */ |
78 | #define FSCHMD_REG_WDOG_PRESET 0x28 | 78 | static const u8 FSCHMD_REG_WDOG_CONTROL[7] = |
79 | #define FSCHMD_REG_WDOG_STATE 0x23 | 79 | { 0x21, 0x21, 0x21, 0x21, 0x21, 0x28, 0x28 }; |
80 | #define FSCHMD_REG_WDOG_CONTROL 0x21 | 80 | static const u8 FSCHMD_REG_WDOG_STATE[7] = |
81 | { 0x23, 0x23, 0x23, 0x23, 0x23, 0x29, 0x29 }; | ||
82 | static const u8 FSCHMD_REG_WDOG_PRESET[7] = | ||
83 | { 0x28, 0x28, 0x28, 0x28, 0x28, 0x2a, 0x2a }; | ||
81 | 84 | ||
82 | #define FSCHMD_WDOG_CONTROL_TRIGGER 0x10 | 85 | #define FSCHMD_WDOG_CONTROL_TRIGGER 0x10 |
83 | #define FSCHMD_WDOG_CONTROL_STARTED 0x10 /* the same as trigger */ | 86 | #define FSCHMD_WDOG_CONTROL_STARTED 0x10 /* the same as trigger */ |
@@ -87,70 +90,95 @@ I2C_CLIENT_INSMOD_5(fscpos, fscher, fscscy, fschrc, fschmd); | |||
87 | #define FSCHMD_WDOG_STATE_CARDRESET 0x02 | 90 | #define FSCHMD_WDOG_STATE_CARDRESET 0x02 |
88 | 91 | ||
89 | /* voltages, weird order is to keep the same order as the old drivers */ | 92 | /* voltages, weird order is to keep the same order as the old drivers */ |
90 | static const u8 FSCHMD_REG_VOLT[3] = { 0x45, 0x42, 0x48 }; | 93 | static const u8 FSCHMD_REG_VOLT[7][6] = { |
94 | { 0x45, 0x42, 0x48 }, /* pos */ | ||
95 | { 0x45, 0x42, 0x48 }, /* her */ | ||
96 | { 0x45, 0x42, 0x48 }, /* scy */ | ||
97 | { 0x45, 0x42, 0x48 }, /* hrc */ | ||
98 | { 0x45, 0x42, 0x48 }, /* hmd */ | ||
99 | { 0x21, 0x20, 0x22 }, /* hds */ | ||
100 | { 0x21, 0x20, 0x22, 0x23, 0x24, 0x25 }, /* syl */ | ||
101 | }; | ||
102 | |||
103 | static const int FSCHMD_NO_VOLT_SENSORS[7] = { 3, 3, 3, 3, 3, 3, 6 }; | ||
91 | 104 | ||
92 | /* minimum pwm at which the fan is driven (pwm can by increased depending on | 105 | /* minimum pwm at which the fan is driven (pwm can by increased depending on |
93 | the temp. Notice that for the scy some fans share there minimum speed. | 106 | the temp. Notice that for the scy some fans share there minimum speed. |
94 | Also notice that with the scy the sensor order is different than with the | 107 | Also notice that with the scy the sensor order is different than with the |
95 | other chips, this order was in the 2.4 driver and kept for consistency. */ | 108 | other chips, this order was in the 2.4 driver and kept for consistency. */ |
96 | static const u8 FSCHMD_REG_FAN_MIN[5][6] = { | 109 | static const u8 FSCHMD_REG_FAN_MIN[7][7] = { |
97 | { 0x55, 0x65 }, /* pos */ | 110 | { 0x55, 0x65 }, /* pos */ |
98 | { 0x55, 0x65, 0xb5 }, /* her */ | 111 | { 0x55, 0x65, 0xb5 }, /* her */ |
99 | { 0x65, 0x65, 0x55, 0xa5, 0x55, 0xa5 }, /* scy */ | 112 | { 0x65, 0x65, 0x55, 0xa5, 0x55, 0xa5 }, /* scy */ |
100 | { 0x55, 0x65, 0xa5, 0xb5 }, /* hrc */ | 113 | { 0x55, 0x65, 0xa5, 0xb5 }, /* hrc */ |
101 | { 0x55, 0x65, 0xa5, 0xb5, 0xc5 }, /* hmd */ | 114 | { 0x55, 0x65, 0xa5, 0xb5, 0xc5 }, /* hmd */ |
115 | { 0x55, 0x65, 0xa5, 0xb5, 0xc5 }, /* hds */ | ||
116 | { 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb4 }, /* syl */ | ||
102 | }; | 117 | }; |
103 | 118 | ||
104 | /* actual fan speed */ | 119 | /* actual fan speed */ |
105 | static const u8 FSCHMD_REG_FAN_ACT[5][6] = { | 120 | static const u8 FSCHMD_REG_FAN_ACT[7][7] = { |
106 | { 0x0e, 0x6b, 0xab }, /* pos */ | 121 | { 0x0e, 0x6b, 0xab }, /* pos */ |
107 | { 0x0e, 0x6b, 0xbb }, /* her */ | 122 | { 0x0e, 0x6b, 0xbb }, /* her */ |
108 | { 0x6b, 0x6c, 0x0e, 0xab, 0x5c, 0xbb }, /* scy */ | 123 | { 0x6b, 0x6c, 0x0e, 0xab, 0x5c, 0xbb }, /* scy */ |
109 | { 0x0e, 0x6b, 0xab, 0xbb }, /* hrc */ | 124 | { 0x0e, 0x6b, 0xab, 0xbb }, /* hrc */ |
110 | { 0x5b, 0x6b, 0xab, 0xbb, 0xcb }, /* hmd */ | 125 | { 0x5b, 0x6b, 0xab, 0xbb, 0xcb }, /* hmd */ |
126 | { 0x5b, 0x6b, 0xab, 0xbb, 0xcb }, /* hds */ | ||
127 | { 0x57, 0x67, 0x77, 0x87, 0x97, 0xa7, 0xb7 }, /* syl */ | ||
111 | }; | 128 | }; |
112 | 129 | ||
113 | /* fan status registers */ | 130 | /* fan status registers */ |
114 | static const u8 FSCHMD_REG_FAN_STATE[5][6] = { | 131 | static const u8 FSCHMD_REG_FAN_STATE[7][7] = { |
115 | { 0x0d, 0x62, 0xa2 }, /* pos */ | 132 | { 0x0d, 0x62, 0xa2 }, /* pos */ |
116 | { 0x0d, 0x62, 0xb2 }, /* her */ | 133 | { 0x0d, 0x62, 0xb2 }, /* her */ |
117 | { 0x62, 0x61, 0x0d, 0xa2, 0x52, 0xb2 }, /* scy */ | 134 | { 0x62, 0x61, 0x0d, 0xa2, 0x52, 0xb2 }, /* scy */ |
118 | { 0x0d, 0x62, 0xa2, 0xb2 }, /* hrc */ | 135 | { 0x0d, 0x62, 0xa2, 0xb2 }, /* hrc */ |
119 | { 0x52, 0x62, 0xa2, 0xb2, 0xc2 }, /* hmd */ | 136 | { 0x52, 0x62, 0xa2, 0xb2, 0xc2 }, /* hmd */ |
137 | { 0x52, 0x62, 0xa2, 0xb2, 0xc2 }, /* hds */ | ||
138 | { 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0 }, /* syl */ | ||
120 | }; | 139 | }; |
121 | 140 | ||
122 | /* fan ripple / divider registers */ | 141 | /* fan ripple / divider registers */ |
123 | static const u8 FSCHMD_REG_FAN_RIPPLE[5][6] = { | 142 | static const u8 FSCHMD_REG_FAN_RIPPLE[7][7] = { |
124 | { 0x0f, 0x6f, 0xaf }, /* pos */ | 143 | { 0x0f, 0x6f, 0xaf }, /* pos */ |
125 | { 0x0f, 0x6f, 0xbf }, /* her */ | 144 | { 0x0f, 0x6f, 0xbf }, /* her */ |
126 | { 0x6f, 0x6f, 0x0f, 0xaf, 0x0f, 0xbf }, /* scy */ | 145 | { 0x6f, 0x6f, 0x0f, 0xaf, 0x0f, 0xbf }, /* scy */ |
127 | { 0x0f, 0x6f, 0xaf, 0xbf }, /* hrc */ | 146 | { 0x0f, 0x6f, 0xaf, 0xbf }, /* hrc */ |
128 | { 0x5f, 0x6f, 0xaf, 0xbf, 0xcf }, /* hmd */ | 147 | { 0x5f, 0x6f, 0xaf, 0xbf, 0xcf }, /* hmd */ |
148 | { 0x5f, 0x6f, 0xaf, 0xbf, 0xcf }, /* hds */ | ||
149 | { 0x56, 0x66, 0x76, 0x86, 0x96, 0xa6, 0xb6 }, /* syl */ | ||
129 | }; | 150 | }; |
130 | 151 | ||
131 | static const int FSCHMD_NO_FAN_SENSORS[5] = { 3, 3, 6, 4, 5 }; | 152 | static const int FSCHMD_NO_FAN_SENSORS[7] = { 3, 3, 6, 4, 5, 5, 7 }; |
132 | 153 | ||
133 | /* Fan status register bitmasks */ | 154 | /* Fan status register bitmasks */ |
134 | #define FSCHMD_FAN_ALARM 0x04 /* called fault by FSC! */ | 155 | #define FSCHMD_FAN_ALARM 0x04 /* called fault by FSC! */ |
135 | #define FSCHMD_FAN_NOT_PRESENT 0x08 /* not documented */ | 156 | #define FSCHMD_FAN_NOT_PRESENT 0x08 |
157 | #define FSCHMD_FAN_DISABLED 0x80 | ||
136 | 158 | ||
137 | 159 | ||
138 | /* actual temperature registers */ | 160 | /* actual temperature registers */ |
139 | static const u8 FSCHMD_REG_TEMP_ACT[5][5] = { | 161 | static const u8 FSCHMD_REG_TEMP_ACT[7][11] = { |
140 | { 0x64, 0x32, 0x35 }, /* pos */ | 162 | { 0x64, 0x32, 0x35 }, /* pos */ |
141 | { 0x64, 0x32, 0x35 }, /* her */ | 163 | { 0x64, 0x32, 0x35 }, /* her */ |
142 | { 0x64, 0xD0, 0x32, 0x35 }, /* scy */ | 164 | { 0x64, 0xD0, 0x32, 0x35 }, /* scy */ |
143 | { 0x64, 0x32, 0x35 }, /* hrc */ | 165 | { 0x64, 0x32, 0x35 }, /* hrc */ |
144 | { 0x70, 0x80, 0x90, 0xd0, 0xe0 }, /* hmd */ | 166 | { 0x70, 0x80, 0x90, 0xd0, 0xe0 }, /* hmd */ |
167 | { 0x70, 0x80, 0x90, 0xd0, 0xe0 }, /* hds */ | ||
168 | { 0x58, 0x68, 0x78, 0x88, 0x98, 0xa8, /* syl */ | ||
169 | 0xb8, 0xc8, 0xd8, 0xe8, 0xf8 }, | ||
145 | }; | 170 | }; |
146 | 171 | ||
147 | /* temperature state registers */ | 172 | /* temperature state registers */ |
148 | static const u8 FSCHMD_REG_TEMP_STATE[5][5] = { | 173 | static const u8 FSCHMD_REG_TEMP_STATE[7][11] = { |
149 | { 0x71, 0x81, 0x91 }, /* pos */ | 174 | { 0x71, 0x81, 0x91 }, /* pos */ |
150 | { 0x71, 0x81, 0x91 }, /* her */ | 175 | { 0x71, 0x81, 0x91 }, /* her */ |
151 | { 0x71, 0xd1, 0x81, 0x91 }, /* scy */ | 176 | { 0x71, 0xd1, 0x81, 0x91 }, /* scy */ |
152 | { 0x71, 0x81, 0x91 }, /* hrc */ | 177 | { 0x71, 0x81, 0x91 }, /* hrc */ |
153 | { 0x71, 0x81, 0x91, 0xd1, 0xe1 }, /* hmd */ | 178 | { 0x71, 0x81, 0x91, 0xd1, 0xe1 }, /* hmd */ |
179 | { 0x71, 0x81, 0x91, 0xd1, 0xe1 }, /* hds */ | ||
180 | { 0x59, 0x69, 0x79, 0x89, 0x99, 0xa9, /* syl */ | ||
181 | 0xb9, 0xc9, 0xd9, 0xe9, 0xf9 }, | ||
154 | }; | 182 | }; |
155 | 183 | ||
156 | /* temperature high limit registers, FSC does not document these. Proven to be | 184 | /* temperature high limit registers, FSC does not document these. Proven to be |
@@ -158,24 +186,31 @@ static const u8 FSCHMD_REG_TEMP_STATE[5][5] = { | |||
158 | in the fscscy 2.4 driver. FSC has confirmed that the fschmd has registers | 186 | in the fscscy 2.4 driver. FSC has confirmed that the fschmd has registers |
159 | at these addresses, but doesn't want to confirm they are the same as with | 187 | at these addresses, but doesn't want to confirm they are the same as with |
160 | the fscher?? */ | 188 | the fscher?? */ |
161 | static const u8 FSCHMD_REG_TEMP_LIMIT[5][5] = { | 189 | static const u8 FSCHMD_REG_TEMP_LIMIT[7][11] = { |
162 | { 0, 0, 0 }, /* pos */ | 190 | { 0, 0, 0 }, /* pos */ |
163 | { 0x76, 0x86, 0x96 }, /* her */ | 191 | { 0x76, 0x86, 0x96 }, /* her */ |
164 | { 0x76, 0xd6, 0x86, 0x96 }, /* scy */ | 192 | { 0x76, 0xd6, 0x86, 0x96 }, /* scy */ |
165 | { 0x76, 0x86, 0x96 }, /* hrc */ | 193 | { 0x76, 0x86, 0x96 }, /* hrc */ |
166 | { 0x76, 0x86, 0x96, 0xd6, 0xe6 }, /* hmd */ | 194 | { 0x76, 0x86, 0x96, 0xd6, 0xe6 }, /* hmd */ |
195 | { 0x76, 0x86, 0x96, 0xd6, 0xe6 }, /* hds */ | ||
196 | { 0x5a, 0x6a, 0x7a, 0x8a, 0x9a, 0xaa, /* syl */ | ||
197 | 0xba, 0xca, 0xda, 0xea, 0xfa }, | ||
167 | }; | 198 | }; |
168 | 199 | ||
169 | /* These were found through experimenting with an fscher, currently they are | 200 | /* These were found through experimenting with an fscher, currently they are |
170 | not used, but we keep them around for future reference. | 201 | not used, but we keep them around for future reference. |
202 | On the fscsyl AUTOP1 lives at 0x#c (so 0x5c for fan1, 0x6c for fan2, etc), | ||
203 | AUTOP2 lives at 0x#e, and 0x#1 is a bitmask defining which temps influence | ||
204 | the fan speed. | ||
171 | static const u8 FSCHER_REG_TEMP_AUTOP1[] = { 0x73, 0x83, 0x93 }; | 205 | static const u8 FSCHER_REG_TEMP_AUTOP1[] = { 0x73, 0x83, 0x93 }; |
172 | static const u8 FSCHER_REG_TEMP_AUTOP2[] = { 0x75, 0x85, 0x95 }; */ | 206 | static const u8 FSCHER_REG_TEMP_AUTOP2[] = { 0x75, 0x85, 0x95 }; */ |
173 | 207 | ||
174 | static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 }; | 208 | static const int FSCHMD_NO_TEMP_SENSORS[7] = { 3, 3, 4, 3, 5, 5, 11 }; |
175 | 209 | ||
176 | /* temp status register bitmasks */ | 210 | /* temp status register bitmasks */ |
177 | #define FSCHMD_TEMP_WORKING 0x01 | 211 | #define FSCHMD_TEMP_WORKING 0x01 |
178 | #define FSCHMD_TEMP_ALERT 0x02 | 212 | #define FSCHMD_TEMP_ALERT 0x02 |
213 | #define FSCHMD_TEMP_DISABLED 0x80 | ||
179 | /* there only really is an alarm if the sensor is working and alert == 1 */ | 214 | /* there only really is an alarm if the sensor is working and alert == 1 */ |
180 | #define FSCHMD_TEMP_ALARM_MASK \ | 215 | #define FSCHMD_TEMP_ALARM_MASK \ |
181 | (FSCHMD_TEMP_WORKING | FSCHMD_TEMP_ALERT) | 216 | (FSCHMD_TEMP_WORKING | FSCHMD_TEMP_ALERT) |
@@ -201,6 +236,8 @@ static const struct i2c_device_id fschmd_id[] = { | |||
201 | { "fscscy", fscscy }, | 236 | { "fscscy", fscscy }, |
202 | { "fschrc", fschrc }, | 237 | { "fschrc", fschrc }, |
203 | { "fschmd", fschmd }, | 238 | { "fschmd", fschmd }, |
239 | { "fschds", fschds }, | ||
240 | { "fscsyl", fscsyl }, | ||
204 | { } | 241 | { } |
205 | }; | 242 | }; |
206 | MODULE_DEVICE_TABLE(i2c, fschmd_id); | 243 | MODULE_DEVICE_TABLE(i2c, fschmd_id); |
@@ -242,14 +279,14 @@ struct fschmd_data { | |||
242 | u8 watchdog_control; /* watchdog control register */ | 279 | u8 watchdog_control; /* watchdog control register */ |
243 | u8 watchdog_state; /* watchdog status register */ | 280 | u8 watchdog_state; /* watchdog status register */ |
244 | u8 watchdog_preset; /* watchdog counter preset on trigger val */ | 281 | u8 watchdog_preset; /* watchdog counter preset on trigger val */ |
245 | u8 volt[3]; /* 12, 5, battery voltage */ | 282 | u8 volt[6]; /* voltage */ |
246 | u8 temp_act[5]; /* temperature */ | 283 | u8 temp_act[11]; /* temperature */ |
247 | u8 temp_status[5]; /* status of sensor */ | 284 | u8 temp_status[11]; /* status of sensor */ |
248 | u8 temp_max[5]; /* high temp limit, notice: undocumented! */ | 285 | u8 temp_max[11]; /* high temp limit, notice: undocumented! */ |
249 | u8 fan_act[6]; /* fans revolutions per second */ | 286 | u8 fan_act[7]; /* fans revolutions per second */ |
250 | u8 fan_status[6]; /* fan status */ | 287 | u8 fan_status[7]; /* fan status */ |
251 | u8 fan_min[6]; /* fan min value for rps */ | 288 | u8 fan_min[7]; /* fan min value for rps */ |
252 | u8 fan_ripple[6]; /* divider for rps */ | 289 | u8 fan_ripple[7]; /* divider for rps */ |
253 | }; | 290 | }; |
254 | 291 | ||
255 | /* Global variables to hold information read from special DMI tables, which are | 292 | /* Global variables to hold information read from special DMI tables, which are |
@@ -257,8 +294,8 @@ struct fschmd_data { | |||
257 | protect these with a lock as they are only modified from our attach function | 294 | protect these with a lock as they are only modified from our attach function |
258 | which always gets called with the i2c-core lock held and never accessed | 295 | which always gets called with the i2c-core lock held and never accessed |
259 | before the attach function is done with them. */ | 296 | before the attach function is done with them. */ |
260 | static int dmi_mult[3] = { 490, 200, 100 }; | 297 | static int dmi_mult[6] = { 490, 200, 100, 100, 200, 100 }; |
261 | static int dmi_offset[3] = { 0, 0, 0 }; | 298 | static int dmi_offset[6] = { 0, 0, 0, 0, 0, 0 }; |
262 | static int dmi_vref = -1; | 299 | static int dmi_vref = -1; |
263 | 300 | ||
264 | /* Somewhat ugly :( global data pointer list with all fschmd devices, so that | 301 | /* Somewhat ugly :( global data pointer list with all fschmd devices, so that |
@@ -450,10 +487,11 @@ static ssize_t show_pwm_auto_point1_pwm(struct device *dev, | |||
450 | struct device_attribute *devattr, char *buf) | 487 | struct device_attribute *devattr, char *buf) |
451 | { | 488 | { |
452 | int index = to_sensor_dev_attr(devattr)->index; | 489 | int index = to_sensor_dev_attr(devattr)->index; |
453 | int val = fschmd_update_device(dev)->fan_min[index]; | 490 | struct fschmd_data *data = fschmd_update_device(dev); |
491 | int val = data->fan_min[index]; | ||
454 | 492 | ||
455 | /* 0 = allow turning off, 1-255 = 50-100% */ | 493 | /* 0 = allow turning off (except on the syl), 1-255 = 50-100% */ |
456 | if (val) | 494 | if (val || data->kind == fscsyl - 1) |
457 | val = val / 2 + 128; | 495 | val = val / 2 + 128; |
458 | 496 | ||
459 | return sprintf(buf, "%d\n", val); | 497 | return sprintf(buf, "%d\n", val); |
@@ -466,8 +504,8 @@ static ssize_t store_pwm_auto_point1_pwm(struct device *dev, | |||
466 | struct fschmd_data *data = dev_get_drvdata(dev); | 504 | struct fschmd_data *data = dev_get_drvdata(dev); |
467 | unsigned long v = simple_strtoul(buf, NULL, 10); | 505 | unsigned long v = simple_strtoul(buf, NULL, 10); |
468 | 506 | ||
469 | /* register: 0 = allow turning off, 1-255 = 50-100% */ | 507 | /* reg: 0 = allow turning off (except on the syl), 1-255 = 50-100% */ |
470 | if (v) { | 508 | if (v || data->kind == fscsyl - 1) { |
471 | v = SENSORS_LIMIT(v, 128, 255); | 509 | v = SENSORS_LIMIT(v, 128, 255); |
472 | v = (v - 128) * 2 + 1; | 510 | v = (v - 128) * 2 + 1; |
473 | } | 511 | } |
@@ -522,11 +560,15 @@ static ssize_t store_alert_led(struct device *dev, | |||
522 | return count; | 560 | return count; |
523 | } | 561 | } |
524 | 562 | ||
563 | static DEVICE_ATTR(alert_led, 0644, show_alert_led, store_alert_led); | ||
564 | |||
525 | static struct sensor_device_attribute fschmd_attr[] = { | 565 | static struct sensor_device_attribute fschmd_attr[] = { |
526 | SENSOR_ATTR(in0_input, 0444, show_in_value, NULL, 0), | 566 | SENSOR_ATTR(in0_input, 0444, show_in_value, NULL, 0), |
527 | SENSOR_ATTR(in1_input, 0444, show_in_value, NULL, 1), | 567 | SENSOR_ATTR(in1_input, 0444, show_in_value, NULL, 1), |
528 | SENSOR_ATTR(in2_input, 0444, show_in_value, NULL, 2), | 568 | SENSOR_ATTR(in2_input, 0444, show_in_value, NULL, 2), |
529 | SENSOR_ATTR(alert_led, 0644, show_alert_led, store_alert_led, 0), | 569 | SENSOR_ATTR(in3_input, 0444, show_in_value, NULL, 3), |
570 | SENSOR_ATTR(in4_input, 0444, show_in_value, NULL, 4), | ||
571 | SENSOR_ATTR(in5_input, 0444, show_in_value, NULL, 5), | ||
530 | }; | 572 | }; |
531 | 573 | ||
532 | static struct sensor_device_attribute fschmd_temp_attr[] = { | 574 | static struct sensor_device_attribute fschmd_temp_attr[] = { |
@@ -550,6 +592,30 @@ static struct sensor_device_attribute fschmd_temp_attr[] = { | |||
550 | SENSOR_ATTR(temp5_max, 0644, show_temp_max, store_temp_max, 4), | 592 | SENSOR_ATTR(temp5_max, 0644, show_temp_max, store_temp_max, 4), |
551 | SENSOR_ATTR(temp5_fault, 0444, show_temp_fault, NULL, 4), | 593 | SENSOR_ATTR(temp5_fault, 0444, show_temp_fault, NULL, 4), |
552 | SENSOR_ATTR(temp5_alarm, 0444, show_temp_alarm, NULL, 4), | 594 | SENSOR_ATTR(temp5_alarm, 0444, show_temp_alarm, NULL, 4), |
595 | SENSOR_ATTR(temp6_input, 0444, show_temp_value, NULL, 5), | ||
596 | SENSOR_ATTR(temp6_max, 0644, show_temp_max, store_temp_max, 5), | ||
597 | SENSOR_ATTR(temp6_fault, 0444, show_temp_fault, NULL, 5), | ||
598 | SENSOR_ATTR(temp6_alarm, 0444, show_temp_alarm, NULL, 5), | ||
599 | SENSOR_ATTR(temp7_input, 0444, show_temp_value, NULL, 6), | ||
600 | SENSOR_ATTR(temp7_max, 0644, show_temp_max, store_temp_max, 6), | ||
601 | SENSOR_ATTR(temp7_fault, 0444, show_temp_fault, NULL, 6), | ||
602 | SENSOR_ATTR(temp7_alarm, 0444, show_temp_alarm, NULL, 6), | ||
603 | SENSOR_ATTR(temp8_input, 0444, show_temp_value, NULL, 7), | ||
604 | SENSOR_ATTR(temp8_max, 0644, show_temp_max, store_temp_max, 7), | ||
605 | SENSOR_ATTR(temp8_fault, 0444, show_temp_fault, NULL, 7), | ||
606 | SENSOR_ATTR(temp8_alarm, 0444, show_temp_alarm, NULL, 7), | ||
607 | SENSOR_ATTR(temp9_input, 0444, show_temp_value, NULL, 8), | ||
608 | SENSOR_ATTR(temp9_max, 0644, show_temp_max, store_temp_max, 8), | ||
609 | SENSOR_ATTR(temp9_fault, 0444, show_temp_fault, NULL, 8), | ||
610 | SENSOR_ATTR(temp9_alarm, 0444, show_temp_alarm, NULL, 8), | ||
611 | SENSOR_ATTR(temp10_input, 0444, show_temp_value, NULL, 9), | ||
612 | SENSOR_ATTR(temp10_max, 0644, show_temp_max, store_temp_max, 9), | ||
613 | SENSOR_ATTR(temp10_fault, 0444, show_temp_fault, NULL, 9), | ||
614 | SENSOR_ATTR(temp10_alarm, 0444, show_temp_alarm, NULL, 9), | ||
615 | SENSOR_ATTR(temp11_input, 0444, show_temp_value, NULL, 10), | ||
616 | SENSOR_ATTR(temp11_max, 0644, show_temp_max, store_temp_max, 10), | ||
617 | SENSOR_ATTR(temp11_fault, 0444, show_temp_fault, NULL, 10), | ||
618 | SENSOR_ATTR(temp11_alarm, 0444, show_temp_alarm, NULL, 10), | ||
553 | }; | 619 | }; |
554 | 620 | ||
555 | static struct sensor_device_attribute fschmd_fan_attr[] = { | 621 | static struct sensor_device_attribute fschmd_fan_attr[] = { |
@@ -589,6 +655,12 @@ static struct sensor_device_attribute fschmd_fan_attr[] = { | |||
589 | SENSOR_ATTR(fan6_fault, 0444, show_fan_fault, NULL, 5), | 655 | SENSOR_ATTR(fan6_fault, 0444, show_fan_fault, NULL, 5), |
590 | SENSOR_ATTR(pwm6_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, | 656 | SENSOR_ATTR(pwm6_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, |
591 | store_pwm_auto_point1_pwm, 5), | 657 | store_pwm_auto_point1_pwm, 5), |
658 | SENSOR_ATTR(fan7_input, 0444, show_fan_value, NULL, 6), | ||
659 | SENSOR_ATTR(fan7_div, 0644, show_fan_div, store_fan_div, 6), | ||
660 | SENSOR_ATTR(fan7_alarm, 0444, show_fan_alarm, NULL, 6), | ||
661 | SENSOR_ATTR(fan7_fault, 0444, show_fan_fault, NULL, 6), | ||
662 | SENSOR_ATTR(pwm7_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, | ||
663 | store_pwm_auto_point1_pwm, 6), | ||
592 | }; | 664 | }; |
593 | 665 | ||
594 | 666 | ||
@@ -624,10 +696,11 @@ static int watchdog_set_timeout(struct fschmd_data *data, int timeout) | |||
624 | data->watchdog_preset = DIV_ROUND_UP(timeout, resolution); | 696 | data->watchdog_preset = DIV_ROUND_UP(timeout, resolution); |
625 | 697 | ||
626 | /* Write new timeout value */ | 698 | /* Write new timeout value */ |
627 | i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_PRESET, | 699 | i2c_smbus_write_byte_data(data->client, |
628 | data->watchdog_preset); | 700 | FSCHMD_REG_WDOG_PRESET[data->kind], data->watchdog_preset); |
629 | /* Write new control register, do not trigger! */ | 701 | /* Write new control register, do not trigger! */ |
630 | i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL, | 702 | i2c_smbus_write_byte_data(data->client, |
703 | FSCHMD_REG_WDOG_CONTROL[data->kind], | ||
631 | data->watchdog_control & ~FSCHMD_WDOG_CONTROL_TRIGGER); | 704 | data->watchdog_control & ~FSCHMD_WDOG_CONTROL_TRIGGER); |
632 | 705 | ||
633 | ret = data->watchdog_preset * resolution; | 706 | ret = data->watchdog_preset * resolution; |
@@ -662,8 +735,9 @@ static int watchdog_trigger(struct fschmd_data *data) | |||
662 | } | 735 | } |
663 | 736 | ||
664 | data->watchdog_control |= FSCHMD_WDOG_CONTROL_TRIGGER; | 737 | data->watchdog_control |= FSCHMD_WDOG_CONTROL_TRIGGER; |
665 | i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL, | 738 | i2c_smbus_write_byte_data(data->client, |
666 | data->watchdog_control); | 739 | FSCHMD_REG_WDOG_CONTROL[data->kind], |
740 | data->watchdog_control); | ||
667 | leave: | 741 | leave: |
668 | mutex_unlock(&data->watchdog_lock); | 742 | mutex_unlock(&data->watchdog_lock); |
669 | return ret; | 743 | return ret; |
@@ -682,7 +756,8 @@ static int watchdog_stop(struct fschmd_data *data) | |||
682 | data->watchdog_control &= ~FSCHMD_WDOG_CONTROL_STARTED; | 756 | data->watchdog_control &= ~FSCHMD_WDOG_CONTROL_STARTED; |
683 | /* Don't store the stop flag in our watchdog control register copy, as | 757 | /* Don't store the stop flag in our watchdog control register copy, as |
684 | its a write only bit (read always returns 0) */ | 758 | its a write only bit (read always returns 0) */ |
685 | i2c_smbus_write_byte_data(data->client, FSCHMD_REG_WDOG_CONTROL, | 759 | i2c_smbus_write_byte_data(data->client, |
760 | FSCHMD_REG_WDOG_CONTROL[data->kind], | ||
686 | data->watchdog_control | FSCHMD_WDOG_CONTROL_STOP); | 761 | data->watchdog_control | FSCHMD_WDOG_CONTROL_STOP); |
687 | leave: | 762 | leave: |
688 | mutex_unlock(&data->watchdog_lock); | 763 | mutex_unlock(&data->watchdog_lock); |
@@ -856,7 +931,7 @@ static struct file_operations watchdog_fops = { | |||
856 | 931 | ||
857 | /* DMI decode routine to read voltage scaling factors from special DMI tables, | 932 | /* DMI decode routine to read voltage scaling factors from special DMI tables, |
858 | which are available on FSC machines with an fscher or later chip. */ | 933 | which are available on FSC machines with an fscher or later chip. */ |
859 | static void fschmd_dmi_decode(const struct dmi_header *header) | 934 | static void fschmd_dmi_decode(const struct dmi_header *header, void *dummy) |
860 | { | 935 | { |
861 | int i, mult[3] = { 0 }, offset[3] = { 0 }, vref = 0, found = 0; | 936 | int i, mult[3] = { 0 }, offset[3] = { 0 }, vref = 0, found = 0; |
862 | 937 | ||
@@ -912,6 +987,15 @@ static void fschmd_dmi_decode(const struct dmi_header *header) | |||
912 | dmi_mult[i] = mult[i] * 10; | 987 | dmi_mult[i] = mult[i] * 10; |
913 | dmi_offset[i] = offset[i] * 10; | 988 | dmi_offset[i] = offset[i] * 10; |
914 | } | 989 | } |
990 | /* According to the docs there should be separate dmi entries | ||
991 | for the mult's and offsets of in3-5 of the syl, but on | ||
992 | my test machine these are not present */ | ||
993 | dmi_mult[3] = dmi_mult[2]; | ||
994 | dmi_mult[4] = dmi_mult[1]; | ||
995 | dmi_mult[5] = dmi_mult[2]; | ||
996 | dmi_offset[3] = dmi_offset[2]; | ||
997 | dmi_offset[4] = dmi_offset[1]; | ||
998 | dmi_offset[5] = dmi_offset[2]; | ||
915 | dmi_vref = vref; | 999 | dmi_vref = vref; |
916 | } | 1000 | } |
917 | } | 1001 | } |
@@ -920,8 +1004,6 @@ static int fschmd_detect(struct i2c_client *client, int kind, | |||
920 | struct i2c_board_info *info) | 1004 | struct i2c_board_info *info) |
921 | { | 1005 | { |
922 | struct i2c_adapter *adapter = client->adapter; | 1006 | struct i2c_adapter *adapter = client->adapter; |
923 | const char * const client_names[5] = { "fscpos", "fscher", "fscscy", | ||
924 | "fschrc", "fschmd" }; | ||
925 | 1007 | ||
926 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 1008 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
927 | return -ENODEV; | 1009 | return -ENODEV; |
@@ -948,11 +1030,15 @@ static int fschmd_detect(struct i2c_client *client, int kind, | |||
948 | kind = fschrc; | 1030 | kind = fschrc; |
949 | else if (!strcmp(id, "HMD")) | 1031 | else if (!strcmp(id, "HMD")) |
950 | kind = fschmd; | 1032 | kind = fschmd; |
1033 | else if (!strcmp(id, "HDS")) | ||
1034 | kind = fschds; | ||
1035 | else if (!strcmp(id, "SYL")) | ||
1036 | kind = fscsyl; | ||
951 | else | 1037 | else |
952 | return -ENODEV; | 1038 | return -ENODEV; |
953 | } | 1039 | } |
954 | 1040 | ||
955 | strlcpy(info->type, client_names[kind - 1], I2C_NAME_SIZE); | 1041 | strlcpy(info->type, fschmd_id[kind - 1].name, I2C_NAME_SIZE); |
956 | 1042 | ||
957 | return 0; | 1043 | return 0; |
958 | } | 1044 | } |
@@ -961,8 +1047,8 @@ static int fschmd_probe(struct i2c_client *client, | |||
961 | const struct i2c_device_id *id) | 1047 | const struct i2c_device_id *id) |
962 | { | 1048 | { |
963 | struct fschmd_data *data; | 1049 | struct fschmd_data *data; |
964 | const char * const names[5] = { "Poseidon", "Hermes", "Scylla", | 1050 | const char * const names[7] = { "Poseidon", "Hermes", "Scylla", |
965 | "Heracles", "Heimdall" }; | 1051 | "Heracles", "Heimdall", "Hades", "Syleus" }; |
966 | const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 }; | 1052 | const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 }; |
967 | int i, err; | 1053 | int i, err; |
968 | enum chips kind = id->driver_data; | 1054 | enum chips kind = id->driver_data; |
@@ -991,7 +1077,7 @@ static int fschmd_probe(struct i2c_client *client, | |||
991 | 1077 | ||
992 | /* Read the special DMI table for fscher and newer chips */ | 1078 | /* Read the special DMI table for fscher and newer chips */ |
993 | if ((kind == fscher || kind >= fschrc) && dmi_vref == -1) { | 1079 | if ((kind == fscher || kind >= fschrc) && dmi_vref == -1) { |
994 | dmi_walk(fschmd_dmi_decode); | 1080 | dmi_walk(fschmd_dmi_decode, NULL); |
995 | if (dmi_vref == -1) { | 1081 | if (dmi_vref == -1) { |
996 | dev_warn(&client->dev, | 1082 | dev_warn(&client->dev, |
997 | "Couldn't get voltage scaling factors from " | 1083 | "Couldn't get voltage scaling factors from " |
@@ -1000,21 +1086,25 @@ static int fschmd_probe(struct i2c_client *client, | |||
1000 | } | 1086 | } |
1001 | } | 1087 | } |
1002 | 1088 | ||
1089 | /* i2c kind goes from 1-6, we want from 0-5 to address arrays */ | ||
1090 | data->kind = kind - 1; | ||
1091 | |||
1003 | /* Read in some never changing registers */ | 1092 | /* Read in some never changing registers */ |
1004 | data->revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION); | 1093 | data->revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION); |
1005 | data->global_control = i2c_smbus_read_byte_data(client, | 1094 | data->global_control = i2c_smbus_read_byte_data(client, |
1006 | FSCHMD_REG_CONTROL); | 1095 | FSCHMD_REG_CONTROL); |
1007 | data->watchdog_control = i2c_smbus_read_byte_data(client, | 1096 | data->watchdog_control = i2c_smbus_read_byte_data(client, |
1008 | FSCHMD_REG_WDOG_CONTROL); | 1097 | FSCHMD_REG_WDOG_CONTROL[data->kind]); |
1009 | data->watchdog_state = i2c_smbus_read_byte_data(client, | 1098 | data->watchdog_state = i2c_smbus_read_byte_data(client, |
1010 | FSCHMD_REG_WDOG_STATE); | 1099 | FSCHMD_REG_WDOG_STATE[data->kind]); |
1011 | data->watchdog_preset = i2c_smbus_read_byte_data(client, | 1100 | data->watchdog_preset = i2c_smbus_read_byte_data(client, |
1012 | FSCHMD_REG_WDOG_PRESET); | 1101 | FSCHMD_REG_WDOG_PRESET[data->kind]); |
1013 | 1102 | ||
1014 | /* i2c kind goes from 1-5, we want from 0-4 to address arrays */ | 1103 | err = device_create_file(&client->dev, &dev_attr_alert_led); |
1015 | data->kind = kind - 1; | 1104 | if (err) |
1105 | goto exit_detach; | ||
1016 | 1106 | ||
1017 | for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++) { | 1107 | for (i = 0; i < FSCHMD_NO_VOLT_SENSORS[data->kind]; i++) { |
1018 | err = device_create_file(&client->dev, | 1108 | err = device_create_file(&client->dev, |
1019 | &fschmd_attr[i].dev_attr); | 1109 | &fschmd_attr[i].dev_attr); |
1020 | if (err) | 1110 | if (err) |
@@ -1027,6 +1117,16 @@ static int fschmd_probe(struct i2c_client *client, | |||
1027 | show_temp_max) | 1117 | show_temp_max) |
1028 | continue; | 1118 | continue; |
1029 | 1119 | ||
1120 | if (kind == fscsyl) { | ||
1121 | if (i % 4 == 0) | ||
1122 | data->temp_status[i / 4] = | ||
1123 | i2c_smbus_read_byte_data(client, | ||
1124 | FSCHMD_REG_TEMP_STATE | ||
1125 | [data->kind][i / 4]); | ||
1126 | if (data->temp_status[i / 4] & FSCHMD_TEMP_DISABLED) | ||
1127 | continue; | ||
1128 | } | ||
1129 | |||
1030 | err = device_create_file(&client->dev, | 1130 | err = device_create_file(&client->dev, |
1031 | &fschmd_temp_attr[i].dev_attr); | 1131 | &fschmd_temp_attr[i].dev_attr); |
1032 | if (err) | 1132 | if (err) |
@@ -1040,6 +1140,16 @@ static int fschmd_probe(struct i2c_client *client, | |||
1040 | "pwm3_auto_point1_pwm")) | 1140 | "pwm3_auto_point1_pwm")) |
1041 | continue; | 1141 | continue; |
1042 | 1142 | ||
1143 | if (kind == fscsyl) { | ||
1144 | if (i % 5 == 0) | ||
1145 | data->fan_status[i / 5] = | ||
1146 | i2c_smbus_read_byte_data(client, | ||
1147 | FSCHMD_REG_FAN_STATE | ||
1148 | [data->kind][i / 5]); | ||
1149 | if (data->fan_status[i / 5] & FSCHMD_FAN_DISABLED) | ||
1150 | continue; | ||
1151 | } | ||
1152 | |||
1043 | err = device_create_file(&client->dev, | 1153 | err = device_create_file(&client->dev, |
1044 | &fschmd_fan_attr[i].dev_attr); | 1154 | &fschmd_fan_attr[i].dev_attr); |
1045 | if (err) | 1155 | if (err) |
@@ -1126,7 +1236,8 @@ static int fschmd_remove(struct i2c_client *client) | |||
1126 | if (data->hwmon_dev) | 1236 | if (data->hwmon_dev) |
1127 | hwmon_device_unregister(data->hwmon_dev); | 1237 | hwmon_device_unregister(data->hwmon_dev); |
1128 | 1238 | ||
1129 | for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++) | 1239 | device_remove_file(&client->dev, &dev_attr_alert_led); |
1240 | for (i = 0; i < (FSCHMD_NO_VOLT_SENSORS[data->kind]); i++) | ||
1130 | device_remove_file(&client->dev, &fschmd_attr[i].dev_attr); | 1241 | device_remove_file(&client->dev, &fschmd_attr[i].dev_attr); |
1131 | for (i = 0; i < (FSCHMD_NO_TEMP_SENSORS[data->kind] * 4); i++) | 1242 | for (i = 0; i < (FSCHMD_NO_TEMP_SENSORS[data->kind] * 4); i++) |
1132 | device_remove_file(&client->dev, | 1243 | device_remove_file(&client->dev, |
@@ -1171,7 +1282,7 @@ static struct fschmd_data *fschmd_update_device(struct device *dev) | |||
1171 | data->temp_act[i] < data->temp_max[i]) | 1282 | data->temp_act[i] < data->temp_max[i]) |
1172 | i2c_smbus_write_byte_data(client, | 1283 | i2c_smbus_write_byte_data(client, |
1173 | FSCHMD_REG_TEMP_STATE[data->kind][i], | 1284 | FSCHMD_REG_TEMP_STATE[data->kind][i], |
1174 | FSCHMD_TEMP_ALERT); | 1285 | data->temp_status[i]); |
1175 | } | 1286 | } |
1176 | 1287 | ||
1177 | for (i = 0; i < FSCHMD_NO_FAN_SENSORS[data->kind]; i++) { | 1288 | for (i = 0; i < FSCHMD_NO_FAN_SENSORS[data->kind]; i++) { |
@@ -1193,12 +1304,12 @@ static struct fschmd_data *fschmd_update_device(struct device *dev) | |||
1193 | data->fan_act[i]) | 1304 | data->fan_act[i]) |
1194 | i2c_smbus_write_byte_data(client, | 1305 | i2c_smbus_write_byte_data(client, |
1195 | FSCHMD_REG_FAN_STATE[data->kind][i], | 1306 | FSCHMD_REG_FAN_STATE[data->kind][i], |
1196 | FSCHMD_FAN_ALARM); | 1307 | data->fan_status[i]); |
1197 | } | 1308 | } |
1198 | 1309 | ||
1199 | for (i = 0; i < 3; i++) | 1310 | for (i = 0; i < FSCHMD_NO_VOLT_SENSORS[data->kind]; i++) |
1200 | data->volt[i] = i2c_smbus_read_byte_data(client, | 1311 | data->volt[i] = i2c_smbus_read_byte_data(client, |
1201 | FSCHMD_REG_VOLT[i]); | 1312 | FSCHMD_REG_VOLT[data->kind][i]); |
1202 | 1313 | ||
1203 | data->last_updated = jiffies; | 1314 | data->last_updated = jiffies; |
1204 | data->valid = 1; | 1315 | data->valid = 1; |
@@ -1220,8 +1331,8 @@ static void __exit fschmd_exit(void) | |||
1220 | } | 1331 | } |
1221 | 1332 | ||
1222 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); | 1333 | MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); |
1223 | MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles and " | 1334 | MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles, Heimdall, Hades " |
1224 | "Heimdall driver"); | 1335 | "and Syleus driver"); |
1225 | MODULE_LICENSE("GPL"); | 1336 | MODULE_LICENSE("GPL"); |
1226 | 1337 | ||
1227 | module_init(fschmd_init); | 1338 | module_init(fschmd_init); |
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index a4d92d246d52..d3612a1f1981 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c | |||
@@ -65,6 +65,10 @@ | |||
65 | #define HDAPS_INPUT_FUZZ 4 /* input event threshold */ | 65 | #define HDAPS_INPUT_FUZZ 4 /* input event threshold */ |
66 | #define HDAPS_INPUT_FLAT 4 | 66 | #define HDAPS_INPUT_FLAT 4 |
67 | 67 | ||
68 | #define HDAPS_X_AXIS (1 << 0) | ||
69 | #define HDAPS_Y_AXIS (1 << 1) | ||
70 | #define HDAPS_BOTH_AXES (HDAPS_X_AXIS | HDAPS_Y_AXIS) | ||
71 | |||
68 | static struct platform_device *pdev; | 72 | static struct platform_device *pdev; |
69 | static struct input_polled_dev *hdaps_idev; | 73 | static struct input_polled_dev *hdaps_idev; |
70 | static unsigned int hdaps_invert; | 74 | static unsigned int hdaps_invert; |
@@ -182,11 +186,11 @@ static int __hdaps_read_pair(unsigned int port1, unsigned int port2, | |||
182 | km_activity = inb(HDAPS_PORT_KMACT); | 186 | km_activity = inb(HDAPS_PORT_KMACT); |
183 | __device_complete(); | 187 | __device_complete(); |
184 | 188 | ||
185 | /* if hdaps_invert is set, negate the two values */ | 189 | /* hdaps_invert is a bitvector to negate the axes */ |
186 | if (hdaps_invert) { | 190 | if (hdaps_invert & HDAPS_X_AXIS) |
187 | *x = -*x; | 191 | *x = -*x; |
192 | if (hdaps_invert & HDAPS_Y_AXIS) | ||
188 | *y = -*y; | 193 | *y = -*y; |
189 | } | ||
190 | 194 | ||
191 | return 0; | 195 | return 0; |
192 | } | 196 | } |
@@ -436,7 +440,8 @@ static ssize_t hdaps_invert_store(struct device *dev, | |||
436 | { | 440 | { |
437 | int invert; | 441 | int invert; |
438 | 442 | ||
439 | if (sscanf(buf, "%d", &invert) != 1 || (invert != 1 && invert != 0)) | 443 | if (sscanf(buf, "%d", &invert) != 1 || |
444 | invert < 0 || invert > HDAPS_BOTH_AXES) | ||
440 | return -EINVAL; | 445 | return -EINVAL; |
441 | 446 | ||
442 | hdaps_invert = invert; | 447 | hdaps_invert = invert; |
@@ -483,56 +488,52 @@ static int __init hdaps_dmi_match(const struct dmi_system_id *id) | |||
483 | /* hdaps_dmi_match_invert - found an inverted match. */ | 488 | /* hdaps_dmi_match_invert - found an inverted match. */ |
484 | static int __init hdaps_dmi_match_invert(const struct dmi_system_id *id) | 489 | static int __init hdaps_dmi_match_invert(const struct dmi_system_id *id) |
485 | { | 490 | { |
486 | hdaps_invert = 1; | 491 | hdaps_invert = (unsigned long)id->driver_data; |
487 | printk(KERN_INFO "hdaps: inverting axis readings.\n"); | 492 | printk(KERN_INFO "hdaps: inverting axis (%u) readings.\n", |
493 | hdaps_invert); | ||
488 | return hdaps_dmi_match(id); | 494 | return hdaps_dmi_match(id); |
489 | } | 495 | } |
490 | 496 | ||
491 | #define HDAPS_DMI_MATCH_NORMAL(vendor, model) { \ | 497 | #define HDAPS_DMI_MATCH_INVERT(vendor, model, axes) { \ |
492 | .ident = vendor " " model, \ | ||
493 | .callback = hdaps_dmi_match, \ | ||
494 | .matches = { \ | ||
495 | DMI_MATCH(DMI_BOARD_VENDOR, vendor), \ | ||
496 | DMI_MATCH(DMI_PRODUCT_VERSION, model) \ | ||
497 | } \ | ||
498 | } | ||
499 | |||
500 | #define HDAPS_DMI_MATCH_INVERT(vendor, model) { \ | ||
501 | .ident = vendor " " model, \ | 498 | .ident = vendor " " model, \ |
502 | .callback = hdaps_dmi_match_invert, \ | 499 | .callback = hdaps_dmi_match_invert, \ |
500 | .driver_data = (void *)axes, \ | ||
503 | .matches = { \ | 501 | .matches = { \ |
504 | DMI_MATCH(DMI_BOARD_VENDOR, vendor), \ | 502 | DMI_MATCH(DMI_BOARD_VENDOR, vendor), \ |
505 | DMI_MATCH(DMI_PRODUCT_VERSION, model) \ | 503 | DMI_MATCH(DMI_PRODUCT_VERSION, model) \ |
506 | } \ | 504 | } \ |
507 | } | 505 | } |
508 | 506 | ||
507 | #define HDAPS_DMI_MATCH_NORMAL(vendor, model) \ | ||
508 | HDAPS_DMI_MATCH_INVERT(vendor, model, 0) | ||
509 | |||
509 | /* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match | 510 | /* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match |
510 | "ThinkPad T42p", so the order of the entries matters. | 511 | "ThinkPad T42p", so the order of the entries matters. |
511 | If your ThinkPad is not recognized, please update to latest | 512 | If your ThinkPad is not recognized, please update to latest |
512 | BIOS. This is especially the case for some R52 ThinkPads. */ | 513 | BIOS. This is especially the case for some R52 ThinkPads. */ |
513 | static struct dmi_system_id __initdata hdaps_whitelist[] = { | 514 | static struct dmi_system_id __initdata hdaps_whitelist[] = { |
514 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad R50p"), | 515 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad R50p", HDAPS_BOTH_AXES), |
515 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R50"), | 516 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R50"), |
516 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"), | 517 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"), |
517 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"), | 518 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"), |
518 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61i"), | 519 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61i", HDAPS_BOTH_AXES), |
519 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61"), | 520 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61", HDAPS_BOTH_AXES), |
520 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p"), | 521 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p", HDAPS_BOTH_AXES), |
521 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"), | 522 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"), |
522 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p"), | 523 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p", HDAPS_BOTH_AXES), |
523 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"), | 524 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"), |
524 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"), | 525 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"), |
525 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60"), | 526 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60", HDAPS_BOTH_AXES), |
526 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61p"), | 527 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61p", HDAPS_BOTH_AXES), |
527 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61"), | 528 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61", HDAPS_BOTH_AXES), |
528 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X40"), | 529 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X40"), |
529 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X41"), | 530 | HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad X41", HDAPS_Y_AXIS), |
530 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X60"), | 531 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X60", HDAPS_BOTH_AXES), |
531 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61s"), | 532 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61s", HDAPS_BOTH_AXES), |
532 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61"), | 533 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61", HDAPS_BOTH_AXES), |
533 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad Z60m"), | 534 | HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad Z60m"), |
534 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61m"), | 535 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61m", HDAPS_BOTH_AXES), |
535 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61p"), | 536 | HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61p", HDAPS_BOTH_AXES), |
536 | { .ident = NULL } | 537 | { .ident = NULL } |
537 | }; | 538 | }; |
538 | 539 | ||
@@ -627,8 +628,9 @@ static void __exit hdaps_exit(void) | |||
627 | module_init(hdaps_init); | 628 | module_init(hdaps_init); |
628 | module_exit(hdaps_exit); | 629 | module_exit(hdaps_exit); |
629 | 630 | ||
630 | module_param_named(invert, hdaps_invert, bool, 0); | 631 | module_param_named(invert, hdaps_invert, int, 0); |
631 | MODULE_PARM_DESC(invert, "invert data along each axis"); | 632 | MODULE_PARM_DESC(invert, "invert data along each axis. 1 invert x-axis, " |
633 | "2 invert y-axis, 3 invert both axes."); | ||
632 | 634 | ||
633 | MODULE_AUTHOR("Robert Love"); | 635 | MODULE_AUTHOR("Robert Love"); |
634 | MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver"); | 636 | MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver"); |
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index 29c83b5b9697..55d3dc565be6 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c | |||
@@ -85,25 +85,31 @@ MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids); | |||
85 | 85 | ||
86 | /** | 86 | /** |
87 | * lis3lv02d_acpi_init - ACPI _INI method: initialize the device. | 87 | * lis3lv02d_acpi_init - ACPI _INI method: initialize the device. |
88 | * @handle: the handle of the device | 88 | * @lis3: pointer to the device struct |
89 | * | 89 | * |
90 | * Returns AE_OK on success. | 90 | * Returns 0 on success. |
91 | */ | 91 | */ |
92 | acpi_status lis3lv02d_acpi_init(acpi_handle handle) | 92 | int lis3lv02d_acpi_init(struct lis3lv02d *lis3) |
93 | { | 93 | { |
94 | return acpi_evaluate_object(handle, METHOD_NAME__INI, NULL, NULL); | 94 | struct acpi_device *dev = lis3->bus_priv; |
95 | if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI, | ||
96 | NULL, NULL) != AE_OK) | ||
97 | return -EINVAL; | ||
98 | |||
99 | return 0; | ||
95 | } | 100 | } |
96 | 101 | ||
97 | /** | 102 | /** |
98 | * lis3lv02d_acpi_read - ACPI ALRD method: read a register | 103 | * lis3lv02d_acpi_read - ACPI ALRD method: read a register |
99 | * @handle: the handle of the device | 104 | * @lis3: pointer to the device struct |
100 | * @reg: the register to read | 105 | * @reg: the register to read |
101 | * @ret: result of the operation | 106 | * @ret: result of the operation |
102 | * | 107 | * |
103 | * Returns AE_OK on success. | 108 | * Returns 0 on success. |
104 | */ | 109 | */ |
105 | acpi_status lis3lv02d_acpi_read(acpi_handle handle, int reg, u8 *ret) | 110 | int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret) |
106 | { | 111 | { |
112 | struct acpi_device *dev = lis3->bus_priv; | ||
107 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | 113 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; |
108 | struct acpi_object_list args = { 1, &arg0 }; | 114 | struct acpi_object_list args = { 1, &arg0 }; |
109 | unsigned long long lret; | 115 | unsigned long long lret; |
@@ -111,21 +117,22 @@ acpi_status lis3lv02d_acpi_read(acpi_handle handle, int reg, u8 *ret) | |||
111 | 117 | ||
112 | arg0.integer.value = reg; | 118 | arg0.integer.value = reg; |
113 | 119 | ||
114 | status = acpi_evaluate_integer(handle, "ALRD", &args, &lret); | 120 | status = acpi_evaluate_integer(dev->handle, "ALRD", &args, &lret); |
115 | *ret = lret; | 121 | *ret = lret; |
116 | return status; | 122 | return (status != AE_OK) ? -EINVAL : 0; |
117 | } | 123 | } |
118 | 124 | ||
119 | /** | 125 | /** |
120 | * lis3lv02d_acpi_write - ACPI ALWR method: write to a register | 126 | * lis3lv02d_acpi_write - ACPI ALWR method: write to a register |
121 | * @handle: the handle of the device | 127 | * @lis3: pointer to the device struct |
122 | * @reg: the register to write to | 128 | * @reg: the register to write to |
123 | * @val: the value to write | 129 | * @val: the value to write |
124 | * | 130 | * |
125 | * Returns AE_OK on success. | 131 | * Returns 0 on success. |
126 | */ | 132 | */ |
127 | acpi_status lis3lv02d_acpi_write(acpi_handle handle, int reg, u8 val) | 133 | int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val) |
128 | { | 134 | { |
135 | struct acpi_device *dev = lis3->bus_priv; | ||
129 | unsigned long long ret; /* Not used when writting */ | 136 | unsigned long long ret; /* Not used when writting */ |
130 | union acpi_object in_obj[2]; | 137 | union acpi_object in_obj[2]; |
131 | struct acpi_object_list args = { 2, in_obj }; | 138 | struct acpi_object_list args = { 2, in_obj }; |
@@ -135,12 +142,15 @@ acpi_status lis3lv02d_acpi_write(acpi_handle handle, int reg, u8 val) | |||
135 | in_obj[1].type = ACPI_TYPE_INTEGER; | 142 | in_obj[1].type = ACPI_TYPE_INTEGER; |
136 | in_obj[1].integer.value = val; | 143 | in_obj[1].integer.value = val; |
137 | 144 | ||
138 | return acpi_evaluate_integer(handle, "ALWR", &args, &ret); | 145 | if (acpi_evaluate_integer(dev->handle, "ALWR", &args, &ret) != AE_OK) |
146 | return -EINVAL; | ||
147 | |||
148 | return 0; | ||
139 | } | 149 | } |
140 | 150 | ||
141 | static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi) | 151 | static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi) |
142 | { | 152 | { |
143 | adev.ac = *((struct axis_conversion *)dmi->driver_data); | 153 | lis3_dev.ac = *((struct axis_conversion *)dmi->driver_data); |
144 | printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident); | 154 | printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident); |
145 | 155 | ||
146 | return 1; | 156 | return 1; |
@@ -187,6 +197,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { | |||
187 | AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted), | 197 | AXIS_DMI_MATCH("NC2510", "HP Compaq 2510", y_inverted), |
188 | AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted), | 198 | AXIS_DMI_MATCH("NC8510", "HP Compaq 8510", xy_swap_inverted), |
189 | AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left), | 199 | AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left), |
200 | AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted), | ||
190 | AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd), | 201 | AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd), |
191 | AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd), | 202 | AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd), |
192 | AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right), | 203 | AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right), |
@@ -201,6 +212,8 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { | |||
201 | PRODUCT_NAME, "HP Pavilion dv5", | 212 | PRODUCT_NAME, "HP Pavilion dv5", |
202 | BOARD_NAME, "3600", | 213 | BOARD_NAME, "3600", |
203 | y_inverted), | 214 | y_inverted), |
215 | AXIS_DMI_MATCH("DV7", "HP Pavilion dv7", x_inverted), | ||
216 | AXIS_DMI_MATCH("HP8710", "HP Compaq 8710", y_inverted), | ||
204 | { NULL, } | 217 | { NULL, } |
205 | /* Laptop models without axis info (yet): | 218 | /* Laptop models without axis info (yet): |
206 | * "NC6910" "HP Compaq 6910" | 219 | * "NC6910" "HP Compaq 6910" |
@@ -214,7 +227,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = { | |||
214 | 227 | ||
215 | static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value) | 228 | static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value) |
216 | { | 229 | { |
217 | acpi_handle handle = adev.device->handle; | 230 | struct acpi_device *dev = lis3_dev.bus_priv; |
218 | unsigned long long ret; /* Not used when writing */ | 231 | unsigned long long ret; /* Not used when writing */ |
219 | union acpi_object in_obj[1]; | 232 | union acpi_object in_obj[1]; |
220 | struct acpi_object_list args = { 1, in_obj }; | 233 | struct acpi_object_list args = { 1, in_obj }; |
@@ -222,7 +235,7 @@ static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness | |||
222 | in_obj[0].type = ACPI_TYPE_INTEGER; | 235 | in_obj[0].type = ACPI_TYPE_INTEGER; |
223 | in_obj[0].integer.value = !!value; | 236 | in_obj[0].integer.value = !!value; |
224 | 237 | ||
225 | acpi_evaluate_integer(handle, "ALED", &args, &ret); | 238 | acpi_evaluate_integer(dev->handle, "ALED", &args, &ret); |
226 | } | 239 | } |
227 | 240 | ||
228 | static struct delayed_led_classdev hpled_led = { | 241 | static struct delayed_led_classdev hpled_led = { |
@@ -254,28 +267,11 @@ static void lis3lv02d_enum_resources(struct acpi_device *device) | |||
254 | acpi_status status; | 267 | acpi_status status; |
255 | 268 | ||
256 | status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, | 269 | status = acpi_walk_resources(device->handle, METHOD_NAME__CRS, |
257 | lis3lv02d_get_resource, &adev.irq); | 270 | lis3lv02d_get_resource, &lis3_dev.irq); |
258 | if (ACPI_FAILURE(status)) | 271 | if (ACPI_FAILURE(status)) |
259 | printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n"); | 272 | printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n"); |
260 | } | 273 | } |
261 | 274 | ||
262 | static s16 lis3lv02d_read_16(acpi_handle handle, int reg) | ||
263 | { | ||
264 | u8 lo, hi; | ||
265 | |||
266 | adev.read(handle, reg - 1, &lo); | ||
267 | adev.read(handle, reg, &hi); | ||
268 | /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */ | ||
269 | return (s16)((hi << 8) | lo); | ||
270 | } | ||
271 | |||
272 | static s16 lis3lv02d_read_8(acpi_handle handle, int reg) | ||
273 | { | ||
274 | s8 lo; | ||
275 | adev.read(handle, reg, &lo); | ||
276 | return lo; | ||
277 | } | ||
278 | |||
279 | static int lis3lv02d_add(struct acpi_device *device) | 275 | static int lis3lv02d_add(struct acpi_device *device) |
280 | { | 276 | { |
281 | int ret; | 277 | int ret; |
@@ -283,51 +279,35 @@ static int lis3lv02d_add(struct acpi_device *device) | |||
283 | if (!device) | 279 | if (!device) |
284 | return -EINVAL; | 280 | return -EINVAL; |
285 | 281 | ||
286 | adev.device = device; | 282 | lis3_dev.bus_priv = device; |
287 | adev.init = lis3lv02d_acpi_init; | 283 | lis3_dev.init = lis3lv02d_acpi_init; |
288 | adev.read = lis3lv02d_acpi_read; | 284 | lis3_dev.read = lis3lv02d_acpi_read; |
289 | adev.write = lis3lv02d_acpi_write; | 285 | lis3_dev.write = lis3lv02d_acpi_write; |
290 | strcpy(acpi_device_name(device), DRIVER_NAME); | 286 | strcpy(acpi_device_name(device), DRIVER_NAME); |
291 | strcpy(acpi_device_class(device), ACPI_MDPS_CLASS); | 287 | strcpy(acpi_device_class(device), ACPI_MDPS_CLASS); |
292 | device->driver_data = &adev; | 288 | device->driver_data = &lis3_dev; |
293 | 289 | ||
294 | lis3lv02d_acpi_read(device->handle, WHO_AM_I, &adev.whoami); | 290 | /* obtain IRQ number of our device from ACPI */ |
295 | switch (adev.whoami) { | 291 | lis3lv02d_enum_resources(device); |
296 | case LIS_DOUBLE_ID: | ||
297 | printk(KERN_INFO DRIVER_NAME ": 2-byte sensor found\n"); | ||
298 | adev.read_data = lis3lv02d_read_16; | ||
299 | adev.mdps_max_val = 2048; | ||
300 | break; | ||
301 | case LIS_SINGLE_ID: | ||
302 | printk(KERN_INFO DRIVER_NAME ": 1-byte sensor found\n"); | ||
303 | adev.read_data = lis3lv02d_read_8; | ||
304 | adev.mdps_max_val = 128; | ||
305 | break; | ||
306 | default: | ||
307 | printk(KERN_ERR DRIVER_NAME | ||
308 | ": unknown sensor type 0x%X\n", adev.whoami); | ||
309 | return -EINVAL; | ||
310 | } | ||
311 | 292 | ||
312 | /* If possible use a "standard" axes order */ | 293 | /* If possible use a "standard" axes order */ |
313 | if (dmi_check_system(lis3lv02d_dmi_ids) == 0) { | 294 | if (dmi_check_system(lis3lv02d_dmi_ids) == 0) { |
314 | printk(KERN_INFO DRIVER_NAME ": laptop model unknown, " | 295 | printk(KERN_INFO DRIVER_NAME ": laptop model unknown, " |
315 | "using default axes configuration\n"); | 296 | "using default axes configuration\n"); |
316 | adev.ac = lis3lv02d_axis_normal; | 297 | lis3_dev.ac = lis3lv02d_axis_normal; |
317 | } | 298 | } |
318 | 299 | ||
319 | INIT_WORK(&hpled_led.work, delayed_set_status_worker); | 300 | /* call the core layer do its init */ |
320 | ret = led_classdev_register(NULL, &hpled_led.led_classdev); | 301 | ret = lis3lv02d_init_device(&lis3_dev); |
321 | if (ret) | 302 | if (ret) |
322 | return ret; | 303 | return ret; |
323 | 304 | ||
324 | /* obtain IRQ number of our device from ACPI */ | 305 | INIT_WORK(&hpled_led.work, delayed_set_status_worker); |
325 | lis3lv02d_enum_resources(adev.device); | 306 | ret = led_classdev_register(NULL, &hpled_led.led_classdev); |
326 | |||
327 | ret = lis3lv02d_init_device(&adev); | ||
328 | if (ret) { | 307 | if (ret) { |
308 | lis3lv02d_joystick_disable(); | ||
309 | lis3lv02d_poweroff(&lis3_dev); | ||
329 | flush_work(&hpled_led.work); | 310 | flush_work(&hpled_led.work); |
330 | led_classdev_unregister(&hpled_led.led_classdev); | ||
331 | return ret; | 311 | return ret; |
332 | } | 312 | } |
333 | 313 | ||
@@ -340,7 +320,7 @@ static int lis3lv02d_remove(struct acpi_device *device, int type) | |||
340 | return -EINVAL; | 320 | return -EINVAL; |
341 | 321 | ||
342 | lis3lv02d_joystick_disable(); | 322 | lis3lv02d_joystick_disable(); |
343 | lis3lv02d_poweroff(device->handle); | 323 | lis3lv02d_poweroff(&lis3_dev); |
344 | 324 | ||
345 | flush_work(&hpled_led.work); | 325 | flush_work(&hpled_led.work); |
346 | led_classdev_unregister(&hpled_led.led_classdev); | 326 | led_classdev_unregister(&hpled_led.led_classdev); |
@@ -353,19 +333,19 @@ static int lis3lv02d_remove(struct acpi_device *device, int type) | |||
353 | static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state) | 333 | static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state) |
354 | { | 334 | { |
355 | /* make sure the device is off when we suspend */ | 335 | /* make sure the device is off when we suspend */ |
356 | lis3lv02d_poweroff(device->handle); | 336 | lis3lv02d_poweroff(&lis3_dev); |
357 | return 0; | 337 | return 0; |
358 | } | 338 | } |
359 | 339 | ||
360 | static int lis3lv02d_resume(struct acpi_device *device) | 340 | static int lis3lv02d_resume(struct acpi_device *device) |
361 | { | 341 | { |
362 | /* put back the device in the right state (ACPI might turn it on) */ | 342 | /* put back the device in the right state (ACPI might turn it on) */ |
363 | mutex_lock(&adev.lock); | 343 | mutex_lock(&lis3_dev.lock); |
364 | if (adev.usage > 0) | 344 | if (lis3_dev.usage > 0) |
365 | lis3lv02d_poweron(device->handle); | 345 | lis3lv02d_poweron(&lis3_dev); |
366 | else | 346 | else |
367 | lis3lv02d_poweroff(device->handle); | 347 | lis3lv02d_poweroff(&lis3_dev); |
368 | mutex_unlock(&adev.lock); | 348 | mutex_unlock(&lis3_dev.lock); |
369 | return 0; | 349 | return 0; |
370 | } | 350 | } |
371 | #else | 351 | #else |
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c index 8bb2158f0453..778eb7795983 100644 --- a/drivers/hwmon/lis3lv02d.c +++ b/drivers/hwmon/lis3lv02d.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <linux/freezer.h> | 36 | #include <linux/freezer.h> |
37 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
38 | #include <linux/miscdevice.h> | 38 | #include <linux/miscdevice.h> |
39 | #include <acpi/acpi_drivers.h> | ||
40 | #include <asm/atomic.h> | 39 | #include <asm/atomic.h> |
41 | #include "lis3lv02d.h" | 40 | #include "lis3lv02d.h" |
42 | 41 | ||
@@ -53,13 +52,30 @@ | |||
53 | * joystick. | 52 | * joystick. |
54 | */ | 53 | */ |
55 | 54 | ||
56 | struct acpi_lis3lv02d adev = { | 55 | struct lis3lv02d lis3_dev = { |
57 | .misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(adev.misc_wait), | 56 | .misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait), |
58 | }; | 57 | }; |
59 | 58 | ||
60 | EXPORT_SYMBOL_GPL(adev); | 59 | EXPORT_SYMBOL_GPL(lis3_dev); |
61 | 60 | ||
62 | static int lis3lv02d_add_fs(struct acpi_device *device); | 61 | static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg) |
62 | { | ||
63 | s8 lo; | ||
64 | if (lis3->read(lis3, reg, &lo) < 0) | ||
65 | return 0; | ||
66 | |||
67 | return lo; | ||
68 | } | ||
69 | |||
70 | static s16 lis3lv02d_read_16(struct lis3lv02d *lis3, int reg) | ||
71 | { | ||
72 | u8 lo, hi; | ||
73 | |||
74 | lis3->read(lis3, reg - 1, &lo); | ||
75 | lis3->read(lis3, reg, &hi); | ||
76 | /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */ | ||
77 | return (s16)((hi << 8) | lo); | ||
78 | } | ||
63 | 79 | ||
64 | /** | 80 | /** |
65 | * lis3lv02d_get_axis - For the given axis, give the value converted | 81 | * lis3lv02d_get_axis - For the given axis, give the value converted |
@@ -78,36 +94,36 @@ static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3]) | |||
78 | 94 | ||
79 | /** | 95 | /** |
80 | * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer | 96 | * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer |
81 | * @handle: the handle to the device | 97 | * @lis3: pointer to the device struct |
82 | * @x: where to store the X axis value | 98 | * @x: where to store the X axis value |
83 | * @y: where to store the Y axis value | 99 | * @y: where to store the Y axis value |
84 | * @z: where to store the Z axis value | 100 | * @z: where to store the Z axis value |
85 | * | 101 | * |
86 | * Note that 40Hz input device can eat up about 10% CPU at 800MHZ | 102 | * Note that 40Hz input device can eat up about 10% CPU at 800MHZ |
87 | */ | 103 | */ |
88 | static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z) | 104 | static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z) |
89 | { | 105 | { |
90 | int position[3]; | 106 | int position[3]; |
91 | 107 | ||
92 | position[0] = adev.read_data(handle, OUTX); | 108 | position[0] = lis3_dev.read_data(lis3, OUTX); |
93 | position[1] = adev.read_data(handle, OUTY); | 109 | position[1] = lis3_dev.read_data(lis3, OUTY); |
94 | position[2] = adev.read_data(handle, OUTZ); | 110 | position[2] = lis3_dev.read_data(lis3, OUTZ); |
95 | 111 | ||
96 | *x = lis3lv02d_get_axis(adev.ac.x, position); | 112 | *x = lis3lv02d_get_axis(lis3_dev.ac.x, position); |
97 | *y = lis3lv02d_get_axis(adev.ac.y, position); | 113 | *y = lis3lv02d_get_axis(lis3_dev.ac.y, position); |
98 | *z = lis3lv02d_get_axis(adev.ac.z, position); | 114 | *z = lis3lv02d_get_axis(lis3_dev.ac.z, position); |
99 | } | 115 | } |
100 | 116 | ||
101 | void lis3lv02d_poweroff(acpi_handle handle) | 117 | void lis3lv02d_poweroff(struct lis3lv02d *lis3) |
102 | { | 118 | { |
103 | adev.is_on = 0; | 119 | lis3_dev.is_on = 0; |
104 | } | 120 | } |
105 | EXPORT_SYMBOL_GPL(lis3lv02d_poweroff); | 121 | EXPORT_SYMBOL_GPL(lis3lv02d_poweroff); |
106 | 122 | ||
107 | void lis3lv02d_poweron(acpi_handle handle) | 123 | void lis3lv02d_poweron(struct lis3lv02d *lis3) |
108 | { | 124 | { |
109 | adev.is_on = 1; | 125 | lis3_dev.is_on = 1; |
110 | adev.init(handle); | 126 | lis3_dev.init(lis3); |
111 | } | 127 | } |
112 | EXPORT_SYMBOL_GPL(lis3lv02d_poweron); | 128 | EXPORT_SYMBOL_GPL(lis3lv02d_poweron); |
113 | 129 | ||
@@ -116,13 +132,13 @@ EXPORT_SYMBOL_GPL(lis3lv02d_poweron); | |||
116 | * device will always be on until a call to lis3lv02d_decrease_use(). Not to be | 132 | * device will always be on until a call to lis3lv02d_decrease_use(). Not to be |
117 | * used from interrupt context. | 133 | * used from interrupt context. |
118 | */ | 134 | */ |
119 | static void lis3lv02d_increase_use(struct acpi_lis3lv02d *dev) | 135 | static void lis3lv02d_increase_use(struct lis3lv02d *dev) |
120 | { | 136 | { |
121 | mutex_lock(&dev->lock); | 137 | mutex_lock(&dev->lock); |
122 | dev->usage++; | 138 | dev->usage++; |
123 | if (dev->usage == 1) { | 139 | if (dev->usage == 1) { |
124 | if (!dev->is_on) | 140 | if (!dev->is_on) |
125 | lis3lv02d_poweron(dev->device->handle); | 141 | lis3lv02d_poweron(dev); |
126 | } | 142 | } |
127 | mutex_unlock(&dev->lock); | 143 | mutex_unlock(&dev->lock); |
128 | } | 144 | } |
@@ -131,12 +147,12 @@ static void lis3lv02d_increase_use(struct acpi_lis3lv02d *dev) | |||
131 | * To be called whenever a usage of the device is stopped. | 147 | * To be called whenever a usage of the device is stopped. |
132 | * It will make sure to turn off the device when there is not usage. | 148 | * It will make sure to turn off the device when there is not usage. |
133 | */ | 149 | */ |
134 | static void lis3lv02d_decrease_use(struct acpi_lis3lv02d *dev) | 150 | static void lis3lv02d_decrease_use(struct lis3lv02d *dev) |
135 | { | 151 | { |
136 | mutex_lock(&dev->lock); | 152 | mutex_lock(&dev->lock); |
137 | dev->usage--; | 153 | dev->usage--; |
138 | if (dev->usage == 0) | 154 | if (dev->usage == 0) |
139 | lis3lv02d_poweroff(dev->device->handle); | 155 | lis3lv02d_poweroff(dev); |
140 | mutex_unlock(&dev->lock); | 156 | mutex_unlock(&dev->lock); |
141 | } | 157 | } |
142 | 158 | ||
@@ -147,10 +163,10 @@ static irqreturn_t lis302dl_interrupt(int irq, void *dummy) | |||
147 | * the lid is closed. This leads to interrupts as soon as a little move | 163 | * the lid is closed. This leads to interrupts as soon as a little move |
148 | * is done. | 164 | * is done. |
149 | */ | 165 | */ |
150 | atomic_inc(&adev.count); | 166 | atomic_inc(&lis3_dev.count); |
151 | 167 | ||
152 | wake_up_interruptible(&adev.misc_wait); | 168 | wake_up_interruptible(&lis3_dev.misc_wait); |
153 | kill_fasync(&adev.async_queue, SIGIO, POLL_IN); | 169 | kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN); |
154 | return IRQ_HANDLED; | 170 | return IRQ_HANDLED; |
155 | } | 171 | } |
156 | 172 | ||
@@ -158,10 +174,10 @@ static int lis3lv02d_misc_open(struct inode *inode, struct file *file) | |||
158 | { | 174 | { |
159 | int ret; | 175 | int ret; |
160 | 176 | ||
161 | if (test_and_set_bit(0, &adev.misc_opened)) | 177 | if (test_and_set_bit(0, &lis3_dev.misc_opened)) |
162 | return -EBUSY; /* already open */ | 178 | return -EBUSY; /* already open */ |
163 | 179 | ||
164 | atomic_set(&adev.count, 0); | 180 | atomic_set(&lis3_dev.count, 0); |
165 | 181 | ||
166 | /* | 182 | /* |
167 | * The sensor can generate interrupts for free-fall and direction | 183 | * The sensor can generate interrupts for free-fall and direction |
@@ -174,25 +190,25 @@ static int lis3lv02d_misc_open(struct inode *inode, struct file *file) | |||
174 | * io-apic is not configurable (and generates a warning) but I keep it | 190 | * io-apic is not configurable (and generates a warning) but I keep it |
175 | * in case of support for other hardware. | 191 | * in case of support for other hardware. |
176 | */ | 192 | */ |
177 | ret = request_irq(adev.irq, lis302dl_interrupt, IRQF_TRIGGER_RISING, | 193 | ret = request_irq(lis3_dev.irq, lis302dl_interrupt, IRQF_TRIGGER_RISING, |
178 | DRIVER_NAME, &adev); | 194 | DRIVER_NAME, &lis3_dev); |
179 | 195 | ||
180 | if (ret) { | 196 | if (ret) { |
181 | clear_bit(0, &adev.misc_opened); | 197 | clear_bit(0, &lis3_dev.misc_opened); |
182 | printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", adev.irq); | 198 | printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", lis3_dev.irq); |
183 | return -EBUSY; | 199 | return -EBUSY; |
184 | } | 200 | } |
185 | lis3lv02d_increase_use(&adev); | 201 | lis3lv02d_increase_use(&lis3_dev); |
186 | printk("lis3: registered interrupt %d\n", adev.irq); | 202 | printk("lis3: registered interrupt %d\n", lis3_dev.irq); |
187 | return 0; | 203 | return 0; |
188 | } | 204 | } |
189 | 205 | ||
190 | static int lis3lv02d_misc_release(struct inode *inode, struct file *file) | 206 | static int lis3lv02d_misc_release(struct inode *inode, struct file *file) |
191 | { | 207 | { |
192 | fasync_helper(-1, file, 0, &adev.async_queue); | 208 | fasync_helper(-1, file, 0, &lis3_dev.async_queue); |
193 | lis3lv02d_decrease_use(&adev); | 209 | lis3lv02d_decrease_use(&lis3_dev); |
194 | free_irq(adev.irq, &adev); | 210 | free_irq(lis3_dev.irq, &lis3_dev); |
195 | clear_bit(0, &adev.misc_opened); /* release the device */ | 211 | clear_bit(0, &lis3_dev.misc_opened); /* release the device */ |
196 | return 0; | 212 | return 0; |
197 | } | 213 | } |
198 | 214 | ||
@@ -207,10 +223,10 @@ static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf, | |||
207 | if (count < 1) | 223 | if (count < 1) |
208 | return -EINVAL; | 224 | return -EINVAL; |
209 | 225 | ||
210 | add_wait_queue(&adev.misc_wait, &wait); | 226 | add_wait_queue(&lis3_dev.misc_wait, &wait); |
211 | while (true) { | 227 | while (true) { |
212 | set_current_state(TASK_INTERRUPTIBLE); | 228 | set_current_state(TASK_INTERRUPTIBLE); |
213 | data = atomic_xchg(&adev.count, 0); | 229 | data = atomic_xchg(&lis3_dev.count, 0); |
214 | if (data) | 230 | if (data) |
215 | break; | 231 | break; |
216 | 232 | ||
@@ -240,22 +256,22 @@ static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf, | |||
240 | 256 | ||
241 | out: | 257 | out: |
242 | __set_current_state(TASK_RUNNING); | 258 | __set_current_state(TASK_RUNNING); |
243 | remove_wait_queue(&adev.misc_wait, &wait); | 259 | remove_wait_queue(&lis3_dev.misc_wait, &wait); |
244 | 260 | ||
245 | return retval; | 261 | return retval; |
246 | } | 262 | } |
247 | 263 | ||
248 | static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait) | 264 | static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait) |
249 | { | 265 | { |
250 | poll_wait(file, &adev.misc_wait, wait); | 266 | poll_wait(file, &lis3_dev.misc_wait, wait); |
251 | if (atomic_read(&adev.count)) | 267 | if (atomic_read(&lis3_dev.count)) |
252 | return POLLIN | POLLRDNORM; | 268 | return POLLIN | POLLRDNORM; |
253 | return 0; | 269 | return 0; |
254 | } | 270 | } |
255 | 271 | ||
256 | static int lis3lv02d_misc_fasync(int fd, struct file *file, int on) | 272 | static int lis3lv02d_misc_fasync(int fd, struct file *file, int on) |
257 | { | 273 | { |
258 | return fasync_helper(fd, file, on, &adev.async_queue); | 274 | return fasync_helper(fd, file, on, &lis3_dev.async_queue); |
259 | } | 275 | } |
260 | 276 | ||
261 | static const struct file_operations lis3lv02d_misc_fops = { | 277 | static const struct file_operations lis3lv02d_misc_fops = { |
@@ -283,12 +299,12 @@ static int lis3lv02d_joystick_kthread(void *data) | |||
283 | int x, y, z; | 299 | int x, y, z; |
284 | 300 | ||
285 | while (!kthread_should_stop()) { | 301 | while (!kthread_should_stop()) { |
286 | lis3lv02d_get_xyz(adev.device->handle, &x, &y, &z); | 302 | lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); |
287 | input_report_abs(adev.idev, ABS_X, x - adev.xcalib); | 303 | input_report_abs(lis3_dev.idev, ABS_X, x - lis3_dev.xcalib); |
288 | input_report_abs(adev.idev, ABS_Y, y - adev.ycalib); | 304 | input_report_abs(lis3_dev.idev, ABS_Y, y - lis3_dev.ycalib); |
289 | input_report_abs(adev.idev, ABS_Z, z - adev.zcalib); | 305 | input_report_abs(lis3_dev.idev, ABS_Z, z - lis3_dev.zcalib); |
290 | 306 | ||
291 | input_sync(adev.idev); | 307 | input_sync(lis3_dev.idev); |
292 | 308 | ||
293 | try_to_freeze(); | 309 | try_to_freeze(); |
294 | msleep_interruptible(MDPS_POLL_INTERVAL); | 310 | msleep_interruptible(MDPS_POLL_INTERVAL); |
@@ -299,11 +315,11 @@ static int lis3lv02d_joystick_kthread(void *data) | |||
299 | 315 | ||
300 | static int lis3lv02d_joystick_open(struct input_dev *input) | 316 | static int lis3lv02d_joystick_open(struct input_dev *input) |
301 | { | 317 | { |
302 | lis3lv02d_increase_use(&adev); | 318 | lis3lv02d_increase_use(&lis3_dev); |
303 | adev.kthread = kthread_run(lis3lv02d_joystick_kthread, NULL, "klis3lv02d"); | 319 | lis3_dev.kthread = kthread_run(lis3lv02d_joystick_kthread, NULL, "klis3lv02d"); |
304 | if (IS_ERR(adev.kthread)) { | 320 | if (IS_ERR(lis3_dev.kthread)) { |
305 | lis3lv02d_decrease_use(&adev); | 321 | lis3lv02d_decrease_use(&lis3_dev); |
306 | return PTR_ERR(adev.kthread); | 322 | return PTR_ERR(lis3_dev.kthread); |
307 | } | 323 | } |
308 | 324 | ||
309 | return 0; | 325 | return 0; |
@@ -311,45 +327,46 @@ static int lis3lv02d_joystick_open(struct input_dev *input) | |||
311 | 327 | ||
312 | static void lis3lv02d_joystick_close(struct input_dev *input) | 328 | static void lis3lv02d_joystick_close(struct input_dev *input) |
313 | { | 329 | { |
314 | kthread_stop(adev.kthread); | 330 | kthread_stop(lis3_dev.kthread); |
315 | lis3lv02d_decrease_use(&adev); | 331 | lis3lv02d_decrease_use(&lis3_dev); |
316 | } | 332 | } |
317 | 333 | ||
318 | static inline void lis3lv02d_calibrate_joystick(void) | 334 | static inline void lis3lv02d_calibrate_joystick(void) |
319 | { | 335 | { |
320 | lis3lv02d_get_xyz(adev.device->handle, &adev.xcalib, &adev.ycalib, &adev.zcalib); | 336 | lis3lv02d_get_xyz(&lis3_dev, |
337 | &lis3_dev.xcalib, &lis3_dev.ycalib, &lis3_dev.zcalib); | ||
321 | } | 338 | } |
322 | 339 | ||
323 | int lis3lv02d_joystick_enable(void) | 340 | int lis3lv02d_joystick_enable(void) |
324 | { | 341 | { |
325 | int err; | 342 | int err; |
326 | 343 | ||
327 | if (adev.idev) | 344 | if (lis3_dev.idev) |
328 | return -EINVAL; | 345 | return -EINVAL; |
329 | 346 | ||
330 | adev.idev = input_allocate_device(); | 347 | lis3_dev.idev = input_allocate_device(); |
331 | if (!adev.idev) | 348 | if (!lis3_dev.idev) |
332 | return -ENOMEM; | 349 | return -ENOMEM; |
333 | 350 | ||
334 | lis3lv02d_calibrate_joystick(); | 351 | lis3lv02d_calibrate_joystick(); |
335 | 352 | ||
336 | adev.idev->name = "ST LIS3LV02DL Accelerometer"; | 353 | lis3_dev.idev->name = "ST LIS3LV02DL Accelerometer"; |
337 | adev.idev->phys = DRIVER_NAME "/input0"; | 354 | lis3_dev.idev->phys = DRIVER_NAME "/input0"; |
338 | adev.idev->id.bustype = BUS_HOST; | 355 | lis3_dev.idev->id.bustype = BUS_HOST; |
339 | adev.idev->id.vendor = 0; | 356 | lis3_dev.idev->id.vendor = 0; |
340 | adev.idev->dev.parent = &adev.pdev->dev; | 357 | lis3_dev.idev->dev.parent = &lis3_dev.pdev->dev; |
341 | adev.idev->open = lis3lv02d_joystick_open; | 358 | lis3_dev.idev->open = lis3lv02d_joystick_open; |
342 | adev.idev->close = lis3lv02d_joystick_close; | 359 | lis3_dev.idev->close = lis3lv02d_joystick_close; |
343 | 360 | ||
344 | set_bit(EV_ABS, adev.idev->evbit); | 361 | set_bit(EV_ABS, lis3_dev.idev->evbit); |
345 | input_set_abs_params(adev.idev, ABS_X, -adev.mdps_max_val, adev.mdps_max_val, 3, 3); | 362 | input_set_abs_params(lis3_dev.idev, ABS_X, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3); |
346 | input_set_abs_params(adev.idev, ABS_Y, -adev.mdps_max_val, adev.mdps_max_val, 3, 3); | 363 | input_set_abs_params(lis3_dev.idev, ABS_Y, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3); |
347 | input_set_abs_params(adev.idev, ABS_Z, -adev.mdps_max_val, adev.mdps_max_val, 3, 3); | 364 | input_set_abs_params(lis3_dev.idev, ABS_Z, -lis3_dev.mdps_max_val, lis3_dev.mdps_max_val, 3, 3); |
348 | 365 | ||
349 | err = input_register_device(adev.idev); | 366 | err = input_register_device(lis3_dev.idev); |
350 | if (err) { | 367 | if (err) { |
351 | input_free_device(adev.idev); | 368 | input_free_device(lis3_dev.idev); |
352 | adev.idev = NULL; | 369 | lis3_dev.idev = NULL; |
353 | } | 370 | } |
354 | 371 | ||
355 | return err; | 372 | return err; |
@@ -358,71 +375,40 @@ EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable); | |||
358 | 375 | ||
359 | void lis3lv02d_joystick_disable(void) | 376 | void lis3lv02d_joystick_disable(void) |
360 | { | 377 | { |
361 | if (!adev.idev) | 378 | if (!lis3_dev.idev) |
362 | return; | 379 | return; |
363 | 380 | ||
364 | misc_deregister(&lis3lv02d_misc_device); | 381 | misc_deregister(&lis3lv02d_misc_device); |
365 | input_unregister_device(adev.idev); | 382 | input_unregister_device(lis3_dev.idev); |
366 | adev.idev = NULL; | 383 | lis3_dev.idev = NULL; |
367 | } | 384 | } |
368 | EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable); | 385 | EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable); |
369 | 386 | ||
370 | /* | ||
371 | * Initialise the accelerometer and the various subsystems. | ||
372 | * Should be rather independant of the bus system. | ||
373 | */ | ||
374 | int lis3lv02d_init_device(struct acpi_lis3lv02d *dev) | ||
375 | { | ||
376 | mutex_init(&dev->lock); | ||
377 | lis3lv02d_add_fs(dev->device); | ||
378 | lis3lv02d_increase_use(dev); | ||
379 | |||
380 | if (lis3lv02d_joystick_enable()) | ||
381 | printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n"); | ||
382 | |||
383 | printk("lis3_init_device: irq %d\n", dev->irq); | ||
384 | |||
385 | /* if we did not get an IRQ from ACPI - we have nothing more to do */ | ||
386 | if (!dev->irq) { | ||
387 | printk(KERN_ERR DRIVER_NAME | ||
388 | ": No IRQ in ACPI. Disabling /dev/freefall\n"); | ||
389 | goto out; | ||
390 | } | ||
391 | |||
392 | printk("lis3: registering device\n"); | ||
393 | if (misc_register(&lis3lv02d_misc_device)) | ||
394 | printk(KERN_ERR DRIVER_NAME ": misc_register failed\n"); | ||
395 | out: | ||
396 | lis3lv02d_decrease_use(dev); | ||
397 | return 0; | ||
398 | } | ||
399 | EXPORT_SYMBOL_GPL(lis3lv02d_init_device); | ||
400 | |||
401 | /* Sysfs stuff */ | 387 | /* Sysfs stuff */ |
402 | static ssize_t lis3lv02d_position_show(struct device *dev, | 388 | static ssize_t lis3lv02d_position_show(struct device *dev, |
403 | struct device_attribute *attr, char *buf) | 389 | struct device_attribute *attr, char *buf) |
404 | { | 390 | { |
405 | int x, y, z; | 391 | int x, y, z; |
406 | 392 | ||
407 | lis3lv02d_increase_use(&adev); | 393 | lis3lv02d_increase_use(&lis3_dev); |
408 | lis3lv02d_get_xyz(adev.device->handle, &x, &y, &z); | 394 | lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z); |
409 | lis3lv02d_decrease_use(&adev); | 395 | lis3lv02d_decrease_use(&lis3_dev); |
410 | return sprintf(buf, "(%d,%d,%d)\n", x, y, z); | 396 | return sprintf(buf, "(%d,%d,%d)\n", x, y, z); |
411 | } | 397 | } |
412 | 398 | ||
413 | static ssize_t lis3lv02d_calibrate_show(struct device *dev, | 399 | static ssize_t lis3lv02d_calibrate_show(struct device *dev, |
414 | struct device_attribute *attr, char *buf) | 400 | struct device_attribute *attr, char *buf) |
415 | { | 401 | { |
416 | return sprintf(buf, "(%d,%d,%d)\n", adev.xcalib, adev.ycalib, adev.zcalib); | 402 | return sprintf(buf, "(%d,%d,%d)\n", lis3_dev.xcalib, lis3_dev.ycalib, lis3_dev.zcalib); |
417 | } | 403 | } |
418 | 404 | ||
419 | static ssize_t lis3lv02d_calibrate_store(struct device *dev, | 405 | static ssize_t lis3lv02d_calibrate_store(struct device *dev, |
420 | struct device_attribute *attr, | 406 | struct device_attribute *attr, |
421 | const char *buf, size_t count) | 407 | const char *buf, size_t count) |
422 | { | 408 | { |
423 | lis3lv02d_increase_use(&adev); | 409 | lis3lv02d_increase_use(&lis3_dev); |
424 | lis3lv02d_calibrate_joystick(); | 410 | lis3lv02d_calibrate_joystick(); |
425 | lis3lv02d_decrease_use(&adev); | 411 | lis3lv02d_decrease_use(&lis3_dev); |
426 | return count; | 412 | return count; |
427 | } | 413 | } |
428 | 414 | ||
@@ -434,9 +420,9 @@ static ssize_t lis3lv02d_rate_show(struct device *dev, | |||
434 | u8 ctrl; | 420 | u8 ctrl; |
435 | int val; | 421 | int val; |
436 | 422 | ||
437 | lis3lv02d_increase_use(&adev); | 423 | lis3lv02d_increase_use(&lis3_dev); |
438 | adev.read(adev.device->handle, CTRL_REG1, &ctrl); | 424 | lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl); |
439 | lis3lv02d_decrease_use(&adev); | 425 | lis3lv02d_decrease_use(&lis3_dev); |
440 | val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4; | 426 | val = (ctrl & (CTRL1_DF0 | CTRL1_DF1)) >> 4; |
441 | return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]); | 427 | return sprintf(buf, "%d\n", lis3lv02dl_df_val[val]); |
442 | } | 428 | } |
@@ -458,23 +444,73 @@ static struct attribute_group lis3lv02d_attribute_group = { | |||
458 | }; | 444 | }; |
459 | 445 | ||
460 | 446 | ||
461 | static int lis3lv02d_add_fs(struct acpi_device *device) | 447 | static int lis3lv02d_add_fs(struct lis3lv02d *lis3) |
462 | { | 448 | { |
463 | adev.pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); | 449 | lis3_dev.pdev = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0); |
464 | if (IS_ERR(adev.pdev)) | 450 | if (IS_ERR(lis3_dev.pdev)) |
465 | return PTR_ERR(adev.pdev); | 451 | return PTR_ERR(lis3_dev.pdev); |
466 | 452 | ||
467 | return sysfs_create_group(&adev.pdev->dev.kobj, &lis3lv02d_attribute_group); | 453 | return sysfs_create_group(&lis3_dev.pdev->dev.kobj, &lis3lv02d_attribute_group); |
468 | } | 454 | } |
469 | 455 | ||
470 | int lis3lv02d_remove_fs(void) | 456 | int lis3lv02d_remove_fs(void) |
471 | { | 457 | { |
472 | sysfs_remove_group(&adev.pdev->dev.kobj, &lis3lv02d_attribute_group); | 458 | sysfs_remove_group(&lis3_dev.pdev->dev.kobj, &lis3lv02d_attribute_group); |
473 | platform_device_unregister(adev.pdev); | 459 | platform_device_unregister(lis3_dev.pdev); |
474 | return 0; | 460 | return 0; |
475 | } | 461 | } |
476 | EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); | 462 | EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); |
477 | 463 | ||
464 | /* | ||
465 | * Initialise the accelerometer and the various subsystems. | ||
466 | * Should be rather independant of the bus system. | ||
467 | */ | ||
468 | int lis3lv02d_init_device(struct lis3lv02d *dev) | ||
469 | { | ||
470 | dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I); | ||
471 | |||
472 | switch (dev->whoami) { | ||
473 | case LIS_DOUBLE_ID: | ||
474 | printk(KERN_INFO DRIVER_NAME ": 2-byte sensor found\n"); | ||
475 | dev->read_data = lis3lv02d_read_16; | ||
476 | dev->mdps_max_val = 2048; | ||
477 | break; | ||
478 | case LIS_SINGLE_ID: | ||
479 | printk(KERN_INFO DRIVER_NAME ": 1-byte sensor found\n"); | ||
480 | dev->read_data = lis3lv02d_read_8; | ||
481 | dev->mdps_max_val = 128; | ||
482 | break; | ||
483 | default: | ||
484 | printk(KERN_ERR DRIVER_NAME | ||
485 | ": unknown sensor type 0x%X\n", lis3_dev.whoami); | ||
486 | return -EINVAL; | ||
487 | } | ||
488 | |||
489 | mutex_init(&dev->lock); | ||
490 | lis3lv02d_add_fs(dev); | ||
491 | lis3lv02d_increase_use(dev); | ||
492 | |||
493 | if (lis3lv02d_joystick_enable()) | ||
494 | printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n"); | ||
495 | |||
496 | printk("lis3_init_device: irq %d\n", dev->irq); | ||
497 | |||
498 | /* bail if we did not get an IRQ from the bus layer */ | ||
499 | if (!dev->irq) { | ||
500 | printk(KERN_ERR DRIVER_NAME | ||
501 | ": No IRQ. Disabling /dev/freefall\n"); | ||
502 | goto out; | ||
503 | } | ||
504 | |||
505 | printk("lis3: registering device\n"); | ||
506 | if (misc_register(&lis3lv02d_misc_device)) | ||
507 | printk(KERN_ERR DRIVER_NAME ": misc_register failed\n"); | ||
508 | out: | ||
509 | lis3lv02d_decrease_use(dev); | ||
510 | return 0; | ||
511 | } | ||
512 | EXPORT_SYMBOL_GPL(lis3lv02d_init_device); | ||
513 | |||
478 | MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver"); | 514 | MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver"); |
479 | MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek"); | 515 | MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek"); |
480 | MODULE_LICENSE("GPL"); | 516 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h index 75972bf372ff..745ec96806d4 100644 --- a/drivers/hwmon/lis3lv02d.h +++ b/drivers/hwmon/lis3lv02d.h | |||
@@ -159,14 +159,14 @@ struct axis_conversion { | |||
159 | s8 z; | 159 | s8 z; |
160 | }; | 160 | }; |
161 | 161 | ||
162 | struct acpi_lis3lv02d { | 162 | struct lis3lv02d { |
163 | struct acpi_device *device; /* The ACPI device */ | 163 | void *bus_priv; /* used by the bus layer only */ |
164 | acpi_status (*init) (acpi_handle handle); | 164 | int (*init) (struct lis3lv02d *lis3); |
165 | acpi_status (*write) (acpi_handle handle, int reg, u8 val); | 165 | int (*write) (struct lis3lv02d *lis3, int reg, u8 val); |
166 | acpi_status (*read) (acpi_handle handle, int reg, u8 *ret); | 166 | int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret); |
167 | 167 | ||
168 | u8 whoami; /* 3Ah: 2-byte registries, 3Bh: 1-byte registries */ | 168 | u8 whoami; /* 3Ah: 2-byte registries, 3Bh: 1-byte registries */ |
169 | s16 (*read_data) (acpi_handle handle, int reg); | 169 | s16 (*read_data) (struct lis3lv02d *lis3, int reg); |
170 | int mdps_max_val; | 170 | int mdps_max_val; |
171 | 171 | ||
172 | struct input_dev *idev; /* input device */ | 172 | struct input_dev *idev; /* input device */ |
@@ -187,11 +187,11 @@ struct acpi_lis3lv02d { | |||
187 | unsigned long misc_opened; /* bit0: whether the device is open */ | 187 | unsigned long misc_opened; /* bit0: whether the device is open */ |
188 | }; | 188 | }; |
189 | 189 | ||
190 | int lis3lv02d_init_device(struct acpi_lis3lv02d *dev); | 190 | int lis3lv02d_init_device(struct lis3lv02d *lis3); |
191 | int lis3lv02d_joystick_enable(void); | 191 | int lis3lv02d_joystick_enable(void); |
192 | void lis3lv02d_joystick_disable(void); | 192 | void lis3lv02d_joystick_disable(void); |
193 | void lis3lv02d_poweroff(acpi_handle handle); | 193 | void lis3lv02d_poweroff(struct lis3lv02d *lis3); |
194 | void lis3lv02d_poweron(acpi_handle handle); | 194 | void lis3lv02d_poweron(struct lis3lv02d *lis3); |
195 | int lis3lv02d_remove_fs(void); | 195 | int lis3lv02d_remove_fs(void); |
196 | 196 | ||
197 | extern struct acpi_lis3lv02d adev; | 197 | extern struct lis3lv02d lis3_dev; |
diff --git a/drivers/hwmon/lis3lv02d_spi.c b/drivers/hwmon/lis3lv02d_spi.c new file mode 100644 index 000000000000..07ae74b0e191 --- /dev/null +++ b/drivers/hwmon/lis3lv02d_spi.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * lis3lv02d_spi - SPI glue layer for lis3lv02d | ||
3 | * | ||
4 | * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * publishhed by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/input.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/workqueue.h> | ||
18 | #include <linux/spi/spi.h> | ||
19 | |||
20 | #include "lis3lv02d.h" | ||
21 | |||
22 | #define DRV_NAME "lis3lv02d_spi" | ||
23 | #define LIS3_SPI_READ 0x80 | ||
24 | |||
25 | static int lis3_spi_read(struct lis3lv02d *lis3, int reg, u8 *v) | ||
26 | { | ||
27 | struct spi_device *spi = lis3->bus_priv; | ||
28 | int ret = spi_w8r8(spi, reg | LIS3_SPI_READ); | ||
29 | if (ret < 0) | ||
30 | return -EINVAL; | ||
31 | |||
32 | *v = (u8) ret; | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static int lis3_spi_write(struct lis3lv02d *lis3, int reg, u8 val) | ||
37 | { | ||
38 | u8 tmp[2] = { reg, val }; | ||
39 | struct spi_device *spi = lis3->bus_priv; | ||
40 | return spi_write(spi, tmp, sizeof(tmp)); | ||
41 | } | ||
42 | |||
43 | static int lis3_spi_init(struct lis3lv02d *lis3) | ||
44 | { | ||
45 | u8 reg; | ||
46 | int ret; | ||
47 | |||
48 | /* power up the device */ | ||
49 | ret = lis3->read(lis3, CTRL_REG1, ®); | ||
50 | if (ret < 0) | ||
51 | return ret; | ||
52 | |||
53 | reg |= CTRL1_PD0; | ||
54 | return lis3->write(lis3, CTRL_REG1, reg); | ||
55 | } | ||
56 | |||
57 | static struct axis_conversion lis3lv02d_axis_normal = { 1, 2, 3 }; | ||
58 | |||
59 | static int __devinit lis302dl_spi_probe(struct spi_device *spi) | ||
60 | { | ||
61 | int ret; | ||
62 | |||
63 | spi->bits_per_word = 8; | ||
64 | spi->mode = SPI_MODE_0; | ||
65 | ret = spi_setup(spi); | ||
66 | if (ret < 0) | ||
67 | return ret; | ||
68 | |||
69 | lis3_dev.bus_priv = spi; | ||
70 | lis3_dev.init = lis3_spi_init; | ||
71 | lis3_dev.read = lis3_spi_read; | ||
72 | lis3_dev.write = lis3_spi_write; | ||
73 | lis3_dev.irq = spi->irq; | ||
74 | lis3_dev.ac = lis3lv02d_axis_normal; | ||
75 | spi_set_drvdata(spi, &lis3_dev); | ||
76 | |||
77 | ret = lis3lv02d_init_device(&lis3_dev); | ||
78 | return ret; | ||
79 | } | ||
80 | |||
81 | static int __devexit lis302dl_spi_remove(struct spi_device *spi) | ||
82 | { | ||
83 | struct lis3lv02d *lis3 = spi_get_drvdata(spi); | ||
84 | lis3lv02d_joystick_disable(); | ||
85 | lis3lv02d_poweroff(lis3); | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static struct spi_driver lis302dl_spi_driver = { | ||
90 | .driver = { | ||
91 | .name = DRV_NAME, | ||
92 | .owner = THIS_MODULE, | ||
93 | }, | ||
94 | .probe = lis302dl_spi_probe, | ||
95 | .remove = __devexit_p(lis302dl_spi_remove), | ||
96 | }; | ||
97 | |||
98 | static int __init lis302dl_init(void) | ||
99 | { | ||
100 | return spi_register_driver(&lis302dl_spi_driver); | ||
101 | } | ||
102 | |||
103 | static void __exit lis302dl_exit(void) | ||
104 | { | ||
105 | spi_unregister_driver(&lis302dl_spi_driver); | ||
106 | } | ||
107 | |||
108 | module_init(lis302dl_init); | ||
109 | module_exit(lis302dl_exit); | ||
110 | |||
111 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | ||
112 | MODULE_DESCRIPTION("lis3lv02d SPI glue layer"); | ||
113 | MODULE_LICENSE("GPL"); | ||
114 | |||
diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c new file mode 100644 index 000000000000..091d95f38aaa --- /dev/null +++ b/drivers/hwmon/lm95241.c | |||
@@ -0,0 +1,527 @@ | |||
1 | /* | ||
2 | * lm95241.c - Part of lm_sensors, Linux kernel modules for hardware | ||
3 | * monitoring | ||
4 | * Copyright (C) 2008 Davide Rizzo <elpa-rizzo@gmail.com> | ||
5 | * | ||
6 | * Based on the max1619 driver. The LM95241 is a sensor chip made by National | ||
7 | * Semiconductors. | ||
8 | * It reports up to three temperatures (its own plus up to | ||
9 | * two external ones). Complete datasheet can be | ||
10 | * obtained from National's website at: | ||
11 | * http://www.national.com/ds.cgi/LM/LM95241.pdf | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/jiffies.h> | ||
32 | #include <linux/i2c.h> | ||
33 | #include <linux/hwmon.h> | ||
34 | #include <linux/hwmon-sysfs.h> | ||
35 | #include <linux/err.h> | ||
36 | #include <linux/mutex.h> | ||
37 | #include <linux/sysfs.h> | ||
38 | |||
39 | static const unsigned short normal_i2c[] = { | ||
40 | 0x19, 0x2a, 0x2b, I2C_CLIENT_END}; | ||
41 | |||
42 | /* Insmod parameters */ | ||
43 | I2C_CLIENT_INSMOD_1(lm95241); | ||
44 | |||
45 | /* LM95241 registers */ | ||
46 | #define LM95241_REG_R_MAN_ID 0xFE | ||
47 | #define LM95241_REG_R_CHIP_ID 0xFF | ||
48 | #define LM95241_REG_R_STATUS 0x02 | ||
49 | #define LM95241_REG_RW_CONFIG 0x03 | ||
50 | #define LM95241_REG_RW_REM_FILTER 0x06 | ||
51 | #define LM95241_REG_RW_TRUTHERM 0x07 | ||
52 | #define LM95241_REG_W_ONE_SHOT 0x0F | ||
53 | #define LM95241_REG_R_LOCAL_TEMPH 0x10 | ||
54 | #define LM95241_REG_R_REMOTE1_TEMPH 0x11 | ||
55 | #define LM95241_REG_R_REMOTE2_TEMPH 0x12 | ||
56 | #define LM95241_REG_R_LOCAL_TEMPL 0x20 | ||
57 | #define LM95241_REG_R_REMOTE1_TEMPL 0x21 | ||
58 | #define LM95241_REG_R_REMOTE2_TEMPL 0x22 | ||
59 | #define LM95241_REG_RW_REMOTE_MODEL 0x30 | ||
60 | |||
61 | /* LM95241 specific bitfields */ | ||
62 | #define CFG_STOP 0x40 | ||
63 | #define CFG_CR0076 0x00 | ||
64 | #define CFG_CR0182 0x10 | ||
65 | #define CFG_CR1000 0x20 | ||
66 | #define CFG_CR2700 0x30 | ||
67 | #define R1MS_SHIFT 0 | ||
68 | #define R2MS_SHIFT 2 | ||
69 | #define R1MS_MASK (0x01 << (R1MS_SHIFT)) | ||
70 | #define R2MS_MASK (0x01 << (R2MS_SHIFT)) | ||
71 | #define R1DF_SHIFT 1 | ||
72 | #define R2DF_SHIFT 2 | ||
73 | #define R1DF_MASK (0x01 << (R1DF_SHIFT)) | ||
74 | #define R2DF_MASK (0x01 << (R2DF_SHIFT)) | ||
75 | #define R1FE_MASK 0x01 | ||
76 | #define R2FE_MASK 0x05 | ||
77 | #define TT1_SHIFT 0 | ||
78 | #define TT2_SHIFT 4 | ||
79 | #define TT_OFF 0 | ||
80 | #define TT_ON 1 | ||
81 | #define TT_MASK 7 | ||
82 | #define MANUFACTURER_ID 0x01 | ||
83 | #define DEFAULT_REVISION 0xA4 | ||
84 | |||
85 | /* Conversions and various macros */ | ||
86 | #define TEMP_FROM_REG(val_h, val_l) (((val_h) & 0x80 ? (val_h) - 0x100 : \ | ||
87 | (val_h)) * 1000 + (val_l) * 1000 / 256) | ||
88 | |||
89 | /* Functions declaration */ | ||
90 | static int lm95241_attach_adapter(struct i2c_adapter *adapter); | ||
91 | static int lm95241_detect(struct i2c_adapter *adapter, int address, | ||
92 | int kind); | ||
93 | static void lm95241_init_client(struct i2c_client *client); | ||
94 | static int lm95241_detach_client(struct i2c_client *client); | ||
95 | static struct lm95241_data *lm95241_update_device(struct device *dev); | ||
96 | |||
97 | /* Driver data (common to all clients) */ | ||
98 | static struct i2c_driver lm95241_driver = { | ||
99 | .driver = { | ||
100 | .name = "lm95241", | ||
101 | }, | ||
102 | .attach_adapter = lm95241_attach_adapter, | ||
103 | .detach_client = lm95241_detach_client, | ||
104 | }; | ||
105 | |||
106 | /* Client data (each client gets its own) */ | ||
107 | struct lm95241_data { | ||
108 | struct i2c_client client; | ||
109 | struct device *hwmon_dev; | ||
110 | struct mutex update_lock; | ||
111 | unsigned long last_updated, rate; /* in jiffies */ | ||
112 | char valid; /* zero until following fields are valid */ | ||
113 | /* registers values */ | ||
114 | u8 local_h, local_l; /* local */ | ||
115 | u8 remote1_h, remote1_l; /* remote1 */ | ||
116 | u8 remote2_h, remote2_l; /* remote2 */ | ||
117 | u8 config, model, trutherm; | ||
118 | }; | ||
119 | |||
120 | /* Sysfs stuff */ | ||
121 | #define show_temp(value) \ | ||
122 | static ssize_t show_##value(struct device *dev, \ | ||
123 | struct device_attribute *attr, char *buf) \ | ||
124 | { \ | ||
125 | struct lm95241_data *data = lm95241_update_device(dev); \ | ||
126 | snprintf(buf, PAGE_SIZE - 1, "%d\n", \ | ||
127 | TEMP_FROM_REG(data->value##_h, data->value##_l)); \ | ||
128 | return strlen(buf); \ | ||
129 | } | ||
130 | show_temp(local); | ||
131 | show_temp(remote1); | ||
132 | show_temp(remote2); | ||
133 | |||
134 | static ssize_t show_rate(struct device *dev, struct device_attribute *attr, | ||
135 | char *buf) | ||
136 | { | ||
137 | struct lm95241_data *data = lm95241_update_device(dev); | ||
138 | |||
139 | snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->rate / HZ); | ||
140 | return strlen(buf); | ||
141 | } | ||
142 | |||
143 | static ssize_t set_rate(struct device *dev, struct device_attribute *attr, | ||
144 | const char *buf, size_t count) | ||
145 | { | ||
146 | struct i2c_client *client = to_i2c_client(dev); | ||
147 | struct lm95241_data *data = i2c_get_clientdata(client); | ||
148 | |||
149 | strict_strtol(buf, 10, &data->rate); | ||
150 | data->rate = data->rate * HZ / 1000; | ||
151 | |||
152 | return count; | ||
153 | } | ||
154 | |||
155 | #define show_type(flag) \ | ||
156 | static ssize_t show_type##flag(struct device *dev, \ | ||
157 | struct device_attribute *attr, char *buf) \ | ||
158 | { \ | ||
159 | struct i2c_client *client = to_i2c_client(dev); \ | ||
160 | struct lm95241_data *data = i2c_get_clientdata(client); \ | ||
161 | \ | ||
162 | snprintf(buf, PAGE_SIZE - 1, \ | ||
163 | data->model & R##flag##MS_MASK ? "1\n" : "2\n"); \ | ||
164 | return strlen(buf); \ | ||
165 | } | ||
166 | show_type(1); | ||
167 | show_type(2); | ||
168 | |||
169 | #define show_min(flag) \ | ||
170 | static ssize_t show_min##flag(struct device *dev, \ | ||
171 | struct device_attribute *attr, char *buf) \ | ||
172 | { \ | ||
173 | struct i2c_client *client = to_i2c_client(dev); \ | ||
174 | struct lm95241_data *data = i2c_get_clientdata(client); \ | ||
175 | \ | ||
176 | snprintf(buf, PAGE_SIZE - 1, \ | ||
177 | data->config & R##flag##DF_MASK ? \ | ||
178 | "-127000\n" : "0\n"); \ | ||
179 | return strlen(buf); \ | ||
180 | } | ||
181 | show_min(1); | ||
182 | show_min(2); | ||
183 | |||
184 | #define show_max(flag) \ | ||
185 | static ssize_t show_max##flag(struct device *dev, \ | ||
186 | struct device_attribute *attr, char *buf) \ | ||
187 | { \ | ||
188 | struct i2c_client *client = to_i2c_client(dev); \ | ||
189 | struct lm95241_data *data = i2c_get_clientdata(client); \ | ||
190 | \ | ||
191 | snprintf(buf, PAGE_SIZE - 1, \ | ||
192 | data->config & R##flag##DF_MASK ? \ | ||
193 | "127000\n" : "255000\n"); \ | ||
194 | return strlen(buf); \ | ||
195 | } | ||
196 | show_max(1); | ||
197 | show_max(2); | ||
198 | |||
199 | #define set_type(flag) \ | ||
200 | static ssize_t set_type##flag(struct device *dev, \ | ||
201 | struct device_attribute *attr, \ | ||
202 | const char *buf, size_t count) \ | ||
203 | { \ | ||
204 | struct i2c_client *client = to_i2c_client(dev); \ | ||
205 | struct lm95241_data *data = i2c_get_clientdata(client); \ | ||
206 | \ | ||
207 | long val; \ | ||
208 | strict_strtol(buf, 10, &val); \ | ||
209 | \ | ||
210 | if ((val == 1) || (val == 2)) { \ | ||
211 | \ | ||
212 | mutex_lock(&data->update_lock); \ | ||
213 | \ | ||
214 | data->trutherm &= ~(TT_MASK << TT##flag##_SHIFT); \ | ||
215 | if (val == 1) { \ | ||
216 | data->model |= R##flag##MS_MASK; \ | ||
217 | data->trutherm |= (TT_ON << TT##flag##_SHIFT); \ | ||
218 | } \ | ||
219 | else { \ | ||
220 | data->model &= ~R##flag##MS_MASK; \ | ||
221 | data->trutherm |= (TT_OFF << TT##flag##_SHIFT); \ | ||
222 | } \ | ||
223 | \ | ||
224 | data->valid = 0; \ | ||
225 | \ | ||
226 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, \ | ||
227 | data->model); \ | ||
228 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, \ | ||
229 | data->trutherm); \ | ||
230 | \ | ||
231 | mutex_unlock(&data->update_lock); \ | ||
232 | \ | ||
233 | } \ | ||
234 | return count; \ | ||
235 | } | ||
236 | set_type(1); | ||
237 | set_type(2); | ||
238 | |||
239 | #define set_min(flag) \ | ||
240 | static ssize_t set_min##flag(struct device *dev, \ | ||
241 | struct device_attribute *devattr, const char *buf, size_t count) \ | ||
242 | { \ | ||
243 | struct i2c_client *client = to_i2c_client(dev); \ | ||
244 | struct lm95241_data *data = i2c_get_clientdata(client); \ | ||
245 | \ | ||
246 | long val; \ | ||
247 | strict_strtol(buf, 10, &val); \ | ||
248 | \ | ||
249 | mutex_lock(&data->update_lock); \ | ||
250 | \ | ||
251 | if (val < 0) \ | ||
252 | data->config |= R##flag##DF_MASK; \ | ||
253 | else \ | ||
254 | data->config &= ~R##flag##DF_MASK; \ | ||
255 | \ | ||
256 | data->valid = 0; \ | ||
257 | \ | ||
258 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \ | ||
259 | data->config); \ | ||
260 | \ | ||
261 | mutex_unlock(&data->update_lock); \ | ||
262 | \ | ||
263 | return count; \ | ||
264 | } | ||
265 | set_min(1); | ||
266 | set_min(2); | ||
267 | |||
268 | #define set_max(flag) \ | ||
269 | static ssize_t set_max##flag(struct device *dev, \ | ||
270 | struct device_attribute *devattr, const char *buf, size_t count) \ | ||
271 | { \ | ||
272 | struct i2c_client *client = to_i2c_client(dev); \ | ||
273 | struct lm95241_data *data = i2c_get_clientdata(client); \ | ||
274 | \ | ||
275 | long val; \ | ||
276 | strict_strtol(buf, 10, &val); \ | ||
277 | \ | ||
278 | mutex_lock(&data->update_lock); \ | ||
279 | \ | ||
280 | if (val <= 127000) \ | ||
281 | data->config |= R##flag##DF_MASK; \ | ||
282 | else \ | ||
283 | data->config &= ~R##flag##DF_MASK; \ | ||
284 | \ | ||
285 | data->valid = 0; \ | ||
286 | \ | ||
287 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, \ | ||
288 | data->config); \ | ||
289 | \ | ||
290 | mutex_unlock(&data->update_lock); \ | ||
291 | \ | ||
292 | return count; \ | ||
293 | } | ||
294 | set_max(1); | ||
295 | set_max(2); | ||
296 | |||
297 | static DEVICE_ATTR(temp1_input, S_IRUGO, show_local, NULL); | ||
298 | static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote1, NULL); | ||
299 | static DEVICE_ATTR(temp3_input, S_IRUGO, show_remote2, NULL); | ||
300 | static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type1, set_type1); | ||
301 | static DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type2, set_type2); | ||
302 | static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min1, set_min1); | ||
303 | static DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min2, set_min2); | ||
304 | static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max1, set_max1); | ||
305 | static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max2, set_max2); | ||
306 | static DEVICE_ATTR(rate, S_IWUSR | S_IRUGO, show_rate, set_rate); | ||
307 | |||
308 | static struct attribute *lm95241_attributes[] = { | ||
309 | &dev_attr_temp1_input.attr, | ||
310 | &dev_attr_temp2_input.attr, | ||
311 | &dev_attr_temp3_input.attr, | ||
312 | &dev_attr_temp2_type.attr, | ||
313 | &dev_attr_temp3_type.attr, | ||
314 | &dev_attr_temp2_min.attr, | ||
315 | &dev_attr_temp3_min.attr, | ||
316 | &dev_attr_temp2_max.attr, | ||
317 | &dev_attr_temp3_max.attr, | ||
318 | &dev_attr_rate.attr, | ||
319 | NULL | ||
320 | }; | ||
321 | |||
322 | static const struct attribute_group lm95241_group = { | ||
323 | .attrs = lm95241_attributes, | ||
324 | }; | ||
325 | |||
326 | /* Init/exit code */ | ||
327 | static int lm95241_attach_adapter(struct i2c_adapter *adapter) | ||
328 | { | ||
329 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
330 | return 0; | ||
331 | return i2c_probe(adapter, &addr_data, lm95241_detect); | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * The following function does more than just detection. If detection | ||
336 | * succeeds, it also registers the new chip. | ||
337 | */ | ||
338 | static int lm95241_detect(struct i2c_adapter *adapter, int address, int kind) | ||
339 | { | ||
340 | struct i2c_client *new_client; | ||
341 | struct lm95241_data *data; | ||
342 | int err = 0; | ||
343 | const char *name = ""; | ||
344 | |||
345 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
346 | goto exit; | ||
347 | |||
348 | data = kzalloc(sizeof(struct lm95241_data), GFP_KERNEL); | ||
349 | if (!data) { | ||
350 | err = -ENOMEM; | ||
351 | goto exit; | ||
352 | } | ||
353 | |||
354 | /* The common I2C client data is placed right before the | ||
355 | LM95241-specific data. */ | ||
356 | new_client = &data->client; | ||
357 | i2c_set_clientdata(new_client, data); | ||
358 | new_client->addr = address; | ||
359 | new_client->adapter = adapter; | ||
360 | new_client->driver = &lm95241_driver; | ||
361 | new_client->flags = 0; | ||
362 | |||
363 | /* | ||
364 | * Now we do the remaining detection. A negative kind means that | ||
365 | * the driver was loaded with no force parameter (default), so we | ||
366 | * must both detect and identify the chip. A zero kind means that | ||
367 | * the driver was loaded with the force parameter, the detection | ||
368 | * step shall be skipped. A positive kind means that the driver | ||
369 | * was loaded with the force parameter and a given kind of chip is | ||
370 | * requested, so both the detection and the identification steps | ||
371 | * are skipped. | ||
372 | */ | ||
373 | if (kind < 0) { /* detection */ | ||
374 | if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) | ||
375 | != MANUFACTURER_ID) | ||
376 | || (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) | ||
377 | < DEFAULT_REVISION)) { | ||
378 | dev_dbg(&adapter->dev, | ||
379 | "LM95241 detection failed at 0x%02x.\n", | ||
380 | address); | ||
381 | goto exit_free; | ||
382 | } | ||
383 | } | ||
384 | |||
385 | if (kind <= 0) { /* identification */ | ||
386 | if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID) | ||
387 | == MANUFACTURER_ID) | ||
388 | && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID) | ||
389 | >= DEFAULT_REVISION)) { | ||
390 | |||
391 | kind = lm95241; | ||
392 | |||
393 | if (kind <= 0) { /* identification failed */ | ||
394 | dev_info(&adapter->dev, "Unsupported chip\n"); | ||
395 | goto exit_free; | ||
396 | } | ||
397 | } | ||
398 | } | ||
399 | |||
400 | if (kind == lm95241) | ||
401 | name = "lm95241"; | ||
402 | |||
403 | /* We can fill in the remaining client fields */ | ||
404 | strlcpy(new_client->name, name, I2C_NAME_SIZE); | ||
405 | data->valid = 0; | ||
406 | mutex_init(&data->update_lock); | ||
407 | |||
408 | /* Tell the I2C layer a new client has arrived */ | ||
409 | err = i2c_attach_client(new_client); | ||
410 | if (err) | ||
411 | goto exit_free; | ||
412 | |||
413 | /* Initialize the LM95241 chip */ | ||
414 | lm95241_init_client(new_client); | ||
415 | |||
416 | /* Register sysfs hooks */ | ||
417 | err = sysfs_create_group(&new_client->dev.kobj, &lm95241_group); | ||
418 | if (err) | ||
419 | goto exit_detach; | ||
420 | |||
421 | data->hwmon_dev = hwmon_device_register(&new_client->dev); | ||
422 | if (IS_ERR(data->hwmon_dev)) { | ||
423 | err = PTR_ERR(data->hwmon_dev); | ||
424 | goto exit_remove_files; | ||
425 | } | ||
426 | |||
427 | return 0; | ||
428 | |||
429 | exit_remove_files: | ||
430 | sysfs_remove_group(&new_client->dev.kobj, &lm95241_group); | ||
431 | exit_detach: | ||
432 | i2c_detach_client(new_client); | ||
433 | exit_free: | ||
434 | kfree(data); | ||
435 | exit: | ||
436 | return err; | ||
437 | } | ||
438 | |||
439 | static void lm95241_init_client(struct i2c_client *client) | ||
440 | { | ||
441 | struct lm95241_data *data = i2c_get_clientdata(client); | ||
442 | |||
443 | data->rate = HZ; /* 1 sec default */ | ||
444 | data->valid = 0; | ||
445 | data->config = CFG_CR0076; | ||
446 | data->model = 0; | ||
447 | data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT); | ||
448 | |||
449 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, | ||
450 | data->config); | ||
451 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER, | ||
452 | R1FE_MASK | R2FE_MASK); | ||
453 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, | ||
454 | data->trutherm); | ||
455 | i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, | ||
456 | data->model); | ||
457 | } | ||
458 | |||
459 | static int lm95241_detach_client(struct i2c_client *client) | ||
460 | { | ||
461 | struct lm95241_data *data = i2c_get_clientdata(client); | ||
462 | int err; | ||
463 | |||
464 | hwmon_device_unregister(data->hwmon_dev); | ||
465 | sysfs_remove_group(&client->dev.kobj, &lm95241_group); | ||
466 | |||
467 | err = i2c_detach_client(client); | ||
468 | if (err) | ||
469 | return err; | ||
470 | |||
471 | kfree(data); | ||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | static struct lm95241_data *lm95241_update_device(struct device *dev) | ||
476 | { | ||
477 | struct i2c_client *client = to_i2c_client(dev); | ||
478 | struct lm95241_data *data = i2c_get_clientdata(client); | ||
479 | |||
480 | mutex_lock(&data->update_lock); | ||
481 | |||
482 | if (time_after(jiffies, data->last_updated + data->rate) || | ||
483 | !data->valid) { | ||
484 | dev_dbg(&client->dev, "Updating lm95241 data.\n"); | ||
485 | data->local_h = | ||
486 | i2c_smbus_read_byte_data(client, | ||
487 | LM95241_REG_R_LOCAL_TEMPH); | ||
488 | data->local_l = | ||
489 | i2c_smbus_read_byte_data(client, | ||
490 | LM95241_REG_R_LOCAL_TEMPL); | ||
491 | data->remote1_h = | ||
492 | i2c_smbus_read_byte_data(client, | ||
493 | LM95241_REG_R_REMOTE1_TEMPH); | ||
494 | data->remote1_l = | ||
495 | i2c_smbus_read_byte_data(client, | ||
496 | LM95241_REG_R_REMOTE1_TEMPL); | ||
497 | data->remote2_h = | ||
498 | i2c_smbus_read_byte_data(client, | ||
499 | LM95241_REG_R_REMOTE2_TEMPH); | ||
500 | data->remote2_l = | ||
501 | i2c_smbus_read_byte_data(client, | ||
502 | LM95241_REG_R_REMOTE2_TEMPL); | ||
503 | data->last_updated = jiffies; | ||
504 | data->valid = 1; | ||
505 | } | ||
506 | |||
507 | mutex_unlock(&data->update_lock); | ||
508 | |||
509 | return data; | ||
510 | } | ||
511 | |||
512 | static int __init sensors_lm95241_init(void) | ||
513 | { | ||
514 | return i2c_add_driver(&lm95241_driver); | ||
515 | } | ||
516 | |||
517 | static void __exit sensors_lm95241_exit(void) | ||
518 | { | ||
519 | i2c_del_driver(&lm95241_driver); | ||
520 | } | ||
521 | |||
522 | MODULE_AUTHOR("Davide Rizzo <elpa-rizzo@gmail.com>"); | ||
523 | MODULE_DESCRIPTION("LM95241 sensor driver"); | ||
524 | MODULE_LICENSE("GPL"); | ||
525 | |||
526 | module_init(sensors_lm95241_init); | ||
527 | module_exit(sensors_lm95241_exit); | ||
diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c new file mode 100644 index 000000000000..9386e2a39211 --- /dev/null +++ b/drivers/hwmon/ltc4215.c | |||
@@ -0,0 +1,364 @@ | |||
1 | /* | ||
2 | * Driver for Linear Technology LTC4215 I2C Hot Swap Controller | ||
3 | * | ||
4 | * Copyright (C) 2009 Ira W. Snyder <iws@ovro.caltech.edu> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * Datasheet: | ||
11 | * http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1006,C1163,P17572,D12697 | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/i2c.h> | ||
20 | #include <linux/hwmon.h> | ||
21 | #include <linux/hwmon-sysfs.h> | ||
22 | |||
23 | static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
24 | |||
25 | /* Insmod parameters */ | ||
26 | I2C_CLIENT_INSMOD_1(ltc4215); | ||
27 | |||
28 | /* Here are names of the chip's registers (a.k.a. commands) */ | ||
29 | enum ltc4215_cmd { | ||
30 | LTC4215_CONTROL = 0x00, /* rw */ | ||
31 | LTC4215_ALERT = 0x01, /* rw */ | ||
32 | LTC4215_STATUS = 0x02, /* ro */ | ||
33 | LTC4215_FAULT = 0x03, /* rw */ | ||
34 | LTC4215_SENSE = 0x04, /* rw */ | ||
35 | LTC4215_SOURCE = 0x05, /* rw */ | ||
36 | LTC4215_ADIN = 0x06, /* rw */ | ||
37 | }; | ||
38 | |||
39 | struct ltc4215_data { | ||
40 | struct device *hwmon_dev; | ||
41 | |||
42 | struct mutex update_lock; | ||
43 | bool valid; | ||
44 | unsigned long last_updated; /* in jiffies */ | ||
45 | |||
46 | /* Registers */ | ||
47 | u8 regs[7]; | ||
48 | }; | ||
49 | |||
50 | static struct ltc4215_data *ltc4215_update_device(struct device *dev) | ||
51 | { | ||
52 | struct i2c_client *client = to_i2c_client(dev); | ||
53 | struct ltc4215_data *data = i2c_get_clientdata(client); | ||
54 | s32 val; | ||
55 | int i; | ||
56 | |||
57 | mutex_lock(&data->update_lock); | ||
58 | |||
59 | /* The chip's A/D updates 10 times per second */ | ||
60 | if (time_after(jiffies, data->last_updated + HZ / 10) || !data->valid) { | ||
61 | |||
62 | dev_dbg(&client->dev, "Starting ltc4215 update\n"); | ||
63 | |||
64 | /* Read all registers */ | ||
65 | for (i = 0; i < ARRAY_SIZE(data->regs); i++) { | ||
66 | val = i2c_smbus_read_byte_data(client, i); | ||
67 | if (unlikely(val < 0)) | ||
68 | data->regs[i] = 0; | ||
69 | else | ||
70 | data->regs[i] = val; | ||
71 | } | ||
72 | |||
73 | data->last_updated = jiffies; | ||
74 | data->valid = 1; | ||
75 | } | ||
76 | |||
77 | mutex_unlock(&data->update_lock); | ||
78 | |||
79 | return data; | ||
80 | } | ||
81 | |||
82 | /* Return the voltage from the given register in millivolts */ | ||
83 | static int ltc4215_get_voltage(struct device *dev, u8 reg) | ||
84 | { | ||
85 | struct ltc4215_data *data = ltc4215_update_device(dev); | ||
86 | const u8 regval = data->regs[reg]; | ||
87 | u32 voltage = 0; | ||
88 | |||
89 | switch (reg) { | ||
90 | case LTC4215_SENSE: | ||
91 | /* 151 uV per increment */ | ||
92 | voltage = regval * 151 / 1000; | ||
93 | break; | ||
94 | case LTC4215_SOURCE: | ||
95 | /* 60.5 mV per increment */ | ||
96 | voltage = regval * 605 / 10; | ||
97 | break; | ||
98 | case LTC4215_ADIN: | ||
99 | /* The ADIN input is divided by 12.5, and has 4.82 mV | ||
100 | * per increment, so we have the additional multiply */ | ||
101 | voltage = regval * 482 * 125 / 1000; | ||
102 | break; | ||
103 | default: | ||
104 | /* If we get here, the developer messed up */ | ||
105 | WARN_ON_ONCE(1); | ||
106 | break; | ||
107 | } | ||
108 | |||
109 | return voltage; | ||
110 | } | ||
111 | |||
112 | /* Return the current from the sense resistor in mA */ | ||
113 | static unsigned int ltc4215_get_current(struct device *dev) | ||
114 | { | ||
115 | struct ltc4215_data *data = ltc4215_update_device(dev); | ||
116 | |||
117 | /* The strange looking conversions that follow are fixed-point | ||
118 | * math, since we cannot do floating point in the kernel. | ||
119 | * | ||
120 | * Step 1: convert sense register to microVolts | ||
121 | * Step 2: convert voltage to milliAmperes | ||
122 | * | ||
123 | * If you play around with the V=IR equation, you come up with | ||
124 | * the following: X uV / Y mOhm == Z mA | ||
125 | * | ||
126 | * With the resistors that are fractions of a milliOhm, we multiply | ||
127 | * the voltage and resistance by 10, to shift the decimal point. | ||
128 | * Now we can use the normal division operator again. | ||
129 | */ | ||
130 | |||
131 | /* Calculate voltage in microVolts (151 uV per increment) */ | ||
132 | const unsigned int voltage = data->regs[LTC4215_SENSE] * 151; | ||
133 | |||
134 | /* Calculate current in milliAmperes (4 milliOhm sense resistor) */ | ||
135 | const unsigned int curr = voltage / 4; | ||
136 | |||
137 | return curr; | ||
138 | } | ||
139 | |||
140 | static ssize_t ltc4215_show_voltage(struct device *dev, | ||
141 | struct device_attribute *da, | ||
142 | char *buf) | ||
143 | { | ||
144 | struct sensor_device_attribute *attr = to_sensor_dev_attr(da); | ||
145 | const int voltage = ltc4215_get_voltage(dev, attr->index); | ||
146 | |||
147 | return snprintf(buf, PAGE_SIZE, "%d\n", voltage); | ||
148 | } | ||
149 | |||
150 | static ssize_t ltc4215_show_current(struct device *dev, | ||
151 | struct device_attribute *da, | ||
152 | char *buf) | ||
153 | { | ||
154 | const unsigned int curr = ltc4215_get_current(dev); | ||
155 | |||
156 | return snprintf(buf, PAGE_SIZE, "%u\n", curr); | ||
157 | } | ||
158 | |||
159 | static ssize_t ltc4215_show_power(struct device *dev, | ||
160 | struct device_attribute *da, | ||
161 | char *buf) | ||
162 | { | ||
163 | const unsigned int curr = ltc4215_get_current(dev); | ||
164 | const int output_voltage = ltc4215_get_voltage(dev, LTC4215_ADIN); | ||
165 | |||
166 | /* current in mA * voltage in mV == power in uW */ | ||
167 | const unsigned int power = abs(output_voltage * curr); | ||
168 | |||
169 | return snprintf(buf, PAGE_SIZE, "%u\n", power); | ||
170 | } | ||
171 | |||
172 | static ssize_t ltc4215_show_alarm(struct device *dev, | ||
173 | struct device_attribute *da, | ||
174 | char *buf) | ||
175 | { | ||
176 | struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da); | ||
177 | struct ltc4215_data *data = ltc4215_update_device(dev); | ||
178 | const u8 reg = data->regs[attr->index]; | ||
179 | const u32 mask = attr->nr; | ||
180 | |||
181 | return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0); | ||
182 | } | ||
183 | |||
184 | /* These macros are used below in constructing device attribute objects | ||
185 | * for use with sysfs_create_group() to make a sysfs device file | ||
186 | * for each register. | ||
187 | */ | ||
188 | |||
189 | #define LTC4215_VOLTAGE(name, ltc4215_cmd_idx) \ | ||
190 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ | ||
191 | ltc4215_show_voltage, NULL, ltc4215_cmd_idx) | ||
192 | |||
193 | #define LTC4215_CURRENT(name) \ | ||
194 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ | ||
195 | ltc4215_show_current, NULL, 0); | ||
196 | |||
197 | #define LTC4215_POWER(name) \ | ||
198 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ | ||
199 | ltc4215_show_power, NULL, 0); | ||
200 | |||
201 | #define LTC4215_ALARM(name, mask, reg) \ | ||
202 | static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \ | ||
203 | ltc4215_show_alarm, NULL, (mask), reg) | ||
204 | |||
205 | /* Construct a sensor_device_attribute structure for each register */ | ||
206 | |||
207 | /* Current */ | ||
208 | LTC4215_CURRENT(curr1_input); | ||
209 | LTC4215_ALARM(curr1_max_alarm, (1 << 2), LTC4215_STATUS); | ||
210 | |||
211 | /* Power (virtual) */ | ||
212 | LTC4215_POWER(power1_input); | ||
213 | LTC4215_ALARM(power1_alarm, (1 << 3), LTC4215_STATUS); | ||
214 | |||
215 | /* Input Voltage */ | ||
216 | LTC4215_VOLTAGE(in1_input, LTC4215_ADIN); | ||
217 | LTC4215_ALARM(in1_max_alarm, (1 << 0), LTC4215_STATUS); | ||
218 | LTC4215_ALARM(in1_min_alarm, (1 << 1), LTC4215_STATUS); | ||
219 | |||
220 | /* Output Voltage */ | ||
221 | LTC4215_VOLTAGE(in2_input, LTC4215_SOURCE); | ||
222 | |||
223 | /* Finally, construct an array of pointers to members of the above objects, | ||
224 | * as required for sysfs_create_group() | ||
225 | */ | ||
226 | static struct attribute *ltc4215_attributes[] = { | ||
227 | &sensor_dev_attr_curr1_input.dev_attr.attr, | ||
228 | &sensor_dev_attr_curr1_max_alarm.dev_attr.attr, | ||
229 | |||
230 | &sensor_dev_attr_power1_input.dev_attr.attr, | ||
231 | &sensor_dev_attr_power1_alarm.dev_attr.attr, | ||
232 | |||
233 | &sensor_dev_attr_in1_input.dev_attr.attr, | ||
234 | &sensor_dev_attr_in1_max_alarm.dev_attr.attr, | ||
235 | &sensor_dev_attr_in1_min_alarm.dev_attr.attr, | ||
236 | |||
237 | &sensor_dev_attr_in2_input.dev_attr.attr, | ||
238 | |||
239 | NULL, | ||
240 | }; | ||
241 | |||
242 | static const struct attribute_group ltc4215_group = { | ||
243 | .attrs = ltc4215_attributes, | ||
244 | }; | ||
245 | |||
246 | static int ltc4215_probe(struct i2c_client *client, | ||
247 | const struct i2c_device_id *id) | ||
248 | { | ||
249 | struct ltc4215_data *data; | ||
250 | int ret; | ||
251 | |||
252 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
253 | if (!data) { | ||
254 | ret = -ENOMEM; | ||
255 | goto out_kzalloc; | ||
256 | } | ||
257 | |||
258 | i2c_set_clientdata(client, data); | ||
259 | mutex_init(&data->update_lock); | ||
260 | |||
261 | /* Initialize the LTC4215 chip */ | ||
262 | /* TODO */ | ||
263 | |||
264 | /* Register sysfs hooks */ | ||
265 | ret = sysfs_create_group(&client->dev.kobj, <c4215_group); | ||
266 | if (ret) | ||
267 | goto out_sysfs_create_group; | ||
268 | |||
269 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
270 | if (IS_ERR(data->hwmon_dev)) { | ||
271 | ret = PTR_ERR(data->hwmon_dev); | ||
272 | goto out_hwmon_device_register; | ||
273 | } | ||
274 | |||
275 | return 0; | ||
276 | |||
277 | out_hwmon_device_register: | ||
278 | sysfs_remove_group(&client->dev.kobj, <c4215_group); | ||
279 | out_sysfs_create_group: | ||
280 | kfree(data); | ||
281 | out_kzalloc: | ||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | static int ltc4215_remove(struct i2c_client *client) | ||
286 | { | ||
287 | struct ltc4215_data *data = i2c_get_clientdata(client); | ||
288 | |||
289 | hwmon_device_unregister(data->hwmon_dev); | ||
290 | sysfs_remove_group(&client->dev.kobj, <c4215_group); | ||
291 | |||
292 | kfree(data); | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static int ltc4215_detect(struct i2c_client *client, | ||
298 | int kind, | ||
299 | struct i2c_board_info *info) | ||
300 | { | ||
301 | struct i2c_adapter *adapter = client->adapter; | ||
302 | |||
303 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
304 | return -ENODEV; | ||
305 | |||
306 | if (kind < 0) { /* probed detection - check the chip type */ | ||
307 | s32 v; /* 8 bits from the chip, or -ERRNO */ | ||
308 | |||
309 | /* | ||
310 | * Register 0x01 bit b7 is reserved, expect 0 | ||
311 | * Register 0x03 bit b6 and b7 are reserved, expect 0 | ||
312 | */ | ||
313 | v = i2c_smbus_read_byte_data(client, LTC4215_ALERT); | ||
314 | if (v < 0 || (v & (1 << 7)) != 0) | ||
315 | return -ENODEV; | ||
316 | |||
317 | v = i2c_smbus_read_byte_data(client, LTC4215_FAULT); | ||
318 | if (v < 0 || (v & ((1 << 6) | (1 << 7))) != 0) | ||
319 | return -ENODEV; | ||
320 | } | ||
321 | |||
322 | strlcpy(info->type, "ltc4215", I2C_NAME_SIZE); | ||
323 | dev_info(&adapter->dev, "ltc4215 %s at address 0x%02x\n", | ||
324 | kind < 0 ? "probed" : "forced", | ||
325 | client->addr); | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
330 | static const struct i2c_device_id ltc4215_id[] = { | ||
331 | { "ltc4215", ltc4215 }, | ||
332 | { } | ||
333 | }; | ||
334 | MODULE_DEVICE_TABLE(i2c, ltc4215_id); | ||
335 | |||
336 | /* This is the driver that will be inserted */ | ||
337 | static struct i2c_driver ltc4215_driver = { | ||
338 | .class = I2C_CLASS_HWMON, | ||
339 | .driver = { | ||
340 | .name = "ltc4215", | ||
341 | }, | ||
342 | .probe = ltc4215_probe, | ||
343 | .remove = ltc4215_remove, | ||
344 | .id_table = ltc4215_id, | ||
345 | .detect = ltc4215_detect, | ||
346 | .address_data = &addr_data, | ||
347 | }; | ||
348 | |||
349 | static int __init ltc4215_init(void) | ||
350 | { | ||
351 | return i2c_add_driver(<c4215_driver); | ||
352 | } | ||
353 | |||
354 | static void __exit ltc4215_exit(void) | ||
355 | { | ||
356 | i2c_del_driver(<c4215_driver); | ||
357 | } | ||
358 | |||
359 | MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>"); | ||
360 | MODULE_DESCRIPTION("LTC4215 driver"); | ||
361 | MODULE_LICENSE("GPL"); | ||
362 | |||
363 | module_init(ltc4215_init); | ||
364 | module_exit(ltc4215_exit); | ||
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/hwmon/pcf8591.c index 16ce3e193776..1d7ffebd679d 100644 --- a/drivers/i2c/chips/pcf8591.c +++ b/drivers/hwmon/pcf8591.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2001-2004 Aurelien Jarno <aurelien@aurel32.net> | 2 | Copyright (C) 2001-2004 Aurelien Jarno <aurelien@aurel32.net> |
3 | Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with | 3 | Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with |
4 | the help of Jean Delvare <khali@linux-fr.org> | 4 | the help of Jean Delvare <khali@linux-fr.org> |
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 |
@@ -41,13 +41,13 @@ MODULE_PARM_DESC(input_mode, | |||
41 | " 3 = two differential inputs\n"); | 41 | " 3 = two differential inputs\n"); |
42 | 42 | ||
43 | /* The PCF8591 control byte | 43 | /* The PCF8591 control byte |
44 | 7 6 5 4 3 2 1 0 | 44 | 7 6 5 4 3 2 1 0 |
45 | | 0 |AOEF| AIP | 0 |AINC| AICH | */ | 45 | | 0 |AOEF| AIP | 0 |AINC| AICH | */ |
46 | 46 | ||
47 | /* Analog Output Enable Flag (analog output active if 1) */ | 47 | /* Analog Output Enable Flag (analog output active if 1) */ |
48 | #define PCF8591_CONTROL_AOEF 0x40 | 48 | #define PCF8591_CONTROL_AOEF 0x40 |
49 | 49 | ||
50 | /* Analog Input Programming | 50 | /* Analog Input Programming |
51 | 0x00 = four single ended inputs | 51 | 0x00 = four single ended inputs |
52 | 0x10 = three differential inputs | 52 | 0x10 = three differential inputs |
53 | 0x20 = single ended and differential mixed | 53 | 0x20 = single ended and differential mixed |
@@ -58,7 +58,7 @@ MODULE_PARM_DESC(input_mode, | |||
58 | #define PCF8591_CONTROL_AINC 0x04 | 58 | #define PCF8591_CONTROL_AINC 0x04 |
59 | 59 | ||
60 | /* Channel selection | 60 | /* Channel selection |
61 | 0x00 = channel 0 | 61 | 0x00 = channel 0 |
62 | 0x01 = channel 1 | 62 | 0x01 = channel 1 |
63 | 0x02 = channel 2 | 63 | 0x02 = channel 2 |
64 | 0x03 = channel 3 */ | 64 | 0x03 = channel 3 */ |
@@ -114,7 +114,7 @@ static ssize_t set_out0_output(struct device *dev, struct device_attribute *attr | |||
114 | return -EINVAL; | 114 | return -EINVAL; |
115 | } | 115 | } |
116 | 116 | ||
117 | static DEVICE_ATTR(out0_output, S_IWUSR | S_IRUGO, | 117 | static DEVICE_ATTR(out0_output, S_IWUSR | S_IRUGO, |
118 | show_out0_ouput, set_out0_output); | 118 | show_out0_ouput, set_out0_output); |
119 | 119 | ||
120 | static ssize_t show_out0_enable(struct device *dev, struct device_attribute *attr, char *buf) | 120 | static ssize_t show_out0_enable(struct device *dev, struct device_attribute *attr, char *buf) |
@@ -139,7 +139,7 @@ static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr | |||
139 | return count; | 139 | return count; |
140 | } | 140 | } |
141 | 141 | ||
142 | static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO, | 142 | static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO, |
143 | show_out0_enable, set_out0_enable); | 143 | show_out0_enable, set_out0_enable); |
144 | 144 | ||
145 | static struct attribute *pcf8591_attributes[] = { | 145 | static struct attribute *pcf8591_attributes[] = { |
@@ -196,7 +196,7 @@ static int pcf8591_probe(struct i2c_client *client, | |||
196 | err = -ENOMEM; | 196 | err = -ENOMEM; |
197 | goto exit; | 197 | goto exit; |
198 | } | 198 | } |
199 | 199 | ||
200 | i2c_set_clientdata(client, data); | 200 | i2c_set_clientdata(client, data); |
201 | mutex_init(&data->update_lock); | 201 | mutex_init(&data->update_lock); |
202 | 202 | ||
@@ -249,8 +249,8 @@ static void pcf8591_init_client(struct i2c_client *client) | |||
249 | data->aout = PCF8591_INIT_AOUT; | 249 | data->aout = PCF8591_INIT_AOUT; |
250 | 250 | ||
251 | i2c_smbus_write_byte_data(client, data->control, data->aout); | 251 | i2c_smbus_write_byte_data(client, data->control, data->aout); |
252 | 252 | ||
253 | /* The first byte transmitted contains the conversion code of the | 253 | /* The first byte transmitted contains the conversion code of the |
254 | previous read cycle. FLUSH IT! */ | 254 | previous read cycle. FLUSH IT! */ |
255 | i2c_smbus_read_byte(client); | 255 | i2c_smbus_read_byte(client); |
256 | } | 256 | } |
@@ -267,8 +267,8 @@ static int pcf8591_read_channel(struct device *dev, int channel) | |||
267 | data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK) | 267 | data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK) |
268 | | channel; | 268 | | channel; |
269 | i2c_smbus_write_byte(client, data->control); | 269 | i2c_smbus_write_byte(client, data->control); |
270 | 270 | ||
271 | /* The first byte transmitted contains the conversion code of | 271 | /* The first byte transmitted contains the conversion code of |
272 | the previous read cycle. FLUSH IT! */ | 272 | the previous read cycle. FLUSH IT! */ |
273 | i2c_smbus_read_byte(client); | 273 | i2c_smbus_read_byte(client); |
274 | } | 274 | } |
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index feae743ba991..e64b42058b21 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c | |||
@@ -36,6 +36,7 @@ | |||
36 | w83627ehf 10 5 4 3 0x8850 0x88 0x5ca3 | 36 | w83627ehf 10 5 4 3 0x8850 0x88 0x5ca3 |
37 | 0x8860 0xa1 | 37 | 0x8860 0xa1 |
38 | w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3 | 38 | w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3 |
39 | w83667hg 9 5 3 3 0xa510 0xc1 0x5ca3 | ||
39 | */ | 40 | */ |
40 | 41 | ||
41 | #include <linux/module.h> | 42 | #include <linux/module.h> |
@@ -52,12 +53,13 @@ | |||
52 | #include <asm/io.h> | 53 | #include <asm/io.h> |
53 | #include "lm75.h" | 54 | #include "lm75.h" |
54 | 55 | ||
55 | enum kinds { w83627ehf, w83627dhg }; | 56 | enum kinds { w83627ehf, w83627dhg, w83667hg }; |
56 | 57 | ||
57 | /* used to set data->name = w83627ehf_device_names[data->sio_kind] */ | 58 | /* used to set data->name = w83627ehf_device_names[data->sio_kind] */ |
58 | static const char * w83627ehf_device_names[] = { | 59 | static const char * w83627ehf_device_names[] = { |
59 | "w83627ehf", | 60 | "w83627ehf", |
60 | "w83627dhg", | 61 | "w83627dhg", |
62 | "w83667hg", | ||
61 | }; | 63 | }; |
62 | 64 | ||
63 | static unsigned short force_id; | 65 | static unsigned short force_id; |
@@ -71,6 +73,7 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID"); | |||
71 | */ | 73 | */ |
72 | 74 | ||
73 | #define W83627EHF_LD_HWM 0x0b | 75 | #define W83627EHF_LD_HWM 0x0b |
76 | #define W83667HG_LD_VID 0x0d | ||
74 | 77 | ||
75 | #define SIO_REG_LDSEL 0x07 /* Logical device select */ | 78 | #define SIO_REG_LDSEL 0x07 /* Logical device select */ |
76 | #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ | 79 | #define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ |
@@ -83,6 +86,7 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID"); | |||
83 | #define SIO_W83627EHF_ID 0x8850 | 86 | #define SIO_W83627EHF_ID 0x8850 |
84 | #define SIO_W83627EHG_ID 0x8860 | 87 | #define SIO_W83627EHG_ID 0x8860 |
85 | #define SIO_W83627DHG_ID 0xa020 | 88 | #define SIO_W83627DHG_ID 0xa020 |
89 | #define SIO_W83667HG_ID 0xa510 | ||
86 | #define SIO_ID_MASK 0xFFF0 | 90 | #define SIO_ID_MASK 0xFFF0 |
87 | 91 | ||
88 | static inline void | 92 | static inline void |
@@ -289,6 +293,7 @@ struct w83627ehf_data { | |||
289 | u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */ | 293 | u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */ |
290 | u8 pwm_enable[4]; /* 1->manual | 294 | u8 pwm_enable[4]; /* 1->manual |
291 | 2->thermal cruise (also called SmartFan I) */ | 295 | 2->thermal cruise (also called SmartFan I) */ |
296 | u8 pwm_num; /* number of pwm */ | ||
292 | u8 pwm[4]; | 297 | u8 pwm[4]; |
293 | u8 target_temp[4]; | 298 | u8 target_temp[4]; |
294 | u8 tolerance[4]; | 299 | u8 tolerance[4]; |
@@ -298,6 +303,9 @@ struct w83627ehf_data { | |||
298 | 303 | ||
299 | u8 vid; | 304 | u8 vid; |
300 | u8 vrm; | 305 | u8 vrm; |
306 | |||
307 | u8 temp3_disable; | ||
308 | u8 in6_skip; | ||
301 | }; | 309 | }; |
302 | 310 | ||
303 | struct w83627ehf_sio_data { | 311 | struct w83627ehf_sio_data { |
@@ -866,25 +874,37 @@ show_temp_type(struct device *dev, struct device_attribute *attr, char *buf) | |||
866 | return sprintf(buf, "%d\n", (int)data->temp_type[nr]); | 874 | return sprintf(buf, "%d\n", (int)data->temp_type[nr]); |
867 | } | 875 | } |
868 | 876 | ||
869 | static struct sensor_device_attribute sda_temp[] = { | 877 | static struct sensor_device_attribute sda_temp_input[] = { |
870 | SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0), | 878 | SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0), |
871 | SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0), | 879 | SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0), |
872 | SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 1), | 880 | SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 1), |
881 | }; | ||
882 | |||
883 | static struct sensor_device_attribute sda_temp_max[] = { | ||
873 | SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1_max, | 884 | SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1_max, |
874 | store_temp1_max, 0), | 885 | store_temp1_max, 0), |
875 | SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max, | 886 | SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max, |
876 | store_temp_max, 0), | 887 | store_temp_max, 0), |
877 | SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max, | 888 | SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max, |
878 | store_temp_max, 1), | 889 | store_temp_max, 1), |
890 | }; | ||
891 | |||
892 | static struct sensor_device_attribute sda_temp_max_hyst[] = { | ||
879 | SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1_max_hyst, | 893 | SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1_max_hyst, |
880 | store_temp1_max_hyst, 0), | 894 | store_temp1_max_hyst, 0), |
881 | SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, | 895 | SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, |
882 | store_temp_max_hyst, 0), | 896 | store_temp_max_hyst, 0), |
883 | SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, | 897 | SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, |
884 | store_temp_max_hyst, 1), | 898 | store_temp_max_hyst, 1), |
899 | }; | ||
900 | |||
901 | static struct sensor_device_attribute sda_temp_alarm[] = { | ||
885 | SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4), | 902 | SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4), |
886 | SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5), | 903 | SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5), |
887 | SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), | 904 | SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), |
905 | }; | ||
906 | |||
907 | static struct sensor_device_attribute sda_temp_type[] = { | ||
888 | SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0), | 908 | SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0), |
889 | SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1), | 909 | SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1), |
890 | SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2), | 910 | SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2), |
@@ -1181,6 +1201,8 @@ static void w83627ehf_device_remove_files(struct device *dev) | |||
1181 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) | 1201 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) |
1182 | device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr); | 1202 | device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr); |
1183 | for (i = 0; i < data->in_num; i++) { | 1203 | for (i = 0; i < data->in_num; i++) { |
1204 | if ((i == 6) && data->in6_skip) | ||
1205 | continue; | ||
1184 | device_remove_file(dev, &sda_in_input[i].dev_attr); | 1206 | device_remove_file(dev, &sda_in_input[i].dev_attr); |
1185 | device_remove_file(dev, &sda_in_alarm[i].dev_attr); | 1207 | device_remove_file(dev, &sda_in_alarm[i].dev_attr); |
1186 | device_remove_file(dev, &sda_in_min[i].dev_attr); | 1208 | device_remove_file(dev, &sda_in_min[i].dev_attr); |
@@ -1192,15 +1214,22 @@ static void w83627ehf_device_remove_files(struct device *dev) | |||
1192 | device_remove_file(dev, &sda_fan_div[i].dev_attr); | 1214 | device_remove_file(dev, &sda_fan_div[i].dev_attr); |
1193 | device_remove_file(dev, &sda_fan_min[i].dev_attr); | 1215 | device_remove_file(dev, &sda_fan_min[i].dev_attr); |
1194 | } | 1216 | } |
1195 | for (i = 0; i < 4; i++) { | 1217 | for (i = 0; i < data->pwm_num; i++) { |
1196 | device_remove_file(dev, &sda_pwm[i].dev_attr); | 1218 | device_remove_file(dev, &sda_pwm[i].dev_attr); |
1197 | device_remove_file(dev, &sda_pwm_mode[i].dev_attr); | 1219 | device_remove_file(dev, &sda_pwm_mode[i].dev_attr); |
1198 | device_remove_file(dev, &sda_pwm_enable[i].dev_attr); | 1220 | device_remove_file(dev, &sda_pwm_enable[i].dev_attr); |
1199 | device_remove_file(dev, &sda_target_temp[i].dev_attr); | 1221 | device_remove_file(dev, &sda_target_temp[i].dev_attr); |
1200 | device_remove_file(dev, &sda_tolerance[i].dev_attr); | 1222 | device_remove_file(dev, &sda_tolerance[i].dev_attr); |
1201 | } | 1223 | } |
1202 | for (i = 0; i < ARRAY_SIZE(sda_temp); i++) | 1224 | for (i = 0; i < 3; i++) { |
1203 | device_remove_file(dev, &sda_temp[i].dev_attr); | 1225 | if ((i == 2) && data->temp3_disable) |
1226 | continue; | ||
1227 | device_remove_file(dev, &sda_temp_input[i].dev_attr); | ||
1228 | device_remove_file(dev, &sda_temp_max[i].dev_attr); | ||
1229 | device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr); | ||
1230 | device_remove_file(dev, &sda_temp_alarm[i].dev_attr); | ||
1231 | device_remove_file(dev, &sda_temp_type[i].dev_attr); | ||
1232 | } | ||
1204 | 1233 | ||
1205 | device_remove_file(dev, &dev_attr_name); | 1234 | device_remove_file(dev, &dev_attr_name); |
1206 | device_remove_file(dev, &dev_attr_cpu0_vid); | 1235 | device_remove_file(dev, &dev_attr_cpu0_vid); |
@@ -1222,6 +1251,8 @@ static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data) | |||
1222 | for (i = 0; i < 2; i++) { | 1251 | for (i = 0; i < 2; i++) { |
1223 | tmp = w83627ehf_read_value(data, | 1252 | tmp = w83627ehf_read_value(data, |
1224 | W83627EHF_REG_TEMP_CONFIG[i]); | 1253 | W83627EHF_REG_TEMP_CONFIG[i]); |
1254 | if ((i == 1) && data->temp3_disable) | ||
1255 | continue; | ||
1225 | if (tmp & 0x01) | 1256 | if (tmp & 0x01) |
1226 | w83627ehf_write_value(data, | 1257 | w83627ehf_write_value(data, |
1227 | W83627EHF_REG_TEMP_CONFIG[i], | 1258 | W83627EHF_REG_TEMP_CONFIG[i], |
@@ -1272,8 +1303,17 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) | |||
1272 | data->name = w83627ehf_device_names[sio_data->kind]; | 1303 | data->name = w83627ehf_device_names[sio_data->kind]; |
1273 | platform_set_drvdata(pdev, data); | 1304 | platform_set_drvdata(pdev, data); |
1274 | 1305 | ||
1275 | /* 627EHG and 627EHF have 10 voltage inputs; DHG has 9 */ | 1306 | /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ |
1276 | data->in_num = (sio_data->kind == w83627dhg) ? 9 : 10; | 1307 | data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9; |
1308 | /* 667HG has 3 pwms */ | ||
1309 | data->pwm_num = (sio_data->kind == w83667hg) ? 3 : 4; | ||
1310 | |||
1311 | /* Check temp3 configuration bit for 667HG */ | ||
1312 | if (sio_data->kind == w83667hg) { | ||
1313 | data->temp3_disable = w83627ehf_read_value(data, | ||
1314 | W83627EHF_REG_TEMP_CONFIG[1]) & 0x01; | ||
1315 | data->in6_skip = !data->temp3_disable; | ||
1316 | } | ||
1277 | 1317 | ||
1278 | /* Initialize the chip */ | 1318 | /* Initialize the chip */ |
1279 | w83627ehf_init_device(data); | 1319 | w83627ehf_init_device(data); |
@@ -1281,44 +1321,64 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) | |||
1281 | data->vrm = vid_which_vrm(); | 1321 | data->vrm = vid_which_vrm(); |
1282 | superio_enter(sio_data->sioreg); | 1322 | superio_enter(sio_data->sioreg); |
1283 | /* Read VID value */ | 1323 | /* Read VID value */ |
1284 | superio_select(sio_data->sioreg, W83627EHF_LD_HWM); | 1324 | if (sio_data->kind == w83667hg) { |
1285 | if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) { | 1325 | /* W83667HG has different pins for VID input and output, so |
1286 | /* Set VID input sensibility if needed. In theory the BIOS | 1326 | we can get the VID input values directly at logical device D |
1287 | should have set it, but in practice it's not always the | 1327 | 0xe3. */ |
1288 | case. We only do it for the W83627EHF/EHG because the | 1328 | superio_select(sio_data->sioreg, W83667HG_LD_VID); |
1289 | W83627DHG is more complex in this respect. */ | 1329 | data->vid = superio_inb(sio_data->sioreg, 0xe3); |
1290 | if (sio_data->kind == w83627ehf) { | ||
1291 | en_vrm10 = superio_inb(sio_data->sioreg, | ||
1292 | SIO_REG_EN_VRM10); | ||
1293 | if ((en_vrm10 & 0x08) && data->vrm == 90) { | ||
1294 | dev_warn(dev, "Setting VID input voltage to " | ||
1295 | "TTL\n"); | ||
1296 | superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10, | ||
1297 | en_vrm10 & ~0x08); | ||
1298 | } else if (!(en_vrm10 & 0x08) && data->vrm == 100) { | ||
1299 | dev_warn(dev, "Setting VID input voltage to " | ||
1300 | "VRM10\n"); | ||
1301 | superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10, | ||
1302 | en_vrm10 | 0x08); | ||
1303 | } | ||
1304 | } | ||
1305 | |||
1306 | data->vid = superio_inb(sio_data->sioreg, SIO_REG_VID_DATA); | ||
1307 | if (sio_data->kind == w83627ehf) /* 6 VID pins only */ | ||
1308 | data->vid &= 0x3f; | ||
1309 | |||
1310 | err = device_create_file(dev, &dev_attr_cpu0_vid); | 1330 | err = device_create_file(dev, &dev_attr_cpu0_vid); |
1311 | if (err) | 1331 | if (err) |
1312 | goto exit_release; | 1332 | goto exit_release; |
1313 | } else { | 1333 | } else { |
1314 | dev_info(dev, "VID pins in output mode, CPU VID not " | 1334 | superio_select(sio_data->sioreg, W83627EHF_LD_HWM); |
1315 | "available\n"); | 1335 | if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) { |
1336 | /* Set VID input sensibility if needed. In theory the | ||
1337 | BIOS should have set it, but in practice it's not | ||
1338 | always the case. We only do it for the W83627EHF/EHG | ||
1339 | because the W83627DHG is more complex in this | ||
1340 | respect. */ | ||
1341 | if (sio_data->kind == w83627ehf) { | ||
1342 | en_vrm10 = superio_inb(sio_data->sioreg, | ||
1343 | SIO_REG_EN_VRM10); | ||
1344 | if ((en_vrm10 & 0x08) && data->vrm == 90) { | ||
1345 | dev_warn(dev, "Setting VID input " | ||
1346 | "voltage to TTL\n"); | ||
1347 | superio_outb(sio_data->sioreg, | ||
1348 | SIO_REG_EN_VRM10, | ||
1349 | en_vrm10 & ~0x08); | ||
1350 | } else if (!(en_vrm10 & 0x08) | ||
1351 | && data->vrm == 100) { | ||
1352 | dev_warn(dev, "Setting VID input " | ||
1353 | "voltage to VRM10\n"); | ||
1354 | superio_outb(sio_data->sioreg, | ||
1355 | SIO_REG_EN_VRM10, | ||
1356 | en_vrm10 | 0x08); | ||
1357 | } | ||
1358 | } | ||
1359 | |||
1360 | data->vid = superio_inb(sio_data->sioreg, | ||
1361 | SIO_REG_VID_DATA); | ||
1362 | if (sio_data->kind == w83627ehf) /* 6 VID pins only */ | ||
1363 | data->vid &= 0x3f; | ||
1364 | |||
1365 | err = device_create_file(dev, &dev_attr_cpu0_vid); | ||
1366 | if (err) | ||
1367 | goto exit_release; | ||
1368 | } else { | ||
1369 | dev_info(dev, "VID pins in output mode, CPU VID not " | ||
1370 | "available\n"); | ||
1371 | } | ||
1316 | } | 1372 | } |
1317 | 1373 | ||
1318 | /* fan4 and fan5 share some pins with the GPIO and serial flash */ | 1374 | /* fan4 and fan5 share some pins with the GPIO and serial flash */ |
1319 | 1375 | if (sio_data->kind == w83667hg) { | |
1320 | fan5pin = superio_inb(sio_data->sioreg, 0x24) & 0x2; | 1376 | fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20; |
1321 | fan4pin = superio_inb(sio_data->sioreg, 0x29) & 0x6; | 1377 | fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40; |
1378 | } else { | ||
1379 | fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x02); | ||
1380 | fan4pin = !(superio_inb(sio_data->sioreg, 0x29) & 0x06); | ||
1381 | } | ||
1322 | superio_exit(sio_data->sioreg); | 1382 | superio_exit(sio_data->sioreg); |
1323 | 1383 | ||
1324 | /* It looks like fan4 and fan5 pins can be alternatively used | 1384 | /* It looks like fan4 and fan5 pins can be alternatively used |
@@ -1329,9 +1389,9 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) | |||
1329 | 1389 | ||
1330 | data->has_fan = 0x07; /* fan1, fan2 and fan3 */ | 1390 | data->has_fan = 0x07; /* fan1, fan2 and fan3 */ |
1331 | i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1); | 1391 | i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1); |
1332 | if ((i & (1 << 2)) && (!fan4pin)) | 1392 | if ((i & (1 << 2)) && fan4pin) |
1333 | data->has_fan |= (1 << 3); | 1393 | data->has_fan |= (1 << 3); |
1334 | if (!(i & (1 << 1)) && (!fan5pin)) | 1394 | if (!(i & (1 << 1)) && fan5pin) |
1335 | data->has_fan |= (1 << 4); | 1395 | data->has_fan |= (1 << 4); |
1336 | 1396 | ||
1337 | /* Read fan clock dividers immediately */ | 1397 | /* Read fan clock dividers immediately */ |
@@ -1344,14 +1404,16 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) | |||
1344 | goto exit_remove; | 1404 | goto exit_remove; |
1345 | 1405 | ||
1346 | /* if fan4 is enabled create the sf3 files for it */ | 1406 | /* if fan4 is enabled create the sf3 files for it */ |
1347 | if (data->has_fan & (1 << 3)) | 1407 | if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4) |
1348 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) { | 1408 | for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) { |
1349 | if ((err = device_create_file(dev, | 1409 | if ((err = device_create_file(dev, |
1350 | &sda_sf3_arrays_fan4[i].dev_attr))) | 1410 | &sda_sf3_arrays_fan4[i].dev_attr))) |
1351 | goto exit_remove; | 1411 | goto exit_remove; |
1352 | } | 1412 | } |
1353 | 1413 | ||
1354 | for (i = 0; i < data->in_num; i++) | 1414 | for (i = 0; i < data->in_num; i++) { |
1415 | if ((i == 6) && data->in6_skip) | ||
1416 | continue; | ||
1355 | if ((err = device_create_file(dev, &sda_in_input[i].dev_attr)) | 1417 | if ((err = device_create_file(dev, &sda_in_input[i].dev_attr)) |
1356 | || (err = device_create_file(dev, | 1418 | || (err = device_create_file(dev, |
1357 | &sda_in_alarm[i].dev_attr)) | 1419 | &sda_in_alarm[i].dev_attr)) |
@@ -1360,6 +1422,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) | |||
1360 | || (err = device_create_file(dev, | 1422 | || (err = device_create_file(dev, |
1361 | &sda_in_max[i].dev_attr))) | 1423 | &sda_in_max[i].dev_attr))) |
1362 | goto exit_remove; | 1424 | goto exit_remove; |
1425 | } | ||
1363 | 1426 | ||
1364 | for (i = 0; i < 5; i++) { | 1427 | for (i = 0; i < 5; i++) { |
1365 | if (data->has_fan & (1 << i)) { | 1428 | if (data->has_fan & (1 << i)) { |
@@ -1372,7 +1435,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) | |||
1372 | || (err = device_create_file(dev, | 1435 | || (err = device_create_file(dev, |
1373 | &sda_fan_min[i].dev_attr))) | 1436 | &sda_fan_min[i].dev_attr))) |
1374 | goto exit_remove; | 1437 | goto exit_remove; |
1375 | if (i < 4 && /* w83627ehf only has 4 pwm */ | 1438 | if (i < data->pwm_num && |
1376 | ((err = device_create_file(dev, | 1439 | ((err = device_create_file(dev, |
1377 | &sda_pwm[i].dev_attr)) | 1440 | &sda_pwm[i].dev_attr)) |
1378 | || (err = device_create_file(dev, | 1441 | || (err = device_create_file(dev, |
@@ -1387,9 +1450,21 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) | |||
1387 | } | 1450 | } |
1388 | } | 1451 | } |
1389 | 1452 | ||
1390 | for (i = 0; i < ARRAY_SIZE(sda_temp); i++) | 1453 | for (i = 0; i < 3; i++) { |
1391 | if ((err = device_create_file(dev, &sda_temp[i].dev_attr))) | 1454 | if ((i == 2) && data->temp3_disable) |
1455 | continue; | ||
1456 | if ((err = device_create_file(dev, | ||
1457 | &sda_temp_input[i].dev_attr)) | ||
1458 | || (err = device_create_file(dev, | ||
1459 | &sda_temp_max[i].dev_attr)) | ||
1460 | || (err = device_create_file(dev, | ||
1461 | &sda_temp_max_hyst[i].dev_attr)) | ||
1462 | || (err = device_create_file(dev, | ||
1463 | &sda_temp_alarm[i].dev_attr)) | ||
1464 | || (err = device_create_file(dev, | ||
1465 | &sda_temp_type[i].dev_attr))) | ||
1392 | goto exit_remove; | 1466 | goto exit_remove; |
1467 | } | ||
1393 | 1468 | ||
1394 | err = device_create_file(dev, &dev_attr_name); | 1469 | err = device_create_file(dev, &dev_attr_name); |
1395 | if (err) | 1470 | if (err) |
@@ -1442,6 +1517,7 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr, | |||
1442 | static const char __initdata sio_name_W83627EHF[] = "W83627EHF"; | 1517 | static const char __initdata sio_name_W83627EHF[] = "W83627EHF"; |
1443 | static const char __initdata sio_name_W83627EHG[] = "W83627EHG"; | 1518 | static const char __initdata sio_name_W83627EHG[] = "W83627EHG"; |
1444 | static const char __initdata sio_name_W83627DHG[] = "W83627DHG"; | 1519 | static const char __initdata sio_name_W83627DHG[] = "W83627DHG"; |
1520 | static const char __initdata sio_name_W83667HG[] = "W83667HG"; | ||
1445 | 1521 | ||
1446 | u16 val; | 1522 | u16 val; |
1447 | const char *sio_name; | 1523 | const char *sio_name; |
@@ -1466,6 +1542,10 @@ static int __init w83627ehf_find(int sioaddr, unsigned short *addr, | |||
1466 | sio_data->kind = w83627dhg; | 1542 | sio_data->kind = w83627dhg; |
1467 | sio_name = sio_name_W83627DHG; | 1543 | sio_name = sio_name_W83627DHG; |
1468 | break; | 1544 | break; |
1545 | case SIO_W83667HG_ID: | ||
1546 | sio_data->kind = w83667hg; | ||
1547 | sio_name = sio_name_W83667HG; | ||
1548 | break; | ||
1469 | default: | 1549 | default: |
1470 | if (val != 0xffff) | 1550 | if (val != 0xffff) |
1471 | pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n", | 1551 | pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n", |
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 230238df56c4..10411848fd70 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
@@ -65,6 +65,7 @@ | |||
65 | #include <linux/i2c.h> | 65 | #include <linux/i2c.h> |
66 | #include <linux/acpi.h> | 66 | #include <linux/acpi.h> |
67 | #include <linux/io.h> | 67 | #include <linux/io.h> |
68 | #include <linux/dmi.h> | ||
68 | 69 | ||
69 | /* I801 SMBus address offsets */ | 70 | /* I801 SMBus address offsets */ |
70 | #define SMBHSTSTS (0 + i801_smba) | 71 | #define SMBHSTSTS (0 + i801_smba) |
@@ -616,10 +617,81 @@ static void __init input_apanel_init(void) | |||
616 | static void __init input_apanel_init(void) {} | 617 | static void __init input_apanel_init(void) {} |
617 | #endif | 618 | #endif |
618 | 619 | ||
620 | #if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE | ||
621 | struct dmi_onboard_device_info { | ||
622 | const char *name; | ||
623 | u8 type; | ||
624 | unsigned short i2c_addr; | ||
625 | const char *i2c_type; | ||
626 | }; | ||
627 | |||
628 | static struct dmi_onboard_device_info __devinitdata dmi_devices[] = { | ||
629 | { "Syleus", DMI_DEV_TYPE_OTHER, 0x73, "fscsyl" }, | ||
630 | { "Hermes", DMI_DEV_TYPE_OTHER, 0x73, "fscher" }, | ||
631 | { "Hades", DMI_DEV_TYPE_OTHER, 0x73, "fschds" }, | ||
632 | }; | ||
633 | |||
634 | static void __devinit dmi_check_onboard_device(u8 type, const char *name, | ||
635 | struct i2c_adapter *adap) | ||
636 | { | ||
637 | int i; | ||
638 | struct i2c_board_info info; | ||
639 | |||
640 | for (i = 0; i < ARRAY_SIZE(dmi_devices); i++) { | ||
641 | /* & ~0x80, ignore enabled/disabled bit */ | ||
642 | if ((type & ~0x80) != dmi_devices[i].type) | ||
643 | continue; | ||
644 | if (strcmp(name, dmi_devices[i].name)) | ||
645 | continue; | ||
646 | |||
647 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
648 | info.addr = dmi_devices[i].i2c_addr; | ||
649 | strlcpy(info.type, dmi_devices[i].i2c_type, I2C_NAME_SIZE); | ||
650 | i2c_new_device(adap, &info); | ||
651 | break; | ||
652 | } | ||
653 | } | ||
654 | |||
655 | /* We use our own function to check for onboard devices instead of | ||
656 | dmi_find_device() as some buggy BIOS's have the devices we are interested | ||
657 | in marked as disabled */ | ||
658 | static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm, | ||
659 | void *adap) | ||
660 | { | ||
661 | int i, count; | ||
662 | |||
663 | if (dm->type != 10) | ||
664 | return; | ||
665 | |||
666 | count = (dm->length - sizeof(struct dmi_header)) / 2; | ||
667 | for (i = 0; i < count; i++) { | ||
668 | const u8 *d = (char *)(dm + 1) + (i * 2); | ||
669 | const char *name = ((char *) dm) + dm->length; | ||
670 | u8 type = d[0]; | ||
671 | u8 s = d[1]; | ||
672 | |||
673 | if (!s) | ||
674 | continue; | ||
675 | s--; | ||
676 | while (s > 0 && name[0]) { | ||
677 | name += strlen(name) + 1; | ||
678 | s--; | ||
679 | } | ||
680 | if (name[0] == 0) /* Bogus string reference */ | ||
681 | continue; | ||
682 | |||
683 | dmi_check_onboard_device(type, name, adap); | ||
684 | } | ||
685 | } | ||
686 | #endif | ||
687 | |||
619 | static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) | 688 | static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) |
620 | { | 689 | { |
621 | unsigned char temp; | 690 | unsigned char temp; |
622 | int err; | 691 | int err; |
692 | #if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE | ||
693 | const char *vendor; | ||
694 | #endif | ||
623 | 695 | ||
624 | I801_dev = dev; | 696 | I801_dev = dev; |
625 | i801_features = 0; | 697 | i801_features = 0; |
@@ -712,6 +784,11 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id | |||
712 | i2c_new_device(&i801_adapter, &info); | 784 | i2c_new_device(&i801_adapter, &info); |
713 | } | 785 | } |
714 | #endif | 786 | #endif |
787 | #if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE | ||
788 | vendor = dmi_get_system_info(DMI_BOARD_VENDOR); | ||
789 | if (vendor && !strcmp(vendor, "FUJITSU SIEMENS")) | ||
790 | dmi_walk(dmi_check_onboard_devices, &i801_adapter); | ||
791 | #endif | ||
715 | 792 | ||
716 | return 0; | 793 | return 0; |
717 | 794 | ||
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig index c80312c1f382..8f8c81eb0aee 100644 --- a/drivers/i2c/chips/Kconfig +++ b/drivers/i2c/chips/Kconfig | |||
@@ -64,19 +64,6 @@ config SENSORS_PCA9539 | |||
64 | This driver is deprecated and will be dropped soon. Use | 64 | This driver is deprecated and will be dropped soon. Use |
65 | drivers/gpio/pca953x.c instead. | 65 | drivers/gpio/pca953x.c instead. |
66 | 66 | ||
67 | config SENSORS_PCF8591 | ||
68 | tristate "Philips PCF8591" | ||
69 | depends on EXPERIMENTAL | ||
70 | default n | ||
71 | help | ||
72 | If you say yes here you get support for Philips PCF8591 chips. | ||
73 | |||
74 | This driver can also be built as a module. If so, the module | ||
75 | will be called pcf8591. | ||
76 | |||
77 | These devices are hard to detect and rarely found on mainstream | ||
78 | hardware. If unsure, say N. | ||
79 | |||
80 | config SENSORS_MAX6875 | 67 | config SENSORS_MAX6875 |
81 | tristate "Maxim MAX6875 Power supply supervisor" | 68 | tristate "Maxim MAX6875 Power supply supervisor" |
82 | depends on EXPERIMENTAL | 69 | depends on EXPERIMENTAL |
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile index d142f238a2de..55a376037183 100644 --- a/drivers/i2c/chips/Makefile +++ b/drivers/i2c/chips/Makefile | |||
@@ -15,7 +15,6 @@ obj-$(CONFIG_SENSORS_MAX6875) += max6875.o | |||
15 | obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o | 15 | obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o |
16 | obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o | 16 | obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o |
17 | obj-$(CONFIG_PCF8575) += pcf8575.o | 17 | obj-$(CONFIG_PCF8575) += pcf8575.o |
18 | obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o | ||
19 | obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o | 18 | obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o |
20 | 19 | ||
21 | ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) | 20 | ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) |
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 640c99207242..cf06494bb744 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig | |||
@@ -222,7 +222,8 @@ comment "IDE chipset support/bugfixes" | |||
222 | 222 | ||
223 | config IDE_GENERIC | 223 | config IDE_GENERIC |
224 | tristate "generic/default IDE chipset support" | 224 | tristate "generic/default IDE chipset support" |
225 | depends on ALPHA || X86 || IA64 || M32R || MIPS | 225 | depends on ALPHA || X86 || IA64 || M32R || MIPS || ARCH_RPC || ARCH_SHARK |
226 | default ARM && (ARCH_RPC || ARCH_SHARK) | ||
226 | help | 227 | help |
227 | This is the generic IDE driver. This driver attaches to the | 228 | This is the generic IDE driver. This driver attaches to the |
228 | fixed legacy ports (e.g. on PCs 0x1f0/0x170, 0x1e8/0x168 and | 229 | fixed legacy ports (e.g. on PCs 0x1f0/0x170, 0x1e8/0x168 and |
@@ -680,7 +681,7 @@ endif | |||
680 | # TODO: BLK_DEV_IDEDMA_PCI -> BLK_DEV_IDEDMA_SFF | 681 | # TODO: BLK_DEV_IDEDMA_PCI -> BLK_DEV_IDEDMA_SFF |
681 | config BLK_DEV_IDE_PMAC | 682 | config BLK_DEV_IDE_PMAC |
682 | tristate "PowerMac on-board IDE support" | 683 | tristate "PowerMac on-board IDE support" |
683 | depends on PPC_PMAC && IDE=y | 684 | depends on PPC_PMAC |
684 | select IDE_TIMINGS | 685 | select IDE_TIMINGS |
685 | select BLK_DEV_IDEDMA_PCI | 686 | select BLK_DEV_IDEDMA_PCI |
686 | help | 687 | help |
@@ -731,11 +732,6 @@ config BLK_DEV_IDE_AT91 | |||
731 | depends on ARM && ARCH_AT91 && !ARCH_AT91RM9200 && !ARCH_AT91X40 | 732 | depends on ARM && ARCH_AT91 && !ARCH_AT91RM9200 && !ARCH_AT91X40 |
732 | select IDE_TIMINGS | 733 | select IDE_TIMINGS |
733 | 734 | ||
734 | config IDE_ARM | ||
735 | tristate "ARM IDE support" | ||
736 | depends on ARM && (ARCH_RPC || ARCH_SHARK) | ||
737 | default y | ||
738 | |||
739 | config BLK_DEV_IDE_ICSIDE | 735 | config BLK_DEV_IDE_ICSIDE |
740 | tristate "ICS IDE interface support" | 736 | tristate "ICS IDE interface support" |
741 | depends on ARM && ARCH_ACORN | 737 | depends on ARM && ARCH_ACORN |
@@ -774,27 +770,20 @@ config BLK_DEV_GAYLE | |||
774 | This includes on-board IDE interfaces on some Amiga models (A600, | 770 | This includes on-board IDE interfaces on some Amiga models (A600, |
775 | A1200, A4000, and A4000T), and IDE interfaces on the Zorro expansion | 771 | A1200, A4000, and A4000T), and IDE interfaces on the Zorro expansion |
776 | bus (M-Tech E-Matrix 530 expansion card). | 772 | bus (M-Tech E-Matrix 530 expansion card). |
777 | Say Y if you have an Amiga with a Gayle IDE interface and want to use | ||
778 | IDE devices (hard disks, CD-ROM drives, etc.) that are connected to | ||
779 | it. | ||
780 | Note that you also have to enable Zorro bus support if you want to | ||
781 | use Gayle IDE interfaces on the Zorro expansion bus. | ||
782 | 773 | ||
783 | config BLK_DEV_IDEDOUBLER | 774 | It also provides support for the so-called `IDE doublers' (made |
784 | bool "Amiga IDE Doubler support (EXPERIMENTAL)" | ||
785 | depends on BLK_DEV_GAYLE && EXPERIMENTAL | ||
786 | ---help--- | ||
787 | This feature provides support for the so-called `IDE doublers' (made | ||
788 | by various manufacturers, e.g. Eyetech) that can be connected to | 775 | by various manufacturers, e.g. Eyetech) that can be connected to |
789 | the on-board IDE interface of some Amiga models. Using such an IDE | 776 | the on-board IDE interface of some Amiga models. Using such an IDE |
790 | doubler, you can connect up to four instead of two IDE devices to | 777 | doubler, you can connect up to four instead of two IDE devices to |
791 | the Amiga's on-board IDE interface. | 778 | the Amiga's on-board IDE interface. The feature is enabled at kernel |
779 | runtime using the "gayle.doubler" kernel boot parameter. | ||
792 | 780 | ||
793 | Note that the normal Amiga Gayle IDE driver may not work correctly | 781 | Say Y if you have an Amiga with a Gayle IDE interface and want to use |
794 | if you have an IDE doubler and don't enable this feature! | 782 | IDE devices (hard disks, CD-ROM drives, etc.) that are connected to |
783 | it. | ||
795 | 784 | ||
796 | Say Y if you have an IDE doubler. The feature is enabled at kernel | 785 | Note that you also have to enable Zorro bus support if you want to |
797 | runtime using the "gayle.doubler" kernel boot parameter. | 786 | use Gayle IDE interfaces on the Zorro expansion bus. |
798 | 787 | ||
799 | config BLK_DEV_BUDDHA | 788 | config BLK_DEV_BUDDHA |
800 | tristate "Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)" | 789 | tristate "Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)" |
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 9b4bbe1cdc1a..81df925f0e8b 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile | |||
@@ -21,8 +21,6 @@ ide-core-$(CONFIG_IDE_LEGACY) += ide-legacy.o | |||
21 | 21 | ||
22 | obj-$(CONFIG_IDE) += ide-core.o | 22 | obj-$(CONFIG_IDE) += ide-core.o |
23 | 23 | ||
24 | obj-$(CONFIG_IDE_ARM) += ide_arm.o | ||
25 | |||
26 | obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o | 24 | obj-$(CONFIG_BLK_DEV_ALI14XX) += ali14xx.o |
27 | obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o | 25 | obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o |
28 | obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o | 26 | obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o |
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index d516168464fc..537da1cde16d 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c | |||
@@ -189,20 +189,20 @@ static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed) | |||
189 | } | 189 | } |
190 | 190 | ||
191 | /** | 191 | /** |
192 | * ali15x3_dma_setup - begin a DMA phase | 192 | * ali_dma_check - DMA check |
193 | * @drive: target device | 193 | * @drive: target device |
194 | * @cmd: command | 194 | * @cmd: command |
195 | * | 195 | * |
196 | * Returns 1 if the DMA cannot be performed, zero on success. | 196 | * Returns 1 if the DMA cannot be performed, zero on success. |
197 | */ | 197 | */ |
198 | 198 | ||
199 | static int ali15x3_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | 199 | static int ali_dma_check(ide_drive_t *drive, struct ide_cmd *cmd) |
200 | { | 200 | { |
201 | if (m5229_revision < 0xC2 && drive->media != ide_disk) { | 201 | if (m5229_revision < 0xC2 && drive->media != ide_disk) { |
202 | if (cmd->tf_flags & IDE_TFLAG_WRITE) | 202 | if (cmd->tf_flags & IDE_TFLAG_WRITE) |
203 | return 1; /* try PIO instead of DMA */ | 203 | return 1; /* try PIO instead of DMA */ |
204 | } | 204 | } |
205 | return ide_dma_setup(drive, cmd); | 205 | return 0; |
206 | } | 206 | } |
207 | 207 | ||
208 | /** | 208 | /** |
@@ -503,13 +503,13 @@ static const struct ide_port_ops ali_port_ops = { | |||
503 | 503 | ||
504 | static const struct ide_dma_ops ali_dma_ops = { | 504 | static const struct ide_dma_ops ali_dma_ops = { |
505 | .dma_host_set = ide_dma_host_set, | 505 | .dma_host_set = ide_dma_host_set, |
506 | .dma_setup = ali15x3_dma_setup, | 506 | .dma_setup = ide_dma_setup, |
507 | .dma_start = ide_dma_start, | 507 | .dma_start = ide_dma_start, |
508 | .dma_end = ide_dma_end, | 508 | .dma_end = ide_dma_end, |
509 | .dma_test_irq = ide_dma_test_irq, | 509 | .dma_test_irq = ide_dma_test_irq, |
510 | .dma_lost_irq = ide_dma_lost_irq, | 510 | .dma_lost_irq = ide_dma_lost_irq, |
511 | .dma_check = ali_dma_check, | ||
511 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 512 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
512 | .dma_timeout = ide_dma_timeout, | ||
513 | .dma_sff_read_status = ide_dma_sff_read_status, | 513 | .dma_sff_read_status = ide_dma_sff_read_status, |
514 | }; | 514 | }; |
515 | 515 | ||
diff --git a/drivers/ide/at91_ide.c b/drivers/ide/at91_ide.c index 27547121daff..8eda552326e9 100644 --- a/drivers/ide/at91_ide.c +++ b/drivers/ide/at91_ide.c | |||
@@ -192,15 +192,9 @@ static void at91_ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | |||
192 | struct ide_taskfile *tf = &cmd->tf; | 192 | struct ide_taskfile *tf = &cmd->tf; |
193 | u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; | 193 | u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; |
194 | 194 | ||
195 | if (cmd->tf_flags & IDE_FTFLAG_FLAGGED) | 195 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) |
196 | HIHI = 0xFF; | 196 | HIHI = 0xFF; |
197 | 197 | ||
198 | if (cmd->tf_flags & IDE_FTFLAG_OUT_DATA) { | ||
199 | u16 data = (tf->hob_data << 8) | tf->data; | ||
200 | |||
201 | at91_ide_output_data(drive, NULL, &data, 2); | ||
202 | } | ||
203 | |||
204 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | 198 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) |
205 | ide_mm_outb(tf->hob_feature, io_ports->feature_addr); | 199 | ide_mm_outb(tf->hob_feature, io_ports->feature_addr); |
206 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | 200 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) |
@@ -233,19 +227,11 @@ static void at91_ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
233 | struct ide_io_ports *io_ports = &hwif->io_ports; | 227 | struct ide_io_ports *io_ports = &hwif->io_ports; |
234 | struct ide_taskfile *tf = &cmd->tf; | 228 | struct ide_taskfile *tf = &cmd->tf; |
235 | 229 | ||
236 | if (cmd->tf_flags & IDE_FTFLAG_IN_DATA) { | ||
237 | u16 data; | ||
238 | |||
239 | at91_ide_input_data(drive, NULL, &data, 2); | ||
240 | tf->data = data & 0xff; | ||
241 | tf->hob_data = (data >> 8) & 0xff; | ||
242 | } | ||
243 | |||
244 | /* be sure we're looking at the low order bits */ | 230 | /* be sure we're looking at the low order bits */ |
245 | ide_mm_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); | 231 | ide_mm_outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); |
246 | 232 | ||
247 | if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE) | 233 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) |
248 | tf->feature = ide_mm_inb(io_ports->feature_addr); | 234 | tf->error = ide_mm_inb(io_ports->feature_addr); |
249 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | 235 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) |
250 | tf->nsect = ide_mm_inb(io_ports->nsect_addr); | 236 | tf->nsect = ide_mm_inb(io_ports->nsect_addr); |
251 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | 237 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) |
@@ -258,18 +244,18 @@ static void at91_ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
258 | tf->device = ide_mm_inb(io_ports->device_addr); | 244 | tf->device = ide_mm_inb(io_ports->device_addr); |
259 | 245 | ||
260 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | 246 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { |
261 | ide_mm_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); | 247 | ide_mm_outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); |
262 | 248 | ||
263 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | 249 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) |
264 | tf->hob_feature = ide_mm_inb(io_ports->feature_addr); | 250 | tf->hob_error = ide_mm_inb(io_ports->feature_addr); |
265 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | 251 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) |
266 | tf->hob_nsect = ide_mm_inb(io_ports->nsect_addr); | 252 | tf->hob_nsect = ide_mm_inb(io_ports->nsect_addr); |
267 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | 253 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) |
268 | tf->hob_lbal = ide_mm_inb(io_ports->lbal_addr); | 254 | tf->hob_lbal = ide_mm_inb(io_ports->lbal_addr); |
269 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | 255 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) |
270 | tf->hob_lbam = ide_mm_inb(io_ports->lbam_addr); | 256 | tf->hob_lbam = ide_mm_inb(io_ports->lbam_addr); |
271 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | 257 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) |
272 | tf->hob_lbah = ide_mm_inb(io_ports->lbah_addr); | 258 | tf->hob_lbah = ide_mm_inb(io_ports->lbah_addr); |
273 | } | 259 | } |
274 | } | 260 | } |
275 | 261 | ||
@@ -295,8 +281,9 @@ static const struct ide_tp_ops at91_ide_tp_ops = { | |||
295 | .exec_command = ide_exec_command, | 281 | .exec_command = ide_exec_command, |
296 | .read_status = ide_read_status, | 282 | .read_status = ide_read_status, |
297 | .read_altstatus = ide_read_altstatus, | 283 | .read_altstatus = ide_read_altstatus, |
298 | .set_irq = ide_set_irq, | 284 | .write_devctl = ide_write_devctl, |
299 | 285 | ||
286 | .dev_select = ide_dev_select, | ||
300 | .tf_load = at91_ide_tf_load, | 287 | .tf_load = at91_ide_tf_load, |
301 | .tf_read = at91_ide_tf_read, | 288 | .tf_read = at91_ide_tf_read, |
302 | 289 | ||
diff --git a/drivers/ide/au1xxx-ide.c b/drivers/ide/au1xxx-ide.c index d3a9d6c15328..46013644c965 100644 --- a/drivers/ide/au1xxx-ide.c +++ b/drivers/ide/au1xxx-ide.c | |||
@@ -50,7 +50,7 @@ static _auide_hwif auide_hwif; | |||
50 | 50 | ||
51 | #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) | 51 | #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) |
52 | 52 | ||
53 | void auide_insw(unsigned long port, void *addr, u32 count) | 53 | static inline void auide_insw(unsigned long port, void *addr, u32 count) |
54 | { | 54 | { |
55 | _auide_hwif *ahwif = &auide_hwif; | 55 | _auide_hwif *ahwif = &auide_hwif; |
56 | chan_tab_t *ctp; | 56 | chan_tab_t *ctp; |
@@ -68,7 +68,7 @@ void auide_insw(unsigned long port, void *addr, u32 count) | |||
68 | ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); | 68 | ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); |
69 | } | 69 | } |
70 | 70 | ||
71 | void auide_outsw(unsigned long port, void *addr, u32 count) | 71 | static inline void auide_outsw(unsigned long port, void *addr, u32 count) |
72 | { | 72 | { |
73 | _auide_hwif *ahwif = &auide_hwif; | 73 | _auide_hwif *ahwif = &auide_hwif; |
74 | chan_tab_t *ctp; | 74 | chan_tab_t *ctp; |
@@ -236,7 +236,7 @@ static int auide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd) | |||
236 | if (++count >= PRD_ENTRIES) { | 236 | if (++count >= PRD_ENTRIES) { |
237 | printk(KERN_WARNING "%s: DMA table too small\n", | 237 | printk(KERN_WARNING "%s: DMA table too small\n", |
238 | drive->name); | 238 | drive->name); |
239 | goto use_pio_instead; | 239 | return 0; |
240 | } | 240 | } |
241 | 241 | ||
242 | /* Lets enable intr for the last descriptor only */ | 242 | /* Lets enable intr for the last descriptor only */ |
@@ -272,16 +272,11 @@ static int auide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd) | |||
272 | if (count) | 272 | if (count) |
273 | return 1; | 273 | return 1; |
274 | 274 | ||
275 | use_pio_instead: | ||
276 | ide_destroy_dmatable(drive); | ||
277 | |||
278 | return 0; /* revert to PIO for this request */ | 275 | return 0; /* revert to PIO for this request */ |
279 | } | 276 | } |
280 | 277 | ||
281 | static int auide_dma_end(ide_drive_t *drive) | 278 | static int auide_dma_end(ide_drive_t *drive) |
282 | { | 279 | { |
283 | ide_destroy_dmatable(drive); | ||
284 | |||
285 | return 0; | 280 | return 0; |
286 | } | 281 | } |
287 | 282 | ||
@@ -292,12 +287,9 @@ static void auide_dma_start(ide_drive_t *drive ) | |||
292 | 287 | ||
293 | static int auide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | 288 | static int auide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) |
294 | { | 289 | { |
295 | if (auide_build_dmatable(drive, cmd) == 0) { | 290 | if (auide_build_dmatable(drive, cmd) == 0) |
296 | ide_map_sg(drive, cmd); | ||
297 | return 1; | 291 | return 1; |
298 | } | ||
299 | 292 | ||
300 | drive->waiting_for_dma = 1; | ||
301 | return 0; | 293 | return 0; |
302 | } | 294 | } |
303 | 295 | ||
@@ -322,16 +314,11 @@ static void auide_dma_host_set(ide_drive_t *drive, int on) | |||
322 | 314 | ||
323 | static void auide_ddma_tx_callback(int irq, void *param) | 315 | static void auide_ddma_tx_callback(int irq, void *param) |
324 | { | 316 | { |
325 | _auide_hwif *ahwif = (_auide_hwif*)param; | ||
326 | ahwif->drive->waiting_for_dma = 0; | ||
327 | } | 317 | } |
328 | 318 | ||
329 | static void auide_ddma_rx_callback(int irq, void *param) | 319 | static void auide_ddma_rx_callback(int irq, void *param) |
330 | { | 320 | { |
331 | _auide_hwif *ahwif = (_auide_hwif*)param; | ||
332 | ahwif->drive->waiting_for_dma = 0; | ||
333 | } | 321 | } |
334 | |||
335 | #endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */ | 322 | #endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */ |
336 | 323 | ||
337 | static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 devwidth, u32 flags) | 324 | static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 devwidth, u32 flags) |
@@ -353,7 +340,6 @@ static const struct ide_dma_ops au1xxx_dma_ops = { | |||
353 | .dma_end = auide_dma_end, | 340 | .dma_end = auide_dma_end, |
354 | .dma_test_irq = auide_dma_test_irq, | 341 | .dma_test_irq = auide_dma_test_irq, |
355 | .dma_lost_irq = ide_dma_lost_irq, | 342 | .dma_lost_irq = ide_dma_lost_irq, |
356 | .dma_timeout = ide_dma_timeout, | ||
357 | }; | 343 | }; |
358 | 344 | ||
359 | static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d) | 345 | static int auide_ddma_init(ide_hwif_t *hwif, const struct ide_port_info *d) |
@@ -481,9 +467,9 @@ static const struct ide_tp_ops au1xxx_tp_ops = { | |||
481 | .exec_command = ide_exec_command, | 467 | .exec_command = ide_exec_command, |
482 | .read_status = ide_read_status, | 468 | .read_status = ide_read_status, |
483 | .read_altstatus = ide_read_altstatus, | 469 | .read_altstatus = ide_read_altstatus, |
470 | .write_devctl = ide_write_devctl, | ||
484 | 471 | ||
485 | .set_irq = ide_set_irq, | 472 | .dev_select = ide_dev_select, |
486 | |||
487 | .tf_load = ide_tf_load, | 473 | .tf_load = ide_tf_load, |
488 | .tf_read = ide_tf_read, | 474 | .tf_read = ide_tf_read, |
489 | 475 | ||
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c index bf0e3f470824..80b777e4247b 100644 --- a/drivers/ide/cmd64x.c +++ b/drivers/ide/cmd64x.c | |||
@@ -318,7 +318,6 @@ static int cmd646_1_dma_end(ide_drive_t *drive) | |||
318 | ide_hwif_t *hwif = drive->hwif; | 318 | ide_hwif_t *hwif = drive->hwif; |
319 | u8 dma_stat = 0, dma_cmd = 0; | 319 | u8 dma_stat = 0, dma_cmd = 0; |
320 | 320 | ||
321 | drive->waiting_for_dma = 0; | ||
322 | /* get DMA status */ | 321 | /* get DMA status */ |
323 | dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); | 322 | dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS); |
324 | /* read DMA command state */ | 323 | /* read DMA command state */ |
@@ -327,8 +326,6 @@ static int cmd646_1_dma_end(ide_drive_t *drive) | |||
327 | outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD); | 326 | outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD); |
328 | /* clear the INTR & ERROR bits */ | 327 | /* clear the INTR & ERROR bits */ |
329 | outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS); | 328 | outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS); |
330 | /* and free any DMA resources */ | ||
331 | ide_destroy_dmatable(drive); | ||
332 | /* verify good DMA status */ | 329 | /* verify good DMA status */ |
333 | return (dma_stat & 7) != 4; | 330 | return (dma_stat & 7) != 4; |
334 | } | 331 | } |
@@ -384,7 +381,6 @@ static const struct ide_dma_ops cmd64x_dma_ops = { | |||
384 | .dma_test_irq = cmd64x_dma_test_irq, | 381 | .dma_test_irq = cmd64x_dma_test_irq, |
385 | .dma_lost_irq = ide_dma_lost_irq, | 382 | .dma_lost_irq = ide_dma_lost_irq, |
386 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 383 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
387 | .dma_timeout = ide_dma_timeout, | ||
388 | .dma_sff_read_status = ide_dma_sff_read_status, | 384 | .dma_sff_read_status = ide_dma_sff_read_status, |
389 | }; | 385 | }; |
390 | 386 | ||
@@ -396,7 +392,6 @@ static const struct ide_dma_ops cmd646_rev1_dma_ops = { | |||
396 | .dma_test_irq = ide_dma_test_irq, | 392 | .dma_test_irq = ide_dma_test_irq, |
397 | .dma_lost_irq = ide_dma_lost_irq, | 393 | .dma_lost_irq = ide_dma_lost_irq, |
398 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 394 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
399 | .dma_timeout = ide_dma_timeout, | ||
400 | .dma_sff_read_status = ide_dma_sff_read_status, | 395 | .dma_sff_read_status = ide_dma_sff_read_status, |
401 | }; | 396 | }; |
402 | 397 | ||
@@ -408,7 +403,6 @@ static const struct ide_dma_ops cmd648_dma_ops = { | |||
408 | .dma_test_irq = cmd648_dma_test_irq, | 403 | .dma_test_irq = cmd648_dma_test_irq, |
409 | .dma_lost_irq = ide_dma_lost_irq, | 404 | .dma_lost_irq = ide_dma_lost_irq, |
410 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 405 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
411 | .dma_timeout = ide_dma_timeout, | ||
412 | .dma_sff_read_status = ide_dma_sff_read_status, | 406 | .dma_sff_read_status = ide_dma_sff_read_status, |
413 | }; | 407 | }; |
414 | 408 | ||
diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c index 8e8b35a89901..40bf05eddf6e 100644 --- a/drivers/ide/cs5530.c +++ b/drivers/ide/cs5530.c | |||
@@ -92,8 +92,7 @@ static u8 cs5530_udma_filter(ide_drive_t *drive) | |||
92 | if ((mateid[ATA_ID_FIELD_VALID] & 4) && | 92 | if ((mateid[ATA_ID_FIELD_VALID] & 4) && |
93 | (mateid[ATA_ID_UDMA_MODES] & 7)) | 93 | (mateid[ATA_ID_UDMA_MODES] & 7)) |
94 | goto out; | 94 | goto out; |
95 | if ((mateid[ATA_ID_FIELD_VALID] & 2) && | 95 | if (mateid[ATA_ID_MWDMA_MODES] & 7) |
96 | (mateid[ATA_ID_MWDMA_MODES] & 7)) | ||
97 | mask = 0; | 96 | mask = 0; |
98 | } | 97 | } |
99 | out: | 98 | out: |
diff --git a/drivers/ide/cs5536.c b/drivers/ide/cs5536.c index d5dcf4899607..353a35bbba63 100644 --- a/drivers/ide/cs5536.c +++ b/drivers/ide/cs5536.c | |||
@@ -236,7 +236,6 @@ static const struct ide_dma_ops cs5536_dma_ops = { | |||
236 | .dma_test_irq = ide_dma_test_irq, | 236 | .dma_test_irq = ide_dma_test_irq, |
237 | .dma_lost_irq = ide_dma_lost_irq, | 237 | .dma_lost_irq = ide_dma_lost_irq, |
238 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 238 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
239 | .dma_timeout = ide_dma_timeout, | ||
240 | }; | 239 | }; |
241 | 240 | ||
242 | static const struct ide_port_info cs5536_info = { | 241 | static const struct ide_port_info cs5536_info = { |
diff --git a/drivers/ide/falconide.c b/drivers/ide/falconide.c index b368a5effc3a..afa2af9a362b 100644 --- a/drivers/ide/falconide.c +++ b/drivers/ide/falconide.c | |||
@@ -89,9 +89,9 @@ static const struct ide_tp_ops falconide_tp_ops = { | |||
89 | .exec_command = ide_exec_command, | 89 | .exec_command = ide_exec_command, |
90 | .read_status = ide_read_status, | 90 | .read_status = ide_read_status, |
91 | .read_altstatus = ide_read_altstatus, | 91 | .read_altstatus = ide_read_altstatus, |
92 | .write_devctl = ide_write_devctl, | ||
92 | 93 | ||
93 | .set_irq = ide_set_irq, | 94 | .dev_select = ide_dev_select, |
94 | |||
95 | .tf_load = ide_tf_load, | 95 | .tf_load = ide_tf_load, |
96 | .tf_read = ide_tf_read, | 96 | .tf_read = ide_tf_read, |
97 | 97 | ||
diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c index dc778251cb05..c7119516c5a7 100644 --- a/drivers/ide/gayle.c +++ b/drivers/ide/gayle.c | |||
@@ -53,11 +53,6 @@ | |||
53 | 53 | ||
54 | #define GAYLE_NEXT_PORT 0x1000 | 54 | #define GAYLE_NEXT_PORT 0x1000 |
55 | 55 | ||
56 | #ifndef CONFIG_BLK_DEV_IDEDOUBLER | ||
57 | #define GAYLE_NUM_HWIFS 1 | ||
58 | #define GAYLE_NUM_PROBE_HWIFS GAYLE_NUM_HWIFS | ||
59 | #define GAYLE_HAS_CONTROL_REG 1 | ||
60 | #else /* CONFIG_BLK_DEV_IDEDOUBLER */ | ||
61 | #define GAYLE_NUM_HWIFS 2 | 56 | #define GAYLE_NUM_HWIFS 2 |
62 | #define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : \ | 57 | #define GAYLE_NUM_PROBE_HWIFS (ide_doubler ? GAYLE_NUM_HWIFS : \ |
63 | GAYLE_NUM_HWIFS-1) | 58 | GAYLE_NUM_HWIFS-1) |
@@ -66,8 +61,6 @@ | |||
66 | static int ide_doubler; | 61 | static int ide_doubler; |
67 | module_param_named(doubler, ide_doubler, bool, 0); | 62 | module_param_named(doubler, ide_doubler, bool, 0); |
68 | MODULE_PARM_DESC(doubler, "enable support for IDE doublers"); | 63 | MODULE_PARM_DESC(doubler, "enable support for IDE doublers"); |
69 | #endif /* CONFIG_BLK_DEV_IDEDOUBLER */ | ||
70 | |||
71 | 64 | ||
72 | /* | 65 | /* |
73 | * Check and acknowledge the interrupt status | 66 | * Check and acknowledge the interrupt status |
@@ -151,10 +144,7 @@ static int __init gayle_init(void) | |||
151 | found: | 144 | found: |
152 | printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n", | 145 | printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n", |
153 | a4000 ? 4000 : 1200, | 146 | a4000 ? 4000 : 1200, |
154 | #ifdef CONFIG_BLK_DEV_IDEDOUBLER | 147 | ide_doubler ? ", IDE doubler" : ""); |
155 | ide_doubler ? ", IDE doubler" : | ||
156 | #endif | ||
157 | ""); | ||
158 | 148 | ||
159 | if (a4000) { | 149 | if (a4000) { |
160 | phys_base = GAYLE_BASE_4000; | 150 | phys_base = GAYLE_BASE_4000; |
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index dbaf184ed9c5..a0eb87f59134 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c | |||
@@ -835,12 +835,6 @@ static int hpt370_dma_end(ide_drive_t *drive) | |||
835 | return ide_dma_end(drive); | 835 | return ide_dma_end(drive); |
836 | } | 836 | } |
837 | 837 | ||
838 | static void hpt370_dma_timeout(ide_drive_t *drive) | ||
839 | { | ||
840 | hpt370_irq_timeout(drive); | ||
841 | ide_dma_timeout(drive); | ||
842 | } | ||
843 | |||
844 | /* returns 1 if DMA IRQ issued, 0 otherwise */ | 838 | /* returns 1 if DMA IRQ issued, 0 otherwise */ |
845 | static int hpt374_dma_test_irq(ide_drive_t *drive) | 839 | static int hpt374_dma_test_irq(ide_drive_t *drive) |
846 | { | 840 | { |
@@ -1423,7 +1417,6 @@ static const struct ide_dma_ops hpt37x_dma_ops = { | |||
1423 | .dma_test_irq = hpt374_dma_test_irq, | 1417 | .dma_test_irq = hpt374_dma_test_irq, |
1424 | .dma_lost_irq = ide_dma_lost_irq, | 1418 | .dma_lost_irq = ide_dma_lost_irq, |
1425 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 1419 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
1426 | .dma_timeout = ide_dma_timeout, | ||
1427 | .dma_sff_read_status = ide_dma_sff_read_status, | 1420 | .dma_sff_read_status = ide_dma_sff_read_status, |
1428 | }; | 1421 | }; |
1429 | 1422 | ||
@@ -1435,7 +1428,7 @@ static const struct ide_dma_ops hpt370_dma_ops = { | |||
1435 | .dma_test_irq = ide_dma_test_irq, | 1428 | .dma_test_irq = ide_dma_test_irq, |
1436 | .dma_lost_irq = ide_dma_lost_irq, | 1429 | .dma_lost_irq = ide_dma_lost_irq, |
1437 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 1430 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
1438 | .dma_timeout = hpt370_dma_timeout, | 1431 | .dma_clear = hpt370_irq_timeout, |
1439 | .dma_sff_read_status = ide_dma_sff_read_status, | 1432 | .dma_sff_read_status = ide_dma_sff_read_status, |
1440 | }; | 1433 | }; |
1441 | 1434 | ||
@@ -1447,7 +1440,6 @@ static const struct ide_dma_ops hpt36x_dma_ops = { | |||
1447 | .dma_test_irq = ide_dma_test_irq, | 1440 | .dma_test_irq = ide_dma_test_irq, |
1448 | .dma_lost_irq = hpt366_dma_lost_irq, | 1441 | .dma_lost_irq = hpt366_dma_lost_irq, |
1449 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 1442 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
1450 | .dma_timeout = ide_dma_timeout, | ||
1451 | .dma_sff_read_status = ide_dma_sff_read_status, | 1443 | .dma_sff_read_status = ide_dma_sff_read_status, |
1452 | }; | 1444 | }; |
1453 | 1445 | ||
diff --git a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c index c7e5c2246b79..2fb0f2965009 100644 --- a/drivers/ide/ht6560b.c +++ b/drivers/ide/ht6560b.c | |||
@@ -103,7 +103,7 @@ | |||
103 | /* | 103 | /* |
104 | * This routine is invoked from ide.c to prepare for access to a given drive. | 104 | * This routine is invoked from ide.c to prepare for access to a given drive. |
105 | */ | 105 | */ |
106 | static void ht6560b_selectproc (ide_drive_t *drive) | 106 | static void ht6560b_dev_select(ide_drive_t *drive) |
107 | { | 107 | { |
108 | ide_hwif_t *hwif = drive->hwif; | 108 | ide_hwif_t *hwif = drive->hwif; |
109 | unsigned long flags; | 109 | unsigned long flags; |
@@ -143,6 +143,8 @@ static void ht6560b_selectproc (ide_drive_t *drive) | |||
143 | #endif | 143 | #endif |
144 | } | 144 | } |
145 | local_irq_restore(flags); | 145 | local_irq_restore(flags); |
146 | |||
147 | outb(drive->select | ATA_DEVICE_OBS, hwif->io_ports.device_addr); | ||
146 | } | 148 | } |
147 | 149 | ||
148 | /* | 150 | /* |
@@ -305,15 +307,29 @@ static int probe_ht6560b; | |||
305 | module_param_named(probe, probe_ht6560b, bool, 0); | 307 | module_param_named(probe, probe_ht6560b, bool, 0); |
306 | MODULE_PARM_DESC(probe, "probe for HT6560B chipset"); | 308 | MODULE_PARM_DESC(probe, "probe for HT6560B chipset"); |
307 | 309 | ||
310 | static const struct ide_tp_ops ht6560b_tp_ops = { | ||
311 | .exec_command = ide_exec_command, | ||
312 | .read_status = ide_read_status, | ||
313 | .read_altstatus = ide_read_altstatus, | ||
314 | .write_devctl = ide_write_devctl, | ||
315 | |||
316 | .dev_select = ht6560b_dev_select, | ||
317 | .tf_load = ide_tf_load, | ||
318 | .tf_read = ide_tf_read, | ||
319 | |||
320 | .input_data = ide_input_data, | ||
321 | .output_data = ide_output_data, | ||
322 | }; | ||
323 | |||
308 | static const struct ide_port_ops ht6560b_port_ops = { | 324 | static const struct ide_port_ops ht6560b_port_ops = { |
309 | .init_dev = ht6560b_init_dev, | 325 | .init_dev = ht6560b_init_dev, |
310 | .set_pio_mode = ht6560b_set_pio_mode, | 326 | .set_pio_mode = ht6560b_set_pio_mode, |
311 | .selectproc = ht6560b_selectproc, | ||
312 | }; | 327 | }; |
313 | 328 | ||
314 | static const struct ide_port_info ht6560b_port_info __initdata = { | 329 | static const struct ide_port_info ht6560b_port_info __initdata = { |
315 | .name = DRV_NAME, | 330 | .name = DRV_NAME, |
316 | .chipset = ide_ht6560b, | 331 | .chipset = ide_ht6560b, |
332 | .tp_ops = &ht6560b_tp_ops, | ||
317 | .port_ops = &ht6560b_port_ops, | 333 | .port_ops = &ht6560b_port_ops, |
318 | .host_flags = IDE_HFLAG_SERIALIZE | /* is this needed? */ | 334 | .host_flags = IDE_HFLAG_SERIALIZE | /* is this needed? */ |
319 | IDE_HFLAG_NO_DMA | | 335 | IDE_HFLAG_NO_DMA | |
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index 51ce404fe532..4e16ce68b063 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c | |||
@@ -287,13 +287,8 @@ static int icside_dma_end(ide_drive_t *drive) | |||
287 | ide_hwif_t *hwif = drive->hwif; | 287 | ide_hwif_t *hwif = drive->hwif; |
288 | struct expansion_card *ec = ECARD_DEV(hwif->dev); | 288 | struct expansion_card *ec = ECARD_DEV(hwif->dev); |
289 | 289 | ||
290 | drive->waiting_for_dma = 0; | ||
291 | |||
292 | disable_dma(ec->dma); | 290 | disable_dma(ec->dma); |
293 | 291 | ||
294 | /* Teardown mappings after DMA has completed. */ | ||
295 | ide_destroy_dmatable(drive); | ||
296 | |||
297 | return get_dma_residue(ec->dma) != 0; | 292 | return get_dma_residue(ec->dma) != 0; |
298 | } | 293 | } |
299 | 294 | ||
@@ -346,8 +341,6 @@ static int icside_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | |||
346 | set_dma_sg(ec->dma, hwif->sg_table, cmd->sg_nents); | 341 | set_dma_sg(ec->dma, hwif->sg_table, cmd->sg_nents); |
347 | set_dma_mode(ec->dma, dma_mode); | 342 | set_dma_mode(ec->dma, dma_mode); |
348 | 343 | ||
349 | drive->waiting_for_dma = 1; | ||
350 | |||
351 | return 0; | 344 | return 0; |
352 | } | 345 | } |
353 | 346 | ||
@@ -377,7 +370,6 @@ static const struct ide_dma_ops icside_v6_dma_ops = { | |||
377 | .dma_start = icside_dma_start, | 370 | .dma_start = icside_dma_start, |
378 | .dma_end = icside_dma_end, | 371 | .dma_end = icside_dma_end, |
379 | .dma_test_irq = icside_dma_test_irq, | 372 | .dma_test_irq = icside_dma_test_irq, |
380 | .dma_timeout = ide_dma_timeout, | ||
381 | .dma_lost_irq = ide_dma_lost_irq, | 373 | .dma_lost_irq = ide_dma_lost_irq, |
382 | }; | 374 | }; |
383 | #else | 375 | #else |
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 2fb5d28a9be5..3e43b889dd64 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c | |||
@@ -6,6 +6,8 @@ | |||
6 | #include <linux/cdrom.h> | 6 | #include <linux/cdrom.h> |
7 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
8 | #include <linux/ide.h> | 8 | #include <linux/ide.h> |
9 | #include <linux/scatterlist.h> | ||
10 | |||
9 | #include <scsi/scsi.h> | 11 | #include <scsi/scsi.h> |
10 | 12 | ||
11 | #ifdef DEBUG | 13 | #ifdef DEBUG |
@@ -69,56 +71,6 @@ int ide_check_atapi_device(ide_drive_t *drive, const char *s) | |||
69 | } | 71 | } |
70 | EXPORT_SYMBOL_GPL(ide_check_atapi_device); | 72 | EXPORT_SYMBOL_GPL(ide_check_atapi_device); |
71 | 73 | ||
72 | /* PIO data transfer routine using the scatter gather table. */ | ||
73 | int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | ||
74 | unsigned int bcount, int write) | ||
75 | { | ||
76 | ide_hwif_t *hwif = drive->hwif; | ||
77 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | ||
78 | xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data; | ||
79 | struct scatterlist *sg = pc->sg; | ||
80 | char *buf; | ||
81 | int count, done = 0; | ||
82 | |||
83 | while (bcount) { | ||
84 | count = min(sg->length - pc->b_count, bcount); | ||
85 | |||
86 | if (PageHighMem(sg_page(sg))) { | ||
87 | unsigned long flags; | ||
88 | |||
89 | local_irq_save(flags); | ||
90 | buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; | ||
91 | xf(drive, NULL, buf + pc->b_count, count); | ||
92 | kunmap_atomic(buf - sg->offset, KM_IRQ0); | ||
93 | local_irq_restore(flags); | ||
94 | } else { | ||
95 | buf = sg_virt(sg); | ||
96 | xf(drive, NULL, buf + pc->b_count, count); | ||
97 | } | ||
98 | |||
99 | bcount -= count; | ||
100 | pc->b_count += count; | ||
101 | done += count; | ||
102 | |||
103 | if (pc->b_count == sg->length) { | ||
104 | if (!--pc->sg_cnt) | ||
105 | break; | ||
106 | pc->sg = sg = sg_next(sg); | ||
107 | pc->b_count = 0; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | if (bcount) { | ||
112 | printk(KERN_ERR "%s: %d leftover bytes, %s\n", drive->name, | ||
113 | bcount, write ? "padding with zeros" | ||
114 | : "discarding data"); | ||
115 | ide_pad_transfer(drive, write, bcount); | ||
116 | } | ||
117 | |||
118 | return done; | ||
119 | } | ||
120 | EXPORT_SYMBOL_GPL(ide_io_buffers); | ||
121 | |||
122 | void ide_init_pc(struct ide_atapi_pc *pc) | 74 | void ide_init_pc(struct ide_atapi_pc *pc) |
123 | { | 75 | { |
124 | memset(pc, 0, sizeof(*pc)); | 76 | memset(pc, 0, sizeof(*pc)); |
@@ -324,12 +276,14 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
324 | { | 276 | { |
325 | struct ide_atapi_pc *pc = drive->pc; | 277 | struct ide_atapi_pc *pc = drive->pc; |
326 | ide_hwif_t *hwif = drive->hwif; | 278 | ide_hwif_t *hwif = drive->hwif; |
279 | struct ide_cmd *cmd = &hwif->cmd; | ||
327 | struct request *rq = hwif->rq; | 280 | struct request *rq = hwif->rq; |
328 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | 281 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; |
329 | xfer_func_t *xferfunc; | 282 | xfer_func_t *xferfunc; |
330 | unsigned int timeout, temp; | 283 | unsigned int timeout, done; |
331 | u16 bcount; | 284 | u16 bcount; |
332 | u8 stat, ireason, dsc = 0; | 285 | u8 stat, ireason, dsc = 0; |
286 | u8 write = !!(pc->flags & PC_FLAG_WRITING); | ||
333 | 287 | ||
334 | debug_log("Enter %s - interrupt handler\n", __func__); | 288 | debug_log("Enter %s - interrupt handler\n", __func__); |
335 | 289 | ||
@@ -340,8 +294,13 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
340 | stat = tp_ops->read_status(hwif); | 294 | stat = tp_ops->read_status(hwif); |
341 | 295 | ||
342 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { | 296 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { |
343 | if (hwif->dma_ops->dma_end(drive) || | 297 | int rc; |
344 | (drive->media == ide_tape && (stat & ATA_ERR))) { | 298 | |
299 | drive->waiting_for_dma = 0; | ||
300 | rc = hwif->dma_ops->dma_end(drive); | ||
301 | ide_dma_unmap_sg(drive, cmd); | ||
302 | |||
303 | if (rc || (drive->media == ide_tape && (stat & ATA_ERR))) { | ||
345 | if (drive->media == ide_floppy) | 304 | if (drive->media == ide_floppy) |
346 | printk(KERN_ERR "%s: DMA %s error\n", | 305 | printk(KERN_ERR "%s: DMA %s error\n", |
347 | drive->name, rq_data_dir(pc->rq) | 306 | drive->name, rq_data_dir(pc->rq) |
@@ -357,7 +316,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
357 | 316 | ||
358 | /* No more interrupts */ | 317 | /* No more interrupts */ |
359 | if ((stat & ATA_DRQ) == 0) { | 318 | if ((stat & ATA_DRQ) == 0) { |
360 | int uptodate; | 319 | int uptodate, error; |
320 | unsigned int done; | ||
361 | 321 | ||
362 | debug_log("Packet command completed, %d bytes transferred\n", | 322 | debug_log("Packet command completed, %d bytes transferred\n", |
363 | pc->xferred); | 323 | pc->xferred); |
@@ -404,16 +364,24 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
404 | 364 | ||
405 | if (blk_special_request(rq)) { | 365 | if (blk_special_request(rq)) { |
406 | rq->errors = 0; | 366 | rq->errors = 0; |
407 | ide_complete_rq(drive, 0, blk_rq_bytes(rq)); | 367 | done = blk_rq_bytes(rq); |
368 | error = 0; | ||
408 | } else { | 369 | } else { |
370 | |||
409 | if (blk_fs_request(rq) == 0 && uptodate <= 0) { | 371 | if (blk_fs_request(rq) == 0 && uptodate <= 0) { |
410 | if (rq->errors == 0) | 372 | if (rq->errors == 0) |
411 | rq->errors = -EIO; | 373 | rq->errors = -EIO; |
412 | } | 374 | } |
413 | ide_complete_rq(drive, uptodate ? 0 : -EIO, | 375 | |
414 | ide_rq_bytes(rq)); | 376 | if (drive->media == ide_tape) |
377 | done = ide_rq_bytes(rq); /* FIXME */ | ||
378 | else | ||
379 | done = blk_rq_bytes(rq); | ||
380 | |||
381 | error = uptodate ? 0 : -EIO; | ||
415 | } | 382 | } |
416 | 383 | ||
384 | ide_complete_rq(drive, error, done); | ||
417 | return ide_stopped; | 385 | return ide_stopped; |
418 | } | 386 | } |
419 | 387 | ||
@@ -433,8 +401,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
433 | return ide_do_reset(drive); | 401 | return ide_do_reset(drive); |
434 | } | 402 | } |
435 | 403 | ||
436 | if (((ireason & ATAPI_IO) == ATAPI_IO) == | 404 | if (((ireason & ATAPI_IO) == ATAPI_IO) == write) { |
437 | !!(pc->flags & PC_FLAG_WRITING)) { | ||
438 | /* Hopefully, we will never get here */ | 405 | /* Hopefully, we will never get here */ |
439 | printk(KERN_ERR "%s: We wanted to %s, but the device wants us " | 406 | printk(KERN_ERR "%s: We wanted to %s, but the device wants us " |
440 | "to %s!\n", drive->name, | 407 | "to %s!\n", drive->name, |
@@ -443,45 +410,30 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
443 | return ide_do_reset(drive); | 410 | return ide_do_reset(drive); |
444 | } | 411 | } |
445 | 412 | ||
446 | if (!(pc->flags & PC_FLAG_WRITING)) { | 413 | xferfunc = write ? tp_ops->output_data : tp_ops->input_data; |
447 | /* Reading - Check that we have enough space */ | 414 | |
448 | temp = pc->xferred + bcount; | 415 | if (drive->media == ide_floppy && pc->buf == NULL) { |
449 | if (temp > pc->req_xfer) { | 416 | done = min_t(unsigned int, bcount, cmd->nleft); |
450 | if (temp > pc->buf_size) { | 417 | ide_pio_bytes(drive, cmd, write, done); |
451 | printk(KERN_ERR "%s: The device wants to send " | 418 | } else if (drive->media == ide_tape && pc->bh) { |
452 | "us more data than expected - " | 419 | done = drive->pc_io_buffers(drive, pc, bcount, write); |
453 | "discarding data\n", | 420 | } else { |
454 | drive->name); | 421 | done = min_t(unsigned int, bcount, pc->req_xfer - pc->xferred); |
455 | 422 | xferfunc(drive, NULL, pc->cur_pos, done); | |
456 | ide_pad_transfer(drive, 0, bcount); | 423 | } |
457 | goto next_irq; | ||
458 | } | ||
459 | debug_log("The device wants to send us more data than " | ||
460 | "expected - allowing transfer\n"); | ||
461 | } | ||
462 | xferfunc = tp_ops->input_data; | ||
463 | } else | ||
464 | xferfunc = tp_ops->output_data; | ||
465 | |||
466 | if ((drive->media == ide_floppy && !pc->buf) || | ||
467 | (drive->media == ide_tape && pc->bh)) { | ||
468 | int done = drive->pc_io_buffers(drive, pc, bcount, | ||
469 | !!(pc->flags & PC_FLAG_WRITING)); | ||
470 | |||
471 | /* FIXME: don't do partial completions */ | ||
472 | if (drive->media == ide_floppy) | ||
473 | ide_complete_rq(drive, 0, | ||
474 | done ? done : ide_rq_bytes(rq)); | ||
475 | } else | ||
476 | xferfunc(drive, NULL, pc->cur_pos, bcount); | ||
477 | 424 | ||
478 | /* Update the current position */ | 425 | /* Update the current position */ |
479 | pc->xferred += bcount; | 426 | pc->xferred += done; |
480 | pc->cur_pos += bcount; | 427 | pc->cur_pos += done; |
428 | |||
429 | bcount -= done; | ||
430 | |||
431 | if (bcount) | ||
432 | ide_pad_transfer(drive, write, bcount); | ||
433 | |||
434 | debug_log("[cmd %x] transferred %d bytes, padded %d bytes\n", | ||
435 | rq->cmd[0], done, bcount); | ||
481 | 436 | ||
482 | debug_log("[cmd %x] transferred %d bytes on that intr.\n", | ||
483 | rq->cmd[0], bcount); | ||
484 | next_irq: | ||
485 | /* And set the interrupt handler again */ | 437 | /* And set the interrupt handler again */ |
486 | ide_set_handler(drive, ide_pc_intr, timeout); | 438 | ide_set_handler(drive, ide_pc_intr, timeout); |
487 | return ide_started; | 439 | return ide_started; |
@@ -611,6 +563,10 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive) | |||
611 | : ide_pc_intr), | 563 | : ide_pc_intr), |
612 | timeout); | 564 | timeout); |
613 | 565 | ||
566 | /* Send the actual packet */ | ||
567 | if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0) | ||
568 | hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len); | ||
569 | |||
614 | /* Begin DMA, if necessary */ | 570 | /* Begin DMA, if necessary */ |
615 | if (dev_is_idecd(drive)) { | 571 | if (dev_is_idecd(drive)) { |
616 | if (drive->dma) | 572 | if (drive->dma) |
@@ -622,10 +578,6 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive) | |||
622 | } | 578 | } |
623 | } | 579 | } |
624 | 580 | ||
625 | /* Send the actual packet */ | ||
626 | if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0) | ||
627 | hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len); | ||
628 | |||
629 | return ide_started; | 581 | return ide_started; |
630 | } | 582 | } |
631 | 583 | ||
@@ -633,7 +585,6 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd) | |||
633 | { | 585 | { |
634 | struct ide_atapi_pc *pc; | 586 | struct ide_atapi_pc *pc; |
635 | ide_hwif_t *hwif = drive->hwif; | 587 | ide_hwif_t *hwif = drive->hwif; |
636 | const struct ide_dma_ops *dma_ops = hwif->dma_ops; | ||
637 | ide_expiry_t *expiry = NULL; | 588 | ide_expiry_t *expiry = NULL; |
638 | struct request *rq = hwif->rq; | 589 | struct request *rq = hwif->rq; |
639 | unsigned int timeout; | 590 | unsigned int timeout; |
@@ -647,12 +598,8 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd) | |||
647 | expiry = ide_cd_expiry; | 598 | expiry = ide_cd_expiry; |
648 | timeout = ATAPI_WAIT_PC; | 599 | timeout = ATAPI_WAIT_PC; |
649 | 600 | ||
650 | if (drive->dma) { | 601 | if (drive->dma) |
651 | if (ide_build_sglist(drive, cmd)) | 602 | drive->dma = !ide_dma_prepare(drive, cmd); |
652 | drive->dma = !dma_ops->dma_setup(drive, cmd); | ||
653 | else | ||
654 | drive->dma = 0; | ||
655 | } | ||
656 | } else { | 603 | } else { |
657 | pc = drive->pc; | 604 | pc = drive->pc; |
658 | 605 | ||
@@ -670,13 +617,8 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd) | |||
670 | ide_dma_off(drive); | 617 | ide_dma_off(drive); |
671 | } | 618 | } |
672 | 619 | ||
673 | if ((pc->flags & PC_FLAG_DMA_OK) && | 620 | if (pc->flags & PC_FLAG_DMA_OK) |
674 | (drive->dev_flags & IDE_DFLAG_USING_DMA)) { | 621 | drive->dma = !ide_dma_prepare(drive, cmd); |
675 | if (ide_build_sglist(drive, cmd)) | ||
676 | drive->dma = !dma_ops->dma_setup(drive, cmd); | ||
677 | else | ||
678 | drive->dma = 0; | ||
679 | } | ||
680 | 622 | ||
681 | if (!drive->dma) | 623 | if (!drive->dma) |
682 | pc->flags &= ~PC_FLAG_DMA_OK; | 624 | pc->flags &= ~PC_FLAG_DMA_OK; |
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 3f630e4080d4..35729a47f797 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (C) 1994-1996 Scott Snyder <snyder@fnald0.fnal.gov> | 4 | * Copyright (C) 1994-1996 Scott Snyder <snyder@fnald0.fnal.gov> |
5 | * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org> | 5 | * Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org> |
6 | * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de> | 6 | * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de> |
7 | * Copyright (C) 2005, 2007 Bartlomiej Zolnierkiewicz | 7 | * Copyright (C) 2005, 2007-2009 Bartlomiej Zolnierkiewicz |
8 | * | 8 | * |
9 | * May be copied or modified under the terms of the GNU General Public | 9 | * May be copied or modified under the terms of the GNU General Public |
10 | * License. See linux/COPYING for more information. | 10 | * License. See linux/COPYING for more information. |
@@ -12,12 +12,9 @@ | |||
12 | * See Documentation/cdrom/ide-cd for usage information. | 12 | * See Documentation/cdrom/ide-cd for usage information. |
13 | * | 13 | * |
14 | * Suggestions are welcome. Patches that work are more welcome though. ;-) | 14 | * Suggestions are welcome. Patches that work are more welcome though. ;-) |
15 | * For those wishing to work on this driver, please be sure you download | 15 | * |
16 | * and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI | 16 | * Documentation: |
17 | * (SFF-8020i rev 2.6) standards. These documents can be obtained by | 17 | * Mt. Fuji (SFF8090 version 4) and ATAPI (SFF-8020i rev 2.6) standards. |
18 | * anonymous ftp from: | ||
19 | * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps | ||
20 | * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf | ||
21 | * | 18 | * |
22 | * For historical changelog please see: | 19 | * For historical changelog please see: |
23 | * Documentation/ide/ChangeLog.ide-cd.1994-2004 | 20 | * Documentation/ide/ChangeLog.ide-cd.1994-2004 |
@@ -245,73 +242,34 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, | |||
245 | elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0); | 242 | elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0); |
246 | } | 243 | } |
247 | 244 | ||
248 | static void cdrom_end_request(ide_drive_t *drive, int uptodate) | 245 | static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq) |
249 | { | 246 | { |
250 | struct request *rq = drive->hwif->rq; | 247 | /* |
251 | int nsectors = rq->hard_cur_sectors; | 248 | * For REQ_TYPE_SENSE, "rq->buffer" points to the original |
252 | 249 | * failed request | |
253 | ide_debug_log(IDE_DBG_FUNC, "cmd: 0x%x, uptodate: 0x%x, nsectors: %d", | 250 | */ |
254 | rq->cmd[0], uptodate, nsectors); | 251 | struct request *failed = (struct request *)rq->buffer; |
255 | 252 | struct cdrom_info *info = drive->driver_data; | |
256 | if (blk_sense_request(rq) && uptodate) { | 253 | void *sense = &info->sense_data; |
257 | /* | ||
258 | * For REQ_TYPE_SENSE, "rq->buffer" points to the original | ||
259 | * failed request | ||
260 | */ | ||
261 | struct request *failed = (struct request *) rq->buffer; | ||
262 | struct cdrom_info *info = drive->driver_data; | ||
263 | void *sense = &info->sense_data; | ||
264 | |||
265 | if (failed) { | ||
266 | if (failed->sense) { | ||
267 | sense = failed->sense; | ||
268 | failed->sense_len = rq->sense_len; | ||
269 | } | ||
270 | cdrom_analyze_sense_data(drive, failed, sense); | ||
271 | /* | ||
272 | * now end the failed request | ||
273 | */ | ||
274 | if (blk_fs_request(failed)) { | ||
275 | if (ide_end_rq(drive, failed, -EIO, | ||
276 | failed->hard_nr_sectors << 9)) | ||
277 | BUG(); | ||
278 | } else { | ||
279 | if (blk_end_request(failed, -EIO, | ||
280 | failed->data_len)) | ||
281 | BUG(); | ||
282 | } | ||
283 | } else | ||
284 | cdrom_analyze_sense_data(drive, NULL, sense); | ||
285 | } | ||
286 | |||
287 | if (!rq->current_nr_sectors && blk_fs_request(rq)) | ||
288 | uptodate = 1; | ||
289 | /* make sure it's fully ended */ | ||
290 | if (blk_pc_request(rq)) | ||
291 | nsectors = (rq->data_len + 511) >> 9; | ||
292 | if (!nsectors) | ||
293 | nsectors = 1; | ||
294 | |||
295 | ide_debug_log(IDE_DBG_FUNC, "uptodate: 0x%x, nsectors: %d", | ||
296 | uptodate, nsectors); | ||
297 | |||
298 | if (blk_fs_request(rq) == 0 && uptodate <= 0 && rq->errors == 0) | ||
299 | rq->errors = -EIO; | ||
300 | 254 | ||
301 | ide_complete_rq(drive, uptodate ? 0 : -EIO, nsectors << 9); | 255 | if (failed) { |
302 | } | 256 | if (failed->sense) { |
257 | sense = failed->sense; | ||
258 | failed->sense_len = rq->sense_len; | ||
259 | } | ||
260 | cdrom_analyze_sense_data(drive, failed, sense); | ||
303 | 261 | ||
304 | static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 st) | 262 | if (ide_end_rq(drive, failed, -EIO, blk_rq_bytes(failed))) |
305 | { | 263 | BUG(); |
306 | if (st & 0x80) | 264 | } else |
307 | return; | 265 | cdrom_analyze_sense_data(drive, NULL, sense); |
308 | ide_dump_status(drive, msg, st); | ||
309 | } | 266 | } |
310 | 267 | ||
311 | /* | 268 | /* |
312 | * Returns: | 269 | * Returns: |
313 | * 0: if the request should be continued. | 270 | * 0: if the request should be continued. |
314 | * 1: if the request was ended. | 271 | * 1: if the request will be going through error recovery. |
272 | * 2: if the request should be ended. | ||
315 | */ | 273 | */ |
316 | static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | 274 | static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) |
317 | { | 275 | { |
@@ -332,12 +290,6 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | |||
332 | err = ide_read_error(drive); | 290 | err = ide_read_error(drive); |
333 | sense_key = err >> 4; | 291 | sense_key = err >> 4; |
334 | 292 | ||
335 | if (rq == NULL) { | ||
336 | printk(KERN_ERR PFX "%s: missing rq in %s\n", | ||
337 | drive->name, __func__); | ||
338 | return 1; | ||
339 | } | ||
340 | |||
341 | ide_debug_log(IDE_DBG_RQ, "stat: 0x%x, good_stat: 0x%x, cmd[0]: 0x%x, " | 293 | ide_debug_log(IDE_DBG_RQ, "stat: 0x%x, good_stat: 0x%x, cmd[0]: 0x%x, " |
342 | "rq->cmd_type: 0x%x, err: 0x%x", | 294 | "rq->cmd_type: 0x%x, err: 0x%x", |
343 | stat, good_stat, rq->cmd[0], rq->cmd_type, | 295 | stat, good_stat, rq->cmd[0], rq->cmd_type, |
@@ -350,10 +302,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | |||
350 | * Just give up. | 302 | * Just give up. |
351 | */ | 303 | */ |
352 | rq->cmd_flags |= REQ_FAILED; | 304 | rq->cmd_flags |= REQ_FAILED; |
353 | cdrom_end_request(drive, 0); | 305 | return 2; |
354 | ide_error(drive, "request sense failure", stat); | ||
355 | return 1; | ||
356 | |||
357 | } else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) { | 306 | } else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) { |
358 | /* All other functions, except for READ. */ | 307 | /* All other functions, except for READ. */ |
359 | 308 | ||
@@ -456,21 +405,19 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | |||
456 | * No point in retrying after an illegal request or data | 405 | * No point in retrying after an illegal request or data |
457 | * protect error. | 406 | * protect error. |
458 | */ | 407 | */ |
459 | ide_dump_status_no_sense(drive, "command error", stat); | 408 | ide_dump_status(drive, "command error", stat); |
460 | do_end_request = 1; | 409 | do_end_request = 1; |
461 | } else if (sense_key == MEDIUM_ERROR) { | 410 | } else if (sense_key == MEDIUM_ERROR) { |
462 | /* | 411 | /* |
463 | * No point in re-trying a zillion times on a bad | 412 | * No point in re-trying a zillion times on a bad |
464 | * sector. If we got here the error is not correctable. | 413 | * sector. If we got here the error is not correctable. |
465 | */ | 414 | */ |
466 | ide_dump_status_no_sense(drive, | 415 | ide_dump_status(drive, "media error (bad sector)", |
467 | "media error (bad sector)", | 416 | stat); |
468 | stat); | ||
469 | do_end_request = 1; | 417 | do_end_request = 1; |
470 | } else if (sense_key == BLANK_CHECK) { | 418 | } else if (sense_key == BLANK_CHECK) { |
471 | /* disk appears blank ?? */ | 419 | /* disk appears blank ?? */ |
472 | ide_dump_status_no_sense(drive, "media error (blank)", | 420 | ide_dump_status(drive, "media error (blank)", stat); |
473 | stat); | ||
474 | do_end_request = 1; | 421 | do_end_request = 1; |
475 | } else if ((err & ~ATA_ABORTED) != 0) { | 422 | } else if ((err & ~ATA_ABORTED) != 0) { |
476 | /* go to the default handler for other errors */ | 423 | /* go to the default handler for other errors */ |
@@ -495,14 +442,12 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | |||
495 | */ | 442 | */ |
496 | if (stat & ATA_ERR) | 443 | if (stat & ATA_ERR) |
497 | cdrom_queue_request_sense(drive, NULL, NULL); | 444 | cdrom_queue_request_sense(drive, NULL, NULL); |
445 | return 1; | ||
498 | } else { | 446 | } else { |
499 | blk_dump_rq_flags(rq, PFX "bad rq"); | 447 | blk_dump_rq_flags(rq, PFX "bad rq"); |
500 | cdrom_end_request(drive, 0); | 448 | return 2; |
501 | } | 449 | } |
502 | 450 | ||
503 | /* retry, or handle the next request */ | ||
504 | return 1; | ||
505 | |||
506 | end_request: | 451 | end_request: |
507 | if (stat & ATA_ERR) { | 452 | if (stat & ATA_ERR) { |
508 | struct request_queue *q = drive->queue; | 453 | struct request_queue *q = drive->queue; |
@@ -515,10 +460,9 @@ end_request: | |||
515 | hwif->rq = NULL; | 460 | hwif->rq = NULL; |
516 | 461 | ||
517 | cdrom_queue_request_sense(drive, rq->sense, rq); | 462 | cdrom_queue_request_sense(drive, rq->sense, rq); |
463 | return 1; | ||
518 | } else | 464 | } else |
519 | cdrom_end_request(drive, 0); | 465 | return 2; |
520 | |||
521 | return 1; | ||
522 | } | 466 | } |
523 | 467 | ||
524 | /* | 468 | /* |
@@ -562,101 +506,13 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq, | |||
562 | if (rq->cmd_type == REQ_TYPE_ATA_PC) | 506 | if (rq->cmd_type == REQ_TYPE_ATA_PC) |
563 | rq->cmd_flags |= REQ_FAILED; | 507 | rq->cmd_flags |= REQ_FAILED; |
564 | 508 | ||
565 | cdrom_end_request(drive, 0); | ||
566 | return -1; | 509 | return -1; |
567 | } | 510 | } |
568 | 511 | ||
569 | /* | 512 | static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd) |
570 | * Assume that the drive will always provide data in multiples of at least | ||
571 | * SECTOR_SIZE, as it gets hairy to keep track of the transfers otherwise. | ||
572 | */ | ||
573 | static int ide_cd_check_transfer_size(ide_drive_t *drive, int len) | ||
574 | { | 513 | { |
575 | ide_debug_log(IDE_DBG_FUNC, "len: %d", len); | 514 | struct request *rq = cmd->rq; |
576 | |||
577 | if ((len % SECTOR_SIZE) == 0) | ||
578 | return 0; | ||
579 | 515 | ||
580 | printk(KERN_ERR PFX "%s: %s: Bad transfer size %d\n", drive->name, | ||
581 | __func__, len); | ||
582 | |||
583 | if (drive->atapi_flags & IDE_AFLAG_LIMIT_NFRAMES) | ||
584 | printk(KERN_ERR PFX "This drive is not supported by this " | ||
585 | "version of the driver\n"); | ||
586 | else { | ||
587 | printk(KERN_ERR PFX "Trying to limit transfer sizes\n"); | ||
588 | drive->atapi_flags |= IDE_AFLAG_LIMIT_NFRAMES; | ||
589 | } | ||
590 | |||
591 | return 1; | ||
592 | } | ||
593 | |||
594 | static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive, | ||
595 | struct request *rq) | ||
596 | { | ||
597 | ide_debug_log(IDE_DBG_RQ, "rq->cmd_flags: 0x%x", rq->cmd_flags); | ||
598 | |||
599 | if (rq_data_dir(rq) == READ) { | ||
600 | unsigned short sectors_per_frame = | ||
601 | queue_hardsect_size(drive->queue) >> SECTOR_BITS; | ||
602 | int nskip = rq->sector & (sectors_per_frame - 1); | ||
603 | |||
604 | /* | ||
605 | * If the requested sector doesn't start on a frame boundary, | ||
606 | * we must adjust the start of the transfer so that it does, | ||
607 | * and remember to skip the first few sectors. | ||
608 | * | ||
609 | * If the rq->current_nr_sectors field is larger than the size | ||
610 | * of the buffer, it will mean that we're to skip a number of | ||
611 | * sectors equal to the amount by which rq->current_nr_sectors | ||
612 | * is larger than the buffer size. | ||
613 | */ | ||
614 | if (nskip > 0) { | ||
615 | /* sanity check... */ | ||
616 | if (rq->current_nr_sectors != | ||
617 | bio_cur_sectors(rq->bio)) { | ||
618 | printk(KERN_ERR PFX "%s: %s: buffer botch (%u)\n", | ||
619 | drive->name, __func__, | ||
620 | rq->current_nr_sectors); | ||
621 | cdrom_end_request(drive, 0); | ||
622 | return ide_stopped; | ||
623 | } | ||
624 | rq->current_nr_sectors += nskip; | ||
625 | } | ||
626 | } | ||
627 | |||
628 | /* set up the command */ | ||
629 | rq->timeout = ATAPI_WAIT_PC; | ||
630 | |||
631 | return ide_started; | ||
632 | } | ||
633 | |||
634 | /* | ||
635 | * Fix up a possibly partially-processed request so that we can start it over | ||
636 | * entirely, or even put it back on the request queue. | ||
637 | */ | ||
638 | static void ide_cd_restore_request(ide_drive_t *drive, struct request *rq) | ||
639 | { | ||
640 | |||
641 | ide_debug_log(IDE_DBG_FUNC, "enter"); | ||
642 | |||
643 | if (rq->buffer != bio_data(rq->bio)) { | ||
644 | sector_t n = | ||
645 | (rq->buffer - (char *)bio_data(rq->bio)) / SECTOR_SIZE; | ||
646 | |||
647 | rq->buffer = bio_data(rq->bio); | ||
648 | rq->nr_sectors += n; | ||
649 | rq->sector -= n; | ||
650 | } | ||
651 | rq->current_nr_sectors = bio_cur_sectors(rq->bio); | ||
652 | rq->hard_cur_sectors = rq->current_nr_sectors; | ||
653 | rq->hard_nr_sectors = rq->nr_sectors; | ||
654 | rq->hard_sector = rq->sector; | ||
655 | rq->q->prep_rq_fn(rq->q, rq); | ||
656 | } | ||
657 | |||
658 | static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct request *rq) | ||
659 | { | ||
660 | ide_debug_log(IDE_DBG_FUNC, "rq->cmd[0]: 0x%x", rq->cmd[0]); | 516 | ide_debug_log(IDE_DBG_FUNC, "rq->cmd[0]: 0x%x", rq->cmd[0]); |
661 | 517 | ||
662 | /* | 518 | /* |
@@ -664,11 +520,14 @@ static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct request *rq) | |||
664 | * and some drives don't send them. Sigh. | 520 | * and some drives don't send them. Sigh. |
665 | */ | 521 | */ |
666 | if (rq->cmd[0] == GPCMD_REQUEST_SENSE && | 522 | if (rq->cmd[0] == GPCMD_REQUEST_SENSE && |
667 | rq->data_len > 0 && rq->data_len <= 5) | 523 | cmd->nleft > 0 && cmd->nleft <= 5) { |
668 | while (rq->data_len > 0) { | 524 | unsigned int ofs = cmd->nbytes - cmd->nleft; |
669 | *(u8 *)rq->data++ = 0; | 525 | |
670 | --rq->data_len; | 526 | while (cmd->nleft > 0) { |
527 | *((u8 *)rq->data + ofs++) = 0; | ||
528 | cmd->nleft--; | ||
671 | } | 529 | } |
530 | } | ||
672 | } | 531 | } |
673 | 532 | ||
674 | int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, | 533 | int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, |
@@ -748,24 +607,26 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, | |||
748 | return (flags & REQ_FAILED) ? -EIO : 0; | 607 | return (flags & REQ_FAILED) ? -EIO : 0; |
749 | } | 608 | } |
750 | 609 | ||
751 | /* | 610 | static void ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd) |
752 | * Called from blk_end_request_callback() after the data of the request is | ||
753 | * completed and before the request itself is completed. By returning value '1', | ||
754 | * blk_end_request_callback() returns immediately without completing it. | ||
755 | */ | ||
756 | static int cdrom_newpc_intr_dummy_cb(struct request *rq) | ||
757 | { | 611 | { |
758 | return 1; | 612 | unsigned int nr_bytes = cmd->nbytes - cmd->nleft; |
613 | |||
614 | if (cmd->tf_flags & IDE_TFLAG_WRITE) | ||
615 | nr_bytes -= cmd->last_xfer_len; | ||
616 | |||
617 | if (nr_bytes > 0) | ||
618 | ide_complete_rq(drive, 0, nr_bytes); | ||
759 | } | 619 | } |
760 | 620 | ||
761 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | 621 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) |
762 | { | 622 | { |
763 | ide_hwif_t *hwif = drive->hwif; | 623 | ide_hwif_t *hwif = drive->hwif; |
624 | struct ide_cmd *cmd = &hwif->cmd; | ||
764 | struct request *rq = hwif->rq; | 625 | struct request *rq = hwif->rq; |
765 | xfer_func_t *xferfunc; | ||
766 | ide_expiry_t *expiry = NULL; | 626 | ide_expiry_t *expiry = NULL; |
767 | int dma_error = 0, dma, stat, thislen, uptodate = 0; | 627 | int dma_error = 0, dma, stat, thislen, uptodate = 0; |
768 | int write = (rq_data_dir(rq) == WRITE) ? 1 : 0; | 628 | int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc, nsectors; |
629 | int sense = blk_sense_request(rq); | ||
769 | unsigned int timeout; | 630 | unsigned int timeout; |
770 | u16 len; | 631 | u16 len; |
771 | u8 ireason; | 632 | u8 ireason; |
@@ -777,7 +638,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
777 | dma = drive->dma; | 638 | dma = drive->dma; |
778 | if (dma) { | 639 | if (dma) { |
779 | drive->dma = 0; | 640 | drive->dma = 0; |
641 | drive->waiting_for_dma = 0; | ||
780 | dma_error = hwif->dma_ops->dma_end(drive); | 642 | dma_error = hwif->dma_ops->dma_end(drive); |
643 | ide_dma_unmap_sg(drive, cmd); | ||
781 | if (dma_error) { | 644 | if (dma_error) { |
782 | printk(KERN_ERR PFX "%s: DMA %s error\n", drive->name, | 645 | printk(KERN_ERR PFX "%s: DMA %s error\n", drive->name, |
783 | write ? "write" : "read"); | 646 | write ? "write" : "read"); |
@@ -785,27 +648,24 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
785 | } | 648 | } |
786 | } | 649 | } |
787 | 650 | ||
788 | if (cdrom_decode_status(drive, 0, &stat)) | 651 | rc = cdrom_decode_status(drive, 0, &stat); |
652 | if (rc) { | ||
653 | if (rc == 2) | ||
654 | goto out_end; | ||
789 | return ide_stopped; | 655 | return ide_stopped; |
656 | } | ||
790 | 657 | ||
791 | /* using dma, transfer is complete now */ | 658 | /* using dma, transfer is complete now */ |
792 | if (dma) { | 659 | if (dma) { |
793 | if (dma_error) | 660 | if (dma_error) |
794 | return ide_error(drive, "dma error", stat); | 661 | return ide_error(drive, "dma error", stat); |
795 | if (blk_fs_request(rq)) { | 662 | uptodate = 1; |
796 | ide_complete_rq(drive, 0, rq->nr_sectors | 663 | goto out_end; |
797 | ? (rq->nr_sectors << 9) : ide_rq_bytes(rq)); | ||
798 | return ide_stopped; | ||
799 | } else if (rq->cmd_type == REQ_TYPE_ATA_PC && !rq->bio) { | ||
800 | ide_complete_rq(drive, 0, 512); | ||
801 | return ide_stopped; | ||
802 | } | ||
803 | goto end_request; | ||
804 | } | 664 | } |
805 | 665 | ||
806 | ide_read_bcount_and_ireason(drive, &len, &ireason); | 666 | ide_read_bcount_and_ireason(drive, &len, &ireason); |
807 | 667 | ||
808 | thislen = blk_fs_request(rq) ? len : rq->data_len; | 668 | thislen = blk_fs_request(rq) ? len : cmd->nleft; |
809 | if (thislen > len) | 669 | if (thislen > len) |
810 | thislen = len; | 670 | thislen = len; |
811 | 671 | ||
@@ -820,60 +680,30 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
820 | * Otherwise, complete the command normally. | 680 | * Otherwise, complete the command normally. |
821 | */ | 681 | */ |
822 | uptodate = 1; | 682 | uptodate = 1; |
823 | if (rq->current_nr_sectors > 0) { | 683 | if (cmd->nleft > 0) { |
824 | printk(KERN_ERR PFX "%s: %s: data underrun " | 684 | printk(KERN_ERR PFX "%s: %s: data underrun " |
825 | "(%d blocks)\n", | 685 | "(%u bytes)\n", drive->name, __func__, |
826 | drive->name, __func__, | 686 | cmd->nleft); |
827 | rq->current_nr_sectors); | ||
828 | if (!write) | 687 | if (!write) |
829 | rq->cmd_flags |= REQ_FAILED; | 688 | rq->cmd_flags |= REQ_FAILED; |
830 | uptodate = 0; | 689 | uptodate = 0; |
831 | } | 690 | } |
832 | cdrom_end_request(drive, uptodate); | ||
833 | return ide_stopped; | ||
834 | } else if (!blk_pc_request(rq)) { | 691 | } else if (!blk_pc_request(rq)) { |
835 | ide_cd_request_sense_fixup(drive, rq); | 692 | ide_cd_request_sense_fixup(drive, cmd); |
836 | /* complain if we still have data left to transfer */ | 693 | /* complain if we still have data left to transfer */ |
837 | uptodate = rq->data_len ? 0 : 1; | 694 | uptodate = cmd->nleft ? 0 : 1; |
695 | if (uptodate == 0) | ||
696 | rq->cmd_flags |= REQ_FAILED; | ||
838 | } | 697 | } |
839 | goto end_request; | 698 | goto out_end; |
840 | } | 699 | } |
841 | 700 | ||
842 | /* check which way to transfer data */ | 701 | /* check which way to transfer data */ |
843 | if (ide_cd_check_ireason(drive, rq, len, ireason, write)) | 702 | rc = ide_cd_check_ireason(drive, rq, len, ireason, write); |
844 | return ide_stopped; | 703 | if (rc) |
704 | goto out_end; | ||
845 | 705 | ||
846 | if (blk_fs_request(rq)) { | 706 | cmd->last_xfer_len = 0; |
847 | if (write == 0) { | ||
848 | int nskip; | ||
849 | |||
850 | if (ide_cd_check_transfer_size(drive, len)) { | ||
851 | cdrom_end_request(drive, 0); | ||
852 | return ide_stopped; | ||
853 | } | ||
854 | |||
855 | /* | ||
856 | * First, figure out if we need to bit-bucket | ||
857 | * any of the leading sectors. | ||
858 | */ | ||
859 | nskip = min_t(int, rq->current_nr_sectors | ||
860 | - bio_cur_sectors(rq->bio), | ||
861 | thislen >> 9); | ||
862 | if (nskip > 0) { | ||
863 | ide_pad_transfer(drive, write, nskip << 9); | ||
864 | rq->current_nr_sectors -= nskip; | ||
865 | thislen -= (nskip << 9); | ||
866 | } | ||
867 | } | ||
868 | } | ||
869 | |||
870 | if (ireason == 0) { | ||
871 | write = 1; | ||
872 | xferfunc = hwif->tp_ops->output_data; | ||
873 | } else { | ||
874 | write = 0; | ||
875 | xferfunc = hwif->tp_ops->input_data; | ||
876 | } | ||
877 | 707 | ||
878 | ide_debug_log(IDE_DBG_PC, "data transfer, rq->cmd_type: 0x%x, " | 708 | ide_debug_log(IDE_DBG_PC, "data transfer, rq->cmd_type: 0x%x, " |
879 | "ireason: 0x%x", | 709 | "ireason: 0x%x", |
@@ -881,75 +711,31 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
881 | 711 | ||
882 | /* transfer data */ | 712 | /* transfer data */ |
883 | while (thislen > 0) { | 713 | while (thislen > 0) { |
884 | u8 *ptr = blk_fs_request(rq) ? NULL : rq->data; | 714 | int blen = min_t(int, thislen, cmd->nleft); |
885 | int blen = rq->data_len; | ||
886 | |||
887 | /* bio backed? */ | ||
888 | if (rq->bio) { | ||
889 | if (blk_fs_request(rq)) { | ||
890 | ptr = rq->buffer; | ||
891 | blen = rq->current_nr_sectors << 9; | ||
892 | } else { | ||
893 | ptr = bio_data(rq->bio); | ||
894 | blen = bio_iovec(rq->bio)->bv_len; | ||
895 | } | ||
896 | } | ||
897 | 715 | ||
898 | if (!ptr) { | 716 | if (cmd->nleft == 0) |
899 | if (blk_fs_request(rq) && !write) | ||
900 | /* | ||
901 | * If the buffers are full, pipe the rest into | ||
902 | * oblivion. | ||
903 | */ | ||
904 | ide_pad_transfer(drive, 0, thislen); | ||
905 | else { | ||
906 | printk(KERN_ERR PFX "%s: confused, missing data\n", | ||
907 | drive->name); | ||
908 | blk_dump_rq_flags(rq, rq_data_dir(rq) | ||
909 | ? "cdrom_newpc_intr, write" | ||
910 | : "cdrom_newpc_intr, read"); | ||
911 | } | ||
912 | break; | 717 | break; |
913 | } | ||
914 | |||
915 | if (blen > thislen) | ||
916 | blen = thislen; | ||
917 | 718 | ||
918 | xferfunc(drive, NULL, ptr, blen); | 719 | ide_pio_bytes(drive, cmd, write, blen); |
720 | cmd->last_xfer_len += blen; | ||
919 | 721 | ||
920 | thislen -= blen; | 722 | thislen -= blen; |
921 | len -= blen; | 723 | len -= blen; |
922 | 724 | ||
923 | if (blk_fs_request(rq)) { | 725 | if (sense && write == 0) |
924 | rq->buffer += blen; | ||
925 | rq->nr_sectors -= (blen >> 9); | ||
926 | rq->current_nr_sectors -= (blen >> 9); | ||
927 | rq->sector += (blen >> 9); | ||
928 | |||
929 | if (rq->current_nr_sectors == 0 && rq->nr_sectors) | ||
930 | cdrom_end_request(drive, 1); | ||
931 | } else { | ||
932 | rq->data_len -= blen; | ||
933 | |||
934 | /* | ||
935 | * The request can't be completed until DRQ is cleared. | ||
936 | * So complete the data, but don't complete the request | ||
937 | * using the dummy function for the callback feature | ||
938 | * of blk_end_request_callback(). | ||
939 | */ | ||
940 | if (rq->bio) | ||
941 | blk_end_request_callback(rq, 0, blen, | ||
942 | cdrom_newpc_intr_dummy_cb); | ||
943 | else | ||
944 | rq->data += blen; | ||
945 | } | ||
946 | if (!write && blk_sense_request(rq)) | ||
947 | rq->sense_len += blen; | 726 | rq->sense_len += blen; |
948 | } | 727 | } |
949 | 728 | ||
950 | /* pad, if necessary */ | 729 | /* pad, if necessary */ |
951 | if (!blk_fs_request(rq) && len > 0) | 730 | if (len > 0) { |
952 | ide_pad_transfer(drive, write, len); | 731 | if (blk_fs_request(rq) == 0 || write == 0) |
732 | ide_pad_transfer(drive, write, len); | ||
733 | else { | ||
734 | printk(KERN_ERR PFX "%s: confused, missing data\n", | ||
735 | drive->name); | ||
736 | blk_dump_rq_flags(rq, "cdrom_newpc_intr"); | ||
737 | } | ||
738 | } | ||
953 | 739 | ||
954 | if (blk_pc_request(rq)) { | 740 | if (blk_pc_request(rq)) { |
955 | timeout = rq->timeout; | 741 | timeout = rq->timeout; |
@@ -963,21 +749,50 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
963 | ide_set_handler(drive, cdrom_newpc_intr, timeout); | 749 | ide_set_handler(drive, cdrom_newpc_intr, timeout); |
964 | return ide_started; | 750 | return ide_started; |
965 | 751 | ||
966 | end_request: | 752 | out_end: |
967 | if (blk_pc_request(rq)) { | 753 | if (blk_pc_request(rq) && rc == 0) { |
968 | unsigned int dlen = rq->data_len; | 754 | unsigned int dlen = rq->data_len; |
969 | 755 | ||
970 | if (dma) | 756 | rq->data_len = 0; |
971 | rq->data_len = 0; | ||
972 | 757 | ||
973 | if (blk_end_request(rq, 0, dlen)) | 758 | if (blk_end_request(rq, 0, dlen)) |
974 | BUG(); | 759 | BUG(); |
975 | 760 | ||
976 | hwif->rq = NULL; | 761 | hwif->rq = NULL; |
977 | } else { | 762 | } else { |
978 | if (!uptodate) | 763 | if (sense && uptodate) |
979 | rq->cmd_flags |= REQ_FAILED; | 764 | ide_cd_complete_failed_rq(drive, rq); |
980 | cdrom_end_request(drive, uptodate); | 765 | |
766 | if (blk_fs_request(rq)) { | ||
767 | if (cmd->nleft == 0) | ||
768 | uptodate = 1; | ||
769 | } else { | ||
770 | if (uptodate <= 0 && rq->errors == 0) | ||
771 | rq->errors = -EIO; | ||
772 | } | ||
773 | |||
774 | if (uptodate == 0) | ||
775 | ide_cd_error_cmd(drive, cmd); | ||
776 | |||
777 | /* make sure it's fully ended */ | ||
778 | if (blk_pc_request(rq)) | ||
779 | nsectors = (rq->data_len + 511) >> 9; | ||
780 | else | ||
781 | nsectors = rq->hard_nr_sectors; | ||
782 | |||
783 | if (nsectors == 0) | ||
784 | nsectors = 1; | ||
785 | |||
786 | if (blk_fs_request(rq) == 0) { | ||
787 | rq->data_len -= (cmd->nbytes - cmd->nleft); | ||
788 | if (uptodate == 0 && (cmd->tf_flags & IDE_TFLAG_WRITE)) | ||
789 | rq->data_len += cmd->last_xfer_len; | ||
790 | } | ||
791 | |||
792 | ide_complete_rq(drive, uptodate ? 0 : -EIO, nsectors << 9); | ||
793 | |||
794 | if (sense && rc == 2) | ||
795 | ide_error(drive, "request sense failure", stat); | ||
981 | } | 796 | } |
982 | return ide_stopped; | 797 | return ide_stopped; |
983 | } | 798 | } |
@@ -985,42 +800,40 @@ end_request: | |||
985 | static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) | 800 | static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) |
986 | { | 801 | { |
987 | struct cdrom_info *cd = drive->driver_data; | 802 | struct cdrom_info *cd = drive->driver_data; |
803 | struct request_queue *q = drive->queue; | ||
988 | int write = rq_data_dir(rq) == WRITE; | 804 | int write = rq_data_dir(rq) == WRITE; |
989 | unsigned short sectors_per_frame = | 805 | unsigned short sectors_per_frame = |
990 | queue_hardsect_size(drive->queue) >> SECTOR_BITS; | 806 | queue_hardsect_size(q) >> SECTOR_BITS; |
991 | 807 | ||
992 | ide_debug_log(IDE_DBG_RQ, "rq->cmd[0]: 0x%x, write: 0x%x, " | 808 | ide_debug_log(IDE_DBG_RQ, "rq->cmd[0]: 0x%x, rq->cmd_flags: 0x%x, " |
993 | "secs_per_frame: %u", | 809 | "secs_per_frame: %u", |
994 | rq->cmd[0], write, sectors_per_frame); | 810 | rq->cmd[0], rq->cmd_flags, sectors_per_frame); |
995 | 811 | ||
996 | if (write) { | 812 | if (write) { |
997 | /* disk has become write protected */ | 813 | /* disk has become write protected */ |
998 | if (get_disk_ro(cd->disk)) { | 814 | if (get_disk_ro(cd->disk)) |
999 | cdrom_end_request(drive, 0); | ||
1000 | return ide_stopped; | 815 | return ide_stopped; |
1001 | } | ||
1002 | } else { | 816 | } else { |
1003 | /* | 817 | /* |
1004 | * We may be retrying this request after an error. Fix up any | 818 | * We may be retrying this request after an error. Fix up any |
1005 | * weirdness which might be present in the request packet. | 819 | * weirdness which might be present in the request packet. |
1006 | */ | 820 | */ |
1007 | ide_cd_restore_request(drive, rq); | 821 | q->prep_rq_fn(q, rq); |
1008 | } | 822 | } |
1009 | 823 | ||
1010 | /* use DMA, if possible / writes *must* be hardware frame aligned */ | 824 | /* fs requests *must* be hardware frame aligned */ |
1011 | if ((rq->nr_sectors & (sectors_per_frame - 1)) || | 825 | if ((rq->nr_sectors & (sectors_per_frame - 1)) || |
1012 | (rq->sector & (sectors_per_frame - 1))) { | 826 | (rq->sector & (sectors_per_frame - 1))) |
1013 | if (write) { | 827 | return ide_stopped; |
1014 | cdrom_end_request(drive, 0); | 828 | |
1015 | return ide_stopped; | 829 | /* use DMA, if possible */ |
1016 | } | 830 | drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); |
1017 | drive->dma = 0; | ||
1018 | } else | ||
1019 | drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); | ||
1020 | 831 | ||
1021 | if (write) | 832 | if (write) |
1022 | cd->devinfo.media_written = 1; | 833 | cd->devinfo.media_written = 1; |
1023 | 834 | ||
835 | rq->timeout = ATAPI_WAIT_PC; | ||
836 | |||
1024 | return ide_started; | 837 | return ide_started; |
1025 | } | 838 | } |
1026 | 839 | ||
@@ -1068,6 +881,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, | |||
1068 | sector_t block) | 881 | sector_t block) |
1069 | { | 882 | { |
1070 | struct ide_cmd cmd; | 883 | struct ide_cmd cmd; |
884 | int uptodate = 0, nsectors; | ||
1071 | 885 | ||
1072 | ide_debug_log(IDE_DBG_RQ, "cmd: 0x%x, block: %llu", | 886 | ide_debug_log(IDE_DBG_RQ, "cmd: 0x%x, block: %llu", |
1073 | rq->cmd[0], (unsigned long long)block); | 887 | rq->cmd[0], (unsigned long long)block); |
@@ -1077,10 +891,7 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, | |||
1077 | 891 | ||
1078 | if (blk_fs_request(rq)) { | 892 | if (blk_fs_request(rq)) { |
1079 | if (cdrom_start_rw(drive, rq) == ide_stopped) | 893 | if (cdrom_start_rw(drive, rq) == ide_stopped) |
1080 | return ide_stopped; | 894 | goto out_end; |
1081 | |||
1082 | if (ide_cd_prepare_rw_request(drive, rq) == ide_stopped) | ||
1083 | return ide_stopped; | ||
1084 | } else if (blk_sense_request(rq) || blk_pc_request(rq) || | 895 | } else if (blk_sense_request(rq) || blk_pc_request(rq) || |
1085 | rq->cmd_type == REQ_TYPE_ATA_PC) { | 896 | rq->cmd_type == REQ_TYPE_ATA_PC) { |
1086 | if (!rq->timeout) | 897 | if (!rq->timeout) |
@@ -1089,12 +900,13 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, | |||
1089 | cdrom_do_block_pc(drive, rq); | 900 | cdrom_do_block_pc(drive, rq); |
1090 | } else if (blk_special_request(rq)) { | 901 | } else if (blk_special_request(rq)) { |
1091 | /* right now this can only be a reset... */ | 902 | /* right now this can only be a reset... */ |
1092 | cdrom_end_request(drive, 1); | 903 | uptodate = 1; |
1093 | return ide_stopped; | 904 | goto out_end; |
1094 | } else { | 905 | } else { |
1095 | blk_dump_rq_flags(rq, DRV_NAME " bad flags"); | 906 | blk_dump_rq_flags(rq, DRV_NAME " bad flags"); |
1096 | cdrom_end_request(drive, 0); | 907 | if (rq->errors == 0) |
1097 | return ide_stopped; | 908 | rq->errors = -EIO; |
909 | goto out_end; | ||
1098 | } | 910 | } |
1099 | 911 | ||
1100 | memset(&cmd, 0, sizeof(cmd)); | 912 | memset(&cmd, 0, sizeof(cmd)); |
@@ -1104,7 +916,22 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, | |||
1104 | 916 | ||
1105 | cmd.rq = rq; | 917 | cmd.rq = rq; |
1106 | 918 | ||
919 | if (blk_fs_request(rq) || rq->data_len) { | ||
920 | ide_init_sg_cmd(&cmd, blk_fs_request(rq) ? (rq->nr_sectors << 9) | ||
921 | : rq->data_len); | ||
922 | ide_map_sg(drive, &cmd); | ||
923 | } | ||
924 | |||
1107 | return ide_issue_pc(drive, &cmd); | 925 | return ide_issue_pc(drive, &cmd); |
926 | out_end: | ||
927 | nsectors = rq->hard_nr_sectors; | ||
928 | |||
929 | if (nsectors == 0) | ||
930 | nsectors = 1; | ||
931 | |||
932 | ide_complete_rq(drive, uptodate ? 0 : -EIO, nsectors << 9); | ||
933 | |||
934 | return ide_stopped; | ||
1108 | } | 935 | } |
1109 | 936 | ||
1110 | /* | 937 | /* |
@@ -1696,9 +1523,6 @@ static const struct ide_proc_devset *ide_cd_proc_devsets(ide_drive_t *drive) | |||
1696 | #endif | 1523 | #endif |
1697 | 1524 | ||
1698 | static const struct cd_list_entry ide_cd_quirks_list[] = { | 1525 | static const struct cd_list_entry ide_cd_quirks_list[] = { |
1699 | /* Limit transfer size per interrupt. */ | ||
1700 | { "SAMSUNG CD-ROM SCR-2430", NULL, IDE_AFLAG_LIMIT_NFRAMES }, | ||
1701 | { "SAMSUNG CD-ROM SCR-2432", NULL, IDE_AFLAG_LIMIT_NFRAMES }, | ||
1702 | /* SCR-3231 doesn't support the SET_CD_SPEED command. */ | 1526 | /* SCR-3231 doesn't support the SET_CD_SPEED command. */ |
1703 | { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_AFLAG_NO_SPEED_SELECT }, | 1527 | { "SAMSUNG CD-ROM SCR-3231", NULL, IDE_AFLAG_NO_SPEED_SELECT }, |
1704 | /* Old NEC260 (not R) was released before ATAPI 1.2 spec. */ | 1528 | /* Old NEC260 (not R) was released before ATAPI 1.2 spec. */ |
@@ -1759,18 +1583,18 @@ static int ide_cdrom_setup(ide_drive_t *drive) | |||
1759 | { | 1583 | { |
1760 | struct cdrom_info *cd = drive->driver_data; | 1584 | struct cdrom_info *cd = drive->driver_data; |
1761 | struct cdrom_device_info *cdi = &cd->devinfo; | 1585 | struct cdrom_device_info *cdi = &cd->devinfo; |
1586 | struct request_queue *q = drive->queue; | ||
1762 | u16 *id = drive->id; | 1587 | u16 *id = drive->id; |
1763 | char *fw_rev = (char *)&id[ATA_ID_FW_REV]; | 1588 | char *fw_rev = (char *)&id[ATA_ID_FW_REV]; |
1764 | int nslots; | 1589 | int nslots; |
1765 | 1590 | ||
1766 | ide_debug_log(IDE_DBG_PROBE, "enter"); | 1591 | ide_debug_log(IDE_DBG_PROBE, "enter"); |
1767 | 1592 | ||
1768 | blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn); | 1593 | blk_queue_prep_rq(q, ide_cdrom_prep_fn); |
1769 | blk_queue_dma_alignment(drive->queue, 31); | 1594 | blk_queue_dma_alignment(q, 31); |
1770 | blk_queue_update_dma_pad(drive->queue, 15); | 1595 | blk_queue_update_dma_pad(q, 15); |
1771 | drive->queue->unplug_delay = (1 * HZ) / 1000; | 1596 | |
1772 | if (!drive->queue->unplug_delay) | 1597 | q->unplug_delay = max((1 * HZ) / 1000, 1); |
1773 | drive->queue->unplug_delay = 1; | ||
1774 | 1598 | ||
1775 | drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED; | 1599 | drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED; |
1776 | drive->atapi_flags = IDE_AFLAG_NO_EJECT | ide_cd_flags(id); | 1600 | drive->atapi_flags = IDE_AFLAG_NO_EJECT | ide_cd_flags(id); |
@@ -1788,8 +1612,7 @@ static int ide_cdrom_setup(ide_drive_t *drive) | |||
1788 | 1612 | ||
1789 | nslots = ide_cdrom_probe_capabilities(drive); | 1613 | nslots = ide_cdrom_probe_capabilities(drive); |
1790 | 1614 | ||
1791 | /* set correct block size */ | 1615 | blk_queue_hardsect_size(q, CD_FRAMESIZE); |
1792 | blk_queue_hardsect_size(drive->queue, CD_FRAMESIZE); | ||
1793 | 1616 | ||
1794 | if (ide_cdrom_register(drive, nslots)) { | 1617 | if (ide_cdrom_register(drive, nslots)) { |
1795 | printk(KERN_ERR PFX "%s: %s failed to register device with the" | 1618 | printk(KERN_ERR PFX "%s: %s failed to register device with the" |
@@ -1968,9 +1791,6 @@ static struct block_device_operations idecd_ops = { | |||
1968 | }; | 1791 | }; |
1969 | 1792 | ||
1970 | /* module options */ | 1793 | /* module options */ |
1971 | static char *ignore; | ||
1972 | module_param(ignore, charp, 0400); | ||
1973 | |||
1974 | static unsigned long debug_mask; | 1794 | static unsigned long debug_mask; |
1975 | module_param(debug_mask, ulong, 0644); | 1795 | module_param(debug_mask, ulong, 0644); |
1976 | 1796 | ||
@@ -1991,15 +1811,6 @@ static int ide_cd_probe(ide_drive_t *drive) | |||
1991 | if (drive->media != ide_cdrom && drive->media != ide_optical) | 1811 | if (drive->media != ide_cdrom && drive->media != ide_optical) |
1992 | goto failed; | 1812 | goto failed; |
1993 | 1813 | ||
1994 | /* skip drives that we were told to ignore */ | ||
1995 | if (ignore != NULL) { | ||
1996 | if (strstr(ignore, drive->name)) { | ||
1997 | printk(KERN_INFO PFX "ignoring drive %s\n", | ||
1998 | drive->name); | ||
1999 | goto failed; | ||
2000 | } | ||
2001 | } | ||
2002 | |||
2003 | drive->debug_mask = debug_mask; | 1814 | drive->debug_mask = debug_mask; |
2004 | drive->irq_handler = cdrom_newpc_intr; | 1815 | drive->irq_handler = cdrom_newpc_intr; |
2005 | 1816 | ||
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index ca934c8a1289..c998cf8e971a 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -227,7 +227,7 @@ static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48) | |||
227 | ide_no_data_taskfile(drive, &cmd); | 227 | ide_no_data_taskfile(drive, &cmd); |
228 | 228 | ||
229 | /* if OK, compute maximum address value */ | 229 | /* if OK, compute maximum address value */ |
230 | if ((tf->status & 0x01) == 0) | 230 | if (!(tf->status & ATA_ERR)) |
231 | addr = ide_get_lba_addr(tf, lba48) + 1; | 231 | addr = ide_get_lba_addr(tf, lba48) + 1; |
232 | 232 | ||
233 | return addr; | 233 | return addr; |
@@ -267,7 +267,7 @@ static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48) | |||
267 | ide_no_data_taskfile(drive, &cmd); | 267 | ide_no_data_taskfile(drive, &cmd); |
268 | 268 | ||
269 | /* if OK, compute maximum address value */ | 269 | /* if OK, compute maximum address value */ |
270 | if ((tf->status & 0x01) == 0) | 270 | if (!(tf->status & ATA_ERR)) |
271 | addr_set = ide_get_lba_addr(tf, lba48) + 1; | 271 | addr_set = ide_get_lba_addr(tf, lba48) + 1; |
272 | 272 | ||
273 | return addr_set; | 273 | return addr_set; |
diff --git a/drivers/ide/ide-dma-sff.c b/drivers/ide/ide-dma-sff.c index 75a9ea2e4c82..16fc46edc32d 100644 --- a/drivers/ide/ide-dma-sff.c +++ b/drivers/ide/ide-dma-sff.c | |||
@@ -38,10 +38,9 @@ int config_drive_for_dma(ide_drive_t *drive) | |||
38 | * Enable DMA on any drive that has mode2 DMA | 38 | * Enable DMA on any drive that has mode2 DMA |
39 | * (multi or single) enabled | 39 | * (multi or single) enabled |
40 | */ | 40 | */ |
41 | if (id[ATA_ID_FIELD_VALID] & 2) /* regular DMA */ | 41 | if ((id[ATA_ID_MWDMA_MODES] & 0x404) == 0x404 || |
42 | if ((id[ATA_ID_MWDMA_MODES] & 0x404) == 0x404 || | 42 | (id[ATA_ID_SWDMA_MODES] & 0x404) == 0x404) |
43 | (id[ATA_ID_SWDMA_MODES] & 0x404) == 0x404) | 43 | return 1; |
44 | return 1; | ||
45 | 44 | ||
46 | /* Consult the list of known "good" drives */ | 45 | /* Consult the list of known "good" drives */ |
47 | if (ide_dma_good_drive(drive)) | 46 | if (ide_dma_good_drive(drive)) |
@@ -166,8 +165,6 @@ use_pio_instead: | |||
166 | printk(KERN_ERR "%s: %s\n", drive->name, | 165 | printk(KERN_ERR "%s: %s\n", drive->name, |
167 | count ? "DMA table too small" : "empty DMA table?"); | 166 | count ? "DMA table too small" : "empty DMA table?"); |
168 | 167 | ||
169 | ide_destroy_dmatable(drive); | ||
170 | |||
171 | return 0; /* revert to PIO for this request */ | 168 | return 0; /* revert to PIO for this request */ |
172 | } | 169 | } |
173 | EXPORT_SYMBOL_GPL(ide_build_dmatable); | 170 | EXPORT_SYMBOL_GPL(ide_build_dmatable); |
@@ -218,7 +215,6 @@ int ide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | |||
218 | /* clear INTR & ERROR flags */ | 215 | /* clear INTR & ERROR flags */ |
219 | ide_dma_sff_write_status(hwif, dma_stat | ATA_DMA_ERR | ATA_DMA_INTR); | 216 | ide_dma_sff_write_status(hwif, dma_stat | ATA_DMA_ERR | ATA_DMA_INTR); |
220 | 217 | ||
221 | drive->waiting_for_dma = 1; | ||
222 | return 0; | 218 | return 0; |
223 | } | 219 | } |
224 | EXPORT_SYMBOL_GPL(ide_dma_setup); | 220 | EXPORT_SYMBOL_GPL(ide_dma_setup); |
@@ -292,8 +288,6 @@ int ide_dma_end(ide_drive_t *drive) | |||
292 | ide_hwif_t *hwif = drive->hwif; | 288 | ide_hwif_t *hwif = drive->hwif; |
293 | u8 dma_stat = 0, dma_cmd = 0, mask; | 289 | u8 dma_stat = 0, dma_cmd = 0, mask; |
294 | 290 | ||
295 | drive->waiting_for_dma = 0; | ||
296 | |||
297 | /* stop DMA */ | 291 | /* stop DMA */ |
298 | if (hwif->host_flags & IDE_HFLAG_MMIO) { | 292 | if (hwif->host_flags & IDE_HFLAG_MMIO) { |
299 | dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD)); | 293 | dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD)); |
@@ -310,8 +304,6 @@ int ide_dma_end(ide_drive_t *drive) | |||
310 | /* clear INTR & ERROR bits */ | 304 | /* clear INTR & ERROR bits */ |
311 | ide_dma_sff_write_status(hwif, dma_stat | ATA_DMA_ERR | ATA_DMA_INTR); | 305 | ide_dma_sff_write_status(hwif, dma_stat | ATA_DMA_ERR | ATA_DMA_INTR); |
312 | 306 | ||
313 | /* purge DMA mappings */ | ||
314 | ide_destroy_dmatable(drive); | ||
315 | wmb(); | 307 | wmb(); |
316 | 308 | ||
317 | /* verify good DMA status */ | 309 | /* verify good DMA status */ |
@@ -338,9 +330,8 @@ const struct ide_dma_ops sff_dma_ops = { | |||
338 | .dma_start = ide_dma_start, | 330 | .dma_start = ide_dma_start, |
339 | .dma_end = ide_dma_end, | 331 | .dma_end = ide_dma_end, |
340 | .dma_test_irq = ide_dma_test_irq, | 332 | .dma_test_irq = ide_dma_test_irq, |
341 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | ||
342 | .dma_timeout = ide_dma_timeout, | ||
343 | .dma_lost_irq = ide_dma_lost_irq, | 333 | .dma_lost_irq = ide_dma_lost_irq, |
334 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | ||
344 | .dma_sff_read_status = ide_dma_sff_read_status, | 335 | .dma_sff_read_status = ide_dma_sff_read_status, |
345 | }; | 336 | }; |
346 | EXPORT_SYMBOL_GPL(sff_dma_ops); | 337 | EXPORT_SYMBOL_GPL(sff_dma_ops); |
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 3dbf80c15491..a0b8cab1d9a6 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c | |||
@@ -89,15 +89,16 @@ static const struct drive_list_entry drive_blacklist[] = { | |||
89 | ide_startstop_t ide_dma_intr(ide_drive_t *drive) | 89 | ide_startstop_t ide_dma_intr(ide_drive_t *drive) |
90 | { | 90 | { |
91 | ide_hwif_t *hwif = drive->hwif; | 91 | ide_hwif_t *hwif = drive->hwif; |
92 | struct ide_cmd *cmd = &hwif->cmd; | ||
92 | u8 stat = 0, dma_stat = 0; | 93 | u8 stat = 0, dma_stat = 0; |
93 | 94 | ||
95 | drive->waiting_for_dma = 0; | ||
94 | dma_stat = hwif->dma_ops->dma_end(drive); | 96 | dma_stat = hwif->dma_ops->dma_end(drive); |
97 | ide_dma_unmap_sg(drive, cmd); | ||
95 | stat = hwif->tp_ops->read_status(hwif); | 98 | stat = hwif->tp_ops->read_status(hwif); |
96 | 99 | ||
97 | if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | ATA_DRQ)) { | 100 | if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | ATA_DRQ)) { |
98 | if (!dma_stat) { | 101 | if (!dma_stat) { |
99 | struct ide_cmd *cmd = &hwif->cmd; | ||
100 | |||
101 | if ((cmd->tf_flags & IDE_TFLAG_FS) == 0) | 102 | if ((cmd->tf_flags & IDE_TFLAG_FS) == 0) |
102 | ide_finish_cmd(drive, cmd, stat); | 103 | ide_finish_cmd(drive, cmd, stat); |
103 | else | 104 | else |
@@ -117,8 +118,8 @@ int ide_dma_good_drive(ide_drive_t *drive) | |||
117 | } | 118 | } |
118 | 119 | ||
119 | /** | 120 | /** |
120 | * ide_build_sglist - map IDE scatter gather for DMA I/O | 121 | * ide_dma_map_sg - map IDE scatter gather for DMA I/O |
121 | * @drive: the drive to build the DMA table for | 122 | * @drive: the drive to map the DMA table for |
122 | * @cmd: command | 123 | * @cmd: command |
123 | * | 124 | * |
124 | * Perform the DMA mapping magic necessary to access the source or | 125 | * Perform the DMA mapping magic necessary to access the source or |
@@ -127,23 +128,19 @@ int ide_dma_good_drive(ide_drive_t *drive) | |||
127 | * operate in a portable fashion. | 128 | * operate in a portable fashion. |
128 | */ | 129 | */ |
129 | 130 | ||
130 | int ide_build_sglist(ide_drive_t *drive, struct ide_cmd *cmd) | 131 | static int ide_dma_map_sg(ide_drive_t *drive, struct ide_cmd *cmd) |
131 | { | 132 | { |
132 | ide_hwif_t *hwif = drive->hwif; | 133 | ide_hwif_t *hwif = drive->hwif; |
133 | struct scatterlist *sg = hwif->sg_table; | 134 | struct scatterlist *sg = hwif->sg_table; |
134 | int i; | 135 | int i; |
135 | 136 | ||
136 | ide_map_sg(drive, cmd); | ||
137 | |||
138 | if (cmd->tf_flags & IDE_TFLAG_WRITE) | 137 | if (cmd->tf_flags & IDE_TFLAG_WRITE) |
139 | cmd->sg_dma_direction = DMA_TO_DEVICE; | 138 | cmd->sg_dma_direction = DMA_TO_DEVICE; |
140 | else | 139 | else |
141 | cmd->sg_dma_direction = DMA_FROM_DEVICE; | 140 | cmd->sg_dma_direction = DMA_FROM_DEVICE; |
142 | 141 | ||
143 | i = dma_map_sg(hwif->dev, sg, cmd->sg_nents, cmd->sg_dma_direction); | 142 | i = dma_map_sg(hwif->dev, sg, cmd->sg_nents, cmd->sg_dma_direction); |
144 | if (i == 0) | 143 | if (i) { |
145 | ide_map_sg(drive, cmd); | ||
146 | else { | ||
147 | cmd->orig_sg_nents = cmd->sg_nents; | 144 | cmd->orig_sg_nents = cmd->sg_nents; |
148 | cmd->sg_nents = i; | 145 | cmd->sg_nents = i; |
149 | } | 146 | } |
@@ -152,7 +149,7 @@ int ide_build_sglist(ide_drive_t *drive, struct ide_cmd *cmd) | |||
152 | } | 149 | } |
153 | 150 | ||
154 | /** | 151 | /** |
155 | * ide_destroy_dmatable - clean up DMA mapping | 152 | * ide_dma_unmap_sg - clean up DMA mapping |
156 | * @drive: The drive to unmap | 153 | * @drive: The drive to unmap |
157 | * | 154 | * |
158 | * Teardown mappings after DMA has completed. This must be called | 155 | * Teardown mappings after DMA has completed. This must be called |
@@ -162,15 +159,14 @@ int ide_build_sglist(ide_drive_t *drive, struct ide_cmd *cmd) | |||
162 | * time. | 159 | * time. |
163 | */ | 160 | */ |
164 | 161 | ||
165 | void ide_destroy_dmatable(ide_drive_t *drive) | 162 | void ide_dma_unmap_sg(ide_drive_t *drive, struct ide_cmd *cmd) |
166 | { | 163 | { |
167 | ide_hwif_t *hwif = drive->hwif; | 164 | ide_hwif_t *hwif = drive->hwif; |
168 | struct ide_cmd *cmd = &hwif->cmd; | ||
169 | 165 | ||
170 | dma_unmap_sg(hwif->dev, hwif->sg_table, cmd->orig_sg_nents, | 166 | dma_unmap_sg(hwif->dev, hwif->sg_table, cmd->orig_sg_nents, |
171 | cmd->sg_dma_direction); | 167 | cmd->sg_dma_direction); |
172 | } | 168 | } |
173 | EXPORT_SYMBOL_GPL(ide_destroy_dmatable); | 169 | EXPORT_SYMBOL_GPL(ide_dma_unmap_sg); |
174 | 170 | ||
175 | /** | 171 | /** |
176 | * ide_dma_off_quietly - Generic DMA kill | 172 | * ide_dma_off_quietly - Generic DMA kill |
@@ -249,12 +245,11 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode) | |||
249 | case XFER_UDMA_0: | 245 | case XFER_UDMA_0: |
250 | if ((id[ATA_ID_FIELD_VALID] & 4) == 0) | 246 | if ((id[ATA_ID_FIELD_VALID] & 4) == 0) |
251 | break; | 247 | break; |
252 | 248 | mask = id[ATA_ID_UDMA_MODES]; | |
253 | if (port_ops && port_ops->udma_filter) | 249 | if (port_ops && port_ops->udma_filter) |
254 | mask = port_ops->udma_filter(drive); | 250 | mask &= port_ops->udma_filter(drive); |
255 | else | 251 | else |
256 | mask = hwif->ultra_mask; | 252 | mask &= hwif->ultra_mask; |
257 | mask &= id[ATA_ID_UDMA_MODES]; | ||
258 | 253 | ||
259 | /* | 254 | /* |
260 | * avoid false cable warning from eighty_ninty_three() | 255 | * avoid false cable warning from eighty_ninty_three() |
@@ -265,18 +260,23 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode) | |||
265 | } | 260 | } |
266 | break; | 261 | break; |
267 | case XFER_MW_DMA_0: | 262 | case XFER_MW_DMA_0: |
268 | if ((id[ATA_ID_FIELD_VALID] & 2) == 0) | 263 | mask = id[ATA_ID_MWDMA_MODES]; |
269 | break; | 264 | |
265 | /* Also look for the CF specific MWDMA modes... */ | ||
266 | if (ata_id_is_cfa(id) && (id[ATA_ID_CFA_MODES] & 0x38)) { | ||
267 | u8 mode = ((id[ATA_ID_CFA_MODES] & 0x38) >> 3) - 1; | ||
268 | |||
269 | mask |= ((2 << mode) - 1) << 3; | ||
270 | } | ||
271 | |||
270 | if (port_ops && port_ops->mdma_filter) | 272 | if (port_ops && port_ops->mdma_filter) |
271 | mask = port_ops->mdma_filter(drive); | 273 | mask &= port_ops->mdma_filter(drive); |
272 | else | 274 | else |
273 | mask = hwif->mwdma_mask; | 275 | mask &= hwif->mwdma_mask; |
274 | mask &= id[ATA_ID_MWDMA_MODES]; | ||
275 | break; | 276 | break; |
276 | case XFER_SW_DMA_0: | 277 | case XFER_SW_DMA_0: |
277 | if (id[ATA_ID_FIELD_VALID] & 2) { | 278 | mask = id[ATA_ID_SWDMA_MODES]; |
278 | mask = id[ATA_ID_SWDMA_MODES] & hwif->swdma_mask; | 279 | if (!(mask & ATA_SWDMA2) && (id[ATA_ID_OLD_DMA_MODES] >> 8)) { |
279 | } else if (id[ATA_ID_OLD_DMA_MODES] >> 8) { | ||
280 | u8 mode = id[ATA_ID_OLD_DMA_MODES] >> 8; | 280 | u8 mode = id[ATA_ID_OLD_DMA_MODES] >> 8; |
281 | 281 | ||
282 | /* | 282 | /* |
@@ -284,8 +284,9 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base, u8 req_mode) | |||
284 | * (the maximum allowed mode is XFER_SW_DMA_2) | 284 | * (the maximum allowed mode is XFER_SW_DMA_2) |
285 | */ | 285 | */ |
286 | if (mode <= 2) | 286 | if (mode <= 2) |
287 | mask = ((2 << mode) - 1) & hwif->swdma_mask; | 287 | mask = (2 << mode) - 1; |
288 | } | 288 | } |
289 | mask &= hwif->swdma_mask; | ||
289 | break; | 290 | break; |
290 | default: | 291 | default: |
291 | BUG(); | 292 | BUG(); |
@@ -402,11 +403,10 @@ int ide_id_dma_bug(ide_drive_t *drive) | |||
402 | if ((id[ATA_ID_UDMA_MODES] >> 8) && | 403 | if ((id[ATA_ID_UDMA_MODES] >> 8) && |
403 | (id[ATA_ID_MWDMA_MODES] >> 8)) | 404 | (id[ATA_ID_MWDMA_MODES] >> 8)) |
404 | goto err_out; | 405 | goto err_out; |
405 | } else if (id[ATA_ID_FIELD_VALID] & 2) { | 406 | } else if ((id[ATA_ID_MWDMA_MODES] >> 8) && |
406 | if ((id[ATA_ID_MWDMA_MODES] >> 8) && | 407 | (id[ATA_ID_SWDMA_MODES] >> 8)) |
407 | (id[ATA_ID_SWDMA_MODES] >> 8)) | 408 | goto err_out; |
408 | goto err_out; | 409 | |
409 | } | ||
410 | return 0; | 410 | return 0; |
411 | err_out: | 411 | err_out: |
412 | printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name); | 412 | printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name); |
@@ -460,21 +460,6 @@ void ide_dma_lost_irq(ide_drive_t *drive) | |||
460 | } | 460 | } |
461 | EXPORT_SYMBOL_GPL(ide_dma_lost_irq); | 461 | EXPORT_SYMBOL_GPL(ide_dma_lost_irq); |
462 | 462 | ||
463 | void ide_dma_timeout(ide_drive_t *drive) | ||
464 | { | ||
465 | ide_hwif_t *hwif = drive->hwif; | ||
466 | |||
467 | printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name); | ||
468 | |||
469 | if (hwif->dma_ops->dma_test_irq(drive)) | ||
470 | return; | ||
471 | |||
472 | ide_dump_status(drive, "DMA timeout", hwif->tp_ops->read_status(hwif)); | ||
473 | |||
474 | hwif->dma_ops->dma_end(drive); | ||
475 | } | ||
476 | EXPORT_SYMBOL_GPL(ide_dma_timeout); | ||
477 | |||
478 | /* | 463 | /* |
479 | * un-busy the port etc, and clear any pending DMA status. we want to | 464 | * un-busy the port etc, and clear any pending DMA status. we want to |
480 | * retry the current request in pio mode instead of risking tossing it | 465 | * retry the current request in pio mode instead of risking tossing it |
@@ -483,6 +468,8 @@ EXPORT_SYMBOL_GPL(ide_dma_timeout); | |||
483 | ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) | 468 | ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) |
484 | { | 469 | { |
485 | ide_hwif_t *hwif = drive->hwif; | 470 | ide_hwif_t *hwif = drive->hwif; |
471 | const struct ide_dma_ops *dma_ops = hwif->dma_ops; | ||
472 | struct ide_cmd *cmd = &hwif->cmd; | ||
486 | struct request *rq; | 473 | struct request *rq; |
487 | ide_startstop_t ret = ide_stopped; | 474 | ide_startstop_t ret = ide_stopped; |
488 | 475 | ||
@@ -492,12 +479,23 @@ ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) | |||
492 | 479 | ||
493 | if (error < 0) { | 480 | if (error < 0) { |
494 | printk(KERN_WARNING "%s: DMA timeout error\n", drive->name); | 481 | printk(KERN_WARNING "%s: DMA timeout error\n", drive->name); |
495 | (void)hwif->dma_ops->dma_end(drive); | 482 | drive->waiting_for_dma = 0; |
483 | (void)dma_ops->dma_end(drive); | ||
484 | ide_dma_unmap_sg(drive, cmd); | ||
496 | ret = ide_error(drive, "dma timeout error", | 485 | ret = ide_error(drive, "dma timeout error", |
497 | hwif->tp_ops->read_status(hwif)); | 486 | hwif->tp_ops->read_status(hwif)); |
498 | } else { | 487 | } else { |
499 | printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name); | 488 | printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name); |
500 | hwif->dma_ops->dma_timeout(drive); | 489 | if (dma_ops->dma_clear) |
490 | dma_ops->dma_clear(drive); | ||
491 | printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name); | ||
492 | if (dma_ops->dma_test_irq(drive) == 0) { | ||
493 | ide_dump_status(drive, "DMA timeout", | ||
494 | hwif->tp_ops->read_status(hwif)); | ||
495 | drive->waiting_for_dma = 0; | ||
496 | (void)dma_ops->dma_end(drive); | ||
497 | ide_dma_unmap_sg(drive, cmd); | ||
498 | } | ||
501 | } | 499 | } |
502 | 500 | ||
503 | /* | 501 | /* |
@@ -567,3 +565,25 @@ int ide_allocate_dma_engine(ide_hwif_t *hwif) | |||
567 | return 0; | 565 | return 0; |
568 | } | 566 | } |
569 | EXPORT_SYMBOL_GPL(ide_allocate_dma_engine); | 567 | EXPORT_SYMBOL_GPL(ide_allocate_dma_engine); |
568 | |||
569 | int ide_dma_prepare(ide_drive_t *drive, struct ide_cmd *cmd) | ||
570 | { | ||
571 | const struct ide_dma_ops *dma_ops = drive->hwif->dma_ops; | ||
572 | |||
573 | if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0 || | ||
574 | (dma_ops->dma_check && dma_ops->dma_check(drive, cmd))) | ||
575 | goto out; | ||
576 | ide_map_sg(drive, cmd); | ||
577 | if (ide_dma_map_sg(drive, cmd) == 0) | ||
578 | goto out_map; | ||
579 | if (dma_ops->dma_setup(drive, cmd)) | ||
580 | goto out_dma_unmap; | ||
581 | drive->waiting_for_dma = 1; | ||
582 | return 0; | ||
583 | out_dma_unmap: | ||
584 | ide_dma_unmap_sg(drive, cmd); | ||
585 | out_map: | ||
586 | ide_map_sg(drive, cmd); | ||
587 | out: | ||
588 | return 1; | ||
589 | } | ||
diff --git a/drivers/ide/ide-eh.c b/drivers/ide/ide-eh.c index 11664976eea3..5d5fb961b5ce 100644 --- a/drivers/ide/ide-eh.c +++ b/drivers/ide/ide-eh.c | |||
@@ -165,11 +165,12 @@ static ide_startstop_t do_reset1(ide_drive_t *, int); | |||
165 | static ide_startstop_t atapi_reset_pollfunc(ide_drive_t *drive) | 165 | static ide_startstop_t atapi_reset_pollfunc(ide_drive_t *drive) |
166 | { | 166 | { |
167 | ide_hwif_t *hwif = drive->hwif; | 167 | ide_hwif_t *hwif = drive->hwif; |
168 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | ||
168 | u8 stat; | 169 | u8 stat; |
169 | 170 | ||
170 | SELECT_DRIVE(drive); | 171 | tp_ops->dev_select(drive); |
171 | udelay(10); | 172 | udelay(10); |
172 | stat = hwif->tp_ops->read_status(hwif); | 173 | stat = tp_ops->read_status(hwif); |
173 | 174 | ||
174 | if (OK_STAT(stat, 0, ATA_BUSY)) | 175 | if (OK_STAT(stat, 0, ATA_BUSY)) |
175 | printk(KERN_INFO "%s: ATAPI reset complete\n", drive->name); | 176 | printk(KERN_INFO "%s: ATAPI reset complete\n", drive->name); |
@@ -348,7 +349,7 @@ static ide_startstop_t do_reset1(ide_drive_t *drive, int do_not_try_atapi) | |||
348 | /* For an ATAPI device, first try an ATAPI SRST. */ | 349 | /* For an ATAPI device, first try an ATAPI SRST. */ |
349 | if (drive->media != ide_disk && !do_not_try_atapi) { | 350 | if (drive->media != ide_disk && !do_not_try_atapi) { |
350 | pre_reset(drive); | 351 | pre_reset(drive); |
351 | SELECT_DRIVE(drive); | 352 | tp_ops->dev_select(drive); |
352 | udelay(20); | 353 | udelay(20); |
353 | tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); | 354 | tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); |
354 | ndelay(400); | 355 | ndelay(400); |
@@ -401,15 +402,14 @@ static ide_startstop_t do_reset1(ide_drive_t *drive, int do_not_try_atapi) | |||
401 | * immediate interrupt due to the edge transition it produces. | 402 | * immediate interrupt due to the edge transition it produces. |
402 | * This single interrupt gives us a "fast poll" for drives that | 403 | * This single interrupt gives us a "fast poll" for drives that |
403 | * recover from reset very quickly, saving us the first 50ms wait time. | 404 | * recover from reset very quickly, saving us the first 50ms wait time. |
404 | * | ||
405 | * TODO: add ->softreset method and stop abusing ->set_irq | ||
406 | */ | 405 | */ |
407 | /* set SRST and nIEN */ | 406 | /* set SRST and nIEN */ |
408 | tp_ops->set_irq(hwif, 4); | 407 | tp_ops->write_devctl(hwif, ATA_SRST | ATA_NIEN | ATA_DEVCTL_OBS); |
409 | /* more than enough time */ | 408 | /* more than enough time */ |
410 | udelay(10); | 409 | udelay(10); |
411 | /* clear SRST, leave nIEN (unless device is on the quirk list) */ | 410 | /* clear SRST, leave nIEN (unless device is on the quirk list) */ |
412 | tp_ops->set_irq(hwif, drive->quirk_list == 2); | 411 | tp_ops->write_devctl(hwif, (drive->quirk_list == 2 ? 0 : ATA_NIEN) | |
412 | ATA_DEVCTL_OBS); | ||
413 | /* more than enough time */ | 413 | /* more than enough time */ |
414 | udelay(10); | 414 | udelay(10); |
415 | hwif->poll_timeout = jiffies + WAIT_WORSTCASE; | 415 | hwif->poll_timeout = jiffies + WAIT_WORSTCASE; |
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 7ae662334835..2b4868d95f8b 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -61,16 +61,6 @@ | |||
61 | */ | 61 | */ |
62 | #define IDEFLOPPY_PC_DELAY (HZ/20) /* default delay for ZIP 100 (50ms) */ | 62 | #define IDEFLOPPY_PC_DELAY (HZ/20) /* default delay for ZIP 100 (50ms) */ |
63 | 63 | ||
64 | static void idefloppy_update_buffers(ide_drive_t *drive, | ||
65 | struct ide_atapi_pc *pc) | ||
66 | { | ||
67 | struct request *rq = pc->rq; | ||
68 | struct bio *bio = rq->bio; | ||
69 | |||
70 | while ((bio = rq->bio) != NULL) | ||
71 | ide_complete_rq(drive, 0, ide_rq_bytes(rq)); | ||
72 | } | ||
73 | |||
74 | static int ide_floppy_callback(ide_drive_t *drive, int dsc) | 64 | static int ide_floppy_callback(ide_drive_t *drive, int dsc) |
75 | { | 65 | { |
76 | struct ide_disk_obj *floppy = drive->driver_data; | 66 | struct ide_disk_obj *floppy = drive->driver_data; |
@@ -213,7 +203,6 @@ static void idefloppy_create_rw_cmd(ide_drive_t *drive, | |||
213 | memcpy(rq->cmd, pc->c, 12); | 203 | memcpy(rq->cmd, pc->c, 12); |
214 | 204 | ||
215 | pc->rq = rq; | 205 | pc->rq = rq; |
216 | pc->b_count = 0; | ||
217 | if (rq->cmd_flags & REQ_RW) | 206 | if (rq->cmd_flags & REQ_RW) |
218 | pc->flags |= PC_FLAG_WRITING; | 207 | pc->flags |= PC_FLAG_WRITING; |
219 | pc->buf = NULL; | 208 | pc->buf = NULL; |
@@ -227,7 +216,6 @@ static void idefloppy_blockpc_cmd(struct ide_disk_obj *floppy, | |||
227 | ide_init_pc(pc); | 216 | ide_init_pc(pc); |
228 | memcpy(pc->c, rq->cmd, sizeof(pc->c)); | 217 | memcpy(pc->c, rq->cmd, sizeof(pc->c)); |
229 | pc->rq = rq; | 218 | pc->rq = rq; |
230 | pc->b_count = 0; | ||
231 | if (rq->data_len && rq_data_dir(rq) == WRITE) | 219 | if (rq->data_len && rq_data_dir(rq) == WRITE) |
232 | pc->flags |= PC_FLAG_WRITING; | 220 | pc->flags |= PC_FLAG_WRITING; |
233 | pc->buf = rq->data; | 221 | pc->buf = rq->data; |
@@ -244,10 +232,11 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, | |||
244 | struct request *rq, sector_t block) | 232 | struct request *rq, sector_t block) |
245 | { | 233 | { |
246 | struct ide_disk_obj *floppy = drive->driver_data; | 234 | struct ide_disk_obj *floppy = drive->driver_data; |
247 | ide_hwif_t *hwif = drive->hwif; | ||
248 | struct ide_cmd cmd; | 235 | struct ide_cmd cmd; |
249 | struct ide_atapi_pc *pc; | 236 | struct ide_atapi_pc *pc; |
250 | 237 | ||
238 | ide_debug_log(IDE_DBG_FUNC, "enter, cmd: 0x%x\n", rq->cmd[0]); | ||
239 | |||
251 | if (drive->debug_mask & IDE_DBG_RQ) | 240 | if (drive->debug_mask & IDE_DBG_RQ) |
252 | blk_dump_rq_flags(rq, (rq->rq_disk | 241 | blk_dump_rq_flags(rq, (rq->rq_disk |
253 | ? rq->rq_disk->disk_name | 242 | ? rq->rq_disk->disk_name |
@@ -294,13 +283,10 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, | |||
294 | cmd.rq = rq; | 283 | cmd.rq = rq; |
295 | 284 | ||
296 | if (blk_fs_request(rq) || pc->req_xfer) { | 285 | if (blk_fs_request(rq) || pc->req_xfer) { |
297 | ide_init_sg_cmd(&cmd, rq->nr_sectors << 9); | 286 | ide_init_sg_cmd(&cmd, pc->req_xfer); |
298 | ide_map_sg(drive, &cmd); | 287 | ide_map_sg(drive, &cmd); |
299 | } | 288 | } |
300 | 289 | ||
301 | pc->sg = hwif->sg_table; | ||
302 | pc->sg_cnt = cmd.sg_nents; | ||
303 | |||
304 | pc->rq = rq; | 290 | pc->rq = rq; |
305 | 291 | ||
306 | return ide_floppy_issue_pc(drive, &cmd, pc); | 292 | return ide_floppy_issue_pc(drive, &cmd, pc); |
@@ -385,9 +371,11 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) | |||
385 | struct gendisk *disk = floppy->disk; | 371 | struct gendisk *disk = floppy->disk; |
386 | struct ide_atapi_pc pc; | 372 | struct ide_atapi_pc pc; |
387 | u8 *cap_desc; | 373 | u8 *cap_desc; |
388 | u8 header_len, desc_cnt; | 374 | u8 pc_buf[256], header_len, desc_cnt; |
389 | int i, rc = 1, blocks, length; | 375 | int i, rc = 1, blocks, length; |
390 | 376 | ||
377 | ide_debug_log(IDE_DBG_FUNC, "enter"); | ||
378 | |||
391 | drive->bios_cyl = 0; | 379 | drive->bios_cyl = 0; |
392 | drive->bios_head = drive->bios_sect = 0; | 380 | drive->bios_head = drive->bios_sect = 0; |
393 | floppy->blocks = 0; | 381 | floppy->blocks = 0; |
@@ -395,6 +383,9 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) | |||
395 | drive->capacity64 = 0; | 383 | drive->capacity64 = 0; |
396 | 384 | ||
397 | ide_floppy_create_read_capacity_cmd(&pc); | 385 | ide_floppy_create_read_capacity_cmd(&pc); |
386 | pc.buf = &pc_buf[0]; | ||
387 | pc.buf_size = sizeof(pc_buf); | ||
388 | |||
398 | if (ide_queue_pc_tail(drive, disk, &pc)) { | 389 | if (ide_queue_pc_tail(drive, disk, &pc)) { |
399 | printk(KERN_ERR PFX "Can't get floppy parameters\n"); | 390 | printk(KERN_ERR PFX "Can't get floppy parameters\n"); |
400 | return 1; | 391 | return 1; |
@@ -485,8 +476,6 @@ static void ide_floppy_setup(ide_drive_t *drive) | |||
485 | u16 *id = drive->id; | 476 | u16 *id = drive->id; |
486 | 477 | ||
487 | drive->pc_callback = ide_floppy_callback; | 478 | drive->pc_callback = ide_floppy_callback; |
488 | drive->pc_update_buffers = idefloppy_update_buffers; | ||
489 | drive->pc_io_buffers = ide_io_buffers; | ||
490 | 479 | ||
491 | /* | 480 | /* |
492 | * We used to check revisions here. At this point however I'm giving up. | 481 | * We used to check revisions here. At this point however I'm giving up. |
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c index 8f8be8546038..cd8a42027ede 100644 --- a/drivers/ide/ide-floppy_ioctl.c +++ b/drivers/ide/ide-floppy_ioctl.c | |||
@@ -36,9 +36,9 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, | |||
36 | int __user *arg) | 36 | int __user *arg) |
37 | { | 37 | { |
38 | struct ide_disk_obj *floppy = drive->driver_data; | 38 | struct ide_disk_obj *floppy = drive->driver_data; |
39 | u8 header_len, desc_cnt; | ||
40 | int i, blocks, length, u_array_size, u_index; | 39 | int i, blocks, length, u_array_size, u_index; |
41 | int __user *argp; | 40 | int __user *argp; |
41 | u8 pc_buf[256], header_len, desc_cnt; | ||
42 | 42 | ||
43 | if (get_user(u_array_size, arg)) | 43 | if (get_user(u_array_size, arg)) |
44 | return -EFAULT; | 44 | return -EFAULT; |
@@ -47,6 +47,9 @@ static int ide_floppy_get_format_capacities(ide_drive_t *drive, | |||
47 | return -EINVAL; | 47 | return -EINVAL; |
48 | 48 | ||
49 | ide_floppy_create_read_capacity_cmd(pc); | 49 | ide_floppy_create_read_capacity_cmd(pc); |
50 | pc->buf = &pc_buf[0]; | ||
51 | pc->buf_size = sizeof(pc_buf); | ||
52 | |||
50 | if (ide_queue_pc_tail(drive, floppy->disk, pc)) { | 53 | if (ide_queue_pc_tail(drive, floppy->disk, pc)) { |
51 | printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); | 54 | printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n"); |
52 | return -EIO; | 55 | return -EIO; |
diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c index 9d03e8211536..7812ca0be13b 100644 --- a/drivers/ide/ide-generic.c +++ b/drivers/ide/ide-generic.c | |||
@@ -1,27 +1,22 @@ | |||
1 | /* | 1 | /* |
2 | * generic/default IDE host driver | 2 | * generic/default IDE host driver |
3 | * | 3 | * |
4 | * Copyright (C) 2004, 2008 Bartlomiej Zolnierkiewicz | 4 | * Copyright (C) 2004, 2008-2009 Bartlomiej Zolnierkiewicz |
5 | * This code was split off from ide.c. See it for original copyrights. | 5 | * This code was split off from ide.c. See it for original copyrights. |
6 | * | 6 | * |
7 | * May be copied or modified under the terms of the GNU General Public License. | 7 | * May be copied or modified under the terms of the GNU General Public License. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | /* | ||
11 | * For special cases new interfaces may be added using sysfs, i.e. | ||
12 | * | ||
13 | * echo -n "0x168:0x36e:10" > /sys/class/ide_generic/add | ||
14 | * | ||
15 | * will add an interface using I/O ports 0x168-0x16f/0x36e and IRQ 10. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
19 | #include <linux/init.h> | 11 | #include <linux/init.h> |
20 | #include <linux/module.h> | 12 | #include <linux/module.h> |
21 | #include <linux/ide.h> | 13 | #include <linux/ide.h> |
22 | #include <linux/pci_ids.h> | 14 | #include <linux/pci_ids.h> |
23 | 15 | ||
24 | /* FIXME: convert m32r to use ide_platform host driver */ | 16 | /* FIXME: convert arm and m32r to use ide_platform host driver */ |
17 | #ifdef CONFIG_ARM | ||
18 | #include <asm/irq.h> | ||
19 | #endif | ||
25 | #ifdef CONFIG_M32R | 20 | #ifdef CONFIG_M32R |
26 | #include <asm/m32r.h> | 21 | #include <asm/m32r.h> |
27 | #endif | 22 | #endif |
@@ -36,62 +31,11 @@ static const struct ide_port_info ide_generic_port_info = { | |||
36 | .host_flags = IDE_HFLAG_NO_DMA, | 31 | .host_flags = IDE_HFLAG_NO_DMA, |
37 | }; | 32 | }; |
38 | 33 | ||
39 | static ssize_t store_add(struct class *cls, const char *buf, size_t n) | 34 | #ifdef CONFIG_ARM |
40 | { | 35 | static const u16 legacy_bases[] = { 0x1f0 }; |
41 | unsigned int base, ctl; | 36 | static const int legacy_irqs[] = { IRQ_HARDDISK }; |
42 | int irq, rc; | 37 | #elif defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) || \ |
43 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | 38 | defined(CONFIG_PLAT_OPSPUT) |
44 | |||
45 | if (sscanf(buf, "%x:%x:%d", &base, &ctl, &irq) != 3) | ||
46 | return -EINVAL; | ||
47 | |||
48 | memset(&hw, 0, sizeof(hw)); | ||
49 | ide_std_init_ports(&hw, base, ctl); | ||
50 | hw.irq = irq; | ||
51 | hw.chipset = ide_generic; | ||
52 | |||
53 | rc = ide_host_add(&ide_generic_port_info, hws, NULL); | ||
54 | if (rc) | ||
55 | return rc; | ||
56 | |||
57 | return n; | ||
58 | }; | ||
59 | |||
60 | static struct class_attribute ide_generic_class_attrs[] = { | ||
61 | __ATTR(add, S_IWUSR, NULL, store_add), | ||
62 | __ATTR_NULL | ||
63 | }; | ||
64 | |||
65 | static void ide_generic_class_release(struct class *cls) | ||
66 | { | ||
67 | kfree(cls); | ||
68 | } | ||
69 | |||
70 | static int __init ide_generic_sysfs_init(void) | ||
71 | { | ||
72 | struct class *cls; | ||
73 | int rc; | ||
74 | |||
75 | cls = kzalloc(sizeof(*cls), GFP_KERNEL); | ||
76 | if (!cls) | ||
77 | return -ENOMEM; | ||
78 | |||
79 | cls->name = DRV_NAME; | ||
80 | cls->owner = THIS_MODULE; | ||
81 | cls->class_release = ide_generic_class_release; | ||
82 | cls->class_attrs = ide_generic_class_attrs; | ||
83 | |||
84 | rc = class_register(cls); | ||
85 | if (rc) { | ||
86 | kfree(cls); | ||
87 | return rc; | ||
88 | } | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | #if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) \ | ||
94 | || defined(CONFIG_PLAT_OPSPUT) | ||
95 | static const u16 legacy_bases[] = { 0x1f0 }; | 39 | static const u16 legacy_bases[] = { 0x1f0 }; |
96 | static const int legacy_irqs[] = { PLD_IRQ_CFIREQ }; | 40 | static const int legacy_irqs[] = { PLD_IRQ_CFIREQ }; |
97 | #elif defined(CONFIG_PLAT_MAPPI3) | 41 | #elif defined(CONFIG_PLAT_MAPPI3) |
@@ -107,11 +51,11 @@ static const int legacy_irqs[] = { 14, 15, 11, 10, 8, 12 }; | |||
107 | 51 | ||
108 | static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary) | 52 | static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary) |
109 | { | 53 | { |
54 | #ifdef CONFIG_PCI | ||
110 | struct pci_dev *p = NULL; | 55 | struct pci_dev *p = NULL; |
111 | u16 val; | 56 | u16 val; |
112 | 57 | ||
113 | for_each_pci_dev(p) { | 58 | for_each_pci_dev(p) { |
114 | |||
115 | if (pci_resource_start(p, 0) == 0x1f0) | 59 | if (pci_resource_start(p, 0) == 0x1f0) |
116 | *primary = 1; | 60 | *primary = 1; |
117 | if (pci_resource_start(p, 2) == 0x170) | 61 | if (pci_resource_start(p, 2) == 0x170) |
@@ -126,7 +70,6 @@ static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary) | |||
126 | /* Intel MPIIX - PIO ATA on non PCI side of bridge */ | 70 | /* Intel MPIIX - PIO ATA on non PCI side of bridge */ |
127 | if (p->vendor == PCI_VENDOR_ID_INTEL && | 71 | if (p->vendor == PCI_VENDOR_ID_INTEL && |
128 | p->device == PCI_DEVICE_ID_INTEL_82371MX) { | 72 | p->device == PCI_DEVICE_ID_INTEL_82371MX) { |
129 | |||
130 | pci_read_config_word(p, 0x6C, &val); | 73 | pci_read_config_word(p, 0x6C, &val); |
131 | if (val & 0x8000) { | 74 | if (val & 0x8000) { |
132 | /* ATA port enabled */ | 75 | /* ATA port enabled */ |
@@ -137,6 +80,7 @@ static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary) | |||
137 | } | 80 | } |
138 | } | 81 | } |
139 | } | 82 | } |
83 | #endif | ||
140 | } | 84 | } |
141 | 85 | ||
142 | static int __init ide_generic_init(void) | 86 | static int __init ide_generic_init(void) |
@@ -168,6 +112,7 @@ static int __init ide_generic_init(void) | |||
168 | printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX " | 112 | printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX " |
169 | "not free.\n", | 113 | "not free.\n", |
170 | DRV_NAME, io_addr, io_addr + 7); | 114 | DRV_NAME, io_addr, io_addr + 7); |
115 | rc = -EBUSY; | ||
171 | continue; | 116 | continue; |
172 | } | 117 | } |
173 | 118 | ||
@@ -176,6 +121,7 @@ static int __init ide_generic_init(void) | |||
176 | "not free.\n", | 121 | "not free.\n", |
177 | DRV_NAME, io_addr + 0x206); | 122 | DRV_NAME, io_addr + 0x206); |
178 | release_region(io_addr, 8); | 123 | release_region(io_addr, 8); |
124 | rc = -EBUSY; | ||
179 | continue; | 125 | continue; |
180 | } | 126 | } |
181 | 127 | ||
@@ -196,10 +142,6 @@ static int __init ide_generic_init(void) | |||
196 | } | 142 | } |
197 | } | 143 | } |
198 | 144 | ||
199 | if (ide_generic_sysfs_init()) | ||
200 | printk(KERN_ERR DRV_NAME ": failed to create ide_generic " | ||
201 | "class\n"); | ||
202 | |||
203 | return rc; | 145 | return rc; |
204 | } | 146 | } |
205 | 147 | ||
diff --git a/drivers/ide/ide-h8300.c b/drivers/ide/ide-h8300.c index ff8339ed59ab..dac9a6d44963 100644 --- a/drivers/ide/ide-h8300.c +++ b/drivers/ide/ide-h8300.c | |||
@@ -54,9 +54,6 @@ static void h8300_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | |||
54 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) | 54 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) |
55 | HIHI = 0xFF; | 55 | HIHI = 0xFF; |
56 | 56 | ||
57 | if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) | ||
58 | mm_outw((tf->hob_data << 8) | tf->data, io_ports->data_addr); | ||
59 | |||
60 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | 57 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) |
61 | outb(tf->hob_feature, io_ports->feature_addr); | 58 | outb(tf->hob_feature, io_ports->feature_addr); |
62 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | 59 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) |
@@ -90,18 +87,11 @@ static void h8300_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
90 | struct ide_io_ports *io_ports = &hwif->io_ports; | 87 | struct ide_io_ports *io_ports = &hwif->io_ports; |
91 | struct ide_taskfile *tf = &cmd->tf; | 88 | struct ide_taskfile *tf = &cmd->tf; |
92 | 89 | ||
93 | if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) { | ||
94 | u16 data = mm_inw(io_ports->data_addr); | ||
95 | |||
96 | tf->data = data & 0xff; | ||
97 | tf->hob_data = (data >> 8) & 0xff; | ||
98 | } | ||
99 | |||
100 | /* be sure we're looking at the low order bits */ | 90 | /* be sure we're looking at the low order bits */ |
101 | outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); | 91 | outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); |
102 | 92 | ||
103 | if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE) | 93 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) |
104 | tf->feature = inb(io_ports->feature_addr); | 94 | tf->error = inb(io_ports->feature_addr); |
105 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | 95 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) |
106 | tf->nsect = inb(io_ports->nsect_addr); | 96 | tf->nsect = inb(io_ports->nsect_addr); |
107 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | 97 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) |
@@ -114,18 +104,18 @@ static void h8300_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
114 | tf->device = inb(io_ports->device_addr); | 104 | tf->device = inb(io_ports->device_addr); |
115 | 105 | ||
116 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | 106 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { |
117 | outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); | 107 | outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); |
118 | 108 | ||
119 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | 109 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) |
120 | tf->hob_feature = inb(io_ports->feature_addr); | 110 | tf->hob_error = inb(io_ports->feature_addr); |
121 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | 111 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) |
122 | tf->hob_nsect = inb(io_ports->nsect_addr); | 112 | tf->hob_nsect = inb(io_ports->nsect_addr); |
123 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | 113 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) |
124 | tf->hob_lbal = inb(io_ports->lbal_addr); | 114 | tf->hob_lbal = inb(io_ports->lbal_addr); |
125 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | 115 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) |
126 | tf->hob_lbam = inb(io_ports->lbam_addr); | 116 | tf->hob_lbam = inb(io_ports->lbam_addr); |
127 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | 117 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) |
128 | tf->hob_lbah = inb(io_ports->lbah_addr); | 118 | tf->hob_lbah = inb(io_ports->lbah_addr); |
129 | } | 119 | } |
130 | } | 120 | } |
131 | 121 | ||
@@ -159,9 +149,9 @@ static const struct ide_tp_ops h8300_tp_ops = { | |||
159 | .exec_command = ide_exec_command, | 149 | .exec_command = ide_exec_command, |
160 | .read_status = ide_read_status, | 150 | .read_status = ide_read_status, |
161 | .read_altstatus = ide_read_altstatus, | 151 | .read_altstatus = ide_read_altstatus, |
152 | .write_devctl = ide_write_devctl, | ||
162 | 153 | ||
163 | .set_irq = ide_set_irq, | 154 | .dev_select = ide_dev_select, |
164 | |||
165 | .tf_load = h8300_tf_load, | 155 | .tf_load = h8300_tf_load, |
166 | .tf_read = h8300_tf_read, | 156 | .tf_read = h8300_tf_read, |
167 | 157 | ||
diff --git a/drivers/ide/ide-io-std.c b/drivers/ide/ide-io-std.c index 2d9c6dc3f956..9cac281d82c4 100644 --- a/drivers/ide/ide-io-std.c +++ b/drivers/ide/ide-io-std.c | |||
@@ -64,23 +64,26 @@ u8 ide_read_altstatus(ide_hwif_t *hwif) | |||
64 | } | 64 | } |
65 | EXPORT_SYMBOL_GPL(ide_read_altstatus); | 65 | EXPORT_SYMBOL_GPL(ide_read_altstatus); |
66 | 66 | ||
67 | void ide_set_irq(ide_hwif_t *hwif, int on) | 67 | void ide_write_devctl(ide_hwif_t *hwif, u8 ctl) |
68 | { | 68 | { |
69 | u8 ctl = ATA_DEVCTL_OBS; | ||
70 | |||
71 | if (on == 4) { /* hack for SRST */ | ||
72 | ctl |= 4; | ||
73 | on &= ~4; | ||
74 | } | ||
75 | |||
76 | ctl |= on ? 0 : 2; | ||
77 | |||
78 | if (hwif->host_flags & IDE_HFLAG_MMIO) | 69 | if (hwif->host_flags & IDE_HFLAG_MMIO) |
79 | writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); | 70 | writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); |
80 | else | 71 | else |
81 | outb(ctl, hwif->io_ports.ctl_addr); | 72 | outb(ctl, hwif->io_ports.ctl_addr); |
82 | } | 73 | } |
83 | EXPORT_SYMBOL_GPL(ide_set_irq); | 74 | EXPORT_SYMBOL_GPL(ide_write_devctl); |
75 | |||
76 | void ide_dev_select(ide_drive_t *drive) | ||
77 | { | ||
78 | ide_hwif_t *hwif = drive->hwif; | ||
79 | u8 select = drive->select | ATA_DEVICE_OBS; | ||
80 | |||
81 | if (hwif->host_flags & IDE_HFLAG_MMIO) | ||
82 | writeb(select, (void __iomem *)hwif->io_ports.device_addr); | ||
83 | else | ||
84 | outb(select, hwif->io_ports.device_addr); | ||
85 | } | ||
86 | EXPORT_SYMBOL_GPL(ide_dev_select); | ||
84 | 87 | ||
85 | void ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | 88 | void ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) |
86 | { | 89 | { |
@@ -99,15 +102,6 @@ void ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | |||
99 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) | 102 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) |
100 | HIHI = 0xFF; | 103 | HIHI = 0xFF; |
101 | 104 | ||
102 | if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) { | ||
103 | u16 data = (tf->hob_data << 8) | tf->data; | ||
104 | |||
105 | if (mmio) | ||
106 | writew(data, (void __iomem *)io_ports->data_addr); | ||
107 | else | ||
108 | outw(data, io_ports->data_addr); | ||
109 | } | ||
110 | |||
111 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | 105 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) |
112 | tf_outb(tf->hob_feature, io_ports->feature_addr); | 106 | tf_outb(tf->hob_feature, io_ports->feature_addr); |
113 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | 107 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) |
@@ -153,23 +147,11 @@ void ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
153 | tf_inb = ide_inb; | 147 | tf_inb = ide_inb; |
154 | } | 148 | } |
155 | 149 | ||
156 | if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) { | ||
157 | u16 data; | ||
158 | |||
159 | if (mmio) | ||
160 | data = readw((void __iomem *)io_ports->data_addr); | ||
161 | else | ||
162 | data = inw(io_ports->data_addr); | ||
163 | |||
164 | tf->data = data & 0xff; | ||
165 | tf->hob_data = (data >> 8) & 0xff; | ||
166 | } | ||
167 | |||
168 | /* be sure we're looking at the low order bits */ | 150 | /* be sure we're looking at the low order bits */ |
169 | tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); | 151 | tf_outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); |
170 | 152 | ||
171 | if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE) | 153 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) |
172 | tf->feature = tf_inb(io_ports->feature_addr); | 154 | tf->error = tf_inb(io_ports->feature_addr); |
173 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | 155 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) |
174 | tf->nsect = tf_inb(io_ports->nsect_addr); | 156 | tf->nsect = tf_inb(io_ports->nsect_addr); |
175 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | 157 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) |
@@ -182,18 +164,18 @@ void ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
182 | tf->device = tf_inb(io_ports->device_addr); | 164 | tf->device = tf_inb(io_ports->device_addr); |
183 | 165 | ||
184 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | 166 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { |
185 | tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); | 167 | tf_outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); |
186 | 168 | ||
187 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | 169 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) |
188 | tf->hob_feature = tf_inb(io_ports->feature_addr); | 170 | tf->hob_error = tf_inb(io_ports->feature_addr); |
189 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | 171 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) |
190 | tf->hob_nsect = tf_inb(io_ports->nsect_addr); | 172 | tf->hob_nsect = tf_inb(io_ports->nsect_addr); |
191 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | 173 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) |
192 | tf->hob_lbal = tf_inb(io_ports->lbal_addr); | 174 | tf->hob_lbal = tf_inb(io_ports->lbal_addr); |
193 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | 175 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) |
194 | tf->hob_lbam = tf_inb(io_ports->lbam_addr); | 176 | tf->hob_lbam = tf_inb(io_ports->lbam_addr); |
195 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | 177 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) |
196 | tf->hob_lbah = tf_inb(io_ports->lbah_addr); | 178 | tf->hob_lbah = tf_inb(io_ports->lbah_addr); |
197 | } | 179 | } |
198 | } | 180 | } |
199 | EXPORT_SYMBOL_GPL(ide_tf_read); | 181 | EXPORT_SYMBOL_GPL(ide_tf_read); |
@@ -225,11 +207,10 @@ void ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf, | |||
225 | ide_hwif_t *hwif = drive->hwif; | 207 | ide_hwif_t *hwif = drive->hwif; |
226 | struct ide_io_ports *io_ports = &hwif->io_ports; | 208 | struct ide_io_ports *io_ports = &hwif->io_ports; |
227 | unsigned long data_addr = io_ports->data_addr; | 209 | unsigned long data_addr = io_ports->data_addr; |
210 | unsigned int words = (len + 1) >> 1; | ||
228 | u8 io_32bit = drive->io_32bit; | 211 | u8 io_32bit = drive->io_32bit; |
229 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | 212 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; |
230 | 213 | ||
231 | len++; | ||
232 | |||
233 | if (io_32bit) { | 214 | if (io_32bit) { |
234 | unsigned long uninitialized_var(flags); | 215 | unsigned long uninitialized_var(flags); |
235 | 216 | ||
@@ -238,27 +219,26 @@ void ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf, | |||
238 | ata_vlb_sync(io_ports->nsect_addr); | 219 | ata_vlb_sync(io_ports->nsect_addr); |
239 | } | 220 | } |
240 | 221 | ||
222 | words >>= 1; | ||
241 | if (mmio) | 223 | if (mmio) |
242 | __ide_mm_insl((void __iomem *)data_addr, buf, len / 4); | 224 | __ide_mm_insl((void __iomem *)data_addr, buf, words); |
243 | else | 225 | else |
244 | insl(data_addr, buf, len / 4); | 226 | insl(data_addr, buf, words); |
245 | 227 | ||
246 | if ((io_32bit & 2) && !mmio) | 228 | if ((io_32bit & 2) && !mmio) |
247 | local_irq_restore(flags); | 229 | local_irq_restore(flags); |
248 | 230 | ||
249 | if ((len & 3) >= 2) { | 231 | if (((len + 1) & 3) < 2) |
250 | if (mmio) | 232 | return; |
251 | __ide_mm_insw((void __iomem *)data_addr, | 233 | |
252 | (u8 *)buf + (len & ~3), 1); | 234 | buf += len & ~3; |
253 | else | 235 | words = 1; |
254 | insw(data_addr, (u8 *)buf + (len & ~3), 1); | ||
255 | } | ||
256 | } else { | ||
257 | if (mmio) | ||
258 | __ide_mm_insw((void __iomem *)data_addr, buf, len / 2); | ||
259 | else | ||
260 | insw(data_addr, buf, len / 2); | ||
261 | } | 236 | } |
237 | |||
238 | if (mmio) | ||
239 | __ide_mm_insw((void __iomem *)data_addr, buf, words); | ||
240 | else | ||
241 | insw(data_addr, buf, words); | ||
262 | } | 242 | } |
263 | EXPORT_SYMBOL_GPL(ide_input_data); | 243 | EXPORT_SYMBOL_GPL(ide_input_data); |
264 | 244 | ||
@@ -271,11 +251,10 @@ void ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf, | |||
271 | ide_hwif_t *hwif = drive->hwif; | 251 | ide_hwif_t *hwif = drive->hwif; |
272 | struct ide_io_ports *io_ports = &hwif->io_ports; | 252 | struct ide_io_ports *io_ports = &hwif->io_ports; |
273 | unsigned long data_addr = io_ports->data_addr; | 253 | unsigned long data_addr = io_ports->data_addr; |
254 | unsigned int words = (len + 1) >> 1; | ||
274 | u8 io_32bit = drive->io_32bit; | 255 | u8 io_32bit = drive->io_32bit; |
275 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | 256 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; |
276 | 257 | ||
277 | len++; | ||
278 | |||
279 | if (io_32bit) { | 258 | if (io_32bit) { |
280 | unsigned long uninitialized_var(flags); | 259 | unsigned long uninitialized_var(flags); |
281 | 260 | ||
@@ -284,27 +263,26 @@ void ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf, | |||
284 | ata_vlb_sync(io_ports->nsect_addr); | 263 | ata_vlb_sync(io_ports->nsect_addr); |
285 | } | 264 | } |
286 | 265 | ||
266 | words >>= 1; | ||
287 | if (mmio) | 267 | if (mmio) |
288 | __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4); | 268 | __ide_mm_outsl((void __iomem *)data_addr, buf, words); |
289 | else | 269 | else |
290 | outsl(data_addr, buf, len / 4); | 270 | outsl(data_addr, buf, words); |
291 | 271 | ||
292 | if ((io_32bit & 2) && !mmio) | 272 | if ((io_32bit & 2) && !mmio) |
293 | local_irq_restore(flags); | 273 | local_irq_restore(flags); |
294 | 274 | ||
295 | if ((len & 3) >= 2) { | 275 | if (((len + 1) & 3) < 2) |
296 | if (mmio) | 276 | return; |
297 | __ide_mm_outsw((void __iomem *)data_addr, | 277 | |
298 | (u8 *)buf + (len & ~3), 1); | 278 | buf += len & ~3; |
299 | else | 279 | words = 1; |
300 | outsw(data_addr, (u8 *)buf + (len & ~3), 1); | ||
301 | } | ||
302 | } else { | ||
303 | if (mmio) | ||
304 | __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2); | ||
305 | else | ||
306 | outsw(data_addr, buf, len / 2); | ||
307 | } | 280 | } |
281 | |||
282 | if (mmio) | ||
283 | __ide_mm_outsw((void __iomem *)data_addr, buf, words); | ||
284 | else | ||
285 | outsw(data_addr, buf, words); | ||
308 | } | 286 | } |
309 | EXPORT_SYMBOL_GPL(ide_output_data); | 287 | EXPORT_SYMBOL_GPL(ide_output_data); |
310 | 288 | ||
@@ -312,9 +290,9 @@ const struct ide_tp_ops default_tp_ops = { | |||
312 | .exec_command = ide_exec_command, | 290 | .exec_command = ide_exec_command, |
313 | .read_status = ide_read_status, | 291 | .read_status = ide_read_status, |
314 | .read_altstatus = ide_read_altstatus, | 292 | .read_altstatus = ide_read_altstatus, |
293 | .write_devctl = ide_write_devctl, | ||
315 | 294 | ||
316 | .set_irq = ide_set_irq, | 295 | .dev_select = ide_dev_select, |
317 | |||
318 | .tf_load = ide_tf_load, | 296 | .tf_load = ide_tf_load, |
319 | .tf_read = ide_tf_read, | 297 | .tf_read = ide_tf_read, |
320 | 298 | ||
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 1adc5e2e7fb3..1deb6d29b186 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -73,6 +73,7 @@ EXPORT_SYMBOL_GPL(ide_end_rq); | |||
73 | 73 | ||
74 | void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err) | 74 | void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err) |
75 | { | 75 | { |
76 | const struct ide_tp_ops *tp_ops = drive->hwif->tp_ops; | ||
76 | struct ide_taskfile *tf = &cmd->tf; | 77 | struct ide_taskfile *tf = &cmd->tf; |
77 | struct request *rq = cmd->rq; | 78 | struct request *rq = cmd->rq; |
78 | u8 tf_cmd = tf->command; | 79 | u8 tf_cmd = tf->command; |
@@ -80,7 +81,16 @@ void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err) | |||
80 | tf->error = err; | 81 | tf->error = err; |
81 | tf->status = stat; | 82 | tf->status = stat; |
82 | 83 | ||
83 | drive->hwif->tp_ops->tf_read(drive, cmd); | 84 | if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) { |
85 | u8 data[2]; | ||
86 | |||
87 | tp_ops->input_data(drive, cmd, data, 2); | ||
88 | |||
89 | tf->data = data[0]; | ||
90 | tf->hob_data = data[1]; | ||
91 | } | ||
92 | |||
93 | tp_ops->tf_read(drive, cmd); | ||
84 | 94 | ||
85 | if ((cmd->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) && | 95 | if ((cmd->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) && |
86 | tf_cmd == ATA_CMD_IDLEIMMEDIATE) { | 96 | tf_cmd == ATA_CMD_IDLEIMMEDIATE) { |
@@ -338,7 +348,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) | |||
338 | if (blk_pm_request(rq)) | 348 | if (blk_pm_request(rq)) |
339 | ide_check_pm_state(drive, rq); | 349 | ide_check_pm_state(drive, rq); |
340 | 350 | ||
341 | SELECT_DRIVE(drive); | 351 | drive->hwif->tp_ops->dev_select(drive); |
342 | if (ide_wait_stat(&startstop, drive, drive->ready_stat, | 352 | if (ide_wait_stat(&startstop, drive, drive->ready_stat, |
343 | ATA_BUSY | ATA_DRQ, WAIT_READY)) { | 353 | ATA_BUSY | ATA_DRQ, WAIT_READY)) { |
344 | printk(KERN_ERR "%s: drive not ready for command\n", drive->name); | 354 | printk(KERN_ERR "%s: drive not ready for command\n", drive->name); |
@@ -481,11 +491,10 @@ repeat: | |||
481 | prev_port = hwif->host->cur_port; | 491 | prev_port = hwif->host->cur_port; |
482 | hwif->rq = NULL; | 492 | hwif->rq = NULL; |
483 | 493 | ||
484 | if (drive->dev_flags & IDE_DFLAG_SLEEPING) { | 494 | if (drive->dev_flags & IDE_DFLAG_SLEEPING && |
485 | if (time_before(drive->sleep, jiffies)) { | 495 | time_after(drive->sleep, jiffies)) { |
486 | ide_unlock_port(hwif); | 496 | ide_unlock_port(hwif); |
487 | goto plug_device; | 497 | goto plug_device; |
488 | } | ||
489 | } | 498 | } |
490 | 499 | ||
491 | if ((hwif->host->host_flags & IDE_HFLAG_SERIALIZE) && | 500 | if ((hwif->host->host_flags & IDE_HFLAG_SERIALIZE) && |
@@ -495,7 +504,9 @@ repeat: | |||
495 | * quirk_list may not like intr setups/cleanups | 504 | * quirk_list may not like intr setups/cleanups |
496 | */ | 505 | */ |
497 | if (prev_port && prev_port->cur_dev->quirk_list == 0) | 506 | if (prev_port && prev_port->cur_dev->quirk_list == 0) |
498 | prev_port->tp_ops->set_irq(prev_port, 0); | 507 | prev_port->tp_ops->write_devctl(prev_port, |
508 | ATA_NIEN | | ||
509 | ATA_DEVCTL_OBS); | ||
499 | 510 | ||
500 | hwif->host->cur_port = hwif; | 511 | hwif->host->cur_port = hwif; |
501 | } | 512 | } |
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 5403e4a44be4..27bb70ddd459 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c | |||
@@ -27,21 +27,6 @@ | |||
27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
28 | #include <asm/io.h> | 28 | #include <asm/io.h> |
29 | 29 | ||
30 | void SELECT_DRIVE(ide_drive_t *drive) | ||
31 | { | ||
32 | ide_hwif_t *hwif = drive->hwif; | ||
33 | const struct ide_port_ops *port_ops = hwif->port_ops; | ||
34 | struct ide_cmd cmd; | ||
35 | |||
36 | if (port_ops && port_ops->selectproc) | ||
37 | port_ops->selectproc(drive); | ||
38 | |||
39 | memset(&cmd, 0, sizeof(cmd)); | ||
40 | cmd.tf_flags = IDE_TFLAG_OUT_DEVICE; | ||
41 | |||
42 | drive->hwif->tp_ops->tf_load(drive, &cmd); | ||
43 | } | ||
44 | |||
45 | void SELECT_MASK(ide_drive_t *drive, int mask) | 30 | void SELECT_MASK(ide_drive_t *drive, int mask) |
46 | { | 31 | { |
47 | const struct ide_port_ops *port_ops = drive->hwif->port_ops; | 32 | const struct ide_port_ops *port_ops = drive->hwif->port_ops; |
@@ -55,7 +40,7 @@ u8 ide_read_error(ide_drive_t *drive) | |||
55 | struct ide_cmd cmd; | 40 | struct ide_cmd cmd; |
56 | 41 | ||
57 | memset(&cmd, 0, sizeof(cmd)); | 42 | memset(&cmd, 0, sizeof(cmd)); |
58 | cmd.tf_flags = IDE_TFLAG_IN_FEATURE; | 43 | cmd.tf_flags = IDE_TFLAG_IN_ERROR; |
59 | 44 | ||
60 | drive->hwif->tp_ops->tf_read(drive, &cmd); | 45 | drive->hwif->tp_ops->tf_read(drive, &cmd); |
61 | 46 | ||
@@ -306,6 +291,7 @@ int ide_driveid_update(ide_drive_t *drive) | |||
306 | drive->id[ATA_ID_UDMA_MODES] = id[ATA_ID_UDMA_MODES]; | 291 | drive->id[ATA_ID_UDMA_MODES] = id[ATA_ID_UDMA_MODES]; |
307 | drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES]; | 292 | drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES]; |
308 | drive->id[ATA_ID_SWDMA_MODES] = id[ATA_ID_SWDMA_MODES]; | 293 | drive->id[ATA_ID_SWDMA_MODES] = id[ATA_ID_SWDMA_MODES]; |
294 | drive->id[ATA_ID_CFA_MODES] = id[ATA_ID_CFA_MODES]; | ||
309 | /* anything more ? */ | 295 | /* anything more ? */ |
310 | 296 | ||
311 | kfree(id); | 297 | kfree(id); |
@@ -356,10 +342,10 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) | |||
356 | disable_irq_nosync(hwif->irq); | 342 | disable_irq_nosync(hwif->irq); |
357 | 343 | ||
358 | udelay(1); | 344 | udelay(1); |
359 | SELECT_DRIVE(drive); | 345 | tp_ops->dev_select(drive); |
360 | SELECT_MASK(drive, 1); | 346 | SELECT_MASK(drive, 1); |
361 | udelay(1); | 347 | udelay(1); |
362 | tp_ops->set_irq(hwif, 0); | 348 | tp_ops->write_devctl(hwif, ATA_NIEN | ATA_DEVCTL_OBS); |
363 | 349 | ||
364 | memset(&cmd, 0, sizeof(cmd)); | 350 | memset(&cmd, 0, sizeof(cmd)); |
365 | cmd.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT; | 351 | cmd.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT; |
@@ -371,7 +357,7 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) | |||
371 | tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES); | 357 | tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES); |
372 | 358 | ||
373 | if (drive->quirk_list == 2) | 359 | if (drive->quirk_list == 2) |
374 | tp_ops->set_irq(hwif, 1); | 360 | tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); |
375 | 361 | ||
376 | error = __ide_wait_stat(drive, drive->ready_stat, | 362 | error = __ide_wait_stat(drive, drive->ready_stat, |
377 | ATA_BUSY | ATA_DRQ | ATA_ERR, | 363 | ATA_BUSY | ATA_DRQ | ATA_ERR, |
@@ -386,9 +372,14 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) | |||
386 | return error; | 372 | return error; |
387 | } | 373 | } |
388 | 374 | ||
389 | id[ATA_ID_UDMA_MODES] &= ~0xFF00; | 375 | if (speed >= XFER_SW_DMA_0) { |
390 | id[ATA_ID_MWDMA_MODES] &= ~0x0F00; | 376 | id[ATA_ID_UDMA_MODES] &= ~0xFF00; |
391 | id[ATA_ID_SWDMA_MODES] &= ~0x0F00; | 377 | id[ATA_ID_MWDMA_MODES] &= ~0x0700; |
378 | id[ATA_ID_SWDMA_MODES] &= ~0x0700; | ||
379 | if (ata_id_is_cfa(id)) | ||
380 | id[ATA_ID_CFA_MODES] &= ~0x0E00; | ||
381 | } else if (ata_id_is_cfa(id)) | ||
382 | id[ATA_ID_CFA_MODES] &= ~0x01C0; | ||
392 | 383 | ||
393 | skip: | 384 | skip: |
394 | #ifdef CONFIG_BLK_DEV_IDEDMA | 385 | #ifdef CONFIG_BLK_DEV_IDEDMA |
@@ -401,12 +392,18 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) | |||
401 | if (speed >= XFER_UDMA_0) { | 392 | if (speed >= XFER_UDMA_0) { |
402 | i = 1 << (speed - XFER_UDMA_0); | 393 | i = 1 << (speed - XFER_UDMA_0); |
403 | id[ATA_ID_UDMA_MODES] |= (i << 8 | i); | 394 | id[ATA_ID_UDMA_MODES] |= (i << 8 | i); |
395 | } else if (ata_id_is_cfa(id) && speed >= XFER_MW_DMA_3) { | ||
396 | i = speed - XFER_MW_DMA_2; | ||
397 | id[ATA_ID_CFA_MODES] |= i << 9; | ||
404 | } else if (speed >= XFER_MW_DMA_0) { | 398 | } else if (speed >= XFER_MW_DMA_0) { |
405 | i = 1 << (speed - XFER_MW_DMA_0); | 399 | i = 1 << (speed - XFER_MW_DMA_0); |
406 | id[ATA_ID_MWDMA_MODES] |= (i << 8 | i); | 400 | id[ATA_ID_MWDMA_MODES] |= (i << 8 | i); |
407 | } else if (speed >= XFER_SW_DMA_0) { | 401 | } else if (speed >= XFER_SW_DMA_0) { |
408 | i = 1 << (speed - XFER_SW_DMA_0); | 402 | i = 1 << (speed - XFER_SW_DMA_0); |
409 | id[ATA_ID_SWDMA_MODES] |= (i << 8 | i); | 403 | id[ATA_ID_SWDMA_MODES] |= (i << 8 | i); |
404 | } else if (ata_id_is_cfa(id) && speed >= XFER_PIO_5) { | ||
405 | i = speed - XFER_PIO_4; | ||
406 | id[ATA_ID_CFA_MODES] |= i << 6; | ||
410 | } | 407 | } |
411 | 408 | ||
412 | if (!drive->init_speed) | 409 | if (!drive->init_speed) |
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c index ebf2d21ebdcb..bb7858ebb7d1 100644 --- a/drivers/ide/ide-pm.c +++ b/drivers/ide/ide-pm.c | |||
@@ -223,6 +223,7 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq) | |||
223 | * point. | 223 | * point. |
224 | */ | 224 | */ |
225 | ide_hwif_t *hwif = drive->hwif; | 225 | ide_hwif_t *hwif = drive->hwif; |
226 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | ||
226 | struct request_queue *q = drive->queue; | 227 | struct request_queue *q = drive->queue; |
227 | unsigned long flags; | 228 | unsigned long flags; |
228 | int rc; | 229 | int rc; |
@@ -232,8 +233,8 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq) | |||
232 | rc = ide_wait_not_busy(hwif, 35000); | 233 | rc = ide_wait_not_busy(hwif, 35000); |
233 | if (rc) | 234 | if (rc) |
234 | printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name); | 235 | printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name); |
235 | SELECT_DRIVE(drive); | 236 | tp_ops->dev_select(drive); |
236 | hwif->tp_ops->set_irq(hwif, 1); | 237 | tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); |
237 | rc = ide_wait_not_busy(hwif, 100000); | 238 | rc = ide_wait_not_busy(hwif, 100000); |
238 | if (rc) | 239 | if (rc) |
239 | printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); | 240 | printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); |
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 548864510ba9..d8c1c3e735bb 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -260,7 +260,7 @@ int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id) | |||
260 | * during the identify phase that the IRQ handler isn't expecting. | 260 | * during the identify phase that the IRQ handler isn't expecting. |
261 | */ | 261 | */ |
262 | if (io_ports->ctl_addr) | 262 | if (io_ports->ctl_addr) |
263 | tp_ops->set_irq(hwif, 0); | 263 | tp_ops->write_devctl(hwif, ATA_NIEN | ATA_DEVCTL_OBS); |
264 | 264 | ||
265 | /* take a deep breath */ | 265 | /* take a deep breath */ |
266 | msleep(50); | 266 | msleep(50); |
@@ -390,13 +390,13 @@ static int do_probe (ide_drive_t *drive, u8 cmd) | |||
390 | * (e.g. crw9624 as drive0 with disk as slave) | 390 | * (e.g. crw9624 as drive0 with disk as slave) |
391 | */ | 391 | */ |
392 | msleep(50); | 392 | msleep(50); |
393 | SELECT_DRIVE(drive); | 393 | tp_ops->dev_select(drive); |
394 | msleep(50); | 394 | msleep(50); |
395 | 395 | ||
396 | if (ide_read_device(drive) != drive->select && present == 0) { | 396 | if (ide_read_device(drive) != drive->select && present == 0) { |
397 | if (drive->dn & 1) { | 397 | if (drive->dn & 1) { |
398 | /* exit with drive0 selected */ | 398 | /* exit with drive0 selected */ |
399 | SELECT_DRIVE(hwif->devices[0]); | 399 | tp_ops->dev_select(hwif->devices[0]); |
400 | /* allow ATA_BUSY to assert & clear */ | 400 | /* allow ATA_BUSY to assert & clear */ |
401 | msleep(50); | 401 | msleep(50); |
402 | } | 402 | } |
@@ -422,7 +422,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) | |||
422 | printk(KERN_ERR "%s: no response (status = 0x%02x), " | 422 | printk(KERN_ERR "%s: no response (status = 0x%02x), " |
423 | "resetting drive\n", drive->name, stat); | 423 | "resetting drive\n", drive->name, stat); |
424 | msleep(50); | 424 | msleep(50); |
425 | SELECT_DRIVE(drive); | 425 | tp_ops->dev_select(drive); |
426 | msleep(50); | 426 | msleep(50); |
427 | tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); | 427 | tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); |
428 | (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0); | 428 | (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0); |
@@ -441,7 +441,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) | |||
441 | } | 441 | } |
442 | if (drive->dn & 1) { | 442 | if (drive->dn & 1) { |
443 | /* exit with drive0 selected */ | 443 | /* exit with drive0 selected */ |
444 | SELECT_DRIVE(hwif->devices[0]); | 444 | tp_ops->dev_select(hwif->devices[0]); |
445 | msleep(50); | 445 | msleep(50); |
446 | /* ensure drive irq is clear */ | 446 | /* ensure drive irq is clear */ |
447 | (void)tp_ops->read_status(hwif); | 447 | (void)tp_ops->read_status(hwif); |
@@ -605,6 +605,7 @@ out: | |||
605 | 605 | ||
606 | static int ide_port_wait_ready(ide_hwif_t *hwif) | 606 | static int ide_port_wait_ready(ide_hwif_t *hwif) |
607 | { | 607 | { |
608 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | ||
608 | ide_drive_t *drive; | 609 | ide_drive_t *drive; |
609 | int i, rc; | 610 | int i, rc; |
610 | 611 | ||
@@ -627,8 +628,8 @@ static int ide_port_wait_ready(ide_hwif_t *hwif) | |||
627 | /* Ignore disks that we will not probe for later. */ | 628 | /* Ignore disks that we will not probe for later. */ |
628 | if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0 || | 629 | if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0 || |
629 | (drive->dev_flags & IDE_DFLAG_PRESENT)) { | 630 | (drive->dev_flags & IDE_DFLAG_PRESENT)) { |
630 | SELECT_DRIVE(drive); | 631 | tp_ops->dev_select(drive); |
631 | hwif->tp_ops->set_irq(hwif, 1); | 632 | tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); |
632 | mdelay(2); | 633 | mdelay(2); |
633 | rc = ide_wait_not_busy(hwif, 35000); | 634 | rc = ide_wait_not_busy(hwif, 35000); |
634 | if (rc) | 635 | if (rc) |
@@ -640,7 +641,7 @@ static int ide_port_wait_ready(ide_hwif_t *hwif) | |||
640 | out: | 641 | out: |
641 | /* Exit function with master reselected (let's be sane) */ | 642 | /* Exit function with master reselected (let's be sane) */ |
642 | if (i) | 643 | if (i) |
643 | SELECT_DRIVE(hwif->devices[0]); | 644 | tp_ops->dev_select(hwif->devices[0]); |
644 | 645 | ||
645 | return rc; | 646 | return rc; |
646 | } | 647 | } |
@@ -845,7 +846,7 @@ static int init_irq (ide_hwif_t *hwif) | |||
845 | irq_handler = ide_intr; | 846 | irq_handler = ide_intr; |
846 | 847 | ||
847 | if (io_ports->ctl_addr) | 848 | if (io_ports->ctl_addr) |
848 | hwif->tp_ops->set_irq(hwif, 1); | 849 | hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); |
849 | 850 | ||
850 | if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif)) | 851 | if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif)) |
851 | goto out_up; | 852 | goto out_up; |
@@ -942,20 +943,16 @@ EXPORT_SYMBOL_GPL(ide_init_disk); | |||
942 | static void drive_release_dev (struct device *dev) | 943 | static void drive_release_dev (struct device *dev) |
943 | { | 944 | { |
944 | ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); | 945 | ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); |
945 | ide_hwif_t *hwif = drive->hwif; | ||
946 | 946 | ||
947 | ide_proc_unregister_device(drive); | 947 | ide_proc_unregister_device(drive); |
948 | 948 | ||
949 | spin_lock_irq(&hwif->lock); | 949 | blk_cleanup_queue(drive->queue); |
950 | drive->queue = NULL; | ||
951 | |||
950 | kfree(drive->id); | 952 | kfree(drive->id); |
951 | drive->id = NULL; | 953 | drive->id = NULL; |
954 | |||
952 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; | 955 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; |
953 | /* Messed up locking ... */ | ||
954 | spin_unlock_irq(&hwif->lock); | ||
955 | blk_cleanup_queue(drive->queue); | ||
956 | spin_lock_irq(&hwif->lock); | ||
957 | drive->queue = NULL; | ||
958 | spin_unlock_irq(&hwif->lock); | ||
959 | 956 | ||
960 | complete(&drive->gendev_rel_comp); | 957 | complete(&drive->gendev_rel_comp); |
961 | } | 958 | } |
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 64dfa7458f8d..cb942a9b580f 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -297,19 +297,15 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i) | |||
297 | return tape; | 297 | return tape; |
298 | } | 298 | } |
299 | 299 | ||
300 | static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | 300 | static int idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, |
301 | unsigned int bcount) | 301 | unsigned int bcount) |
302 | { | 302 | { |
303 | struct idetape_bh *bh = pc->bh; | 303 | struct idetape_bh *bh = pc->bh; |
304 | int count; | 304 | int count; |
305 | 305 | ||
306 | while (bcount) { | 306 | while (bcount) { |
307 | if (bh == NULL) { | 307 | if (bh == NULL) |
308 | printk(KERN_ERR "ide-tape: bh == NULL in " | 308 | break; |
309 | "idetape_input_buffers\n"); | ||
310 | ide_pad_transfer(drive, 0, bcount); | ||
311 | return; | ||
312 | } | ||
313 | count = min( | 309 | count = min( |
314 | (unsigned int)(bh->b_size - atomic_read(&bh->b_count)), | 310 | (unsigned int)(bh->b_size - atomic_read(&bh->b_count)), |
315 | bcount); | 311 | bcount); |
@@ -323,21 +319,21 @@ static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | |||
323 | atomic_set(&bh->b_count, 0); | 319 | atomic_set(&bh->b_count, 0); |
324 | } | 320 | } |
325 | } | 321 | } |
322 | |||
326 | pc->bh = bh; | 323 | pc->bh = bh; |
324 | |||
325 | return bcount; | ||
327 | } | 326 | } |
328 | 327 | ||
329 | static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | 328 | static int idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, |
330 | unsigned int bcount) | 329 | unsigned int bcount) |
331 | { | 330 | { |
332 | struct idetape_bh *bh = pc->bh; | 331 | struct idetape_bh *bh = pc->bh; |
333 | int count; | 332 | int count; |
334 | 333 | ||
335 | while (bcount) { | 334 | while (bcount) { |
336 | if (bh == NULL) { | 335 | if (bh == NULL) |
337 | printk(KERN_ERR "ide-tape: bh == NULL in %s\n", | 336 | break; |
338 | __func__); | ||
339 | return; | ||
340 | } | ||
341 | count = min((unsigned int)pc->b_count, (unsigned int)bcount); | 337 | count = min((unsigned int)pc->b_count, (unsigned int)bcount); |
342 | drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count); | 338 | drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count); |
343 | bcount -= count; | 339 | bcount -= count; |
@@ -352,6 +348,8 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | |||
352 | } | 348 | } |
353 | } | 349 | } |
354 | } | 350 | } |
351 | |||
352 | return bcount; | ||
355 | } | 353 | } |
356 | 354 | ||
357 | static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc) | 355 | static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc) |
@@ -563,12 +561,14 @@ static void ide_tape_handle_dsc(ide_drive_t *drive) | |||
563 | static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | 561 | static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, |
564 | unsigned int bcount, int write) | 562 | unsigned int bcount, int write) |
565 | { | 563 | { |
564 | unsigned int bleft; | ||
565 | |||
566 | if (write) | 566 | if (write) |
567 | idetape_output_buffers(drive, pc, bcount); | 567 | bleft = idetape_output_buffers(drive, pc, bcount); |
568 | else | 568 | else |
569 | idetape_input_buffers(drive, pc, bcount); | 569 | bleft = idetape_input_buffers(drive, pc, bcount); |
570 | 570 | ||
571 | return bcount; | 571 | return bcount - bleft; |
572 | } | 572 | } |
573 | 573 | ||
574 | /* | 574 | /* |
@@ -2014,9 +2014,13 @@ static void idetape_get_inquiry_results(ide_drive_t *drive) | |||
2014 | { | 2014 | { |
2015 | idetape_tape_t *tape = drive->driver_data; | 2015 | idetape_tape_t *tape = drive->driver_data; |
2016 | struct ide_atapi_pc pc; | 2016 | struct ide_atapi_pc pc; |
2017 | u8 pc_buf[256]; | ||
2017 | char fw_rev[4], vendor_id[8], product_id[16]; | 2018 | char fw_rev[4], vendor_id[8], product_id[16]; |
2018 | 2019 | ||
2019 | idetape_create_inquiry_cmd(&pc); | 2020 | idetape_create_inquiry_cmd(&pc); |
2021 | pc.buf = &pc_buf[0]; | ||
2022 | pc.buf_size = sizeof(pc_buf); | ||
2023 | |||
2020 | if (ide_queue_pc_tail(drive, tape->disk, &pc)) { | 2024 | if (ide_queue_pc_tail(drive, tape->disk, &pc)) { |
2021 | printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n", | 2025 | printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n", |
2022 | tape->name); | 2026 | tape->name); |
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 84532be97c00..243421ce40d0 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c | |||
@@ -80,8 +80,14 @@ ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd) | |||
80 | 80 | ||
81 | if ((cmd->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { | 81 | if ((cmd->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) { |
82 | ide_tf_dump(drive->name, tf); | 82 | ide_tf_dump(drive->name, tf); |
83 | tp_ops->set_irq(hwif, 1); | 83 | tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); |
84 | SELECT_MASK(drive, 0); | 84 | SELECT_MASK(drive, 0); |
85 | |||
86 | if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) { | ||
87 | u8 data[2] = { tf->data, tf->hob_data }; | ||
88 | |||
89 | tp_ops->output_data(drive, cmd, data, 2); | ||
90 | } | ||
85 | tp_ops->tf_load(drive, cmd); | 91 | tp_ops->tf_load(drive, cmd); |
86 | } | 92 | } |
87 | 93 | ||
@@ -100,9 +106,7 @@ ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd) | |||
100 | ide_execute_command(drive, cmd, handler, WAIT_WORSTCASE); | 106 | ide_execute_command(drive, cmd, handler, WAIT_WORSTCASE); |
101 | return ide_started; | 107 | return ide_started; |
102 | case ATA_PROT_DMA: | 108 | case ATA_PROT_DMA: |
103 | if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0 || | 109 | if (ide_dma_prepare(drive, cmd)) |
104 | ide_build_sglist(drive, cmd) == 0 || | ||
105 | dma_ops->dma_setup(drive, cmd)) | ||
106 | return ide_stopped; | 110 | return ide_stopped; |
107 | hwif->expiry = dma_ops->dma_timer_expiry; | 111 | hwif->expiry = dma_ops->dma_timer_expiry; |
108 | ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD); | 112 | ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD); |
@@ -188,70 +192,68 @@ static u8 wait_drive_not_busy(ide_drive_t *drive) | |||
188 | return stat; | 192 | return stat; |
189 | } | 193 | } |
190 | 194 | ||
191 | static void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd, | 195 | void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd, |
192 | unsigned int write, unsigned int nr_bytes) | 196 | unsigned int write, unsigned int len) |
193 | { | 197 | { |
194 | ide_hwif_t *hwif = drive->hwif; | 198 | ide_hwif_t *hwif = drive->hwif; |
195 | struct scatterlist *sg = hwif->sg_table; | 199 | struct scatterlist *sg = hwif->sg_table; |
196 | struct scatterlist *cursg = cmd->cursg; | 200 | struct scatterlist *cursg = cmd->cursg; |
197 | struct page *page; | 201 | struct page *page; |
198 | #ifdef CONFIG_HIGHMEM | ||
199 | unsigned long flags; | 202 | unsigned long flags; |
200 | #endif | ||
201 | unsigned int offset; | 203 | unsigned int offset; |
202 | u8 *buf; | 204 | u8 *buf; |
203 | 205 | ||
204 | cursg = cmd->cursg; | 206 | cursg = cmd->cursg; |
205 | if (!cursg) { | 207 | if (cursg == NULL) |
206 | cursg = sg; | 208 | cursg = cmd->cursg = sg; |
207 | cmd->cursg = sg; | ||
208 | } | ||
209 | 209 | ||
210 | page = sg_page(cursg); | 210 | while (len) { |
211 | offset = cursg->offset + cmd->cursg_ofs; | 211 | unsigned nr_bytes = min(len, cursg->length - cmd->cursg_ofs); |
212 | 212 | ||
213 | /* get the current page and offset */ | 213 | if (nr_bytes > PAGE_SIZE) |
214 | page = nth_page(page, (offset >> PAGE_SHIFT)); | 214 | nr_bytes = PAGE_SIZE; |
215 | offset %= PAGE_SIZE; | ||
216 | 215 | ||
217 | #ifdef CONFIG_HIGHMEM | 216 | page = sg_page(cursg); |
218 | local_irq_save(flags); | 217 | offset = cursg->offset + cmd->cursg_ofs; |
219 | #endif | ||
220 | buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + offset; | ||
221 | 218 | ||
222 | cmd->nleft -= nr_bytes; | 219 | /* get the current page and offset */ |
223 | cmd->cursg_ofs += nr_bytes; | 220 | page = nth_page(page, (offset >> PAGE_SHIFT)); |
221 | offset %= PAGE_SIZE; | ||
224 | 222 | ||
225 | if (cmd->cursg_ofs == cursg->length) { | 223 | if (PageHighMem(page)) |
226 | cmd->cursg = sg_next(cmd->cursg); | 224 | local_irq_save(flags); |
227 | cmd->cursg_ofs = 0; | ||
228 | } | ||
229 | 225 | ||
230 | /* do the actual data transfer */ | 226 | buf = kmap_atomic(page, KM_BIO_SRC_IRQ) + offset; |
231 | if (write) | ||
232 | hwif->tp_ops->output_data(drive, cmd, buf, nr_bytes); | ||
233 | else | ||
234 | hwif->tp_ops->input_data(drive, cmd, buf, nr_bytes); | ||
235 | 227 | ||
236 | kunmap_atomic(buf, KM_BIO_SRC_IRQ); | 228 | cmd->nleft -= nr_bytes; |
237 | #ifdef CONFIG_HIGHMEM | 229 | cmd->cursg_ofs += nr_bytes; |
238 | local_irq_restore(flags); | ||
239 | #endif | ||
240 | } | ||
241 | 230 | ||
242 | static void ide_pio_multi(ide_drive_t *drive, struct ide_cmd *cmd, | 231 | if (cmd->cursg_ofs == cursg->length) { |
243 | unsigned int write) | 232 | cursg = cmd->cursg = sg_next(cmd->cursg); |
244 | { | 233 | cmd->cursg_ofs = 0; |
245 | unsigned int nsect; | 234 | } |
235 | |||
236 | /* do the actual data transfer */ | ||
237 | if (write) | ||
238 | hwif->tp_ops->output_data(drive, cmd, buf, nr_bytes); | ||
239 | else | ||
240 | hwif->tp_ops->input_data(drive, cmd, buf, nr_bytes); | ||
241 | |||
242 | kunmap_atomic(buf, KM_BIO_SRC_IRQ); | ||
246 | 243 | ||
247 | nsect = min_t(unsigned int, cmd->nleft >> 9, drive->mult_count); | 244 | if (PageHighMem(page)) |
248 | while (nsect--) | 245 | local_irq_restore(flags); |
249 | ide_pio_bytes(drive, cmd, write, SECTOR_SIZE); | 246 | |
247 | len -= nr_bytes; | ||
248 | } | ||
250 | } | 249 | } |
250 | EXPORT_SYMBOL_GPL(ide_pio_bytes); | ||
251 | 251 | ||
252 | static void ide_pio_datablock(ide_drive_t *drive, struct ide_cmd *cmd, | 252 | static void ide_pio_datablock(ide_drive_t *drive, struct ide_cmd *cmd, |
253 | unsigned int write) | 253 | unsigned int write) |
254 | { | 254 | { |
255 | unsigned int nr_bytes; | ||
256 | |||
255 | u8 saved_io_32bit = drive->io_32bit; | 257 | u8 saved_io_32bit = drive->io_32bit; |
256 | 258 | ||
257 | if (cmd->tf_flags & IDE_TFLAG_FS) | 259 | if (cmd->tf_flags & IDE_TFLAG_FS) |
@@ -263,9 +265,11 @@ static void ide_pio_datablock(ide_drive_t *drive, struct ide_cmd *cmd, | |||
263 | touch_softlockup_watchdog(); | 265 | touch_softlockup_watchdog(); |
264 | 266 | ||
265 | if (cmd->tf_flags & IDE_TFLAG_MULTI_PIO) | 267 | if (cmd->tf_flags & IDE_TFLAG_MULTI_PIO) |
266 | ide_pio_multi(drive, cmd, write); | 268 | nr_bytes = min_t(unsigned, cmd->nleft, drive->mult_count << 9); |
267 | else | 269 | else |
268 | ide_pio_bytes(drive, cmd, write, SECTOR_SIZE); | 270 | nr_bytes = SECTOR_SIZE; |
271 | |||
272 | ide_pio_bytes(drive, cmd, write, nr_bytes); | ||
269 | 273 | ||
270 | drive->io_32bit = saved_io_32bit; | 274 | drive->io_32bit = saved_io_32bit; |
271 | } | 275 | } |
diff --git a/drivers/ide/ide-timings.c b/drivers/ide/ide-timings.c index 81f527af8fae..001a56365be5 100644 --- a/drivers/ide/ide-timings.c +++ b/drivers/ide/ide-timings.c | |||
@@ -43,6 +43,8 @@ static struct ide_timing ide_timing[] = { | |||
43 | { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 }, | 43 | { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 }, |
44 | { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 }, | 44 | { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 }, |
45 | 45 | ||
46 | { XFER_MW_DMA_4, 25, 0, 0, 0, 55, 20, 80, 0 }, | ||
47 | { XFER_MW_DMA_3, 25, 0, 0, 0, 65, 25, 100, 0 }, | ||
46 | { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 }, | 48 | { XFER_MW_DMA_2, 25, 0, 0, 0, 70, 25, 120, 0 }, |
47 | { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 }, | 49 | { XFER_MW_DMA_1, 45, 0, 0, 0, 80, 50, 150, 0 }, |
48 | { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 }, | 50 | { XFER_MW_DMA_0, 60, 0, 0, 0, 215, 215, 480, 0 }, |
@@ -51,7 +53,8 @@ static struct ide_timing ide_timing[] = { | |||
51 | { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 }, | 53 | { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 }, |
52 | { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 }, | 54 | { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 }, |
53 | 55 | ||
54 | { XFER_PIO_5, 20, 50, 30, 100, 50, 30, 100, 0 }, | 56 | { XFER_PIO_6, 10, 55, 20, 80, 55, 20, 80, 0 }, |
57 | { XFER_PIO_5, 15, 65, 25, 100, 65, 25, 100, 0 }, | ||
55 | { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 }, | 58 | { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 }, |
56 | { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 }, | 59 | { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 }, |
57 | 60 | ||
@@ -90,6 +93,10 @@ u16 ide_pio_cycle_time(ide_drive_t *drive, u8 pio) | |||
90 | /* conservative "downgrade" for all pre-ATA2 drives */ | 93 | /* conservative "downgrade" for all pre-ATA2 drives */ |
91 | if (pio < 3 && cycle < t->cycle) | 94 | if (pio < 3 && cycle < t->cycle) |
92 | cycle = 0; /* use standard timing */ | 95 | cycle = 0; /* use standard timing */ |
96 | |||
97 | /* Use the standard timing for the CF specific modes too */ | ||
98 | if (pio > 4 && ata_id_is_cfa(id)) | ||
99 | cycle = 0; | ||
93 | } | 100 | } |
94 | 101 | ||
95 | return cycle ? cycle : t->cycle; | 102 | return cycle ? cycle : t->cycle; |
@@ -161,7 +168,8 @@ int ide_timing_compute(ide_drive_t *drive, u8 speed, | |||
161 | 168 | ||
162 | if (speed <= XFER_PIO_2) | 169 | if (speed <= XFER_PIO_2) |
163 | p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO]; | 170 | p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO]; |
164 | else if (speed <= XFER_PIO_5) | 171 | else if ((speed <= XFER_PIO_4) || |
172 | (speed == XFER_PIO_5 && !ata_id_is_cfa(id))) | ||
165 | p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY]; | 173 | p.cycle = p.cyc8b = id[ATA_ID_EIDE_PIO_IORDY]; |
166 | else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) | 174 | else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2) |
167 | p.cycle = id[ATA_ID_EIDE_DMA_MIN]; | 175 | p.cycle = id[ATA_ID_EIDE_DMA_MIN]; |
diff --git a/drivers/ide/ide-xfer-mode.c b/drivers/ide/ide-xfer-mode.c index 6910f6a257e8..af44be9d546c 100644 --- a/drivers/ide/ide-xfer-mode.c +++ b/drivers/ide/ide-xfer-mode.c | |||
@@ -9,11 +9,11 @@ static const char *udma_str[] = | |||
9 | { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44", | 9 | { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44", |
10 | "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" }; | 10 | "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" }; |
11 | static const char *mwdma_str[] = | 11 | static const char *mwdma_str[] = |
12 | { "MWDMA0", "MWDMA1", "MWDMA2" }; | 12 | { "MWDMA0", "MWDMA1", "MWDMA2", "MWDMA3", "MWDMA4" }; |
13 | static const char *swdma_str[] = | 13 | static const char *swdma_str[] = |
14 | { "SWDMA0", "SWDMA1", "SWDMA2" }; | 14 | { "SWDMA0", "SWDMA1", "SWDMA2" }; |
15 | static const char *pio_str[] = | 15 | static const char *pio_str[] = |
16 | { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" }; | 16 | { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5", "PIO6" }; |
17 | 17 | ||
18 | /** | 18 | /** |
19 | * ide_xfer_verbose - return IDE mode names | 19 | * ide_xfer_verbose - return IDE mode names |
@@ -30,11 +30,11 @@ const char *ide_xfer_verbose(u8 mode) | |||
30 | 30 | ||
31 | if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7) | 31 | if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7) |
32 | s = udma_str[i]; | 32 | s = udma_str[i]; |
33 | else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2) | 33 | else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_4) |
34 | s = mwdma_str[i]; | 34 | s = mwdma_str[i]; |
35 | else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2) | 35 | else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2) |
36 | s = swdma_str[i]; | 36 | s = swdma_str[i]; |
37 | else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5) | 37 | else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_6) |
38 | s = pio_str[i & 0x7]; | 38 | s = pio_str[i & 0x7]; |
39 | else if (mode == XFER_PIO_SLOW) | 39 | else if (mode == XFER_PIO_SLOW) |
40 | s = "PIO SLOW"; | 40 | s = "PIO SLOW"; |
@@ -79,7 +79,10 @@ u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode) | |||
79 | } | 79 | } |
80 | 80 | ||
81 | if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */ | 81 | if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */ |
82 | if (ata_id_has_iordy(id)) { | 82 | if (ata_id_is_cfa(id) && (id[ATA_ID_CFA_MODES] & 7)) |
83 | pio_mode = 4 + min_t(int, 2, | ||
84 | id[ATA_ID_CFA_MODES] & 7); | ||
85 | else if (ata_id_has_iordy(id)) { | ||
83 | if (id[ATA_ID_PIO_MODES] & 7) { | 86 | if (id[ATA_ID_PIO_MODES] & 7) { |
84 | overridden = 0; | 87 | overridden = 0; |
85 | if (id[ATA_ID_PIO_MODES] & 4) | 88 | if (id[ATA_ID_PIO_MODES] & 4) |
@@ -239,7 +242,7 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) | |||
239 | 242 | ||
240 | BUG_ON(rate < XFER_PIO_0); | 243 | BUG_ON(rate < XFER_PIO_0); |
241 | 244 | ||
242 | if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5) | 245 | if (rate >= XFER_PIO_0 && rate <= XFER_PIO_6) |
243 | return ide_set_pio_mode(drive, rate); | 246 | return ide_set_pio_mode(drive, rate); |
244 | 247 | ||
245 | return ide_set_dma_mode(drive, rate); | 248 | return ide_set_dma_mode(drive, rate); |
diff --git a/drivers/ide/ide_arm.c b/drivers/ide/ide_arm.c deleted file mode 100644 index cf6385446ece..000000000000 --- a/drivers/ide/ide_arm.c +++ /dev/null | |||
@@ -1,53 +0,0 @@ | |||
1 | /* | ||
2 | * ARM default IDE host driver | ||
3 | * | ||
4 | * Copyright (C) 2004 Bartlomiej Zolnierkiewicz | ||
5 | * Based on code by: Russell King, Ian Molton and Alexander Schulz. | ||
6 | * | ||
7 | * May be copied or modified under the terms of the GNU General Public License. | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/ide.h> | ||
13 | |||
14 | #include <asm/irq.h> | ||
15 | |||
16 | #define DRV_NAME "ide_arm" | ||
17 | |||
18 | #define IDE_ARM_IO 0x1f0 | ||
19 | #define IDE_ARM_IRQ IRQ_HARDDISK | ||
20 | |||
21 | static const struct ide_port_info ide_arm_port_info = { | ||
22 | .host_flags = IDE_HFLAG_NO_DMA, | ||
23 | }; | ||
24 | |||
25 | static int __init ide_arm_init(void) | ||
26 | { | ||
27 | unsigned long base = IDE_ARM_IO, ctl = IDE_ARM_IO + 0x206; | ||
28 | hw_regs_t hw, *hws[] = { &hw, NULL, NULL, NULL }; | ||
29 | |||
30 | if (!request_region(base, 8, DRV_NAME)) { | ||
31 | printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX not free.\n", | ||
32 | DRV_NAME, base, base + 7); | ||
33 | return -EBUSY; | ||
34 | } | ||
35 | |||
36 | if (!request_region(ctl, 1, DRV_NAME)) { | ||
37 | printk(KERN_ERR "%s: I/O resource 0x%lX not free.\n", | ||
38 | DRV_NAME, ctl); | ||
39 | release_region(base, 8); | ||
40 | return -EBUSY; | ||
41 | } | ||
42 | |||
43 | memset(&hw, 0, sizeof(hw)); | ||
44 | ide_std_init_ports(&hw, base, ctl); | ||
45 | hw.irq = IDE_ARM_IRQ; | ||
46 | hw.chipset = ide_generic; | ||
47 | |||
48 | return ide_host_add(&ide_arm_port_info, hws, NULL); | ||
49 | } | ||
50 | |||
51 | module_init(ide_arm_init); | ||
52 | |||
53 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c index 0d4ac65cf949..51aa745246dc 100644 --- a/drivers/ide/it821x.c +++ b/drivers/ide/it821x.c | |||
@@ -511,9 +511,8 @@ static struct ide_dma_ops it821x_pass_through_dma_ops = { | |||
511 | .dma_start = it821x_dma_start, | 511 | .dma_start = it821x_dma_start, |
512 | .dma_end = it821x_dma_end, | 512 | .dma_end = it821x_dma_end, |
513 | .dma_test_irq = ide_dma_test_irq, | 513 | .dma_test_irq = ide_dma_test_irq, |
514 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | ||
515 | .dma_timeout = ide_dma_timeout, | ||
516 | .dma_lost_irq = ide_dma_lost_irq, | 514 | .dma_lost_irq = ide_dma_lost_irq, |
515 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | ||
517 | .dma_sff_read_status = ide_dma_sff_read_status, | 516 | .dma_sff_read_status = ide_dma_sff_read_status, |
518 | }; | 517 | }; |
519 | 518 | ||
diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c index 7b65fe5bf449..71a39fb3856f 100644 --- a/drivers/ide/ns87415.c +++ b/drivers/ide/ns87415.c | |||
@@ -66,18 +66,11 @@ static void superio_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
66 | struct ide_io_ports *io_ports = &drive->hwif->io_ports; | 66 | struct ide_io_ports *io_ports = &drive->hwif->io_ports; |
67 | struct ide_taskfile *tf = &cmd->tf; | 67 | struct ide_taskfile *tf = &cmd->tf; |
68 | 68 | ||
69 | if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) { | ||
70 | u16 data = inw(io_ports->data_addr); | ||
71 | |||
72 | tf->data = data & 0xff; | ||
73 | tf->hob_data = (data >> 8) & 0xff; | ||
74 | } | ||
75 | |||
76 | /* be sure we're looking at the low order bits */ | 69 | /* be sure we're looking at the low order bits */ |
77 | outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); | 70 | outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); |
78 | 71 | ||
79 | if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE) | 72 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) |
80 | tf->feature = inb(io_ports->feature_addr); | 73 | tf->error = inb(io_ports->feature_addr); |
81 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | 74 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) |
82 | tf->nsect = inb(io_ports->nsect_addr); | 75 | tf->nsect = inb(io_ports->nsect_addr); |
83 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | 76 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) |
@@ -90,28 +83,30 @@ static void superio_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
90 | tf->device = superio_ide_inb(io_ports->device_addr); | 83 | tf->device = superio_ide_inb(io_ports->device_addr); |
91 | 84 | ||
92 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | 85 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { |
93 | outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); | 86 | outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); |
94 | 87 | ||
95 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | 88 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) |
96 | tf->hob_feature = inb(io_ports->feature_addr); | 89 | tf->hob_error = inb(io_ports->feature_addr); |
97 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | 90 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) |
98 | tf->hob_nsect = inb(io_ports->nsect_addr); | 91 | tf->hob_nsect = inb(io_ports->nsect_addr); |
99 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | 92 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) |
100 | tf->hob_lbal = inb(io_ports->lbal_addr); | 93 | tf->hob_lbal = inb(io_ports->lbal_addr); |
101 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | 94 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) |
102 | tf->hob_lbam = inb(io_ports->lbam_addr); | 95 | tf->hob_lbam = inb(io_ports->lbam_addr); |
103 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | 96 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) |
104 | tf->hob_lbah = inb(io_ports->lbah_addr); | 97 | tf->hob_lbah = inb(io_ports->lbah_addr); |
105 | } | 98 | } |
106 | } | 99 | } |
107 | 100 | ||
101 | static void ns87415_dev_select(ide_drive_t *drive); | ||
102 | |||
108 | static const struct ide_tp_ops superio_tp_ops = { | 103 | static const struct ide_tp_ops superio_tp_ops = { |
109 | .exec_command = ide_exec_command, | 104 | .exec_command = ide_exec_command, |
110 | .read_status = superio_read_status, | 105 | .read_status = superio_read_status, |
111 | .read_altstatus = ide_read_altstatus, | 106 | .read_altstatus = ide_read_altstatus, |
107 | .write_devctl = ide_write_devctl, | ||
112 | 108 | ||
113 | .set_irq = ide_set_irq, | 109 | .dev_select = ns87415_dev_select, |
114 | |||
115 | .tf_load = ide_tf_load, | 110 | .tf_load = ide_tf_load, |
116 | .tf_read = superio_tf_read, | 111 | .tf_read = superio_tf_read, |
117 | 112 | ||
@@ -190,10 +185,18 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma) | |||
190 | local_irq_restore(flags); | 185 | local_irq_restore(flags); |
191 | } | 186 | } |
192 | 187 | ||
193 | static void ns87415_selectproc (ide_drive_t *drive) | 188 | static void ns87415_dev_select(ide_drive_t *drive) |
194 | { | 189 | { |
195 | ns87415_prepare_drive(drive, | 190 | ns87415_prepare_drive(drive, |
196 | !!(drive->dev_flags & IDE_DFLAG_USING_DMA)); | 191 | !!(drive->dev_flags & IDE_DFLAG_USING_DMA)); |
192 | |||
193 | outb(drive->select | ATA_DEVICE_OBS, drive->hwif->io_ports.device_addr); | ||
194 | } | ||
195 | |||
196 | static void ns87415_dma_start(ide_drive_t *drive) | ||
197 | { | ||
198 | ns87415_prepare_drive(drive, 1); | ||
199 | ide_dma_start(drive); | ||
197 | } | 200 | } |
198 | 201 | ||
199 | static int ns87415_dma_end(ide_drive_t *drive) | 202 | static int ns87415_dma_end(ide_drive_t *drive) |
@@ -201,7 +204,6 @@ static int ns87415_dma_end(ide_drive_t *drive) | |||
201 | ide_hwif_t *hwif = drive->hwif; | 204 | ide_hwif_t *hwif = drive->hwif; |
202 | u8 dma_stat = 0, dma_cmd = 0; | 205 | u8 dma_stat = 0, dma_cmd = 0; |
203 | 206 | ||
204 | drive->waiting_for_dma = 0; | ||
205 | dma_stat = hwif->dma_ops->dma_sff_read_status(hwif); | 207 | dma_stat = hwif->dma_ops->dma_sff_read_status(hwif); |
206 | /* get DMA command mode */ | 208 | /* get DMA command mode */ |
207 | dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); | 209 | dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); |
@@ -210,21 +212,11 @@ static int ns87415_dma_end(ide_drive_t *drive) | |||
210 | /* from ERRATA: clear the INTR & ERROR bits */ | 212 | /* from ERRATA: clear the INTR & ERROR bits */ |
211 | dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); | 213 | dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD); |
212 | outb(dma_cmd | 6, hwif->dma_base + ATA_DMA_CMD); | 214 | outb(dma_cmd | 6, hwif->dma_base + ATA_DMA_CMD); |
213 | /* and free any DMA resources */ | ||
214 | ide_destroy_dmatable(drive); | ||
215 | /* verify good DMA status */ | ||
216 | return (dma_stat & 7) != 4; | ||
217 | } | ||
218 | 215 | ||
219 | static int ns87415_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | ||
220 | { | ||
221 | /* select DMA xfer */ | ||
222 | ns87415_prepare_drive(drive, 1); | ||
223 | if (ide_dma_setup(drive, cmd) == 0) | ||
224 | return 0; | ||
225 | /* DMA failed: select PIO xfer */ | ||
226 | ns87415_prepare_drive(drive, 0); | 216 | ns87415_prepare_drive(drive, 0); |
227 | return 1; | 217 | |
218 | /* verify good DMA status */ | ||
219 | return (dma_stat & 7) != 4; | ||
228 | } | 220 | } |
229 | 221 | ||
230 | static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) | 222 | static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) |
@@ -242,7 +234,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) | |||
242 | * Also, leave IRQ masked during drive probing, to prevent infinite | 234 | * Also, leave IRQ masked during drive probing, to prevent infinite |
243 | * interrupts from a potentially floating INTA.. | 235 | * interrupts from a potentially floating INTA.. |
244 | * | 236 | * |
245 | * IRQs get unmasked in selectproc when drive is first used. | 237 | * IRQs get unmasked in dev_select() when drive is first used. |
246 | */ | 238 | */ |
247 | (void) pci_read_config_dword(dev, 0x40, &ctrl); | 239 | (void) pci_read_config_dword(dev, 0x40, &ctrl); |
248 | (void) pci_read_config_byte(dev, 0x09, &progif); | 240 | (void) pci_read_config_byte(dev, 0x09, &progif); |
@@ -270,7 +262,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) | |||
270 | #ifdef __sparc_v9__ | 262 | #ifdef __sparc_v9__ |
271 | /* | 263 | /* |
272 | * XXX: Reset the device, if we don't it will not respond to | 264 | * XXX: Reset the device, if we don't it will not respond to |
273 | * SELECT_DRIVE() properly during first ide_probe_port(). | 265 | * dev_select() properly during first ide_probe_port(). |
274 | */ | 266 | */ |
275 | timeout = 10000; | 267 | timeout = 10000; |
276 | outb(12, hwif->io_ports.ctl_addr); | 268 | outb(12, hwif->io_ports.ctl_addr); |
@@ -294,26 +286,35 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) | |||
294 | outb(0x60, hwif->dma_base + ATA_DMA_STATUS); | 286 | outb(0x60, hwif->dma_base + ATA_DMA_STATUS); |
295 | } | 287 | } |
296 | 288 | ||
297 | static const struct ide_port_ops ns87415_port_ops = { | 289 | static const struct ide_tp_ops ns87415_tp_ops = { |
298 | .selectproc = ns87415_selectproc, | 290 | .exec_command = ide_exec_command, |
291 | .read_status = ide_read_status, | ||
292 | .read_altstatus = ide_read_altstatus, | ||
293 | .write_devctl = ide_write_devctl, | ||
294 | |||
295 | .dev_select = ns87415_dev_select, | ||
296 | .tf_load = ide_tf_load, | ||
297 | .tf_read = ide_tf_read, | ||
298 | |||
299 | .input_data = ide_input_data, | ||
300 | .output_data = ide_output_data, | ||
299 | }; | 301 | }; |
300 | 302 | ||
301 | static const struct ide_dma_ops ns87415_dma_ops = { | 303 | static const struct ide_dma_ops ns87415_dma_ops = { |
302 | .dma_host_set = ide_dma_host_set, | 304 | .dma_host_set = ide_dma_host_set, |
303 | .dma_setup = ns87415_dma_setup, | 305 | .dma_setup = ide_dma_setup, |
304 | .dma_start = ide_dma_start, | 306 | .dma_start = ns87415_dma_start, |
305 | .dma_end = ns87415_dma_end, | 307 | .dma_end = ns87415_dma_end, |
306 | .dma_test_irq = ide_dma_test_irq, | 308 | .dma_test_irq = ide_dma_test_irq, |
307 | .dma_lost_irq = ide_dma_lost_irq, | 309 | .dma_lost_irq = ide_dma_lost_irq, |
308 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 310 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
309 | .dma_timeout = ide_dma_timeout, | ||
310 | .dma_sff_read_status = superio_dma_sff_read_status, | 311 | .dma_sff_read_status = superio_dma_sff_read_status, |
311 | }; | 312 | }; |
312 | 313 | ||
313 | static const struct ide_port_info ns87415_chipset __devinitdata = { | 314 | static const struct ide_port_info ns87415_chipset __devinitdata = { |
314 | .name = DRV_NAME, | 315 | .name = DRV_NAME, |
315 | .init_hwif = init_hwif_ns87415, | 316 | .init_hwif = init_hwif_ns87415, |
316 | .port_ops = &ns87415_port_ops, | 317 | .tp_ops = &ns87415_tp_ops, |
317 | .dma_ops = &ns87415_dma_ops, | 318 | .dma_ops = &ns87415_dma_ops, |
318 | .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | | 319 | .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | |
319 | IDE_HFLAG_NO_ATAPI_DMA, | 320 | IDE_HFLAG_NO_ATAPI_DMA, |
diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c index f7536d1943f7..248a54bd2386 100644 --- a/drivers/ide/pdc202xx_old.c +++ b/drivers/ide/pdc202xx_old.c | |||
@@ -258,12 +258,6 @@ static void pdc202xx_dma_lost_irq(ide_drive_t *drive) | |||
258 | ide_dma_lost_irq(drive); | 258 | ide_dma_lost_irq(drive); |
259 | } | 259 | } |
260 | 260 | ||
261 | static void pdc202xx_dma_timeout(ide_drive_t *drive) | ||
262 | { | ||
263 | pdc202xx_reset(drive); | ||
264 | ide_dma_timeout(drive); | ||
265 | } | ||
266 | |||
267 | static int init_chipset_pdc202xx(struct pci_dev *dev) | 261 | static int init_chipset_pdc202xx(struct pci_dev *dev) |
268 | { | 262 | { |
269 | unsigned long dmabase = pci_resource_start(dev, 4); | 263 | unsigned long dmabase = pci_resource_start(dev, 4); |
@@ -336,7 +330,7 @@ static const struct ide_dma_ops pdc20246_dma_ops = { | |||
336 | .dma_test_irq = pdc202xx_dma_test_irq, | 330 | .dma_test_irq = pdc202xx_dma_test_irq, |
337 | .dma_lost_irq = pdc202xx_dma_lost_irq, | 331 | .dma_lost_irq = pdc202xx_dma_lost_irq, |
338 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 332 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
339 | .dma_timeout = pdc202xx_dma_timeout, | 333 | .dma_clear = pdc202xx_reset, |
340 | .dma_sff_read_status = ide_dma_sff_read_status, | 334 | .dma_sff_read_status = ide_dma_sff_read_status, |
341 | }; | 335 | }; |
342 | 336 | ||
@@ -348,7 +342,7 @@ static const struct ide_dma_ops pdc2026x_dma_ops = { | |||
348 | .dma_test_irq = pdc202xx_dma_test_irq, | 342 | .dma_test_irq = pdc202xx_dma_test_irq, |
349 | .dma_lost_irq = pdc202xx_dma_lost_irq, | 343 | .dma_lost_irq = pdc202xx_dma_lost_irq, |
350 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 344 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
351 | .dma_timeout = pdc202xx_dma_timeout, | 345 | .dma_clear = pdc202xx_reset, |
352 | .dma_sff_read_status = ide_dma_sff_read_status, | 346 | .dma_sff_read_status = ide_dma_sff_read_status, |
353 | }; | 347 | }; |
354 | 348 | ||
diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c index 2bfcfedaa076..052b9bf1f8fb 100644 --- a/drivers/ide/pmac.c +++ b/drivers/ide/pmac.c | |||
@@ -404,8 +404,6 @@ kauai_lookup_timing(struct kauai_timing* table, int cycle_time) | |||
404 | #define IDE_WAKEUP_DELAY (1*HZ) | 404 | #define IDE_WAKEUP_DELAY (1*HZ) |
405 | 405 | ||
406 | static int pmac_ide_init_dma(ide_hwif_t *, const struct ide_port_info *); | 406 | static int pmac_ide_init_dma(ide_hwif_t *, const struct ide_port_info *); |
407 | static void pmac_ide_selectproc(ide_drive_t *drive); | ||
408 | static void pmac_ide_kauai_selectproc(ide_drive_t *drive); | ||
409 | 407 | ||
410 | #define PMAC_IDE_REG(x) \ | 408 | #define PMAC_IDE_REG(x) \ |
411 | ((void __iomem *)((drive)->hwif->io_ports.data_addr + (x))) | 409 | ((void __iomem *)((drive)->hwif->io_ports.data_addr + (x))) |
@@ -415,8 +413,7 @@ static void pmac_ide_kauai_selectproc(ide_drive_t *drive); | |||
415 | * timing register when selecting that unit. This version is for | 413 | * timing register when selecting that unit. This version is for |
416 | * ASICs with a single timing register | 414 | * ASICs with a single timing register |
417 | */ | 415 | */ |
418 | static void | 416 | static void pmac_ide_apply_timings(ide_drive_t *drive) |
419 | pmac_ide_selectproc(ide_drive_t *drive) | ||
420 | { | 417 | { |
421 | ide_hwif_t *hwif = drive->hwif; | 418 | ide_hwif_t *hwif = drive->hwif; |
422 | pmac_ide_hwif_t *pmif = | 419 | pmac_ide_hwif_t *pmif = |
@@ -434,8 +431,7 @@ pmac_ide_selectproc(ide_drive_t *drive) | |||
434 | * timing register when selecting that unit. This version is for | 431 | * timing register when selecting that unit. This version is for |
435 | * ASICs with a dual timing register (Kauai) | 432 | * ASICs with a dual timing register (Kauai) |
436 | */ | 433 | */ |
437 | static void | 434 | static void pmac_ide_kauai_apply_timings(ide_drive_t *drive) |
438 | pmac_ide_kauai_selectproc(ide_drive_t *drive) | ||
439 | { | 435 | { |
440 | ide_hwif_t *hwif = drive->hwif; | 436 | ide_hwif_t *hwif = drive->hwif; |
441 | pmac_ide_hwif_t *pmif = | 437 | pmac_ide_hwif_t *pmif = |
@@ -464,9 +460,25 @@ pmac_ide_do_update_timings(ide_drive_t *drive) | |||
464 | if (pmif->kind == controller_sh_ata6 || | 460 | if (pmif->kind == controller_sh_ata6 || |
465 | pmif->kind == controller_un_ata6 || | 461 | pmif->kind == controller_un_ata6 || |
466 | pmif->kind == controller_k2_ata6) | 462 | pmif->kind == controller_k2_ata6) |
467 | pmac_ide_kauai_selectproc(drive); | 463 | pmac_ide_kauai_apply_timings(drive); |
468 | else | 464 | else |
469 | pmac_ide_selectproc(drive); | 465 | pmac_ide_apply_timings(drive); |
466 | } | ||
467 | |||
468 | static void pmac_dev_select(ide_drive_t *drive) | ||
469 | { | ||
470 | pmac_ide_apply_timings(drive); | ||
471 | |||
472 | writeb(drive->select | ATA_DEVICE_OBS, | ||
473 | (void __iomem *)drive->hwif->io_ports.device_addr); | ||
474 | } | ||
475 | |||
476 | static void pmac_kauai_dev_select(ide_drive_t *drive) | ||
477 | { | ||
478 | pmac_ide_kauai_apply_timings(drive); | ||
479 | |||
480 | writeb(drive->select | ATA_DEVICE_OBS, | ||
481 | (void __iomem *)drive->hwif->io_ports.device_addr); | ||
470 | } | 482 | } |
471 | 483 | ||
472 | static void pmac_exec_command(ide_hwif_t *hwif, u8 cmd) | 484 | static void pmac_exec_command(ide_hwif_t *hwif, u8 cmd) |
@@ -476,17 +488,8 @@ static void pmac_exec_command(ide_hwif_t *hwif, u8 cmd) | |||
476 | + IDE_TIMING_CONFIG)); | 488 | + IDE_TIMING_CONFIG)); |
477 | } | 489 | } |
478 | 490 | ||
479 | static void pmac_set_irq(ide_hwif_t *hwif, int on) | 491 | static void pmac_write_devctl(ide_hwif_t *hwif, u8 ctl) |
480 | { | 492 | { |
481 | u8 ctl = ATA_DEVCTL_OBS; | ||
482 | |||
483 | if (on == 4) { /* hack for SRST */ | ||
484 | ctl |= 4; | ||
485 | on &= ~4; | ||
486 | } | ||
487 | |||
488 | ctl |= on ? 0 : 2; | ||
489 | |||
490 | writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); | 493 | writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); |
491 | (void)readl((void __iomem *)(hwif->io_ports.data_addr | 494 | (void)readl((void __iomem *)(hwif->io_ports.data_addr |
492 | + IDE_TIMING_CONFIG)); | 495 | + IDE_TIMING_CONFIG)); |
@@ -916,10 +919,18 @@ static u8 pmac_ide_cable_detect(ide_hwif_t *hwif) | |||
916 | (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); | 919 | (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent); |
917 | struct device_node *np = pmif->node; | 920 | struct device_node *np = pmif->node; |
918 | const char *cable = of_get_property(np, "cable-type", NULL); | 921 | const char *cable = of_get_property(np, "cable-type", NULL); |
922 | struct device_node *root = of_find_node_by_path("/"); | ||
923 | const char *model = of_get_property(root, "model", NULL); | ||
919 | 924 | ||
920 | /* Get cable type from device-tree. */ | 925 | /* Get cable type from device-tree. */ |
921 | if (cable && !strncmp(cable, "80-", 3)) | 926 | if (cable && !strncmp(cable, "80-", 3)) { |
922 | return ATA_CBL_PATA80; | 927 | /* Some drives fail to detect 80c cable in PowerBook */ |
928 | /* These machine use proprietary short IDE cable anyway */ | ||
929 | if (!strncmp(model, "PowerBook", 9)) | ||
930 | return ATA_CBL_PATA40_SHORT; | ||
931 | else | ||
932 | return ATA_CBL_PATA80; | ||
933 | } | ||
923 | 934 | ||
924 | /* | 935 | /* |
925 | * G5's seem to have incorrect cable type in device-tree. | 936 | * G5's seem to have incorrect cable type in device-tree. |
@@ -954,9 +965,9 @@ static const struct ide_tp_ops pmac_tp_ops = { | |||
954 | .exec_command = pmac_exec_command, | 965 | .exec_command = pmac_exec_command, |
955 | .read_status = ide_read_status, | 966 | .read_status = ide_read_status, |
956 | .read_altstatus = ide_read_altstatus, | 967 | .read_altstatus = ide_read_altstatus, |
968 | .write_devctl = pmac_write_devctl, | ||
957 | 969 | ||
958 | .set_irq = pmac_set_irq, | 970 | .dev_select = pmac_dev_select, |
959 | |||
960 | .tf_load = ide_tf_load, | 971 | .tf_load = ide_tf_load, |
961 | .tf_read = ide_tf_read, | 972 | .tf_read = ide_tf_read, |
962 | 973 | ||
@@ -964,19 +975,24 @@ static const struct ide_tp_ops pmac_tp_ops = { | |||
964 | .output_data = ide_output_data, | 975 | .output_data = ide_output_data, |
965 | }; | 976 | }; |
966 | 977 | ||
967 | static const struct ide_port_ops pmac_ide_ata6_port_ops = { | 978 | static const struct ide_tp_ops pmac_ata6_tp_ops = { |
968 | .init_dev = pmac_ide_init_dev, | 979 | .exec_command = pmac_exec_command, |
969 | .set_pio_mode = pmac_ide_set_pio_mode, | 980 | .read_status = ide_read_status, |
970 | .set_dma_mode = pmac_ide_set_dma_mode, | 981 | .read_altstatus = ide_read_altstatus, |
971 | .selectproc = pmac_ide_kauai_selectproc, | 982 | .write_devctl = pmac_write_devctl, |
972 | .cable_detect = pmac_ide_cable_detect, | 983 | |
984 | .dev_select = pmac_kauai_dev_select, | ||
985 | .tf_load = ide_tf_load, | ||
986 | .tf_read = ide_tf_read, | ||
987 | |||
988 | .input_data = ide_input_data, | ||
989 | .output_data = ide_output_data, | ||
973 | }; | 990 | }; |
974 | 991 | ||
975 | static const struct ide_port_ops pmac_ide_ata4_port_ops = { | 992 | static const struct ide_port_ops pmac_ide_ata4_port_ops = { |
976 | .init_dev = pmac_ide_init_dev, | 993 | .init_dev = pmac_ide_init_dev, |
977 | .set_pio_mode = pmac_ide_set_pio_mode, | 994 | .set_pio_mode = pmac_ide_set_pio_mode, |
978 | .set_dma_mode = pmac_ide_set_dma_mode, | 995 | .set_dma_mode = pmac_ide_set_dma_mode, |
979 | .selectproc = pmac_ide_selectproc, | ||
980 | .cable_detect = pmac_ide_cable_detect, | 996 | .cable_detect = pmac_ide_cable_detect, |
981 | }; | 997 | }; |
982 | 998 | ||
@@ -984,7 +1000,6 @@ static const struct ide_port_ops pmac_ide_port_ops = { | |||
984 | .init_dev = pmac_ide_init_dev, | 1000 | .init_dev = pmac_ide_init_dev, |
985 | .set_pio_mode = pmac_ide_set_pio_mode, | 1001 | .set_pio_mode = pmac_ide_set_pio_mode, |
986 | .set_dma_mode = pmac_ide_set_dma_mode, | 1002 | .set_dma_mode = pmac_ide_set_dma_mode, |
987 | .selectproc = pmac_ide_selectproc, | ||
988 | }; | 1003 | }; |
989 | 1004 | ||
990 | static const struct ide_dma_ops pmac_dma_ops; | 1005 | static const struct ide_dma_ops pmac_dma_ops; |
@@ -1021,15 +1036,18 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw) | |||
1021 | pmif->broken_dma = pmif->broken_dma_warn = 0; | 1036 | pmif->broken_dma = pmif->broken_dma_warn = 0; |
1022 | if (of_device_is_compatible(np, "shasta-ata")) { | 1037 | if (of_device_is_compatible(np, "shasta-ata")) { |
1023 | pmif->kind = controller_sh_ata6; | 1038 | pmif->kind = controller_sh_ata6; |
1024 | d.port_ops = &pmac_ide_ata6_port_ops; | 1039 | d.tp_ops = &pmac_ata6_tp_ops; |
1040 | d.port_ops = &pmac_ide_ata4_port_ops; | ||
1025 | d.udma_mask = ATA_UDMA6; | 1041 | d.udma_mask = ATA_UDMA6; |
1026 | } else if (of_device_is_compatible(np, "kauai-ata")) { | 1042 | } else if (of_device_is_compatible(np, "kauai-ata")) { |
1027 | pmif->kind = controller_un_ata6; | 1043 | pmif->kind = controller_un_ata6; |
1028 | d.port_ops = &pmac_ide_ata6_port_ops; | 1044 | d.tp_ops = &pmac_ata6_tp_ops; |
1045 | d.port_ops = &pmac_ide_ata4_port_ops; | ||
1029 | d.udma_mask = ATA_UDMA5; | 1046 | d.udma_mask = ATA_UDMA5; |
1030 | } else if (of_device_is_compatible(np, "K2-UATA")) { | 1047 | } else if (of_device_is_compatible(np, "K2-UATA")) { |
1031 | pmif->kind = controller_k2_ata6; | 1048 | pmif->kind = controller_k2_ata6; |
1032 | d.port_ops = &pmac_ide_ata6_port_ops; | 1049 | d.tp_ops = &pmac_ata6_tp_ops; |
1050 | d.port_ops = &pmac_ide_ata4_port_ops; | ||
1033 | d.udma_mask = ATA_UDMA5; | 1051 | d.udma_mask = ATA_UDMA5; |
1034 | } else if (of_device_is_compatible(np, "keylargo-ata")) { | 1052 | } else if (of_device_is_compatible(np, "keylargo-ata")) { |
1035 | if (strcmp(np->name, "ata-4") == 0) { | 1053 | if (strcmp(np->name, "ata-4") == 0) { |
@@ -1455,7 +1473,7 @@ static int pmac_ide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd) | |||
1455 | "switching to PIO on Ohare chipset\n", drive->name); | 1473 | "switching to PIO on Ohare chipset\n", drive->name); |
1456 | pmif->broken_dma_warn = 1; | 1474 | pmif->broken_dma_warn = 1; |
1457 | } | 1475 | } |
1458 | goto use_pio_instead; | 1476 | return 0; |
1459 | } | 1477 | } |
1460 | while (cur_len) { | 1478 | while (cur_len) { |
1461 | unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; | 1479 | unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; |
@@ -1463,7 +1481,7 @@ static int pmac_ide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd) | |||
1463 | if (count++ >= MAX_DCMDS) { | 1481 | if (count++ >= MAX_DCMDS) { |
1464 | printk(KERN_WARNING "%s: DMA table too small\n", | 1482 | printk(KERN_WARNING "%s: DMA table too small\n", |
1465 | drive->name); | 1483 | drive->name); |
1466 | goto use_pio_instead; | 1484 | return 0; |
1467 | } | 1485 | } |
1468 | st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE); | 1486 | st_le16(&table->command, wr? OUTPUT_MORE: INPUT_MORE); |
1469 | st_le16(&table->req_count, tc); | 1487 | st_le16(&table->req_count, tc); |
@@ -1492,9 +1510,6 @@ static int pmac_ide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd) | |||
1492 | 1510 | ||
1493 | printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); | 1511 | printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name); |
1494 | 1512 | ||
1495 | use_pio_instead: | ||
1496 | ide_destroy_dmatable(drive); | ||
1497 | |||
1498 | return 0; /* revert to PIO for this request */ | 1513 | return 0; /* revert to PIO for this request */ |
1499 | } | 1514 | } |
1500 | 1515 | ||
@@ -1510,10 +1525,8 @@ static int pmac_ide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | |||
1510 | u8 unit = drive->dn & 1, ata4 = (pmif->kind == controller_kl_ata4); | 1525 | u8 unit = drive->dn & 1, ata4 = (pmif->kind == controller_kl_ata4); |
1511 | u8 write = !!(cmd->tf_flags & IDE_TFLAG_WRITE); | 1526 | u8 write = !!(cmd->tf_flags & IDE_TFLAG_WRITE); |
1512 | 1527 | ||
1513 | if (pmac_ide_build_dmatable(drive, cmd) == 0) { | 1528 | if (pmac_ide_build_dmatable(drive, cmd) == 0) |
1514 | ide_map_sg(drive, cmd); | ||
1515 | return 1; | 1529 | return 1; |
1516 | } | ||
1517 | 1530 | ||
1518 | /* Apple adds 60ns to wrDataSetup on reads */ | 1531 | /* Apple adds 60ns to wrDataSetup on reads */ |
1519 | if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) { | 1532 | if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) { |
@@ -1522,8 +1535,6 @@ static int pmac_ide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | |||
1522 | (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG)); | 1535 | (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG)); |
1523 | } | 1536 | } |
1524 | 1537 | ||
1525 | drive->waiting_for_dma = 1; | ||
1526 | |||
1527 | return 0; | 1538 | return 0; |
1528 | } | 1539 | } |
1529 | 1540 | ||
@@ -1558,12 +1569,9 @@ pmac_ide_dma_end (ide_drive_t *drive) | |||
1558 | volatile struct dbdma_regs __iomem *dma = pmif->dma_regs; | 1569 | volatile struct dbdma_regs __iomem *dma = pmif->dma_regs; |
1559 | u32 dstat; | 1570 | u32 dstat; |
1560 | 1571 | ||
1561 | drive->waiting_for_dma = 0; | ||
1562 | dstat = readl(&dma->status); | 1572 | dstat = readl(&dma->status); |
1563 | writel(((RUN|WAKE|DEAD) << 16), &dma->control); | 1573 | writel(((RUN|WAKE|DEAD) << 16), &dma->control); |
1564 | 1574 | ||
1565 | ide_destroy_dmatable(drive); | ||
1566 | |||
1567 | /* verify good dma status. we don't check for ACTIVE beeing 0. We should... | 1575 | /* verify good dma status. we don't check for ACTIVE beeing 0. We should... |
1568 | * in theory, but with ATAPI decices doing buffer underruns, that would | 1576 | * in theory, but with ATAPI decices doing buffer underruns, that would |
1569 | * cause us to disable DMA, which isn't what we want | 1577 | * cause us to disable DMA, which isn't what we want |
@@ -1650,7 +1658,6 @@ static const struct ide_dma_ops pmac_dma_ops = { | |||
1650 | .dma_start = pmac_ide_dma_start, | 1658 | .dma_start = pmac_ide_dma_start, |
1651 | .dma_end = pmac_ide_dma_end, | 1659 | .dma_end = pmac_ide_dma_end, |
1652 | .dma_test_irq = pmac_ide_dma_test_irq, | 1660 | .dma_test_irq = pmac_ide_dma_test_irq, |
1653 | .dma_timeout = ide_dma_timeout, | ||
1654 | .dma_lost_irq = pmac_ide_dma_lost_irq, | 1661 | .dma_lost_irq = pmac_ide_dma_lost_irq, |
1655 | }; | 1662 | }; |
1656 | 1663 | ||
diff --git a/drivers/ide/q40ide.c b/drivers/ide/q40ide.c index 2a43a2f49633..d007e7f66598 100644 --- a/drivers/ide/q40ide.c +++ b/drivers/ide/q40ide.c | |||
@@ -99,9 +99,9 @@ static const struct ide_tp_ops q40ide_tp_ops = { | |||
99 | .exec_command = ide_exec_command, | 99 | .exec_command = ide_exec_command, |
100 | .read_status = ide_read_status, | 100 | .read_status = ide_read_status, |
101 | .read_altstatus = ide_read_altstatus, | 101 | .read_altstatus = ide_read_altstatus, |
102 | .write_devctl = ide_write_devctl, | ||
102 | 103 | ||
103 | .set_irq = ide_set_irq, | 104 | .dev_select = ide_dev_select, |
104 | |||
105 | .tf_load = ide_tf_load, | 105 | .tf_load = ide_tf_load, |
106 | .tf_read = ide_tf_read, | 106 | .tf_read = ide_tf_read, |
107 | 107 | ||
diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c index 08c4fa35e9b1..c9a134986891 100644 --- a/drivers/ide/qd65xx.c +++ b/drivers/ide/qd65xx.c | |||
@@ -90,13 +90,15 @@ static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */ | |||
90 | * This routine is invoked to prepare for access to a given drive. | 90 | * This routine is invoked to prepare for access to a given drive. |
91 | */ | 91 | */ |
92 | 92 | ||
93 | static void qd65xx_select(ide_drive_t *drive) | 93 | static void qd65xx_dev_select(ide_drive_t *drive) |
94 | { | 94 | { |
95 | u8 index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) | | 95 | u8 index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) | |
96 | (QD_TIMREG(drive) & 0x02); | 96 | (QD_TIMREG(drive) & 0x02); |
97 | 97 | ||
98 | if (timings[index] != QD_TIMING(drive)) | 98 | if (timings[index] != QD_TIMING(drive)) |
99 | outb(timings[index] = QD_TIMING(drive), QD_TIMREG(drive)); | 99 | outb(timings[index] = QD_TIMING(drive), QD_TIMREG(drive)); |
100 | |||
101 | outb(drive->select | ATA_DEVICE_OBS, drive->hwif->io_ports.device_addr); | ||
100 | } | 102 | } |
101 | 103 | ||
102 | /* | 104 | /* |
@@ -309,20 +311,33 @@ static void __init qd6580_init_dev(ide_drive_t *drive) | |||
309 | drive->drive_data = (drive->dn & 1) ? t2 : t1; | 311 | drive->drive_data = (drive->dn & 1) ? t2 : t1; |
310 | } | 312 | } |
311 | 313 | ||
314 | static const struct ide_tp_ops qd65xx_tp_ops = { | ||
315 | .exec_command = ide_exec_command, | ||
316 | .read_status = ide_read_status, | ||
317 | .read_altstatus = ide_read_altstatus, | ||
318 | .write_devctl = ide_write_devctl, | ||
319 | |||
320 | .dev_select = qd65xx_dev_select, | ||
321 | .tf_load = ide_tf_load, | ||
322 | .tf_read = ide_tf_read, | ||
323 | |||
324 | .input_data = ide_input_data, | ||
325 | .output_data = ide_output_data, | ||
326 | }; | ||
327 | |||
312 | static const struct ide_port_ops qd6500_port_ops = { | 328 | static const struct ide_port_ops qd6500_port_ops = { |
313 | .init_dev = qd6500_init_dev, | 329 | .init_dev = qd6500_init_dev, |
314 | .set_pio_mode = qd6500_set_pio_mode, | 330 | .set_pio_mode = qd6500_set_pio_mode, |
315 | .selectproc = qd65xx_select, | ||
316 | }; | 331 | }; |
317 | 332 | ||
318 | static const struct ide_port_ops qd6580_port_ops = { | 333 | static const struct ide_port_ops qd6580_port_ops = { |
319 | .init_dev = qd6580_init_dev, | 334 | .init_dev = qd6580_init_dev, |
320 | .set_pio_mode = qd6580_set_pio_mode, | 335 | .set_pio_mode = qd6580_set_pio_mode, |
321 | .selectproc = qd65xx_select, | ||
322 | }; | 336 | }; |
323 | 337 | ||
324 | static const struct ide_port_info qd65xx_port_info __initdata = { | 338 | static const struct ide_port_info qd65xx_port_info __initdata = { |
325 | .name = DRV_NAME, | 339 | .name = DRV_NAME, |
340 | .tp_ops = &qd65xx_tp_ops, | ||
326 | .chipset = ide_qd65xx, | 341 | .chipset = ide_qd65xx, |
327 | .host_flags = IDE_HFLAG_IO_32BIT | | 342 | .host_flags = IDE_HFLAG_IO_32BIT | |
328 | IDE_HFLAG_NO_DMA, | 343 | IDE_HFLAG_NO_DMA, |
diff --git a/drivers/ide/sc1200.c b/drivers/ide/sc1200.c index 1c3a82914999..d467478d68da 100644 --- a/drivers/ide/sc1200.c +++ b/drivers/ide/sc1200.c | |||
@@ -115,8 +115,7 @@ static u8 sc1200_udma_filter(ide_drive_t *drive) | |||
115 | if ((mateid[ATA_ID_FIELD_VALID] & 4) && | 115 | if ((mateid[ATA_ID_FIELD_VALID] & 4) && |
116 | (mateid[ATA_ID_UDMA_MODES] & 7)) | 116 | (mateid[ATA_ID_UDMA_MODES] & 7)) |
117 | goto out; | 117 | goto out; |
118 | if ((mateid[ATA_ID_FIELD_VALID] & 2) && | 118 | if (mateid[ATA_ID_MWDMA_MODES] & 7) |
119 | (mateid[ATA_ID_MWDMA_MODES] & 7)) | ||
120 | mask = 0; | 119 | mask = 0; |
121 | } | 120 | } |
122 | out: | 121 | out: |
@@ -183,9 +182,6 @@ static int sc1200_dma_end(ide_drive_t *drive) | |||
183 | outb(dma_stat|0x1b, dma_base+2); /* clear the INTR & ERROR bits */ | 182 | outb(dma_stat|0x1b, dma_base+2); /* clear the INTR & ERROR bits */ |
184 | outb(inb(dma_base)&~1, dma_base); /* !! DO THIS HERE !! stop DMA */ | 183 | outb(inb(dma_base)&~1, dma_base); /* !! DO THIS HERE !! stop DMA */ |
185 | 184 | ||
186 | drive->waiting_for_dma = 0; | ||
187 | ide_destroy_dmatable(drive); /* purge DMA mappings */ | ||
188 | |||
189 | return (dma_stat & 7) != 4; /* verify good DMA status */ | 185 | return (dma_stat & 7) != 4; /* verify good DMA status */ |
190 | } | 186 | } |
191 | 187 | ||
@@ -291,7 +287,6 @@ static const struct ide_dma_ops sc1200_dma_ops = { | |||
291 | .dma_test_irq = ide_dma_test_irq, | 287 | .dma_test_irq = ide_dma_test_irq, |
292 | .dma_lost_irq = ide_dma_lost_irq, | 288 | .dma_lost_irq = ide_dma_lost_irq, |
293 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 289 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
294 | .dma_timeout = ide_dma_timeout, | ||
295 | .dma_sff_read_status = ide_dma_sff_read_status, | 290 | .dma_sff_read_status = ide_dma_sff_read_status, |
296 | }; | 291 | }; |
297 | 292 | ||
diff --git a/drivers/ide/scc_pata.c b/drivers/ide/scc_pata.c index 0cc137cfe76d..6d8dbd9c10bc 100644 --- a/drivers/ide/scc_pata.c +++ b/drivers/ide/scc_pata.c | |||
@@ -148,17 +148,8 @@ static u8 scc_dma_sff_read_status(ide_hwif_t *hwif) | |||
148 | return (u8)in_be32((void *)(hwif->dma_base + 4)); | 148 | return (u8)in_be32((void *)(hwif->dma_base + 4)); |
149 | } | 149 | } |
150 | 150 | ||
151 | static void scc_set_irq(ide_hwif_t *hwif, int on) | 151 | static void scc_write_devctl(ide_hwif_t *hwif, u8 ctl) |
152 | { | 152 | { |
153 | u8 ctl = ATA_DEVCTL_OBS; | ||
154 | |||
155 | if (on == 4) { /* hack for SRST */ | ||
156 | ctl |= 4; | ||
157 | on &= ~4; | ||
158 | } | ||
159 | |||
160 | ctl |= on ? 0 : 2; | ||
161 | |||
162 | out_be32((void *)hwif->io_ports.ctl_addr, ctl); | 153 | out_be32((void *)hwif->io_ports.ctl_addr, ctl); |
163 | eieio(); | 154 | eieio(); |
164 | in_be32((void *)(hwif->dma_base + 0x01c)); | 155 | in_be32((void *)(hwif->dma_base + 0x01c)); |
@@ -321,10 +312,8 @@ static int scc_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | |||
321 | u8 dma_stat; | 312 | u8 dma_stat; |
322 | 313 | ||
323 | /* fall back to pio! */ | 314 | /* fall back to pio! */ |
324 | if (ide_build_dmatable(drive, cmd) == 0) { | 315 | if (ide_build_dmatable(drive, cmd) == 0) |
325 | ide_map_sg(drive, cmd); | ||
326 | return 1; | 316 | return 1; |
327 | } | ||
328 | 317 | ||
329 | /* PRD table */ | 318 | /* PRD table */ |
330 | out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma); | 319 | out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma); |
@@ -337,7 +326,7 @@ static int scc_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | |||
337 | 326 | ||
338 | /* clear INTR & ERROR flags */ | 327 | /* clear INTR & ERROR flags */ |
339 | out_be32((void __iomem *)(hwif->dma_base + 4), dma_stat | 6); | 328 | out_be32((void __iomem *)(hwif->dma_base + 4), dma_stat | 6); |
340 | drive->waiting_for_dma = 1; | 329 | |
341 | return 0; | 330 | return 0; |
342 | } | 331 | } |
343 | 332 | ||
@@ -356,7 +345,6 @@ static int __scc_dma_end(ide_drive_t *drive) | |||
356 | ide_hwif_t *hwif = drive->hwif; | 345 | ide_hwif_t *hwif = drive->hwif; |
357 | u8 dma_stat, dma_cmd; | 346 | u8 dma_stat, dma_cmd; |
358 | 347 | ||
359 | drive->waiting_for_dma = 0; | ||
360 | /* get DMA command mode */ | 348 | /* get DMA command mode */ |
361 | dma_cmd = scc_ide_inb(hwif->dma_base); | 349 | dma_cmd = scc_ide_inb(hwif->dma_base); |
362 | /* stop DMA */ | 350 | /* stop DMA */ |
@@ -365,8 +353,6 @@ static int __scc_dma_end(ide_drive_t *drive) | |||
365 | dma_stat = scc_dma_sff_read_status(hwif); | 353 | dma_stat = scc_dma_sff_read_status(hwif); |
366 | /* clear the INTR & ERROR bits */ | 354 | /* clear the INTR & ERROR bits */ |
367 | scc_ide_outb(dma_stat | 6, hwif->dma_base + 4); | 355 | scc_ide_outb(dma_stat | 6, hwif->dma_base + 4); |
368 | /* purge DMA mappings */ | ||
369 | ide_destroy_dmatable(drive); | ||
370 | /* verify good DMA status */ | 356 | /* verify good DMA status */ |
371 | wmb(); | 357 | wmb(); |
372 | return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; | 358 | return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; |
@@ -670,10 +656,6 @@ static void scc_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | |||
670 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) | 656 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) |
671 | HIHI = 0xFF; | 657 | HIHI = 0xFF; |
672 | 658 | ||
673 | if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) | ||
674 | out_be32((void *)io_ports->data_addr, | ||
675 | (tf->hob_data << 8) | tf->data); | ||
676 | |||
677 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | 659 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) |
678 | scc_ide_outb(tf->hob_feature, io_ports->feature_addr); | 660 | scc_ide_outb(tf->hob_feature, io_ports->feature_addr); |
679 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | 661 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) |
@@ -706,18 +688,11 @@ static void scc_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
706 | struct ide_io_ports *io_ports = &drive->hwif->io_ports; | 688 | struct ide_io_ports *io_ports = &drive->hwif->io_ports; |
707 | struct ide_taskfile *tf = &cmd->tf; | 689 | struct ide_taskfile *tf = &cmd->tf; |
708 | 690 | ||
709 | if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) { | ||
710 | u16 data = (u16)in_be32((void *)io_ports->data_addr); | ||
711 | |||
712 | tf->data = data & 0xff; | ||
713 | tf->hob_data = (data >> 8) & 0xff; | ||
714 | } | ||
715 | |||
716 | /* be sure we're looking at the low order bits */ | 691 | /* be sure we're looking at the low order bits */ |
717 | scc_ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); | 692 | scc_ide_outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); |
718 | 693 | ||
719 | if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE) | 694 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) |
720 | tf->feature = scc_ide_inb(io_ports->feature_addr); | 695 | tf->error = scc_ide_inb(io_ports->feature_addr); |
721 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | 696 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) |
722 | tf->nsect = scc_ide_inb(io_ports->nsect_addr); | 697 | tf->nsect = scc_ide_inb(io_ports->nsect_addr); |
723 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | 698 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) |
@@ -730,18 +705,18 @@ static void scc_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
730 | tf->device = scc_ide_inb(io_ports->device_addr); | 705 | tf->device = scc_ide_inb(io_ports->device_addr); |
731 | 706 | ||
732 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | 707 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { |
733 | scc_ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); | 708 | scc_ide_outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); |
734 | 709 | ||
735 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | 710 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) |
736 | tf->hob_feature = scc_ide_inb(io_ports->feature_addr); | 711 | tf->hob_error = scc_ide_inb(io_ports->feature_addr); |
737 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | 712 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) |
738 | tf->hob_nsect = scc_ide_inb(io_ports->nsect_addr); | 713 | tf->hob_nsect = scc_ide_inb(io_ports->nsect_addr); |
739 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | 714 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) |
740 | tf->hob_lbal = scc_ide_inb(io_ports->lbal_addr); | 715 | tf->hob_lbal = scc_ide_inb(io_ports->lbal_addr); |
741 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | 716 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) |
742 | tf->hob_lbam = scc_ide_inb(io_ports->lbam_addr); | 717 | tf->hob_lbam = scc_ide_inb(io_ports->lbam_addr); |
743 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | 718 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) |
744 | tf->hob_lbah = scc_ide_inb(io_ports->lbah_addr); | 719 | tf->hob_lbah = scc_ide_inb(io_ports->lbah_addr); |
745 | } | 720 | } |
746 | } | 721 | } |
747 | 722 | ||
@@ -848,9 +823,9 @@ static const struct ide_tp_ops scc_tp_ops = { | |||
848 | .exec_command = scc_exec_command, | 823 | .exec_command = scc_exec_command, |
849 | .read_status = scc_read_status, | 824 | .read_status = scc_read_status, |
850 | .read_altstatus = scc_read_altstatus, | 825 | .read_altstatus = scc_read_altstatus, |
826 | .write_devctl = scc_write_devctl, | ||
851 | 827 | ||
852 | .set_irq = scc_set_irq, | 828 | .dev_select = ide_dev_select, |
853 | |||
854 | .tf_load = scc_tf_load, | 829 | .tf_load = scc_tf_load, |
855 | .tf_read = scc_tf_read, | 830 | .tf_read = scc_tf_read, |
856 | 831 | ||
@@ -872,7 +847,6 @@ static const struct ide_dma_ops scc_dma_ops = { | |||
872 | .dma_end = scc_dma_end, | 847 | .dma_end = scc_dma_end, |
873 | .dma_test_irq = scc_dma_test_irq, | 848 | .dma_test_irq = scc_dma_test_irq, |
874 | .dma_lost_irq = ide_dma_lost_irq, | 849 | .dma_lost_irq = ide_dma_lost_irq, |
875 | .dma_timeout = ide_dma_timeout, | ||
876 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 850 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
877 | .dma_sff_read_status = scc_dma_sff_read_status, | 851 | .dma_sff_read_status = scc_dma_sff_read_status, |
878 | }; | 852 | }; |
diff --git a/drivers/ide/sgiioc4.c b/drivers/ide/sgiioc4.c index b12de8346c73..e5d2a48a84de 100644 --- a/drivers/ide/sgiioc4.c +++ b/drivers/ide/sgiioc4.c | |||
@@ -258,9 +258,6 @@ static int sgiioc4_dma_end(ide_drive_t *drive) | |||
258 | } | 258 | } |
259 | } | 259 | } |
260 | 260 | ||
261 | drive->waiting_for_dma = 0; | ||
262 | ide_destroy_dmatable(drive); | ||
263 | |||
264 | return dma_stat; | 261 | return dma_stat; |
265 | } | 262 | } |
266 | 263 | ||
@@ -280,10 +277,12 @@ static void sgiioc4_dma_host_set(ide_drive_t *drive, int on) | |||
280 | sgiioc4_clearirq(drive); | 277 | sgiioc4_clearirq(drive); |
281 | } | 278 | } |
282 | 279 | ||
283 | static void | 280 | static void sgiioc4_resetproc(ide_drive_t *drive) |
284 | sgiioc4_resetproc(ide_drive_t * drive) | ||
285 | { | 281 | { |
282 | struct ide_cmd *cmd = &drive->hwif->cmd; | ||
283 | |||
286 | sgiioc4_dma_end(drive); | 284 | sgiioc4_dma_end(drive); |
285 | ide_dma_unmap_sg(drive, cmd); | ||
287 | sgiioc4_clearirq(drive); | 286 | sgiioc4_clearirq(drive); |
288 | } | 287 | } |
289 | 288 | ||
@@ -412,7 +411,6 @@ sgiioc4_configure_for_dma(int dma_direction, ide_drive_t * drive) | |||
412 | writel(ending_dma_addr, (void __iomem *)(dma_base + IOC4_DMA_END_ADDR * 4)); | 411 | writel(ending_dma_addr, (void __iomem *)(dma_base + IOC4_DMA_END_ADDR * 4)); |
413 | 412 | ||
414 | writel(dma_direction, (void __iomem *)ioc4_dma_addr); | 413 | writel(dma_direction, (void __iomem *)ioc4_dma_addr); |
415 | drive->waiting_for_dma = 1; | ||
416 | } | 414 | } |
417 | 415 | ||
418 | /* IOC4 Scatter Gather list Format */ | 416 | /* IOC4 Scatter Gather list Format */ |
@@ -442,7 +440,7 @@ static int sgiioc4_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd) | |||
442 | printk(KERN_WARNING | 440 | printk(KERN_WARNING |
443 | "%s: DMA table too small\n", | 441 | "%s: DMA table too small\n", |
444 | drive->name); | 442 | drive->name); |
445 | goto use_pio_instead; | 443 | return 0; |
446 | } else { | 444 | } else { |
447 | u32 bcount = | 445 | u32 bcount = |
448 | 0x10000 - (cur_addr & 0xffff); | 446 | 0x10000 - (cur_addr & 0xffff); |
@@ -477,9 +475,6 @@ static int sgiioc4_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd) | |||
477 | return count; | 475 | return count; |
478 | } | 476 | } |
479 | 477 | ||
480 | use_pio_instead: | ||
481 | ide_destroy_dmatable(drive); | ||
482 | |||
483 | return 0; /* revert to PIO for this request */ | 478 | return 0; /* revert to PIO for this request */ |
484 | } | 479 | } |
485 | 480 | ||
@@ -488,11 +483,9 @@ static int sgiioc4_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | |||
488 | int ddir; | 483 | int ddir; |
489 | u8 write = !!(cmd->tf_flags & IDE_TFLAG_WRITE); | 484 | u8 write = !!(cmd->tf_flags & IDE_TFLAG_WRITE); |
490 | 485 | ||
491 | if (sgiioc4_build_dmatable(drive, cmd) == 0) { | 486 | if (sgiioc4_build_dmatable(drive, cmd) == 0) |
492 | /* try PIO instead of DMA */ | 487 | /* try PIO instead of DMA */ |
493 | ide_map_sg(drive, cmd); | ||
494 | return 1; | 488 | return 1; |
495 | } | ||
496 | 489 | ||
497 | if (write) | 490 | if (write) |
498 | /* Writes TO the IOC4 FROM Main Memory */ | 491 | /* Writes TO the IOC4 FROM Main Memory */ |
@@ -510,9 +503,9 @@ static const struct ide_tp_ops sgiioc4_tp_ops = { | |||
510 | .exec_command = ide_exec_command, | 503 | .exec_command = ide_exec_command, |
511 | .read_status = sgiioc4_read_status, | 504 | .read_status = sgiioc4_read_status, |
512 | .read_altstatus = ide_read_altstatus, | 505 | .read_altstatus = ide_read_altstatus, |
506 | .write_devctl = ide_write_devctl, | ||
513 | 507 | ||
514 | .set_irq = ide_set_irq, | 508 | .dev_select = ide_dev_select, |
515 | |||
516 | .tf_load = ide_tf_load, | 509 | .tf_load = ide_tf_load, |
517 | .tf_read = ide_tf_read, | 510 | .tf_read = ide_tf_read, |
518 | 511 | ||
@@ -533,7 +526,6 @@ static const struct ide_dma_ops sgiioc4_dma_ops = { | |||
533 | .dma_end = sgiioc4_dma_end, | 526 | .dma_end = sgiioc4_dma_end, |
534 | .dma_test_irq = sgiioc4_dma_test_irq, | 527 | .dma_test_irq = sgiioc4_dma_test_irq, |
535 | .dma_lost_irq = sgiioc4_dma_lost_irq, | 528 | .dma_lost_irq = sgiioc4_dma_lost_irq, |
536 | .dma_timeout = ide_dma_timeout, | ||
537 | }; | 529 | }; |
538 | 530 | ||
539 | static const struct ide_port_info sgiioc4_port_info __devinitconst = { | 531 | static const struct ide_port_info sgiioc4_port_info __devinitconst = { |
diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c index 075cb1243b2a..e4973cd1fba9 100644 --- a/drivers/ide/siimage.c +++ b/drivers/ide/siimage.c | |||
@@ -715,7 +715,6 @@ static const struct ide_dma_ops sil_dma_ops = { | |||
715 | .dma_end = ide_dma_end, | 715 | .dma_end = ide_dma_end, |
716 | .dma_test_irq = siimage_dma_test_irq, | 716 | .dma_test_irq = siimage_dma_test_irq, |
717 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 717 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
718 | .dma_timeout = ide_dma_timeout, | ||
719 | .dma_lost_irq = ide_dma_lost_irq, | 718 | .dma_lost_irq = ide_dma_lost_irq, |
720 | .dma_sff_read_status = ide_dma_sff_read_status, | 719 | .dma_sff_read_status = ide_dma_sff_read_status, |
721 | }; | 720 | }; |
diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c index d25137b04e7a..b0a460625335 100644 --- a/drivers/ide/sl82c105.c +++ b/drivers/ide/sl82c105.c | |||
@@ -61,7 +61,8 @@ static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio) | |||
61 | if (cmd_off == 0) | 61 | if (cmd_off == 0) |
62 | cmd_off = 1; | 62 | cmd_off = 1; |
63 | 63 | ||
64 | if (pio > 2 || ata_id_has_iordy(drive->id)) | 64 | if ((pio > 2 || ata_id_has_iordy(drive->id)) && |
65 | !(pio > 4 && ata_id_is_cfa(drive->id))) | ||
65 | iordy = 0x40; | 66 | iordy = 0x40; |
66 | 67 | ||
67 | return (cmd_on - 1) << 8 | (cmd_off - 1) | iordy; | 68 | return (cmd_on - 1) << 8 | (cmd_off - 1) | iordy; |
@@ -189,14 +190,13 @@ static void sl82c105_dma_start(ide_drive_t *drive) | |||
189 | ide_dma_start(drive); | 190 | ide_dma_start(drive); |
190 | } | 191 | } |
191 | 192 | ||
192 | static void sl82c105_dma_timeout(ide_drive_t *drive) | 193 | static void sl82c105_dma_clear(ide_drive_t *drive) |
193 | { | 194 | { |
194 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); | 195 | struct pci_dev *dev = to_pci_dev(drive->hwif->dev); |
195 | 196 | ||
196 | DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name)); | 197 | DBG(("sl82c105_dma_clear(drive:%s)\n", drive->name)); |
197 | 198 | ||
198 | sl82c105_reset_host(dev); | 199 | sl82c105_reset_host(dev); |
199 | ide_dma_timeout(drive); | ||
200 | } | 200 | } |
201 | 201 | ||
202 | static int sl82c105_dma_end(ide_drive_t *drive) | 202 | static int sl82c105_dma_end(ide_drive_t *drive) |
@@ -298,7 +298,7 @@ static const struct ide_dma_ops sl82c105_dma_ops = { | |||
298 | .dma_test_irq = ide_dma_test_irq, | 298 | .dma_test_irq = ide_dma_test_irq, |
299 | .dma_lost_irq = sl82c105_dma_lost_irq, | 299 | .dma_lost_irq = sl82c105_dma_lost_irq, |
300 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 300 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
301 | .dma_timeout = sl82c105_dma_timeout, | 301 | .dma_clear = sl82c105_dma_clear, |
302 | .dma_sff_read_status = ide_dma_sff_read_status, | 302 | .dma_sff_read_status = ide_dma_sff_read_status, |
303 | }; | 303 | }; |
304 | 304 | ||
diff --git a/drivers/ide/tc86c001.c b/drivers/ide/tc86c001.c index 427d4b3c2c63..b4cf42dc8a6f 100644 --- a/drivers/ide/tc86c001.c +++ b/drivers/ide/tc86c001.c | |||
@@ -187,7 +187,6 @@ static const struct ide_dma_ops tc86c001_dma_ops = { | |||
187 | .dma_test_irq = ide_dma_test_irq, | 187 | .dma_test_irq = ide_dma_test_irq, |
188 | .dma_lost_irq = ide_dma_lost_irq, | 188 | .dma_lost_irq = ide_dma_lost_irq, |
189 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 189 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
190 | .dma_timeout = ide_dma_timeout, | ||
191 | .dma_sff_read_status = ide_dma_sff_read_status, | 190 | .dma_sff_read_status = ide_dma_sff_read_status, |
192 | }; | 191 | }; |
193 | 192 | ||
diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c index ed1496845a93..4b42ca091534 100644 --- a/drivers/ide/trm290.c +++ b/drivers/ide/trm290.c | |||
@@ -171,54 +171,51 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma) | |||
171 | local_irq_restore(flags); | 171 | local_irq_restore(flags); |
172 | } | 172 | } |
173 | 173 | ||
174 | static void trm290_selectproc (ide_drive_t *drive) | 174 | static void trm290_dev_select(ide_drive_t *drive) |
175 | { | 175 | { |
176 | trm290_prepare_drive(drive, !!(drive->dev_flags & IDE_DFLAG_USING_DMA)); | 176 | trm290_prepare_drive(drive, !!(drive->dev_flags & IDE_DFLAG_USING_DMA)); |
177 | |||
178 | outb(drive->select | ATA_DEVICE_OBS, drive->hwif->io_ports.device_addr); | ||
177 | } | 179 | } |
178 | 180 | ||
179 | static int trm290_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | 181 | static int trm290_dma_check(ide_drive_t *drive, struct ide_cmd *cmd) |
180 | { | 182 | { |
181 | ide_hwif_t *hwif = drive->hwif; | ||
182 | unsigned int count, rw; | ||
183 | |||
184 | if (cmd->tf_flags & IDE_TFLAG_WRITE) { | 183 | if (cmd->tf_flags & IDE_TFLAG_WRITE) { |
185 | #ifdef TRM290_NO_DMA_WRITES | 184 | #ifdef TRM290_NO_DMA_WRITES |
186 | /* always use PIO for writes */ | 185 | /* always use PIO for writes */ |
187 | trm290_prepare_drive(drive, 0); /* select PIO xfer */ | ||
188 | return 1; | 186 | return 1; |
189 | #endif | 187 | #endif |
190 | rw = 1; | 188 | } |
191 | } else | 189 | return 0; |
192 | rw = 2; | 190 | } |
191 | |||
192 | static int trm290_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | ||
193 | { | ||
194 | ide_hwif_t *hwif = drive->hwif; | ||
195 | unsigned int count, rw = (cmd->tf_flags & IDE_TFLAG_WRITE) ? 1 : 2; | ||
193 | 196 | ||
194 | count = ide_build_dmatable(drive, cmd); | 197 | count = ide_build_dmatable(drive, cmd); |
195 | if (count == 0) { | 198 | if (count == 0) |
196 | ide_map_sg(drive, cmd); | ||
197 | /* try PIO instead of DMA */ | 199 | /* try PIO instead of DMA */ |
198 | trm290_prepare_drive(drive, 0); /* select PIO xfer */ | ||
199 | return 1; | 200 | return 1; |
200 | } | 201 | |
201 | /* select DMA xfer */ | ||
202 | trm290_prepare_drive(drive, 1); | ||
203 | outl(hwif->dmatable_dma | rw, hwif->dma_base); | 202 | outl(hwif->dmatable_dma | rw, hwif->dma_base); |
204 | drive->waiting_for_dma = 1; | ||
205 | /* start DMA */ | 203 | /* start DMA */ |
206 | outw(count * 2 - 1, hwif->dma_base + 2); | 204 | outw(count * 2 - 1, hwif->dma_base + 2); |
205 | |||
207 | return 0; | 206 | return 0; |
208 | } | 207 | } |
209 | 208 | ||
210 | static void trm290_dma_start(ide_drive_t *drive) | 209 | static void trm290_dma_start(ide_drive_t *drive) |
211 | { | 210 | { |
211 | trm290_prepare_drive(drive, 1); | ||
212 | } | 212 | } |
213 | 213 | ||
214 | static int trm290_dma_end(ide_drive_t *drive) | 214 | static int trm290_dma_end(ide_drive_t *drive) |
215 | { | 215 | { |
216 | u16 status; | 216 | u16 status = inw(drive->hwif->dma_base + 2); |
217 | 217 | ||
218 | drive->waiting_for_dma = 0; | 218 | trm290_prepare_drive(drive, 0); |
219 | /* purge DMA mappings */ | ||
220 | ide_destroy_dmatable(drive); | ||
221 | status = inw(drive->hwif->dma_base + 2); | ||
222 | 219 | ||
223 | return status != 0x00ff; | 220 | return status != 0x00ff; |
224 | } | 221 | } |
@@ -303,8 +300,18 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) | |||
303 | #endif | 300 | #endif |
304 | } | 301 | } |
305 | 302 | ||
306 | static const struct ide_port_ops trm290_port_ops = { | 303 | static const struct ide_tp_ops trm290_tp_ops = { |
307 | .selectproc = trm290_selectproc, | 304 | .exec_command = ide_exec_command, |
305 | .read_status = ide_read_status, | ||
306 | .read_altstatus = ide_read_altstatus, | ||
307 | .write_devctl = ide_write_devctl, | ||
308 | |||
309 | .dev_select = trm290_dev_select, | ||
310 | .tf_load = ide_tf_load, | ||
311 | .tf_read = ide_tf_read, | ||
312 | |||
313 | .input_data = ide_input_data, | ||
314 | .output_data = ide_output_data, | ||
308 | }; | 315 | }; |
309 | 316 | ||
310 | static struct ide_dma_ops trm290_dma_ops = { | 317 | static struct ide_dma_ops trm290_dma_ops = { |
@@ -314,13 +321,13 @@ static struct ide_dma_ops trm290_dma_ops = { | |||
314 | .dma_end = trm290_dma_end, | 321 | .dma_end = trm290_dma_end, |
315 | .dma_test_irq = trm290_dma_test_irq, | 322 | .dma_test_irq = trm290_dma_test_irq, |
316 | .dma_lost_irq = ide_dma_lost_irq, | 323 | .dma_lost_irq = ide_dma_lost_irq, |
317 | .dma_timeout = ide_dma_timeout, | 324 | .dma_check = trm290_dma_check, |
318 | }; | 325 | }; |
319 | 326 | ||
320 | static const struct ide_port_info trm290_chipset __devinitdata = { | 327 | static const struct ide_port_info trm290_chipset __devinitdata = { |
321 | .name = DRV_NAME, | 328 | .name = DRV_NAME, |
322 | .init_hwif = init_hwif_trm290, | 329 | .init_hwif = init_hwif_trm290, |
323 | .port_ops = &trm290_port_ops, | 330 | .tp_ops = &trm290_tp_ops, |
324 | .dma_ops = &trm290_dma_ops, | 331 | .dma_ops = &trm290_dma_ops, |
325 | .host_flags = IDE_HFLAG_TRM290 | | 332 | .host_flags = IDE_HFLAG_TRM290 | |
326 | IDE_HFLAG_NO_ATAPI_DMA | | 333 | IDE_HFLAG_NO_ATAPI_DMA | |
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c index 657a61890b1c..4cb79c4c2604 100644 --- a/drivers/ide/tx4938ide.c +++ b/drivers/ide/tx4938ide.c | |||
@@ -92,13 +92,6 @@ static void tx4938ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | |||
92 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) | 92 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) |
93 | HIHI = 0xFF; | 93 | HIHI = 0xFF; |
94 | 94 | ||
95 | if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) { | ||
96 | u16 data = (tf->hob_data << 8) | tf->data; | ||
97 | |||
98 | /* no endian swap */ | ||
99 | __raw_writew(data, (void __iomem *)io_ports->data_addr); | ||
100 | } | ||
101 | |||
102 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | 95 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) |
103 | tx4938ide_outb(tf->hob_feature, io_ports->feature_addr); | 96 | tx4938ide_outb(tf->hob_feature, io_ports->feature_addr); |
104 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | 97 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) |
@@ -132,20 +125,11 @@ static void tx4938ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
132 | struct ide_io_ports *io_ports = &hwif->io_ports; | 125 | struct ide_io_ports *io_ports = &hwif->io_ports; |
133 | struct ide_taskfile *tf = &cmd->tf; | 126 | struct ide_taskfile *tf = &cmd->tf; |
134 | 127 | ||
135 | if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) { | ||
136 | u16 data; | ||
137 | |||
138 | /* no endian swap */ | ||
139 | data = __raw_readw((void __iomem *)io_ports->data_addr); | ||
140 | tf->data = data & 0xff; | ||
141 | tf->hob_data = (data >> 8) & 0xff; | ||
142 | } | ||
143 | |||
144 | /* be sure we're looking at the low order bits */ | 128 | /* be sure we're looking at the low order bits */ |
145 | tx4938ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); | 129 | tx4938ide_outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); |
146 | 130 | ||
147 | if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE) | 131 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) |
148 | tf->feature = tx4938ide_inb(io_ports->feature_addr); | 132 | tf->error = tx4938ide_inb(io_ports->feature_addr); |
149 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | 133 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) |
150 | tf->nsect = tx4938ide_inb(io_ports->nsect_addr); | 134 | tf->nsect = tx4938ide_inb(io_ports->nsect_addr); |
151 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | 135 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) |
@@ -158,19 +142,18 @@ static void tx4938ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
158 | tf->device = tx4938ide_inb(io_ports->device_addr); | 142 | tf->device = tx4938ide_inb(io_ports->device_addr); |
159 | 143 | ||
160 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | 144 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { |
161 | tx4938ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); | 145 | tx4938ide_outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); |
162 | 146 | ||
163 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | 147 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) |
164 | tf->hob_feature = | 148 | tf->hob_error = tx4938ide_inb(io_ports->feature_addr); |
165 | tx4938ide_inb(io_ports->feature_addr); | ||
166 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | 149 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) |
167 | tf->hob_nsect = tx4938ide_inb(io_ports->nsect_addr); | 150 | tf->hob_nsect = tx4938ide_inb(io_ports->nsect_addr); |
168 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | 151 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) |
169 | tf->hob_lbal = tx4938ide_inb(io_ports->lbal_addr); | 152 | tf->hob_lbal = tx4938ide_inb(io_ports->lbal_addr); |
170 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | 153 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) |
171 | tf->hob_lbam = tx4938ide_inb(io_ports->lbam_addr); | 154 | tf->hob_lbam = tx4938ide_inb(io_ports->lbam_addr); |
172 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | 155 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) |
173 | tf->hob_lbah = tx4938ide_inb(io_ports->lbah_addr); | 156 | tf->hob_lbah = tx4938ide_inb(io_ports->lbah_addr); |
174 | } | 157 | } |
175 | } | 158 | } |
176 | 159 | ||
@@ -204,9 +187,9 @@ static const struct ide_tp_ops tx4938ide_tp_ops = { | |||
204 | .exec_command = ide_exec_command, | 187 | .exec_command = ide_exec_command, |
205 | .read_status = ide_read_status, | 188 | .read_status = ide_read_status, |
206 | .read_altstatus = ide_read_altstatus, | 189 | .read_altstatus = ide_read_altstatus, |
190 | .write_devctl = ide_write_devctl, | ||
207 | 191 | ||
208 | .set_irq = ide_set_irq, | 192 | .dev_select = ide_dev_select, |
209 | |||
210 | .tf_load = tx4938ide_tf_load, | 193 | .tf_load = tx4938ide_tf_load, |
211 | .tf_read = tx4938ide_tf_read, | 194 | .tf_read = tx4938ide_tf_read, |
212 | 195 | ||
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c index e0e0a803dde3..0040a9a3e26e 100644 --- a/drivers/ide/tx4939ide.c +++ b/drivers/ide/tx4939ide.c | |||
@@ -279,8 +279,6 @@ use_pio_instead: | |||
279 | printk(KERN_ERR "%s: %s\n", drive->name, | 279 | printk(KERN_ERR "%s: %s\n", drive->name, |
280 | count ? "DMA table too small" : "empty DMA table?"); | 280 | count ? "DMA table too small" : "empty DMA table?"); |
281 | 281 | ||
282 | ide_destroy_dmatable(drive); | ||
283 | |||
284 | return 0; /* revert to PIO for this request */ | 282 | return 0; /* revert to PIO for this request */ |
285 | } | 283 | } |
286 | #else | 284 | #else |
@@ -294,10 +292,8 @@ static int tx4939ide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | |||
294 | u8 rw = (cmd->tf_flags & IDE_TFLAG_WRITE) ? 0 : ATA_DMA_WR; | 292 | u8 rw = (cmd->tf_flags & IDE_TFLAG_WRITE) ? 0 : ATA_DMA_WR; |
295 | 293 | ||
296 | /* fall back to PIO! */ | 294 | /* fall back to PIO! */ |
297 | if (tx4939ide_build_dmatable(drive, cmd) == 0) { | 295 | if (tx4939ide_build_dmatable(drive, cmd) == 0) |
298 | ide_map_sg(drive, cmd); | ||
299 | return 1; | 296 | return 1; |
300 | } | ||
301 | 297 | ||
302 | /* PRD table */ | 298 | /* PRD table */ |
303 | tx4939ide_writel(hwif->dmatable_dma, base, TX4939IDE_PRD_Ptr); | 299 | tx4939ide_writel(hwif->dmatable_dma, base, TX4939IDE_PRD_Ptr); |
@@ -308,8 +304,6 @@ static int tx4939ide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | |||
308 | /* clear INTR & ERROR flags */ | 304 | /* clear INTR & ERROR flags */ |
309 | tx4939ide_clear_dma_status(base); | 305 | tx4939ide_clear_dma_status(base); |
310 | 306 | ||
311 | drive->waiting_for_dma = 1; | ||
312 | |||
313 | tx4939ide_writew(SECTOR_SIZE / 2, base, drive->dn ? | 307 | tx4939ide_writew(SECTOR_SIZE / 2, base, drive->dn ? |
314 | TX4939IDE_Xfer_Cnt_2 : TX4939IDE_Xfer_Cnt_1); | 308 | TX4939IDE_Xfer_Cnt_2 : TX4939IDE_Xfer_Cnt_1); |
315 | 309 | ||
@@ -325,8 +319,6 @@ static int tx4939ide_dma_end(ide_drive_t *drive) | |||
325 | void __iomem *base = TX4939IDE_BASE(hwif); | 319 | void __iomem *base = TX4939IDE_BASE(hwif); |
326 | u16 ctl = tx4939ide_readw(base, TX4939IDE_Int_Ctl); | 320 | u16 ctl = tx4939ide_readw(base, TX4939IDE_Int_Ctl); |
327 | 321 | ||
328 | drive->waiting_for_dma = 0; | ||
329 | |||
330 | /* get DMA command mode */ | 322 | /* get DMA command mode */ |
331 | dma_cmd = tx4939ide_readb(base, TX4939IDE_DMA_Cmd); | 323 | dma_cmd = tx4939ide_readb(base, TX4939IDE_DMA_Cmd); |
332 | /* stop DMA */ | 324 | /* stop DMA */ |
@@ -335,11 +327,9 @@ static int tx4939ide_dma_end(ide_drive_t *drive) | |||
335 | /* read and clear the INTR & ERROR bits */ | 327 | /* read and clear the INTR & ERROR bits */ |
336 | dma_stat = tx4939ide_clear_dma_status(base); | 328 | dma_stat = tx4939ide_clear_dma_status(base); |
337 | 329 | ||
338 | /* purge DMA mappings */ | ||
339 | ide_destroy_dmatable(drive); | ||
340 | /* verify good DMA status */ | ||
341 | wmb(); | 330 | wmb(); |
342 | 331 | ||
332 | /* verify good DMA status */ | ||
343 | if ((dma_stat & (ATA_DMA_INTR | ATA_DMA_ERR | ATA_DMA_ACTIVE)) == 0 && | 333 | if ((dma_stat & (ATA_DMA_INTR | ATA_DMA_ERR | ATA_DMA_ACTIVE)) == 0 && |
344 | (ctl & (TX4939IDE_INT_XFEREND | TX4939IDE_INT_HOST)) == | 334 | (ctl & (TX4939IDE_INT_XFEREND | TX4939IDE_INT_HOST)) == |
345 | (TX4939IDE_INT_XFEREND | TX4939IDE_INT_HOST)) | 335 | (TX4939IDE_INT_XFEREND | TX4939IDE_INT_HOST)) |
@@ -439,7 +429,7 @@ static void tx4939ide_tf_load_fixup(ide_drive_t *drive) | |||
439 | * Fix ATA100 CORE System Control Register. (The write to the | 429 | * Fix ATA100 CORE System Control Register. (The write to the |
440 | * Device/Head register may write wrong data to the System | 430 | * Device/Head register may write wrong data to the System |
441 | * Control Register) | 431 | * Control Register) |
442 | * While Sys_Ctl is written here, selectproc is not needed. | 432 | * While Sys_Ctl is written here, dev_select() is not needed. |
443 | */ | 433 | */ |
444 | tx4939ide_writew(sysctl, base, TX4939IDE_Sys_Ctl); | 434 | tx4939ide_writew(sysctl, base, TX4939IDE_Sys_Ctl); |
445 | } | 435 | } |
@@ -467,13 +457,6 @@ static void tx4939ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | |||
467 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) | 457 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) |
468 | HIHI = 0xFF; | 458 | HIHI = 0xFF; |
469 | 459 | ||
470 | if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) { | ||
471 | u16 data = (tf->hob_data << 8) | tf->data; | ||
472 | |||
473 | /* no endian swap */ | ||
474 | __raw_writew(data, (void __iomem *)io_ports->data_addr); | ||
475 | } | ||
476 | |||
477 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | 460 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) |
478 | tx4939ide_outb(tf->hob_feature, io_ports->feature_addr); | 461 | tx4939ide_outb(tf->hob_feature, io_ports->feature_addr); |
479 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | 462 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) |
@@ -509,20 +492,11 @@ static void tx4939ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
509 | struct ide_io_ports *io_ports = &hwif->io_ports; | 492 | struct ide_io_ports *io_ports = &hwif->io_ports; |
510 | struct ide_taskfile *tf = &cmd->tf; | 493 | struct ide_taskfile *tf = &cmd->tf; |
511 | 494 | ||
512 | if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) { | ||
513 | u16 data; | ||
514 | |||
515 | /* no endian swap */ | ||
516 | data = __raw_readw((void __iomem *)io_ports->data_addr); | ||
517 | tf->data = data & 0xff; | ||
518 | tf->hob_data = (data >> 8) & 0xff; | ||
519 | } | ||
520 | |||
521 | /* be sure we're looking at the low order bits */ | 495 | /* be sure we're looking at the low order bits */ |
522 | tx4939ide_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); | 496 | tx4939ide_outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); |
523 | 497 | ||
524 | if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE) | 498 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) |
525 | tf->feature = tx4939ide_inb(io_ports->feature_addr); | 499 | tf->error = tx4939ide_inb(io_ports->feature_addr); |
526 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | 500 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) |
527 | tf->nsect = tx4939ide_inb(io_ports->nsect_addr); | 501 | tf->nsect = tx4939ide_inb(io_ports->nsect_addr); |
528 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | 502 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) |
@@ -535,19 +509,18 @@ static void tx4939ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
535 | tf->device = tx4939ide_inb(io_ports->device_addr); | 509 | tf->device = tx4939ide_inb(io_ports->device_addr); |
536 | 510 | ||
537 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | 511 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { |
538 | tx4939ide_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); | 512 | tx4939ide_outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); |
539 | 513 | ||
540 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | 514 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) |
541 | tf->hob_feature = | 515 | tf->hob_error = tx4939ide_inb(io_ports->feature_addr); |
542 | tx4939ide_inb(io_ports->feature_addr); | ||
543 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | 516 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) |
544 | tf->hob_nsect = tx4939ide_inb(io_ports->nsect_addr); | 517 | tf->hob_nsect = tx4939ide_inb(io_ports->nsect_addr); |
545 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | 518 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) |
546 | tf->hob_lbal = tx4939ide_inb(io_ports->lbal_addr); | 519 | tf->hob_lbal = tx4939ide_inb(io_ports->lbal_addr); |
547 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | 520 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) |
548 | tf->hob_lbam = tx4939ide_inb(io_ports->lbam_addr); | 521 | tf->hob_lbam = tx4939ide_inb(io_ports->lbam_addr); |
549 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | 522 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) |
550 | tf->hob_lbah = tx4939ide_inb(io_ports->lbah_addr); | 523 | tf->hob_lbah = tx4939ide_inb(io_ports->lbah_addr); |
551 | } | 524 | } |
552 | } | 525 | } |
553 | 526 | ||
@@ -581,9 +554,9 @@ static const struct ide_tp_ops tx4939ide_tp_ops = { | |||
581 | .exec_command = ide_exec_command, | 554 | .exec_command = ide_exec_command, |
582 | .read_status = ide_read_status, | 555 | .read_status = ide_read_status, |
583 | .read_altstatus = ide_read_altstatus, | 556 | .read_altstatus = ide_read_altstatus, |
557 | .write_devctl = ide_write_devctl, | ||
584 | 558 | ||
585 | .set_irq = ide_set_irq, | 559 | .dev_select = ide_dev_select, |
586 | |||
587 | .tf_load = tx4939ide_tf_load, | 560 | .tf_load = tx4939ide_tf_load, |
588 | .tf_read = tx4939ide_tf_read, | 561 | .tf_read = tx4939ide_tf_read, |
589 | 562 | ||
@@ -605,9 +578,9 @@ static const struct ide_tp_ops tx4939ide_tp_ops = { | |||
605 | .exec_command = ide_exec_command, | 578 | .exec_command = ide_exec_command, |
606 | .read_status = ide_read_status, | 579 | .read_status = ide_read_status, |
607 | .read_altstatus = ide_read_altstatus, | 580 | .read_altstatus = ide_read_altstatus, |
581 | .write_devctl = ide_write_devctl, | ||
608 | 582 | ||
609 | .set_irq = ide_set_irq, | 583 | .dev_select = ide_dev_select, |
610 | |||
611 | .tf_load = tx4939ide_tf_load, | 584 | .tf_load = tx4939ide_tf_load, |
612 | .tf_read = ide_tf_read, | 585 | .tf_read = ide_tf_read, |
613 | 586 | ||
@@ -632,7 +605,6 @@ static const struct ide_dma_ops tx4939ide_dma_ops = { | |||
632 | .dma_test_irq = tx4939ide_dma_test_irq, | 605 | .dma_test_irq = tx4939ide_dma_test_irq, |
633 | .dma_lost_irq = ide_dma_lost_irq, | 606 | .dma_lost_irq = ide_dma_lost_irq, |
634 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 607 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
635 | .dma_timeout = ide_dma_timeout, | ||
636 | .dma_sff_read_status = tx4939ide_dma_sff_read_status, | 608 | .dma_sff_read_status = tx4939ide_dma_sff_read_status, |
637 | }; | 609 | }; |
638 | 610 | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index 1730d7331a5d..ec3db3ade118 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -903,8 +903,6 @@ static int __init input_proc_init(void) | |||
903 | if (!proc_bus_input_dir) | 903 | if (!proc_bus_input_dir) |
904 | return -ENOMEM; | 904 | return -ENOMEM; |
905 | 905 | ||
906 | proc_bus_input_dir->owner = THIS_MODULE; | ||
907 | |||
908 | entry = proc_create("devices", 0, proc_bus_input_dir, | 906 | entry = proc_create("devices", 0, proc_bus_input_dir, |
909 | &input_devices_fileops); | 907 | &input_devices_fileops); |
910 | if (!entry) | 908 | if (!entry) |
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c index 3e468d2cf730..2d8352419c0d 100644 --- a/drivers/isdn/capi/capi.c +++ b/drivers/isdn/capi/capi.c | |||
@@ -1331,12 +1331,6 @@ static void capinc_tty_send_xchar(struct tty_struct *tty, char ch) | |||
1331 | #endif | 1331 | #endif |
1332 | } | 1332 | } |
1333 | 1333 | ||
1334 | static int capinc_tty_read_proc(char *page, char **start, off_t off, | ||
1335 | int count, int *eof, void *data) | ||
1336 | { | ||
1337 | return 0; | ||
1338 | } | ||
1339 | |||
1340 | static struct tty_driver *capinc_tty_driver; | 1334 | static struct tty_driver *capinc_tty_driver; |
1341 | 1335 | ||
1342 | static const struct tty_operations capinc_ops = { | 1336 | static const struct tty_operations capinc_ops = { |
@@ -1358,7 +1352,6 @@ static const struct tty_operations capinc_ops = { | |||
1358 | .flush_buffer = capinc_tty_flush_buffer, | 1352 | .flush_buffer = capinc_tty_flush_buffer, |
1359 | .set_ldisc = capinc_tty_set_ldisc, | 1353 | .set_ldisc = capinc_tty_set_ldisc, |
1360 | .send_xchar = capinc_tty_send_xchar, | 1354 | .send_xchar = capinc_tty_send_xchar, |
1361 | .read_proc = capinc_tty_read_proc, | ||
1362 | }; | 1355 | }; |
1363 | 1356 | ||
1364 | static int capinc_tty_init(void) | 1357 | static int capinc_tty_init(void) |
diff --git a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c index f4969fe0a055..69e71ebe7841 100644 --- a/drivers/isdn/hardware/eicon/divasi.c +++ b/drivers/isdn/hardware/eicon/divasi.c | |||
@@ -118,7 +118,6 @@ static int DIVA_INIT_FUNCTION create_um_idi_proc(void) | |||
118 | return (0); | 118 | return (0); |
119 | 119 | ||
120 | um_idi_proc_entry->read_proc = um_idi_proc_read; | 120 | um_idi_proc_entry->read_proc = um_idi_proc_read; |
121 | um_idi_proc_entry->owner = THIS_MODULE; | ||
122 | 121 | ||
123 | return (1); | 122 | return (1); |
124 | } | 123 | } |
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c index 60156dfdc608..4845fb3cf74b 100644 --- a/drivers/lguest/core.c +++ b/drivers/lguest/core.c | |||
@@ -152,8 +152,8 @@ static void unmap_switcher(void) | |||
152 | * code. We have to check that the range is below the pfn_limit the Launcher | 152 | * code. We have to check that the range is below the pfn_limit the Launcher |
153 | * gave us. We have to make sure that addr + len doesn't give us a false | 153 | * gave us. We have to make sure that addr + len doesn't give us a false |
154 | * positive by overflowing, too. */ | 154 | * positive by overflowing, too. */ |
155 | int lguest_address_ok(const struct lguest *lg, | 155 | bool lguest_address_ok(const struct lguest *lg, |
156 | unsigned long addr, unsigned long len) | 156 | unsigned long addr, unsigned long len) |
157 | { | 157 | { |
158 | return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr); | 158 | return (addr+len) / PAGE_SIZE < lg->pfn_limit && (addr+len >= addr); |
159 | } | 159 | } |
diff --git a/drivers/lguest/interrupts_and_traps.c b/drivers/lguest/interrupts_and_traps.c index 415fab0125ac..6e99adbe1946 100644 --- a/drivers/lguest/interrupts_and_traps.c +++ b/drivers/lguest/interrupts_and_traps.c | |||
@@ -34,7 +34,7 @@ static int idt_type(u32 lo, u32 hi) | |||
34 | } | 34 | } |
35 | 35 | ||
36 | /* An IDT entry can't be used unless the "present" bit is set. */ | 36 | /* An IDT entry can't be used unless the "present" bit is set. */ |
37 | static int idt_present(u32 lo, u32 hi) | 37 | static bool idt_present(u32 lo, u32 hi) |
38 | { | 38 | { |
39 | return (hi & 0x8000); | 39 | return (hi & 0x8000); |
40 | } | 40 | } |
@@ -60,7 +60,8 @@ static void push_guest_stack(struct lg_cpu *cpu, unsigned long *gstack, u32 val) | |||
60 | * We set up the stack just like the CPU does for a real interrupt, so it's | 60 | * We set up the stack just like the CPU does for a real interrupt, so it's |
61 | * identical for the Guest (and the standard "iret" instruction will undo | 61 | * identical for the Guest (and the standard "iret" instruction will undo |
62 | * it). */ | 62 | * it). */ |
63 | static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, int has_err) | 63 | static void set_guest_interrupt(struct lg_cpu *cpu, u32 lo, u32 hi, |
64 | bool has_err) | ||
64 | { | 65 | { |
65 | unsigned long gstack, origstack; | 66 | unsigned long gstack, origstack; |
66 | u32 eflags, ss, irq_enable; | 67 | u32 eflags, ss, irq_enable; |
@@ -184,7 +185,7 @@ void maybe_do_interrupt(struct lg_cpu *cpu) | |||
184 | /* set_guest_interrupt() takes the interrupt descriptor and a | 185 | /* set_guest_interrupt() takes the interrupt descriptor and a |
185 | * flag to say whether this interrupt pushes an error code onto | 186 | * flag to say whether this interrupt pushes an error code onto |
186 | * the stack as well: virtual interrupts never do. */ | 187 | * the stack as well: virtual interrupts never do. */ |
187 | set_guest_interrupt(cpu, idt->a, idt->b, 0); | 188 | set_guest_interrupt(cpu, idt->a, idt->b, false); |
188 | } | 189 | } |
189 | 190 | ||
190 | /* Every time we deliver an interrupt, we update the timestamp in the | 191 | /* Every time we deliver an interrupt, we update the timestamp in the |
@@ -244,26 +245,26 @@ void free_interrupts(void) | |||
244 | /*H:220 Now we've got the routines to deliver interrupts, delivering traps like | 245 | /*H:220 Now we've got the routines to deliver interrupts, delivering traps like |
245 | * page fault is easy. The only trick is that Intel decided that some traps | 246 | * page fault is easy. The only trick is that Intel decided that some traps |
246 | * should have error codes: */ | 247 | * should have error codes: */ |
247 | static int has_err(unsigned int trap) | 248 | static bool has_err(unsigned int trap) |
248 | { | 249 | { |
249 | return (trap == 8 || (trap >= 10 && trap <= 14) || trap == 17); | 250 | return (trap == 8 || (trap >= 10 && trap <= 14) || trap == 17); |
250 | } | 251 | } |
251 | 252 | ||
252 | /* deliver_trap() returns true if it could deliver the trap. */ | 253 | /* deliver_trap() returns true if it could deliver the trap. */ |
253 | int deliver_trap(struct lg_cpu *cpu, unsigned int num) | 254 | bool deliver_trap(struct lg_cpu *cpu, unsigned int num) |
254 | { | 255 | { |
255 | /* Trap numbers are always 8 bit, but we set an impossible trap number | 256 | /* Trap numbers are always 8 bit, but we set an impossible trap number |
256 | * for traps inside the Switcher, so check that here. */ | 257 | * for traps inside the Switcher, so check that here. */ |
257 | if (num >= ARRAY_SIZE(cpu->arch.idt)) | 258 | if (num >= ARRAY_SIZE(cpu->arch.idt)) |
258 | return 0; | 259 | return false; |
259 | 260 | ||
260 | /* Early on the Guest hasn't set the IDT entries (or maybe it put a | 261 | /* Early on the Guest hasn't set the IDT entries (or maybe it put a |
261 | * bogus one in): if we fail here, the Guest will be killed. */ | 262 | * bogus one in): if we fail here, the Guest will be killed. */ |
262 | if (!idt_present(cpu->arch.idt[num].a, cpu->arch.idt[num].b)) | 263 | if (!idt_present(cpu->arch.idt[num].a, cpu->arch.idt[num].b)) |
263 | return 0; | 264 | return false; |
264 | set_guest_interrupt(cpu, cpu->arch.idt[num].a, | 265 | set_guest_interrupt(cpu, cpu->arch.idt[num].a, |
265 | cpu->arch.idt[num].b, has_err(num)); | 266 | cpu->arch.idt[num].b, has_err(num)); |
266 | return 1; | 267 | return true; |
267 | } | 268 | } |
268 | 269 | ||
269 | /*H:250 Here's the hard part: returning to the Host every time a trap happens | 270 | /*H:250 Here's the hard part: returning to the Host every time a trap happens |
@@ -279,18 +280,19 @@ int deliver_trap(struct lg_cpu *cpu, unsigned int num) | |||
279 | * | 280 | * |
280 | * This routine indicates if a particular trap number could be delivered | 281 | * This routine indicates if a particular trap number could be delivered |
281 | * directly. */ | 282 | * directly. */ |
282 | static int direct_trap(unsigned int num) | 283 | static bool direct_trap(unsigned int num) |
283 | { | 284 | { |
284 | /* Hardware interrupts don't go to the Guest at all (except system | 285 | /* Hardware interrupts don't go to the Guest at all (except system |
285 | * call). */ | 286 | * call). */ |
286 | if (num >= FIRST_EXTERNAL_VECTOR && !could_be_syscall(num)) | 287 | if (num >= FIRST_EXTERNAL_VECTOR && !could_be_syscall(num)) |
287 | return 0; | 288 | return false; |
288 | 289 | ||
289 | /* The Host needs to see page faults (for shadow paging and to save the | 290 | /* The Host needs to see page faults (for shadow paging and to save the |
290 | * fault address), general protection faults (in/out emulation) and | 291 | * fault address), general protection faults (in/out emulation) and |
291 | * device not available (TS handling), and of course, the hypercall | 292 | * device not available (TS handling), invalid opcode fault (kvm hcall), |
292 | * trap. */ | 293 | * and of course, the hypercall trap. */ |
293 | return num != 14 && num != 13 && num != 7 && num != LGUEST_TRAP_ENTRY; | 294 | return num != 14 && num != 13 && num != 7 && |
295 | num != 6 && num != LGUEST_TRAP_ENTRY; | ||
294 | } | 296 | } |
295 | /*:*/ | 297 | /*:*/ |
296 | 298 | ||
diff --git a/drivers/lguest/lg.h b/drivers/lguest/lg.h index f2c641e0bdde..ac8a4a3741b8 100644 --- a/drivers/lguest/lg.h +++ b/drivers/lguest/lg.h | |||
@@ -109,8 +109,8 @@ struct lguest | |||
109 | extern struct mutex lguest_lock; | 109 | extern struct mutex lguest_lock; |
110 | 110 | ||
111 | /* core.c: */ | 111 | /* core.c: */ |
112 | int lguest_address_ok(const struct lguest *lg, | 112 | bool lguest_address_ok(const struct lguest *lg, |
113 | unsigned long addr, unsigned long len); | 113 | unsigned long addr, unsigned long len); |
114 | void __lgread(struct lg_cpu *, void *, unsigned long, unsigned); | 114 | void __lgread(struct lg_cpu *, void *, unsigned long, unsigned); |
115 | void __lgwrite(struct lg_cpu *, unsigned long, const void *, unsigned); | 115 | void __lgwrite(struct lg_cpu *, unsigned long, const void *, unsigned); |
116 | 116 | ||
@@ -140,7 +140,7 @@ int run_guest(struct lg_cpu *cpu, unsigned long __user *user); | |||
140 | 140 | ||
141 | /* interrupts_and_traps.c: */ | 141 | /* interrupts_and_traps.c: */ |
142 | void maybe_do_interrupt(struct lg_cpu *cpu); | 142 | void maybe_do_interrupt(struct lg_cpu *cpu); |
143 | int deliver_trap(struct lg_cpu *cpu, unsigned int num); | 143 | bool deliver_trap(struct lg_cpu *cpu, unsigned int num); |
144 | void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int i, | 144 | void load_guest_idt_entry(struct lg_cpu *cpu, unsigned int i, |
145 | u32 low, u32 hi); | 145 | u32 low, u32 hi); |
146 | void guest_set_stack(struct lg_cpu *cpu, u32 seg, u32 esp, unsigned int pages); | 146 | void guest_set_stack(struct lg_cpu *cpu, u32 seg, u32 esp, unsigned int pages); |
@@ -173,7 +173,7 @@ void guest_pagetable_flush_user(struct lg_cpu *cpu); | |||
173 | void guest_set_pte(struct lg_cpu *cpu, unsigned long gpgdir, | 173 | void guest_set_pte(struct lg_cpu *cpu, unsigned long gpgdir, |
174 | unsigned long vaddr, pte_t val); | 174 | unsigned long vaddr, pte_t val); |
175 | void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages); | 175 | void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages); |
176 | int demand_page(struct lg_cpu *cpu, unsigned long cr2, int errcode); | 176 | bool demand_page(struct lg_cpu *cpu, unsigned long cr2, int errcode); |
177 | void pin_page(struct lg_cpu *cpu, unsigned long vaddr); | 177 | void pin_page(struct lg_cpu *cpu, unsigned long vaddr); |
178 | unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr); | 178 | unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr); |
179 | void page_table_guest_data_init(struct lg_cpu *cpu); | 179 | void page_table_guest_data_init(struct lg_cpu *cpu); |
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 8132533d71f9..df44d962626d 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c | |||
@@ -161,7 +161,7 @@ static void set_status(struct virtio_device *vdev, u8 status) | |||
161 | 161 | ||
162 | /* We set the status. */ | 162 | /* We set the status. */ |
163 | to_lgdev(vdev)->desc->status = status; | 163 | to_lgdev(vdev)->desc->status = status; |
164 | hcall(LHCALL_NOTIFY, (max_pfn<<PAGE_SHIFT) + offset, 0, 0); | 164 | kvm_hypercall1(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset); |
165 | } | 165 | } |
166 | 166 | ||
167 | static void lg_set_status(struct virtio_device *vdev, u8 status) | 167 | static void lg_set_status(struct virtio_device *vdev, u8 status) |
@@ -209,7 +209,7 @@ static void lg_notify(struct virtqueue *vq) | |||
209 | * virtqueue structure. */ | 209 | * virtqueue structure. */ |
210 | struct lguest_vq_info *lvq = vq->priv; | 210 | struct lguest_vq_info *lvq = vq->priv; |
211 | 211 | ||
212 | hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0); | 212 | kvm_hypercall1(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT); |
213 | } | 213 | } |
214 | 214 | ||
215 | /* An extern declaration inside a C file is bad form. Don't do it. */ | 215 | /* An extern declaration inside a C file is bad form. Don't do it. */ |
diff --git a/drivers/lguest/page_tables.c b/drivers/lguest/page_tables.c index 576a8318221c..a059cf9980f7 100644 --- a/drivers/lguest/page_tables.c +++ b/drivers/lguest/page_tables.c | |||
@@ -199,7 +199,7 @@ static void check_gpgd(struct lg_cpu *cpu, pgd_t gpgd) | |||
199 | * | 199 | * |
200 | * If we fixed up the fault (ie. we mapped the address), this routine returns | 200 | * If we fixed up the fault (ie. we mapped the address), this routine returns |
201 | * true. Otherwise, it was a real fault and we need to tell the Guest. */ | 201 | * true. Otherwise, it was a real fault and we need to tell the Guest. */ |
202 | int demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode) | 202 | bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode) |
203 | { | 203 | { |
204 | pgd_t gpgd; | 204 | pgd_t gpgd; |
205 | pgd_t *spgd; | 205 | pgd_t *spgd; |
@@ -211,7 +211,7 @@ int demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode) | |||
211 | gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t); | 211 | gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t); |
212 | /* Toplevel not present? We can't map it in. */ | 212 | /* Toplevel not present? We can't map it in. */ |
213 | if (!(pgd_flags(gpgd) & _PAGE_PRESENT)) | 213 | if (!(pgd_flags(gpgd) & _PAGE_PRESENT)) |
214 | return 0; | 214 | return false; |
215 | 215 | ||
216 | /* Now look at the matching shadow entry. */ | 216 | /* Now look at the matching shadow entry. */ |
217 | spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr); | 217 | spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr); |
@@ -222,7 +222,7 @@ int demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode) | |||
222 | * simple for this corner case. */ | 222 | * simple for this corner case. */ |
223 | if (!ptepage) { | 223 | if (!ptepage) { |
224 | kill_guest(cpu, "out of memory allocating pte page"); | 224 | kill_guest(cpu, "out of memory allocating pte page"); |
225 | return 0; | 225 | return false; |
226 | } | 226 | } |
227 | /* We check that the Guest pgd is OK. */ | 227 | /* We check that the Guest pgd is OK. */ |
228 | check_gpgd(cpu, gpgd); | 228 | check_gpgd(cpu, gpgd); |
@@ -238,16 +238,16 @@ int demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode) | |||
238 | 238 | ||
239 | /* If this page isn't in the Guest page tables, we can't page it in. */ | 239 | /* If this page isn't in the Guest page tables, we can't page it in. */ |
240 | if (!(pte_flags(gpte) & _PAGE_PRESENT)) | 240 | if (!(pte_flags(gpte) & _PAGE_PRESENT)) |
241 | return 0; | 241 | return false; |
242 | 242 | ||
243 | /* Check they're not trying to write to a page the Guest wants | 243 | /* Check they're not trying to write to a page the Guest wants |
244 | * read-only (bit 2 of errcode == write). */ | 244 | * read-only (bit 2 of errcode == write). */ |
245 | if ((errcode & 2) && !(pte_flags(gpte) & _PAGE_RW)) | 245 | if ((errcode & 2) && !(pte_flags(gpte) & _PAGE_RW)) |
246 | return 0; | 246 | return false; |
247 | 247 | ||
248 | /* User access to a kernel-only page? (bit 3 == user access) */ | 248 | /* User access to a kernel-only page? (bit 3 == user access) */ |
249 | if ((errcode & 4) && !(pte_flags(gpte) & _PAGE_USER)) | 249 | if ((errcode & 4) && !(pte_flags(gpte) & _PAGE_USER)) |
250 | return 0; | 250 | return false; |
251 | 251 | ||
252 | /* Check that the Guest PTE flags are OK, and the page number is below | 252 | /* Check that the Guest PTE flags are OK, and the page number is below |
253 | * the pfn_limit (ie. not mapping the Launcher binary). */ | 253 | * the pfn_limit (ie. not mapping the Launcher binary). */ |
@@ -283,7 +283,7 @@ int demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode) | |||
283 | * manipulated, the result returned and the code complete. A small | 283 | * manipulated, the result returned and the code complete. A small |
284 | * delay and a trace of alliteration are the only indications the Guest | 284 | * delay and a trace of alliteration are the only indications the Guest |
285 | * has that a page fault occurred at all. */ | 285 | * has that a page fault occurred at all. */ |
286 | return 1; | 286 | return true; |
287 | } | 287 | } |
288 | 288 | ||
289 | /*H:360 | 289 | /*H:360 |
@@ -296,7 +296,7 @@ int demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode) | |||
296 | * | 296 | * |
297 | * This is a quick version which answers the question: is this virtual address | 297 | * This is a quick version which answers the question: is this virtual address |
298 | * mapped by the shadow page tables, and is it writable? */ | 298 | * mapped by the shadow page tables, and is it writable? */ |
299 | static int page_writable(struct lg_cpu *cpu, unsigned long vaddr) | 299 | static bool page_writable(struct lg_cpu *cpu, unsigned long vaddr) |
300 | { | 300 | { |
301 | pgd_t *spgd; | 301 | pgd_t *spgd; |
302 | unsigned long flags; | 302 | unsigned long flags; |
@@ -304,7 +304,7 @@ static int page_writable(struct lg_cpu *cpu, unsigned long vaddr) | |||
304 | /* Look at the current top level entry: is it present? */ | 304 | /* Look at the current top level entry: is it present? */ |
305 | spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr); | 305 | spgd = spgd_addr(cpu, cpu->cpu_pgd, vaddr); |
306 | if (!(pgd_flags(*spgd) & _PAGE_PRESENT)) | 306 | if (!(pgd_flags(*spgd) & _PAGE_PRESENT)) |
307 | return 0; | 307 | return false; |
308 | 308 | ||
309 | /* Check the flags on the pte entry itself: it must be present and | 309 | /* Check the flags on the pte entry itself: it must be present and |
310 | * writable. */ | 310 | * writable. */ |
@@ -373,8 +373,10 @@ unsigned long guest_pa(struct lg_cpu *cpu, unsigned long vaddr) | |||
373 | /* First step: get the top-level Guest page table entry. */ | 373 | /* First step: get the top-level Guest page table entry. */ |
374 | gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t); | 374 | gpgd = lgread(cpu, gpgd_addr(cpu, vaddr), pgd_t); |
375 | /* Toplevel not present? We can't map it in. */ | 375 | /* Toplevel not present? We can't map it in. */ |
376 | if (!(pgd_flags(gpgd) & _PAGE_PRESENT)) | 376 | if (!(pgd_flags(gpgd) & _PAGE_PRESENT)) { |
377 | kill_guest(cpu, "Bad address %#lx", vaddr); | 377 | kill_guest(cpu, "Bad address %#lx", vaddr); |
378 | return -1UL; | ||
379 | } | ||
378 | 380 | ||
379 | gpte = lgread(cpu, gpte_addr(gpgd, vaddr), pte_t); | 381 | gpte = lgread(cpu, gpte_addr(gpgd, vaddr), pte_t); |
380 | if (!(pte_flags(gpte) & _PAGE_PRESENT)) | 382 | if (!(pte_flags(gpte) & _PAGE_PRESENT)) |
diff --git a/drivers/lguest/segments.c b/drivers/lguest/segments.c index ec6aa3f1c36b..4f15439b7f12 100644 --- a/drivers/lguest/segments.c +++ b/drivers/lguest/segments.c | |||
@@ -45,7 +45,7 @@ | |||
45 | * "Task State Segment" which controls all kinds of delicate things. The | 45 | * "Task State Segment" which controls all kinds of delicate things. The |
46 | * LGUEST_CS and LGUEST_DS entries are reserved for the Switcher, and the | 46 | * LGUEST_CS and LGUEST_DS entries are reserved for the Switcher, and the |
47 | * the Guest can't be trusted to deal with double faults. */ | 47 | * the Guest can't be trusted to deal with double faults. */ |
48 | static int ignored_gdt(unsigned int num) | 48 | static bool ignored_gdt(unsigned int num) |
49 | { | 49 | { |
50 | return (num == GDT_ENTRY_TSS | 50 | return (num == GDT_ENTRY_TSS |
51 | || num == GDT_ENTRY_LGUEST_CS | 51 | || num == GDT_ENTRY_LGUEST_CS |
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index bf7942327bda..a6b717644be0 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c | |||
@@ -290,6 +290,57 @@ static int emulate_insn(struct lg_cpu *cpu) | |||
290 | return 1; | 290 | return 1; |
291 | } | 291 | } |
292 | 292 | ||
293 | /* Our hypercalls mechanism used to be based on direct software interrupts. | ||
294 | * After Anthony's "Refactor hypercall infrastructure" kvm patch, we decided to | ||
295 | * change over to using kvm hypercalls. | ||
296 | * | ||
297 | * KVM_HYPERCALL is actually a "vmcall" instruction, which generates an invalid | ||
298 | * opcode fault (fault 6) on non-VT cpus, so the easiest solution seemed to be | ||
299 | * an *emulation approach*: if the fault was really produced by an hypercall | ||
300 | * (is_hypercall() does exactly this check), we can just call the corresponding | ||
301 | * hypercall host implementation function. | ||
302 | * | ||
303 | * But these invalid opcode faults are notably slower than software interrupts. | ||
304 | * So we implemented the *patching (or rewriting) approach*: every time we hit | ||
305 | * the KVM_HYPERCALL opcode in Guest code, we patch it to the old "int 0x1f" | ||
306 | * opcode, so next time the Guest calls this hypercall it will use the | ||
307 | * faster trap mechanism. | ||
308 | * | ||
309 | * Matias even benchmarked it to convince you: this shows the average cycle | ||
310 | * cost of a hypercall. For each alternative solution mentioned above we've | ||
311 | * made 5 runs of the benchmark: | ||
312 | * | ||
313 | * 1) direct software interrupt: 2915, 2789, 2764, 2721, 2898 | ||
314 | * 2) emulation technique: 3410, 3681, 3466, 3392, 3780 | ||
315 | * 3) patching (rewrite) technique: 2977, 2975, 2891, 2637, 2884 | ||
316 | * | ||
317 | * One two-line function is worth a 20% hypercall speed boost! | ||
318 | */ | ||
319 | static void rewrite_hypercall(struct lg_cpu *cpu) | ||
320 | { | ||
321 | /* This are the opcodes we use to patch the Guest. The opcode for "int | ||
322 | * $0x1f" is "0xcd 0x1f" but vmcall instruction is 3 bytes long, so we | ||
323 | * complete the sequence with a NOP (0x90). */ | ||
324 | u8 insn[3] = {0xcd, 0x1f, 0x90}; | ||
325 | |||
326 | __lgwrite(cpu, guest_pa(cpu, cpu->regs->eip), insn, sizeof(insn)); | ||
327 | } | ||
328 | |||
329 | static bool is_hypercall(struct lg_cpu *cpu) | ||
330 | { | ||
331 | u8 insn[3]; | ||
332 | |||
333 | /* This must be the Guest kernel trying to do something. | ||
334 | * The bottom two bits of the CS segment register are the privilege | ||
335 | * level. */ | ||
336 | if ((cpu->regs->cs & 3) != GUEST_PL) | ||
337 | return false; | ||
338 | |||
339 | /* Is it a vmcall? */ | ||
340 | __lgread(cpu, insn, guest_pa(cpu, cpu->regs->eip), sizeof(insn)); | ||
341 | return insn[0] == 0x0f && insn[1] == 0x01 && insn[2] == 0xc1; | ||
342 | } | ||
343 | |||
293 | /*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */ | 344 | /*H:050 Once we've re-enabled interrupts, we look at why the Guest exited. */ |
294 | void lguest_arch_handle_trap(struct lg_cpu *cpu) | 345 | void lguest_arch_handle_trap(struct lg_cpu *cpu) |
295 | { | 346 | { |
@@ -337,7 +388,7 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) | |||
337 | break; | 388 | break; |
338 | case 32 ... 255: | 389 | case 32 ... 255: |
339 | /* These values mean a real interrupt occurred, in which case | 390 | /* These values mean a real interrupt occurred, in which case |
340 | * the Host handler has already been run. We just do a | 391 | * the Host handler has already been run. We just do a |
341 | * friendly check if another process should now be run, then | 392 | * friendly check if another process should now be run, then |
342 | * return to run the Guest again */ | 393 | * return to run the Guest again */ |
343 | cond_resched(); | 394 | cond_resched(); |
@@ -347,6 +398,15 @@ void lguest_arch_handle_trap(struct lg_cpu *cpu) | |||
347 | * up the pointer now to indicate a hypercall is pending. */ | 398 | * up the pointer now to indicate a hypercall is pending. */ |
348 | cpu->hcall = (struct hcall_args *)cpu->regs; | 399 | cpu->hcall = (struct hcall_args *)cpu->regs; |
349 | return; | 400 | return; |
401 | case 6: | ||
402 | /* kvm hypercalls trigger an invalid opcode fault (6). | ||
403 | * We need to check if ring == GUEST_PL and | ||
404 | * faulting instruction == vmcall. */ | ||
405 | if (is_hypercall(cpu)) { | ||
406 | rewrite_hypercall(cpu); | ||
407 | return; | ||
408 | } | ||
409 | break; | ||
350 | } | 410 | } |
351 | 411 | ||
352 | /* We didn't handle the trap, so it needs to go to the Guest. */ | 412 | /* We didn't handle the trap, so it needs to go to the Guest. */ |
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c index c3b0c8c63c76..43ab0adf3b61 100644 --- a/drivers/media/video/cpia.c +++ b/drivers/media/video/cpia.c | |||
@@ -1381,9 +1381,7 @@ static void proc_cpia_create(void) | |||
1381 | { | 1381 | { |
1382 | cpia_proc_root = proc_mkdir("cpia", NULL); | 1382 | cpia_proc_root = proc_mkdir("cpia", NULL); |
1383 | 1383 | ||
1384 | if (cpia_proc_root) | 1384 | if (!cpia_proc_root) |
1385 | cpia_proc_root->owner = THIS_MODULE; | ||
1386 | else | ||
1387 | LOG("Unable to initialise /proc/cpia\n"); | 1385 | LOG("Unable to initialise /proc/cpia\n"); |
1388 | } | 1386 | } |
1389 | 1387 | ||
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c index 9a36b5a7de57..7045c45da9b1 100644 --- a/drivers/message/i2o/i2o_proc.c +++ b/drivers/message/i2o/i2o_proc.c | |||
@@ -2037,8 +2037,6 @@ static int __init i2o_proc_fs_create(void) | |||
2037 | if (!i2o_proc_dir_root) | 2037 | if (!i2o_proc_dir_root) |
2038 | return -1; | 2038 | return -1; |
2039 | 2039 | ||
2040 | i2o_proc_dir_root->owner = THIS_MODULE; | ||
2041 | |||
2042 | list_for_each_entry(c, &i2o_controllers, list) | 2040 | list_for_each_entry(c, &i2o_controllers, list) |
2043 | i2o_proc_iop_add(i2o_proc_dir_root, c); | 2041 | i2o_proc_iop_add(i2o_proc_dir_root, c); |
2044 | 2042 | ||
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 1c484084ed4f..5f3bff434621 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -223,6 +223,16 @@ config DELL_LAPTOP | |||
223 | This driver adds support for rfkill and backlight control to Dell | 223 | This driver adds support for rfkill and backlight control to Dell |
224 | laptops. | 224 | laptops. |
225 | 225 | ||
226 | config ISL29003 | ||
227 | tristate "Intersil ISL29003 ambient light sensor" | ||
228 | depends on I2C && SYSFS | ||
229 | help | ||
230 | If you say yes here you get support for the Intersil ISL29003 | ||
231 | ambient light sensor. | ||
232 | |||
233 | This driver can also be built as a module. If so, the module | ||
234 | will be called isl29003. | ||
235 | |||
226 | source "drivers/misc/c2port/Kconfig" | 236 | source "drivers/misc/c2port/Kconfig" |
227 | source "drivers/misc/eeprom/Kconfig" | 237 | source "drivers/misc/eeprom/Kconfig" |
228 | 238 | ||
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index bc1199830554..7871f05dcb9b 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
@@ -18,5 +18,6 @@ obj-$(CONFIG_KGDB_TESTS) += kgdbts.o | |||
18 | obj-$(CONFIG_SGI_XP) += sgi-xp/ | 18 | obj-$(CONFIG_SGI_XP) += sgi-xp/ |
19 | obj-$(CONFIG_SGI_GRU) += sgi-gru/ | 19 | obj-$(CONFIG_SGI_GRU) += sgi-gru/ |
20 | obj-$(CONFIG_HP_ILO) += hpilo.o | 20 | obj-$(CONFIG_HP_ILO) += hpilo.o |
21 | obj-$(CONFIG_ISL29003) += isl29003.o | ||
21 | obj-$(CONFIG_C2PORT) += c2port/ | 22 | obj-$(CONFIG_C2PORT) += c2port/ |
22 | obj-y += eeprom/ | 23 | obj-y += eeprom/ |
diff --git a/drivers/misc/hpilo.c b/drivers/misc/hpilo.c index cf991850f01b..880ccf39e23b 100644 --- a/drivers/misc/hpilo.c +++ b/drivers/misc/hpilo.c | |||
@@ -209,7 +209,7 @@ static void ilo_ccb_close(struct pci_dev *pdev, struct ccb_data *data) | |||
209 | /* give iLO some time to process stop request */ | 209 | /* give iLO some time to process stop request */ |
210 | for (retries = MAX_WAIT; retries > 0; retries--) { | 210 | for (retries = MAX_WAIT; retries > 0; retries--) { |
211 | doorbell_set(driver_ccb); | 211 | doorbell_set(driver_ccb); |
212 | udelay(1); | 212 | udelay(WAIT_TIME); |
213 | if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A)) | 213 | if (!(ioread32(&device_ccb->send_ctrl) & (1 << CTRL_BITPOS_A)) |
214 | && | 214 | && |
215 | !(ioread32(&device_ccb->recv_ctrl) & (1 << CTRL_BITPOS_A))) | 215 | !(ioread32(&device_ccb->recv_ctrl) & (1 << CTRL_BITPOS_A))) |
@@ -312,7 +312,7 @@ static int ilo_ccb_open(struct ilo_hwinfo *hw, struct ccb_data *data, int slot) | |||
312 | for (i = MAX_WAIT; i > 0; i--) { | 312 | for (i = MAX_WAIT; i > 0; i--) { |
313 | if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL)) | 313 | if (ilo_pkt_dequeue(hw, driver_ccb, SENDQ, &pkt_id, NULL, NULL)) |
314 | break; | 314 | break; |
315 | udelay(1); | 315 | udelay(WAIT_TIME); |
316 | } | 316 | } |
317 | 317 | ||
318 | if (i) { | 318 | if (i) { |
@@ -759,7 +759,7 @@ static void __exit ilo_exit(void) | |||
759 | class_destroy(ilo_class); | 759 | class_destroy(ilo_class); |
760 | } | 760 | } |
761 | 761 | ||
762 | MODULE_VERSION("1.0"); | 762 | MODULE_VERSION("1.1"); |
763 | MODULE_ALIAS(ILO_NAME); | 763 | MODULE_ALIAS(ILO_NAME); |
764 | MODULE_DESCRIPTION(ILO_NAME); | 764 | MODULE_DESCRIPTION(ILO_NAME); |
765 | MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>"); | 765 | MODULE_AUTHOR("David Altobelli <david.altobelli@hp.com>"); |
diff --git a/drivers/misc/hpilo.h b/drivers/misc/hpilo.h index b64a20ef07e3..03a14c82aad9 100644 --- a/drivers/misc/hpilo.h +++ b/drivers/misc/hpilo.h | |||
@@ -19,8 +19,12 @@ | |||
19 | #define MAX_ILO_DEV 1 | 19 | #define MAX_ILO_DEV 1 |
20 | /* max number of files */ | 20 | /* max number of files */ |
21 | #define MAX_OPEN (MAX_CCB * MAX_ILO_DEV) | 21 | #define MAX_OPEN (MAX_CCB * MAX_ILO_DEV) |
22 | /* total wait time in usec */ | ||
23 | #define MAX_WAIT_TIME 10000 | ||
24 | /* per spin wait time in usec */ | ||
25 | #define WAIT_TIME 10 | ||
22 | /* spin counter for open/close delay */ | 26 | /* spin counter for open/close delay */ |
23 | #define MAX_WAIT 10000 | 27 | #define MAX_WAIT (MAX_WAIT_TIME / WAIT_TIME) |
24 | 28 | ||
25 | /* | 29 | /* |
26 | * Per device, used to track global memory allocations. | 30 | * Per device, used to track global memory allocations. |
diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c new file mode 100644 index 000000000000..2e2a5923d4c2 --- /dev/null +++ b/drivers/misc/isl29003.c | |||
@@ -0,0 +1,470 @@ | |||
1 | /* | ||
2 | * isl29003.c - Linux kernel module for | ||
3 | * Intersil ISL29003 ambient light sensor | ||
4 | * | ||
5 | * See file:Documentation/misc-devices/isl29003 | ||
6 | * | ||
7 | * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> | ||
8 | * | ||
9 | * Based on code written by | ||
10 | * Rodolfo Giometti <giometti@linux.it> | ||
11 | * Eurotech S.p.A. <info@eurotech.it> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/i2c.h> | ||
32 | #include <linux/mutex.h> | ||
33 | #include <linux/delay.h> | ||
34 | |||
35 | #define ISL29003_DRV_NAME "isl29003" | ||
36 | #define DRIVER_VERSION "1.0" | ||
37 | |||
38 | #define ISL29003_REG_COMMAND 0x00 | ||
39 | #define ISL29003_ADC_ENABLED (1 << 7) | ||
40 | #define ISL29003_ADC_PD (1 << 6) | ||
41 | #define ISL29003_TIMING_INT (1 << 5) | ||
42 | #define ISL29003_MODE_SHIFT (2) | ||
43 | #define ISL29003_MODE_MASK (0x3 << ISL29003_MODE_SHIFT) | ||
44 | #define ISL29003_RES_SHIFT (0) | ||
45 | #define ISL29003_RES_MASK (0x3 << ISL29003_RES_SHIFT) | ||
46 | |||
47 | #define ISL29003_REG_CONTROL 0x01 | ||
48 | #define ISL29003_INT_FLG (1 << 5) | ||
49 | #define ISL29003_RANGE_SHIFT (2) | ||
50 | #define ISL29003_RANGE_MASK (0x3 << ISL29003_RANGE_SHIFT) | ||
51 | #define ISL29003_INT_PERSISTS_SHIFT (0) | ||
52 | #define ISL29003_INT_PERSISTS_MASK (0xf << ISL29003_INT_PERSISTS_SHIFT) | ||
53 | |||
54 | #define ISL29003_REG_IRQ_THRESH_HI 0x02 | ||
55 | #define ISL29003_REG_IRQ_THRESH_LO 0x03 | ||
56 | #define ISL29003_REG_LSB_SENSOR 0x04 | ||
57 | #define ISL29003_REG_MSB_SENSOR 0x05 | ||
58 | #define ISL29003_REG_LSB_TIMER 0x06 | ||
59 | #define ISL29003_REG_MSB_TIMER 0x07 | ||
60 | |||
61 | #define ISL29003_NUM_CACHABLE_REGS 4 | ||
62 | |||
63 | struct isl29003_data { | ||
64 | struct i2c_client *client; | ||
65 | struct mutex lock; | ||
66 | u8 reg_cache[ISL29003_NUM_CACHABLE_REGS]; | ||
67 | }; | ||
68 | |||
69 | static int gain_range[] = { | ||
70 | 1000, 4000, 16000, 64000 | ||
71 | }; | ||
72 | |||
73 | /* | ||
74 | * register access helpers | ||
75 | */ | ||
76 | |||
77 | static int __isl29003_read_reg(struct i2c_client *client, | ||
78 | u32 reg, u8 mask, u8 shift) | ||
79 | { | ||
80 | struct isl29003_data *data = i2c_get_clientdata(client); | ||
81 | return (data->reg_cache[reg] & mask) >> shift; | ||
82 | } | ||
83 | |||
84 | static int __isl29003_write_reg(struct i2c_client *client, | ||
85 | u32 reg, u8 mask, u8 shift, u8 val) | ||
86 | { | ||
87 | struct isl29003_data *data = i2c_get_clientdata(client); | ||
88 | int ret = 0; | ||
89 | u8 tmp; | ||
90 | |||
91 | if (reg >= ISL29003_NUM_CACHABLE_REGS) | ||
92 | return -EINVAL; | ||
93 | |||
94 | mutex_lock(&data->lock); | ||
95 | |||
96 | tmp = data->reg_cache[reg]; | ||
97 | tmp &= ~mask; | ||
98 | tmp |= val << shift; | ||
99 | |||
100 | ret = i2c_smbus_write_byte_data(client, reg, tmp); | ||
101 | if (!ret) | ||
102 | data->reg_cache[reg] = tmp; | ||
103 | |||
104 | mutex_unlock(&data->lock); | ||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * internally used functions | ||
110 | */ | ||
111 | |||
112 | /* range */ | ||
113 | static int isl29003_get_range(struct i2c_client *client) | ||
114 | { | ||
115 | return __isl29003_read_reg(client, ISL29003_REG_CONTROL, | ||
116 | ISL29003_RANGE_MASK, ISL29003_RANGE_SHIFT); | ||
117 | } | ||
118 | |||
119 | static int isl29003_set_range(struct i2c_client *client, int range) | ||
120 | { | ||
121 | return __isl29003_write_reg(client, ISL29003_REG_CONTROL, | ||
122 | ISL29003_RANGE_MASK, ISL29003_RANGE_SHIFT, range); | ||
123 | } | ||
124 | |||
125 | /* resolution */ | ||
126 | static int isl29003_get_resolution(struct i2c_client *client) | ||
127 | { | ||
128 | return __isl29003_read_reg(client, ISL29003_REG_COMMAND, | ||
129 | ISL29003_RES_MASK, ISL29003_RES_SHIFT); | ||
130 | } | ||
131 | |||
132 | static int isl29003_set_resolution(struct i2c_client *client, int res) | ||
133 | { | ||
134 | return __isl29003_write_reg(client, ISL29003_REG_COMMAND, | ||
135 | ISL29003_RES_MASK, ISL29003_RES_SHIFT, res); | ||
136 | } | ||
137 | |||
138 | /* mode */ | ||
139 | static int isl29003_get_mode(struct i2c_client *client) | ||
140 | { | ||
141 | return __isl29003_read_reg(client, ISL29003_REG_COMMAND, | ||
142 | ISL29003_RES_MASK, ISL29003_RES_SHIFT); | ||
143 | } | ||
144 | |||
145 | static int isl29003_set_mode(struct i2c_client *client, int mode) | ||
146 | { | ||
147 | return __isl29003_write_reg(client, ISL29003_REG_COMMAND, | ||
148 | ISL29003_RES_MASK, ISL29003_RES_SHIFT, mode); | ||
149 | } | ||
150 | |||
151 | /* power_state */ | ||
152 | static int isl29003_set_power_state(struct i2c_client *client, int state) | ||
153 | { | ||
154 | return __isl29003_write_reg(client, ISL29003_REG_COMMAND, | ||
155 | ISL29003_ADC_ENABLED | ISL29003_ADC_PD, 0, | ||
156 | state ? ISL29003_ADC_ENABLED : ISL29003_ADC_PD); | ||
157 | } | ||
158 | |||
159 | static int isl29003_get_power_state(struct i2c_client *client) | ||
160 | { | ||
161 | struct isl29003_data *data = i2c_get_clientdata(client); | ||
162 | u8 cmdreg = data->reg_cache[ISL29003_REG_COMMAND]; | ||
163 | return ~cmdreg & ISL29003_ADC_PD; | ||
164 | } | ||
165 | |||
166 | static int isl29003_get_adc_value(struct i2c_client *client) | ||
167 | { | ||
168 | struct isl29003_data *data = i2c_get_clientdata(client); | ||
169 | int lsb, msb, range, bitdepth; | ||
170 | |||
171 | mutex_lock(&data->lock); | ||
172 | lsb = i2c_smbus_read_byte_data(client, ISL29003_REG_LSB_SENSOR); | ||
173 | |||
174 | if (lsb < 0) { | ||
175 | mutex_unlock(&data->lock); | ||
176 | return lsb; | ||
177 | } | ||
178 | |||
179 | msb = i2c_smbus_read_byte_data(client, ISL29003_REG_MSB_SENSOR); | ||
180 | mutex_unlock(&data->lock); | ||
181 | |||
182 | if (msb < 0) | ||
183 | return msb; | ||
184 | |||
185 | range = isl29003_get_range(client); | ||
186 | bitdepth = (4 - isl29003_get_resolution(client)) * 4; | ||
187 | return (((msb << 8) | lsb) * gain_range[range]) >> bitdepth; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * sysfs layer | ||
192 | */ | ||
193 | |||
194 | /* range */ | ||
195 | static ssize_t isl29003_show_range(struct device *dev, | ||
196 | struct device_attribute *attr, char *buf) | ||
197 | { | ||
198 | struct i2c_client *client = to_i2c_client(dev); | ||
199 | return sprintf(buf, "%i\n", isl29003_get_range(client)); | ||
200 | } | ||
201 | |||
202 | static ssize_t isl29003_store_range(struct device *dev, | ||
203 | struct device_attribute *attr, | ||
204 | const char *buf, size_t count) | ||
205 | { | ||
206 | struct i2c_client *client = to_i2c_client(dev); | ||
207 | unsigned long val; | ||
208 | int ret; | ||
209 | |||
210 | if ((strict_strtoul(buf, 10, &val) < 0) || (val > 3)) | ||
211 | return -EINVAL; | ||
212 | |||
213 | ret = isl29003_set_range(client, val); | ||
214 | if (ret < 0) | ||
215 | return ret; | ||
216 | |||
217 | return count; | ||
218 | } | ||
219 | |||
220 | static DEVICE_ATTR(range, S_IWUSR | S_IRUGO, | ||
221 | isl29003_show_range, isl29003_store_range); | ||
222 | |||
223 | |||
224 | /* resolution */ | ||
225 | static ssize_t isl29003_show_resolution(struct device *dev, | ||
226 | struct device_attribute *attr, | ||
227 | char *buf) | ||
228 | { | ||
229 | struct i2c_client *client = to_i2c_client(dev); | ||
230 | return sprintf(buf, "%d\n", isl29003_get_resolution(client)); | ||
231 | } | ||
232 | |||
233 | static ssize_t isl29003_store_resolution(struct device *dev, | ||
234 | struct device_attribute *attr, | ||
235 | const char *buf, size_t count) | ||
236 | { | ||
237 | struct i2c_client *client = to_i2c_client(dev); | ||
238 | unsigned long val; | ||
239 | int ret; | ||
240 | |||
241 | if ((strict_strtoul(buf, 10, &val) < 0) || (val > 3)) | ||
242 | return -EINVAL; | ||
243 | |||
244 | ret = isl29003_set_resolution(client, val); | ||
245 | if (ret < 0) | ||
246 | return ret; | ||
247 | |||
248 | return count; | ||
249 | } | ||
250 | |||
251 | static DEVICE_ATTR(resolution, S_IWUSR | S_IRUGO, | ||
252 | isl29003_show_resolution, isl29003_store_resolution); | ||
253 | |||
254 | /* mode */ | ||
255 | static ssize_t isl29003_show_mode(struct device *dev, | ||
256 | struct device_attribute *attr, char *buf) | ||
257 | { | ||
258 | struct i2c_client *client = to_i2c_client(dev); | ||
259 | return sprintf(buf, "%d\n", isl29003_get_mode(client)); | ||
260 | } | ||
261 | |||
262 | static ssize_t isl29003_store_mode(struct device *dev, | ||
263 | struct device_attribute *attr, const char *buf, size_t count) | ||
264 | { | ||
265 | struct i2c_client *client = to_i2c_client(dev); | ||
266 | unsigned long val; | ||
267 | int ret; | ||
268 | |||
269 | if ((strict_strtoul(buf, 10, &val) < 0) || (val > 2)) | ||
270 | return -EINVAL; | ||
271 | |||
272 | ret = isl29003_set_mode(client, val); | ||
273 | if (ret < 0) | ||
274 | return ret; | ||
275 | |||
276 | return count; | ||
277 | } | ||
278 | |||
279 | static DEVICE_ATTR(mode, S_IWUSR | S_IRUGO, | ||
280 | isl29003_show_mode, isl29003_store_mode); | ||
281 | |||
282 | |||
283 | /* power state */ | ||
284 | static ssize_t isl29003_show_power_state(struct device *dev, | ||
285 | struct device_attribute *attr, | ||
286 | char *buf) | ||
287 | { | ||
288 | struct i2c_client *client = to_i2c_client(dev); | ||
289 | return sprintf(buf, "%d\n", isl29003_get_power_state(client)); | ||
290 | } | ||
291 | |||
292 | static ssize_t isl29003_store_power_state(struct device *dev, | ||
293 | struct device_attribute *attr, | ||
294 | const char *buf, size_t count) | ||
295 | { | ||
296 | struct i2c_client *client = to_i2c_client(dev); | ||
297 | unsigned long val; | ||
298 | int ret; | ||
299 | |||
300 | if ((strict_strtoul(buf, 10, &val) < 0) || (val > 1)) | ||
301 | return -EINVAL; | ||
302 | |||
303 | ret = isl29003_set_power_state(client, val); | ||
304 | return ret ? ret : count; | ||
305 | } | ||
306 | |||
307 | static DEVICE_ATTR(power_state, S_IWUSR | S_IRUGO, | ||
308 | isl29003_show_power_state, isl29003_store_power_state); | ||
309 | |||
310 | |||
311 | /* lux */ | ||
312 | static ssize_t isl29003_show_lux(struct device *dev, | ||
313 | struct device_attribute *attr, char *buf) | ||
314 | { | ||
315 | struct i2c_client *client = to_i2c_client(dev); | ||
316 | |||
317 | /* No LUX data if not operational */ | ||
318 | if (!isl29003_get_power_state(client)) | ||
319 | return -EBUSY; | ||
320 | |||
321 | return sprintf(buf, "%d\n", isl29003_get_adc_value(client)); | ||
322 | } | ||
323 | |||
324 | static DEVICE_ATTR(lux, S_IRUGO, isl29003_show_lux, NULL); | ||
325 | |||
326 | static struct attribute *isl29003_attributes[] = { | ||
327 | &dev_attr_range.attr, | ||
328 | &dev_attr_resolution.attr, | ||
329 | &dev_attr_mode.attr, | ||
330 | &dev_attr_power_state.attr, | ||
331 | &dev_attr_lux.attr, | ||
332 | NULL | ||
333 | }; | ||
334 | |||
335 | static const struct attribute_group isl29003_attr_group = { | ||
336 | .attrs = isl29003_attributes, | ||
337 | }; | ||
338 | |||
339 | static int isl29003_init_client(struct i2c_client *client) | ||
340 | { | ||
341 | struct isl29003_data *data = i2c_get_clientdata(client); | ||
342 | int i; | ||
343 | |||
344 | /* read all the registers once to fill the cache. | ||
345 | * if one of the reads fails, we consider the init failed */ | ||
346 | for (i = 0; i < ARRAY_SIZE(data->reg_cache); i++) { | ||
347 | int v = i2c_smbus_read_byte_data(client, i); | ||
348 | if (v < 0) | ||
349 | return -ENODEV; | ||
350 | |||
351 | data->reg_cache[i] = v; | ||
352 | } | ||
353 | |||
354 | /* set defaults */ | ||
355 | isl29003_set_range(client, 0); | ||
356 | isl29003_set_resolution(client, 0); | ||
357 | isl29003_set_mode(client, 0); | ||
358 | isl29003_set_power_state(client, 0); | ||
359 | |||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | /* | ||
364 | * I2C layer | ||
365 | */ | ||
366 | |||
367 | static int __devinit isl29003_probe(struct i2c_client *client, | ||
368 | const struct i2c_device_id *id) | ||
369 | { | ||
370 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | ||
371 | struct isl29003_data *data; | ||
372 | int err = 0; | ||
373 | |||
374 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) | ||
375 | return -EIO; | ||
376 | |||
377 | data = kzalloc(sizeof(struct isl29003_data), GFP_KERNEL); | ||
378 | if (!data) | ||
379 | return -ENOMEM; | ||
380 | |||
381 | data->client = client; | ||
382 | i2c_set_clientdata(client, data); | ||
383 | mutex_init(&data->lock); | ||
384 | |||
385 | /* initialize the ISL29003 chip */ | ||
386 | err = isl29003_init_client(client); | ||
387 | if (err) | ||
388 | goto exit_kfree; | ||
389 | |||
390 | /* register sysfs hooks */ | ||
391 | err = sysfs_create_group(&client->dev.kobj, &isl29003_attr_group); | ||
392 | if (err) | ||
393 | goto exit_kfree; | ||
394 | |||
395 | dev_info(&client->dev, "driver version %s enabled\n", DRIVER_VERSION); | ||
396 | return 0; | ||
397 | |||
398 | exit_kfree: | ||
399 | kfree(data); | ||
400 | return err; | ||
401 | } | ||
402 | |||
403 | static int __devexit isl29003_remove(struct i2c_client *client) | ||
404 | { | ||
405 | sysfs_remove_group(&client->dev.kobj, &isl29003_attr_group); | ||
406 | isl29003_set_power_state(client, 0); | ||
407 | kfree(i2c_get_clientdata(client)); | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | #ifdef CONFIG_PM | ||
412 | static int isl29003_suspend(struct i2c_client *client, pm_message_t mesg) | ||
413 | { | ||
414 | return isl29003_set_power_state(client, 0); | ||
415 | } | ||
416 | |||
417 | static int isl29003_resume(struct i2c_client *client) | ||
418 | { | ||
419 | int i; | ||
420 | struct isl29003_data *data = i2c_get_clientdata(client); | ||
421 | |||
422 | /* restore registers from cache */ | ||
423 | for (i = 0; i < ARRAY_SIZE(data->reg_cache); i++) | ||
424 | if (!i2c_smbus_write_byte_data(client, i, data->reg_cache[i])) | ||
425 | return -EIO; | ||
426 | |||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | #else | ||
431 | #define isl29003_suspend NULL | ||
432 | #define isl29003_resume NULL | ||
433 | #endif /* CONFIG_PM */ | ||
434 | |||
435 | static const struct i2c_device_id isl29003_id[] = { | ||
436 | { "isl29003", 0 }, | ||
437 | {} | ||
438 | }; | ||
439 | MODULE_DEVICE_TABLE(i2c, isl29003_id); | ||
440 | |||
441 | static struct i2c_driver isl29003_driver = { | ||
442 | .driver = { | ||
443 | .name = ISL29003_DRV_NAME, | ||
444 | .owner = THIS_MODULE, | ||
445 | }, | ||
446 | .suspend = isl29003_suspend, | ||
447 | .resume = isl29003_resume, | ||
448 | .probe = isl29003_probe, | ||
449 | .remove = __devexit_p(isl29003_remove), | ||
450 | .id_table = isl29003_id, | ||
451 | }; | ||
452 | |||
453 | static int __init isl29003_init(void) | ||
454 | { | ||
455 | return i2c_add_driver(&isl29003_driver); | ||
456 | } | ||
457 | |||
458 | static void __exit isl29003_exit(void) | ||
459 | { | ||
460 | i2c_del_driver(&isl29003_driver); | ||
461 | } | ||
462 | |||
463 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | ||
464 | MODULE_DESCRIPTION("ISL29003 ambient light sensor driver"); | ||
465 | MODULE_LICENSE("GPL v2"); | ||
466 | MODULE_VERSION(DRIVER_VERSION); | ||
467 | |||
468 | module_init(isl29003_init); | ||
469 | module_exit(isl29003_exit); | ||
470 | |||
diff --git a/drivers/mmc/card/sdio_uart.c b/drivers/mmc/card/sdio_uart.c index 78ad48718ab0..36a8d53ad2a2 100644 --- a/drivers/mmc/card/sdio_uart.c +++ b/drivers/mmc/card/sdio_uart.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
33 | #include <linux/seq_file.h> | ||
33 | #include <linux/serial_reg.h> | 34 | #include <linux/serial_reg.h> |
34 | #include <linux/circ_buf.h> | 35 | #include <linux/circ_buf.h> |
35 | #include <linux/gfp.h> | 36 | #include <linux/gfp.h> |
@@ -933,67 +934,64 @@ static int sdio_uart_tiocmset(struct tty_struct *tty, struct file *file, | |||
933 | return result; | 934 | return result; |
934 | } | 935 | } |
935 | 936 | ||
936 | static int sdio_uart_read_proc(char *page, char **start, off_t off, | 937 | static int sdio_uart_proc_show(struct seq_file *m, void *v) |
937 | int count, int *eof, void *data) | ||
938 | { | 938 | { |
939 | int i, len = 0; | 939 | int i; |
940 | off_t begin = 0; | ||
941 | 940 | ||
942 | len += sprintf(page, "serinfo:1.0 driver%s%s revision:%s\n", | 941 | seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n", |
943 | "", "", ""); | 942 | "", "", ""); |
944 | for (i = 0; i < UART_NR && len < PAGE_SIZE - 96; i++) { | 943 | for (i = 0; i < UART_NR; i++) { |
945 | struct sdio_uart_port *port = sdio_uart_port_get(i); | 944 | struct sdio_uart_port *port = sdio_uart_port_get(i); |
946 | if (port) { | 945 | if (port) { |
947 | len += sprintf(page+len, "%d: uart:SDIO", i); | 946 | seq_printf(m, "%d: uart:SDIO", i); |
948 | if(capable(CAP_SYS_ADMIN)) { | 947 | if(capable(CAP_SYS_ADMIN)) { |
949 | len += sprintf(page + len, " tx:%d rx:%d", | 948 | seq_printf(m, " tx:%d rx:%d", |
950 | port->icount.tx, port->icount.rx); | 949 | port->icount.tx, port->icount.rx); |
951 | if (port->icount.frame) | 950 | if (port->icount.frame) |
952 | len += sprintf(page + len, " fe:%d", | 951 | seq_printf(m, " fe:%d", |
953 | port->icount.frame); | 952 | port->icount.frame); |
954 | if (port->icount.parity) | 953 | if (port->icount.parity) |
955 | len += sprintf(page + len, " pe:%d", | 954 | seq_printf(m, " pe:%d", |
956 | port->icount.parity); | 955 | port->icount.parity); |
957 | if (port->icount.brk) | 956 | if (port->icount.brk) |
958 | len += sprintf(page + len, " brk:%d", | 957 | seq_printf(m, " brk:%d", |
959 | port->icount.brk); | 958 | port->icount.brk); |
960 | if (port->icount.overrun) | 959 | if (port->icount.overrun) |
961 | len += sprintf(page + len, " oe:%d", | 960 | seq_printf(m, " oe:%d", |
962 | port->icount.overrun); | 961 | port->icount.overrun); |
963 | if (port->icount.cts) | 962 | if (port->icount.cts) |
964 | len += sprintf(page + len, " cts:%d", | 963 | seq_printf(m, " cts:%d", |
965 | port->icount.cts); | 964 | port->icount.cts); |
966 | if (port->icount.dsr) | 965 | if (port->icount.dsr) |
967 | len += sprintf(page + len, " dsr:%d", | 966 | seq_printf(m, " dsr:%d", |
968 | port->icount.dsr); | 967 | port->icount.dsr); |
969 | if (port->icount.rng) | 968 | if (port->icount.rng) |
970 | len += sprintf(page + len, " rng:%d", | 969 | seq_printf(m, " rng:%d", |
971 | port->icount.rng); | 970 | port->icount.rng); |
972 | if (port->icount.dcd) | 971 | if (port->icount.dcd) |
973 | len += sprintf(page + len, " dcd:%d", | 972 | seq_printf(m, " dcd:%d", |
974 | port->icount.dcd); | 973 | port->icount.dcd); |
975 | } | 974 | } |
976 | strcat(page, "\n"); | ||
977 | len++; | ||
978 | sdio_uart_port_put(port); | 975 | sdio_uart_port_put(port); |
979 | } | 976 | seq_putc(m, '\n'); |
980 | |||
981 | if (len + begin > off + count) | ||
982 | goto done; | ||
983 | if (len + begin < off) { | ||
984 | begin += len; | ||
985 | len = 0; | ||
986 | } | 977 | } |
987 | } | 978 | } |
988 | *eof = 1; | 979 | return 0; |
980 | } | ||
989 | 981 | ||
990 | done: | 982 | static int sdio_uart_proc_open(struct inode *inode, struct file *file) |
991 | if (off >= len + begin) | 983 | { |
992 | return 0; | 984 | return single_open(file, sdio_uart_proc_show, NULL); |
993 | *start = page + (off - begin); | ||
994 | return (count < begin + len - off) ? count : (begin + len - off); | ||
995 | } | 985 | } |
996 | 986 | ||
987 | static const struct file_operations sdio_uart_proc_fops = { | ||
988 | .owner = THIS_MODULE, | ||
989 | .open = sdio_uart_proc_open, | ||
990 | .read = seq_read, | ||
991 | .llseek = seq_lseek, | ||
992 | .release = single_release, | ||
993 | }; | ||
994 | |||
997 | static const struct tty_operations sdio_uart_ops = { | 995 | static const struct tty_operations sdio_uart_ops = { |
998 | .open = sdio_uart_open, | 996 | .open = sdio_uart_open, |
999 | .close = sdio_uart_close, | 997 | .close = sdio_uart_close, |
@@ -1007,7 +1005,7 @@ static const struct tty_operations sdio_uart_ops = { | |||
1007 | .break_ctl = sdio_uart_break_ctl, | 1005 | .break_ctl = sdio_uart_break_ctl, |
1008 | .tiocmget = sdio_uart_tiocmget, | 1006 | .tiocmget = sdio_uart_tiocmget, |
1009 | .tiocmset = sdio_uart_tiocmset, | 1007 | .tiocmset = sdio_uart_tiocmset, |
1010 | .read_proc = sdio_uart_read_proc, | 1008 | .proc_fops = &sdio_uart_proc_fops, |
1011 | }; | 1009 | }; |
1012 | 1010 | ||
1013 | static struct tty_driver *sdio_uart_tty_driver; | 1011 | static struct tty_driver *sdio_uart_tty_driver; |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 9c326a50a3ee..99610f358c40 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -3444,25 +3444,12 @@ static void bond_remove_proc_entry(struct bonding *bond) | |||
3444 | */ | 3444 | */ |
3445 | static void bond_create_proc_dir(void) | 3445 | static void bond_create_proc_dir(void) |
3446 | { | 3446 | { |
3447 | int len = strlen(DRV_NAME); | ||
3448 | |||
3449 | for (bond_proc_dir = init_net.proc_net->subdir; bond_proc_dir; | ||
3450 | bond_proc_dir = bond_proc_dir->next) { | ||
3451 | if ((bond_proc_dir->namelen == len) && | ||
3452 | !memcmp(bond_proc_dir->name, DRV_NAME, len)) { | ||
3453 | break; | ||
3454 | } | ||
3455 | } | ||
3456 | |||
3457 | if (!bond_proc_dir) { | 3447 | if (!bond_proc_dir) { |
3458 | bond_proc_dir = proc_mkdir(DRV_NAME, init_net.proc_net); | 3448 | bond_proc_dir = proc_mkdir(DRV_NAME, init_net.proc_net); |
3459 | if (bond_proc_dir) { | 3449 | if (!bond_proc_dir) |
3460 | bond_proc_dir->owner = THIS_MODULE; | ||
3461 | } else { | ||
3462 | printk(KERN_WARNING DRV_NAME | 3450 | printk(KERN_WARNING DRV_NAME |
3463 | ": Warning: cannot create /proc/net/%s\n", | 3451 | ": Warning: cannot create /proc/net/%s\n", |
3464 | DRV_NAME); | 3452 | DRV_NAME); |
3465 | } | ||
3466 | } | 3453 | } |
3467 | } | 3454 | } |
3468 | 3455 | ||
@@ -3471,25 +3458,7 @@ static void bond_create_proc_dir(void) | |||
3471 | */ | 3458 | */ |
3472 | static void bond_destroy_proc_dir(void) | 3459 | static void bond_destroy_proc_dir(void) |
3473 | { | 3460 | { |
3474 | struct proc_dir_entry *de; | 3461 | if (bond_proc_dir) { |
3475 | |||
3476 | if (!bond_proc_dir) { | ||
3477 | return; | ||
3478 | } | ||
3479 | |||
3480 | /* verify that the /proc dir is empty */ | ||
3481 | for (de = bond_proc_dir->subdir; de; de = de->next) { | ||
3482 | /* ignore . and .. */ | ||
3483 | if (*(de->name) != '.') { | ||
3484 | break; | ||
3485 | } | ||
3486 | } | ||
3487 | |||
3488 | if (de) { | ||
3489 | if (bond_proc_dir->owner == THIS_MODULE) { | ||
3490 | bond_proc_dir->owner = NULL; | ||
3491 | } | ||
3492 | } else { | ||
3493 | remove_proc_entry(DRV_NAME, init_net.proc_net); | 3462 | remove_proc_entry(DRV_NAME, init_net.proc_net); |
3494 | bond_proc_dir = NULL; | 3463 | bond_proc_dir = NULL; |
3495 | } | 3464 | } |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 6a38800be3f1..65f55877be95 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -289,9 +289,9 @@ static int gfar_of_init(struct net_device *dev) | |||
289 | id = of_get_property(phy, "reg", NULL); | 289 | id = of_get_property(phy, "reg", NULL); |
290 | 290 | ||
291 | of_node_put(phy); | 291 | of_node_put(phy); |
292 | of_node_put(mdio); | ||
293 | 292 | ||
294 | fsl_pq_mdio_bus_name(bus_name, mdio); | 293 | fsl_pq_mdio_bus_name(bus_name, mdio); |
294 | of_node_put(mdio); | ||
295 | snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), "%s:%02x", | 295 | snprintf(priv->phy_bus_id, sizeof(priv->phy_bus_id), "%s:%02x", |
296 | bus_name, *id); | 296 | bus_name, *id); |
297 | } | 297 | } |
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index 881bf818bb48..7459b3ac77a9 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c | |||
@@ -445,6 +445,7 @@ static const struct net_device_ops scc_netdev_ops = { | |||
445 | .ndo_stop = scc_close, | 445 | .ndo_stop = scc_close, |
446 | .ndo_start_xmit = scc_send_packet, | 446 | .ndo_start_xmit = scc_send_packet, |
447 | .ndo_do_ioctl = scc_ioctl, | 447 | .ndo_do_ioctl = scc_ioctl, |
448 | .ndo_set_mac_address = scc_set_mac_address, | ||
448 | }; | 449 | }; |
449 | 450 | ||
450 | static int __init setup_adapter(int card_base, int type, int n) | 451 | static int __init setup_adapter(int card_base, int type, int n) |
@@ -584,7 +585,6 @@ static int __init setup_adapter(int card_base, int type, int n) | |||
584 | dev->irq = irq; | 585 | dev->irq = irq; |
585 | dev->netdev_ops = &scc_netdev_ops; | 586 | dev->netdev_ops = &scc_netdev_ops; |
586 | dev->header_ops = &ax25_header_ops; | 587 | dev->header_ops = &ax25_header_ops; |
587 | dev->set_mac_address = scc_set_mac_address; | ||
588 | } | 588 | } |
589 | if (register_netdev(info->dev[0])) { | 589 | if (register_netdev(info->dev[0])) { |
590 | printk(KERN_ERR "dmascc: could not register %s\n", | 590 | printk(KERN_ERR "dmascc: could not register %s\n", |
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index 1243bc8e0035..ac0e4b6b6b66 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c | |||
@@ -1871,13 +1871,6 @@ static int __init vlsi_mod_init(void) | |||
1871 | * without procfs - it's not required for the driver to work. | 1871 | * without procfs - it's not required for the driver to work. |
1872 | */ | 1872 | */ |
1873 | vlsi_proc_root = proc_mkdir(PROC_DIR, NULL); | 1873 | vlsi_proc_root = proc_mkdir(PROC_DIR, NULL); |
1874 | if (vlsi_proc_root) { | ||
1875 | /* protect registered procdir against module removal. | ||
1876 | * Because we are in the module init path there's no race | ||
1877 | * window after create_proc_entry (and no barrier needed). | ||
1878 | */ | ||
1879 | vlsi_proc_root->owner = THIS_MODULE; | ||
1880 | } | ||
1881 | 1874 | ||
1882 | ret = pci_register_driver(&vlsi_irda_driver); | 1875 | ret = pci_register_driver(&vlsi_irda_driver); |
1883 | 1876 | ||
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index d304d38cd5d1..eceadf787a67 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c | |||
@@ -294,14 +294,12 @@ static ssize_t show_remote_port(struct netconsole_target *nt, char *buf) | |||
294 | 294 | ||
295 | static ssize_t show_local_ip(struct netconsole_target *nt, char *buf) | 295 | static ssize_t show_local_ip(struct netconsole_target *nt, char *buf) |
296 | { | 296 | { |
297 | return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n", | 297 | return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.local_ip); |
298 | HIPQUAD(nt->np.local_ip)); | ||
299 | } | 298 | } |
300 | 299 | ||
301 | static ssize_t show_remote_ip(struct netconsole_target *nt, char *buf) | 300 | static ssize_t show_remote_ip(struct netconsole_target *nt, char *buf) |
302 | { | 301 | { |
303 | return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n", | 302 | return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.remote_ip); |
304 | HIPQUAD(nt->np.remote_ip)); | ||
305 | } | 303 | } |
306 | 304 | ||
307 | static ssize_t show_local_mac(struct netconsole_target *nt, char *buf) | 305 | static ssize_t show_local_mac(struct netconsole_target *nt, char *buf) |
@@ -438,7 +436,7 @@ static ssize_t store_local_ip(struct netconsole_target *nt, | |||
438 | return -EINVAL; | 436 | return -EINVAL; |
439 | } | 437 | } |
440 | 438 | ||
441 | nt->np.local_ip = ntohl(in_aton(buf)); | 439 | nt->np.local_ip = in_aton(buf); |
442 | 440 | ||
443 | return strnlen(buf, count); | 441 | return strnlen(buf, count); |
444 | } | 442 | } |
@@ -454,7 +452,7 @@ static ssize_t store_remote_ip(struct netconsole_target *nt, | |||
454 | return -EINVAL; | 452 | return -EINVAL; |
455 | } | 453 | } |
456 | 454 | ||
457 | nt->np.remote_ip = ntohl(in_aton(buf)); | 455 | nt->np.remote_ip = in_aton(buf); |
458 | 456 | ||
459 | return strnlen(buf, count); | 457 | return strnlen(buf, count); |
460 | } | 458 | } |
diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c index 539e18ab485c..2a8da476ab3d 100644 --- a/drivers/net/ni5010.c +++ b/drivers/net/ni5010.c | |||
@@ -189,6 +189,17 @@ static void __init trigger_irq(int ioaddr) | |||
189 | outb(MM_EN_XMT|MM_MUX, IE_MMODE); /* Start transmission */ | 189 | outb(MM_EN_XMT|MM_MUX, IE_MMODE); /* Start transmission */ |
190 | } | 190 | } |
191 | 191 | ||
192 | static const struct net_device_ops ni5010_netdev_ops = { | ||
193 | .ndo_open = ni5010_open, | ||
194 | .ndo_stop = ni5010_close, | ||
195 | .ndo_start_xmit = ni5010_send_packet, | ||
196 | .ndo_set_multicast_list = ni5010_set_multicast_list, | ||
197 | .ndo_tx_timeout = ni5010_timeout, | ||
198 | .ndo_validate_addr = eth_validate_addr, | ||
199 | .ndo_set_mac_address = eth_mac_addr, | ||
200 | .ndo_change_mtu = eth_change_mtu, | ||
201 | }; | ||
202 | |||
192 | /* | 203 | /* |
193 | * This is the real probe routine. Linux has a history of friendly device | 204 | * This is the real probe routine. Linux has a history of friendly device |
194 | * probes on the ISA bus. A good device probes avoids doing writes, and | 205 | * probes on the ISA bus. A good device probes avoids doing writes, and |
@@ -328,13 +339,8 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr) | |||
328 | outb(0, IE_RBUF); /* set buffer byte 0 to 0 again */ | 339 | outb(0, IE_RBUF); /* set buffer byte 0 to 0 again */ |
329 | } | 340 | } |
330 | printk("-> bufsize rcv/xmt=%d/%d\n", bufsize_rcv, NI5010_BUFSIZE); | 341 | printk("-> bufsize rcv/xmt=%d/%d\n", bufsize_rcv, NI5010_BUFSIZE); |
331 | memset(netdev_priv(dev), 0, sizeof(struct ni5010_local)); | ||
332 | 342 | ||
333 | dev->open = ni5010_open; | 343 | dev->netdev_ops = &ni5010_netdev_ops; |
334 | dev->stop = ni5010_close; | ||
335 | dev->hard_start_xmit = ni5010_send_packet; | ||
336 | dev->set_multicast_list = ni5010_set_multicast_list; | ||
337 | dev->tx_timeout = ni5010_timeout; | ||
338 | dev->watchdog_timeo = HZ/20; | 344 | dev->watchdog_timeo = HZ/20; |
339 | 345 | ||
340 | dev->flags &= ~IFF_MULTICAST; /* Multicast doesn't work */ | 346 | dev->flags &= ~IFF_MULTICAST; /* Multicast doesn't work */ |
diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 50c11126a3db..02c37e2f08a9 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c | |||
@@ -3441,7 +3441,8 @@ static int niu_rx_pkt_ignore(struct niu *np, struct rx_ring_info *rp) | |||
3441 | return num_rcr; | 3441 | return num_rcr; |
3442 | } | 3442 | } |
3443 | 3443 | ||
3444 | static int niu_process_rx_pkt(struct niu *np, struct rx_ring_info *rp) | 3444 | static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np, |
3445 | struct rx_ring_info *rp) | ||
3445 | { | 3446 | { |
3446 | unsigned int index = rp->rcr_index; | 3447 | unsigned int index = rp->rcr_index; |
3447 | struct sk_buff *skb; | 3448 | struct sk_buff *skb; |
@@ -3518,7 +3519,7 @@ static int niu_process_rx_pkt(struct niu *np, struct rx_ring_info *rp) | |||
3518 | 3519 | ||
3519 | skb->protocol = eth_type_trans(skb, np->dev); | 3520 | skb->protocol = eth_type_trans(skb, np->dev); |
3520 | skb_record_rx_queue(skb, rp->rx_channel); | 3521 | skb_record_rx_queue(skb, rp->rx_channel); |
3521 | netif_receive_skb(skb); | 3522 | napi_gro_receive(napi, skb); |
3522 | 3523 | ||
3523 | return num_rcr; | 3524 | return num_rcr; |
3524 | } | 3525 | } |
@@ -3706,7 +3707,8 @@ static inline void niu_sync_rx_discard_stats(struct niu *np, | |||
3706 | } | 3707 | } |
3707 | } | 3708 | } |
3708 | 3709 | ||
3709 | static int niu_rx_work(struct niu *np, struct rx_ring_info *rp, int budget) | 3710 | static int niu_rx_work(struct napi_struct *napi, struct niu *np, |
3711 | struct rx_ring_info *rp, int budget) | ||
3710 | { | 3712 | { |
3711 | int qlen, rcr_done = 0, work_done = 0; | 3713 | int qlen, rcr_done = 0, work_done = 0; |
3712 | struct rxdma_mailbox *mbox = rp->mbox; | 3714 | struct rxdma_mailbox *mbox = rp->mbox; |
@@ -3728,7 +3730,7 @@ static int niu_rx_work(struct niu *np, struct rx_ring_info *rp, int budget) | |||
3728 | rcr_done = work_done = 0; | 3730 | rcr_done = work_done = 0; |
3729 | qlen = min(qlen, budget); | 3731 | qlen = min(qlen, budget); |
3730 | while (work_done < qlen) { | 3732 | while (work_done < qlen) { |
3731 | rcr_done += niu_process_rx_pkt(np, rp); | 3733 | rcr_done += niu_process_rx_pkt(napi, np, rp); |
3732 | work_done++; | 3734 | work_done++; |
3733 | } | 3735 | } |
3734 | 3736 | ||
@@ -3776,7 +3778,7 @@ static int niu_poll_core(struct niu *np, struct niu_ldg *lp, int budget) | |||
3776 | if (rx_vec & (1 << rp->rx_channel)) { | 3778 | if (rx_vec & (1 << rp->rx_channel)) { |
3777 | int this_work_done; | 3779 | int this_work_done; |
3778 | 3780 | ||
3779 | this_work_done = niu_rx_work(np, rp, | 3781 | this_work_done = niu_rx_work(&lp->napi, np, rp, |
3780 | budget); | 3782 | budget); |
3781 | 3783 | ||
3782 | budget -= this_work_done; | 3784 | budget -= this_work_done; |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f7efcecc4108..1205c2a22657 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -4392,7 +4392,7 @@ static void tg3_recycle_rx(struct tg3 *tp, u32 opaque_key, | |||
4392 | #if TG3_VLAN_TAG_USED | 4392 | #if TG3_VLAN_TAG_USED |
4393 | static int tg3_vlan_rx(struct tg3 *tp, struct sk_buff *skb, u16 vlan_tag) | 4393 | static int tg3_vlan_rx(struct tg3 *tp, struct sk_buff *skb, u16 vlan_tag) |
4394 | { | 4394 | { |
4395 | return vlan_hwaccel_receive_skb(skb, tp->vlgrp, vlan_tag); | 4395 | return vlan_gro_receive(&tp->napi, tp->vlgrp, vlan_tag, skb); |
4396 | } | 4396 | } |
4397 | #endif | 4397 | #endif |
4398 | 4398 | ||
@@ -4539,7 +4539,7 @@ static int tg3_rx(struct tg3 *tp, int budget) | |||
4539 | desc->err_vlan & RXD_VLAN_MASK); | 4539 | desc->err_vlan & RXD_VLAN_MASK); |
4540 | } else | 4540 | } else |
4541 | #endif | 4541 | #endif |
4542 | netif_receive_skb(skb); | 4542 | napi_gro_receive(&tp->napi, skb); |
4543 | 4543 | ||
4544 | received++; | 4544 | received++; |
4545 | budget--; | 4545 | budget--; |
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 86a479f61c0c..933fcfbf35e1 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c | |||
@@ -3648,15 +3648,16 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
3648 | mdio = of_get_parent(phy); | 3648 | mdio = of_get_parent(phy); |
3649 | 3649 | ||
3650 | if (mdio == NULL) | 3650 | if (mdio == NULL) |
3651 | return -1; | 3651 | return -ENODEV; |
3652 | 3652 | ||
3653 | err = of_address_to_resource(mdio, 0, &res); | 3653 | err = of_address_to_resource(mdio, 0, &res); |
3654 | of_node_put(mdio); | ||
3655 | |||
3656 | if (err) | ||
3657 | return -1; | ||
3658 | 3654 | ||
3655 | if (err) { | ||
3656 | of_node_put(mdio); | ||
3657 | return err; | ||
3658 | } | ||
3659 | fsl_pq_mdio_bus_name(bus_name, mdio); | 3659 | fsl_pq_mdio_bus_name(bus_name, mdio); |
3660 | of_node_put(mdio); | ||
3660 | snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), | 3661 | snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), |
3661 | "%s:%02x", bus_name, *prop); | 3662 | "%s:%02x", bus_name, *prop); |
3662 | } | 3663 | } |
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 7e80aba8a148..f21a6171c691 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -2752,7 +2752,6 @@ static const struct net_device_ops airo_netdev_ops = { | |||
2752 | .ndo_set_mac_address = airo_set_mac_address, | 2752 | .ndo_set_mac_address = airo_set_mac_address, |
2753 | .ndo_do_ioctl = airo_ioctl, | 2753 | .ndo_do_ioctl = airo_ioctl, |
2754 | .ndo_change_mtu = airo_change_mtu, | 2754 | .ndo_change_mtu = airo_change_mtu, |
2755 | .ndo_set_mac_address = eth_mac_addr, | ||
2756 | .ndo_validate_addr = eth_validate_addr, | 2755 | .ndo_validate_addr = eth_validate_addr, |
2757 | }; | 2756 | }; |
2758 | 2757 | ||
@@ -2765,7 +2764,6 @@ static const struct net_device_ops mpi_netdev_ops = { | |||
2765 | .ndo_set_mac_address = airo_set_mac_address, | 2764 | .ndo_set_mac_address = airo_set_mac_address, |
2766 | .ndo_do_ioctl = airo_ioctl, | 2765 | .ndo_do_ioctl = airo_ioctl, |
2767 | .ndo_change_mtu = airo_change_mtu, | 2766 | .ndo_change_mtu = airo_change_mtu, |
2768 | .ndo_set_mac_address = eth_mac_addr, | ||
2769 | .ndo_validate_addr = eth_validate_addr, | 2767 | .ndo_validate_addr = eth_validate_addr, |
2770 | }; | 2768 | }; |
2771 | 2769 | ||
@@ -4494,7 +4492,6 @@ static int setup_proc_entry( struct net_device *dev, | |||
4494 | goto fail; | 4492 | goto fail; |
4495 | apriv->proc_entry->uid = proc_uid; | 4493 | apriv->proc_entry->uid = proc_uid; |
4496 | apriv->proc_entry->gid = proc_gid; | 4494 | apriv->proc_entry->gid = proc_gid; |
4497 | apriv->proc_entry->owner = THIS_MODULE; | ||
4498 | 4495 | ||
4499 | /* Setup the StatsDelta */ | 4496 | /* Setup the StatsDelta */ |
4500 | entry = proc_create_data("StatsDelta", | 4497 | entry = proc_create_data("StatsDelta", |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index b3449948a25a..4a92af1d7877 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -11593,7 +11593,6 @@ static const struct net_device_ops ipw_netdev_ops = { | |||
11593 | .ndo_set_mac_address = ipw_net_set_mac_address, | 11593 | .ndo_set_mac_address = ipw_net_set_mac_address, |
11594 | .ndo_start_xmit = ieee80211_xmit, | 11594 | .ndo_start_xmit = ieee80211_xmit, |
11595 | .ndo_change_mtu = ieee80211_change_mtu, | 11595 | .ndo_change_mtu = ieee80211_change_mtu, |
11596 | .ndo_set_mac_address = eth_mac_addr, | ||
11597 | .ndo_validate_addr = eth_validate_addr, | 11596 | .ndo_validate_addr = eth_validate_addr, |
11598 | }; | 11597 | }; |
11599 | 11598 | ||
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 166ed9584601..e26d7b3ceab5 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c | |||
@@ -803,7 +803,6 @@ static const struct net_device_ops islpci_netdev_ops = { | |||
803 | .ndo_tx_timeout = islpci_eth_tx_timeout, | 803 | .ndo_tx_timeout = islpci_eth_tx_timeout, |
804 | .ndo_set_mac_address = prism54_set_mac_address, | 804 | .ndo_set_mac_address = prism54_set_mac_address, |
805 | .ndo_change_mtu = eth_change_mtu, | 805 | .ndo_change_mtu = eth_change_mtu, |
806 | .ndo_set_mac_address = eth_mac_addr, | ||
807 | .ndo_validate_addr = eth_validate_addr, | 806 | .ndo_validate_addr = eth_validate_addr, |
808 | }; | 807 | }; |
809 | 808 | ||
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 9b244c96b221..5fabd9c0f07a 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c | |||
@@ -1725,7 +1725,6 @@ static const struct net_device_ops zd1201_netdev_ops = { | |||
1725 | .ndo_set_multicast_list = zd1201_set_multicast, | 1725 | .ndo_set_multicast_list = zd1201_set_multicast, |
1726 | .ndo_set_mac_address = zd1201_set_mac_address, | 1726 | .ndo_set_mac_address = zd1201_set_mac_address, |
1727 | .ndo_change_mtu = eth_change_mtu, | 1727 | .ndo_change_mtu = eth_change_mtu, |
1728 | .ndo_set_mac_address = eth_mac_addr, | ||
1729 | .ndo_validate_addr = eth_validate_addr, | 1728 | .ndo_validate_addr = eth_validate_addr, |
1730 | }; | 1729 | }; |
1731 | 1730 | ||
diff --git a/drivers/of/base.c b/drivers/of/base.c index cd17092b82bd..41c5dfd85358 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -446,6 +446,7 @@ struct of_modalias_table { | |||
446 | }; | 446 | }; |
447 | static struct of_modalias_table of_modalias_table[] = { | 447 | static struct of_modalias_table of_modalias_table[] = { |
448 | { "fsl,mcu-mpc8349emitx", "mcu-mpc8349emitx" }, | 448 | { "fsl,mcu-mpc8349emitx", "mcu-mpc8349emitx" }, |
449 | { "mmc-spi-slot", "mmc_spi" }, | ||
449 | }; | 450 | }; |
450 | 451 | ||
451 | /** | 452 | /** |
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index c3ea5fa7d05a..2c9aa49e43cd 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c | |||
@@ -574,7 +574,7 @@ int __init buffer_sync_init(void) | |||
574 | return 0; | 574 | return 0; |
575 | } | 575 | } |
576 | 576 | ||
577 | void __exit buffer_sync_cleanup(void) | 577 | void buffer_sync_cleanup(void) |
578 | { | 578 | { |
579 | free_cpumask_var(marked_cpus); | 579 | free_cpumask_var(marked_cpus); |
580 | } | 580 | } |
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 2a4501dd2515..fdc864f9cf23 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig | |||
@@ -59,3 +59,13 @@ config HT_IRQ | |||
59 | This allows native hypertransport devices to use interrupts. | 59 | This allows native hypertransport devices to use interrupts. |
60 | 60 | ||
61 | If unsure say Y. | 61 | If unsure say Y. |
62 | |||
63 | config PCI_IOV | ||
64 | bool "PCI IOV support" | ||
65 | depends on PCI | ||
66 | help | ||
67 | I/O Virtualization is a PCI feature supported by some devices | ||
68 | which allows them to create virtual devices which share their | ||
69 | physical resources. | ||
70 | |||
71 | If unsure, say N. | ||
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 3d07ce24f6a8..ba6af162fd39 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile | |||
@@ -29,6 +29,8 @@ obj-$(CONFIG_DMAR) += dmar.o iova.o intel-iommu.o | |||
29 | 29 | ||
30 | obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o | 30 | obj-$(CONFIG_INTR_REMAP) += dmar.o intr_remapping.o |
31 | 31 | ||
32 | obj-$(CONFIG_PCI_IOV) += iov.o | ||
33 | |||
32 | # | 34 | # |
33 | # Some architectures use the generic PCI setup functions | 35 | # Some architectures use the generic PCI setup functions |
34 | # | 36 | # |
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 52b54f053be0..68f91a252595 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c | |||
@@ -133,7 +133,7 @@ int pci_bus_add_child(struct pci_bus *bus) | |||
133 | * | 133 | * |
134 | * Call hotplug for each new devices. | 134 | * Call hotplug for each new devices. |
135 | */ | 135 | */ |
136 | void pci_bus_add_devices(struct pci_bus *bus) | 136 | void pci_bus_add_devices(const struct pci_bus *bus) |
137 | { | 137 | { |
138 | struct pci_dev *dev; | 138 | struct pci_dev *dev; |
139 | struct pci_bus *child; | 139 | struct pci_bus *child; |
@@ -184,8 +184,10 @@ void pci_enable_bridges(struct pci_bus *bus) | |||
184 | 184 | ||
185 | list_for_each_entry(dev, &bus->devices, bus_list) { | 185 | list_for_each_entry(dev, &bus->devices, bus_list) { |
186 | if (dev->subordinate) { | 186 | if (dev->subordinate) { |
187 | retval = pci_enable_device(dev); | 187 | if (atomic_read(&dev->enable_cnt) == 0) { |
188 | pci_set_master(dev); | 188 | retval = pci_enable_device(dev); |
189 | pci_set_master(dev); | ||
190 | } | ||
189 | pci_enable_bridges(dev->subordinate); | 191 | pci_enable_bridges(dev->subordinate); |
190 | } | 192 | } |
191 | } | 193 | } |
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 1c1141801060..fbc63d5e459f 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
@@ -30,9 +30,8 @@ | |||
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/pci.h> | 31 | #include <linux/pci.h> |
32 | #include <linux/pci_hotplug.h> | 32 | #include <linux/pci_hotplug.h> |
33 | #include <linux/acpi.h> | ||
33 | #include <linux/pci-acpi.h> | 34 | #include <linux/pci-acpi.h> |
34 | #include <acpi/acpi.h> | ||
35 | #include <acpi/acpi_bus.h> | ||
36 | 35 | ||
37 | #define MY_NAME "acpi_pcihp" | 36 | #define MY_NAME "acpi_pcihp" |
38 | 37 | ||
@@ -333,19 +332,14 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, | |||
333 | { | 332 | { |
334 | acpi_status status = AE_NOT_FOUND; | 333 | acpi_status status = AE_NOT_FOUND; |
335 | acpi_handle handle, phandle; | 334 | acpi_handle handle, phandle; |
336 | struct pci_bus *pbus = bus; | 335 | struct pci_bus *pbus; |
337 | struct pci_dev *pdev; | 336 | |
338 | 337 | handle = NULL; | |
339 | do { | 338 | for (pbus = bus; pbus; pbus = pbus->parent) { |
340 | pdev = pbus->self; | 339 | handle = acpi_pci_get_bridge_handle(pbus); |
341 | if (!pdev) { | 340 | if (handle) |
342 | handle = acpi_get_pci_rootbridge_handle( | ||
343 | pci_domain_nr(pbus), pbus->number); | ||
344 | break; | 341 | break; |
345 | } | 342 | } |
346 | handle = DEVICE_ACPI_HANDLE(&(pdev->dev)); | ||
347 | pbus = pbus->parent; | ||
348 | } while (!handle); | ||
349 | 343 | ||
350 | /* | 344 | /* |
351 | * _HPP settings apply to all child buses, until another _HPP is | 345 | * _HPP settings apply to all child buses, until another _HPP is |
@@ -378,12 +372,10 @@ EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); | |||
378 | * | 372 | * |
379 | * Attempt to take hotplug control from firmware. | 373 | * Attempt to take hotplug control from firmware. |
380 | */ | 374 | */ |
381 | int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) | 375 | int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags) |
382 | { | 376 | { |
383 | acpi_status status; | 377 | acpi_status status; |
384 | acpi_handle chandle, handle; | 378 | acpi_handle chandle, handle; |
385 | struct pci_dev *pdev = dev; | ||
386 | struct pci_bus *parent; | ||
387 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; | 379 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; |
388 | 380 | ||
389 | flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | | 381 | flags &= (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | |
@@ -408,33 +400,25 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) | |||
408 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | 400 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); |
409 | dbg("Trying to get hotplug control for %s\n", | 401 | dbg("Trying to get hotplug control for %s\n", |
410 | (char *)string.pointer); | 402 | (char *)string.pointer); |
411 | status = pci_osc_control_set(handle, flags); | 403 | status = acpi_pci_osc_control_set(handle, flags); |
412 | if (ACPI_SUCCESS(status)) | 404 | if (ACPI_SUCCESS(status)) |
413 | goto got_one; | 405 | goto got_one; |
414 | kfree(string.pointer); | 406 | kfree(string.pointer); |
415 | string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL }; | 407 | string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL }; |
416 | } | 408 | } |
417 | 409 | ||
418 | pdev = dev; | 410 | handle = DEVICE_ACPI_HANDLE(&pdev->dev); |
419 | handle = DEVICE_ACPI_HANDLE(&dev->dev); | 411 | if (!handle) { |
420 | while (!handle) { | ||
421 | /* | 412 | /* |
422 | * This hotplug controller was not listed in the ACPI name | 413 | * This hotplug controller was not listed in the ACPI name |
423 | * space at all. Try to get acpi handle of parent pci bus. | 414 | * space at all. Try to get acpi handle of parent pci bus. |
424 | */ | 415 | */ |
425 | if (!pdev || !pdev->bus->parent) | 416 | struct pci_bus *pbus; |
426 | break; | 417 | for (pbus = pdev->bus; pbus; pbus = pbus->parent) { |
427 | parent = pdev->bus->parent; | 418 | handle = acpi_pci_get_bridge_handle(pbus); |
428 | dbg("Could not find %s in acpi namespace, trying parent\n", | 419 | if (handle) |
429 | pci_name(pdev)); | 420 | break; |
430 | if (!parent->self) | 421 | } |
431 | /* Parent must be a host bridge */ | ||
432 | handle = acpi_get_pci_rootbridge_handle( | ||
433 | pci_domain_nr(parent), | ||
434 | parent->number); | ||
435 | else | ||
436 | handle = DEVICE_ACPI_HANDLE(&(parent->self->dev)); | ||
437 | pdev = parent->self; | ||
438 | } | 422 | } |
439 | 423 | ||
440 | while (handle) { | 424 | while (handle) { |
@@ -453,13 +437,13 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) | |||
453 | } | 437 | } |
454 | 438 | ||
455 | dbg("Cannot get control of hotplug hardware for pci %s\n", | 439 | dbg("Cannot get control of hotplug hardware for pci %s\n", |
456 | pci_name(dev)); | 440 | pci_name(pdev)); |
457 | 441 | ||
458 | kfree(string.pointer); | 442 | kfree(string.pointer); |
459 | return -ENODEV; | 443 | return -ENODEV; |
460 | got_one: | 444 | got_one: |
461 | dbg("Gained control for hotplug HW for pci %s (%s)\n", pci_name(dev), | 445 | dbg("Gained control for hotplug HW for pci %s (%s)\n", |
462 | (char *)string.pointer); | 446 | pci_name(pdev), (char *)string.pointer); |
463 | kfree(string.pointer); | 447 | kfree(string.pointer); |
464 | return 0; | 448 | return 0; |
465 | } | 449 | } |
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index d8649e127298..6151389fd903 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c | |||
@@ -1,395 +1,163 @@ | |||
1 | /* | 1 | /* Works like the fakephp driver used to, except a little better. |
2 | * Fake PCI Hot Plug Controller Driver | ||
3 | * | 2 | * |
4 | * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com> | 3 | * - It's possible to remove devices with subordinate busses. |
5 | * Copyright (C) 2003 IBM Corp. | 4 | * - New PCI devices that appear via any method, not just a fakephp triggered |
6 | * Copyright (C) 2003 Rolf Eike Beer <eike-kernel@sf-tec.de> | 5 | * rescan, will be noticed. |
6 | * - Devices that are removed via any method, not just a fakephp triggered | ||
7 | * removal, will also be noticed. | ||
7 | * | 8 | * |
8 | * Based on ideas and code from: | 9 | * Uses nothing from the pci-hotplug subsystem. |
9 | * Vladimir Kondratiev <vladimir.kondratiev@intel.com> | ||
10 | * Rolf Eike Beer <eike-kernel@sf-tec.de> | ||
11 | * | 10 | * |
12 | * All rights reserved. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License as published by | ||
16 | * the Free Software Foundation, version 2 of the License. | ||
17 | * | ||
18 | * Send feedback to <greg@kroah.com> | ||
19 | */ | 11 | */ |
20 | 12 | ||
21 | /* | ||
22 | * | ||
23 | * This driver will "emulate" removing PCI devices from the system. If | ||
24 | * the "power" file is written to with "0" then the specified PCI device | ||
25 | * will be completely removed from the kernel. | ||
26 | * | ||
27 | * WARNING, this does NOT turn off the power to the PCI device. This is | ||
28 | * a "logical" removal, not a physical or electrical removal. | ||
29 | * | ||
30 | * Use this module at your own risk, you have been warned! | ||
31 | * | ||
32 | * Enabling PCI devices is left as an exercise for the reader... | ||
33 | * | ||
34 | */ | ||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/module.h> | 13 | #include <linux/module.h> |
37 | #include <linux/pci.h> | 14 | #include <linux/kernel.h> |
38 | #include <linux/pci_hotplug.h> | 15 | #include <linux/types.h> |
16 | #include <linux/list.h> | ||
17 | #include <linux/kobject.h> | ||
18 | #include <linux/sysfs.h> | ||
39 | #include <linux/init.h> | 19 | #include <linux/init.h> |
40 | #include <linux/string.h> | 20 | #include <linux/pci.h> |
41 | #include <linux/slab.h> | 21 | #include <linux/device.h> |
42 | #include <linux/workqueue.h> | ||
43 | #include "../pci.h" | 22 | #include "../pci.h" |
44 | 23 | ||
45 | #if !defined(MODULE) | 24 | struct legacy_slot { |
46 | #define MY_NAME "fakephp" | 25 | struct kobject kobj; |
47 | #else | 26 | struct pci_dev *dev; |
48 | #define MY_NAME THIS_MODULE->name | 27 | struct list_head list; |
49 | #endif | ||
50 | |||
51 | #define dbg(format, arg...) \ | ||
52 | do { \ | ||
53 | if (debug) \ | ||
54 | printk(KERN_DEBUG "%s: " format, \ | ||
55 | MY_NAME , ## arg); \ | ||
56 | } while (0) | ||
57 | #define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg) | ||
58 | #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) | ||
59 | |||
60 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>" | ||
61 | #define DRIVER_DESC "Fake PCI Hot Plug Controller Driver" | ||
62 | |||
63 | struct dummy_slot { | ||
64 | struct list_head node; | ||
65 | struct hotplug_slot *slot; | ||
66 | struct pci_dev *dev; | ||
67 | struct work_struct remove_work; | ||
68 | unsigned long removed; | ||
69 | }; | 28 | }; |
70 | 29 | ||
71 | static int debug; | 30 | static LIST_HEAD(legacy_list); |
72 | static int dup_slots; | ||
73 | static LIST_HEAD(slot_list); | ||
74 | static struct workqueue_struct *dummyphp_wq; | ||
75 | |||
76 | static void pci_rescan_worker(struct work_struct *work); | ||
77 | static DECLARE_WORK(pci_rescan_work, pci_rescan_worker); | ||
78 | |||
79 | static int enable_slot (struct hotplug_slot *slot); | ||
80 | static int disable_slot (struct hotplug_slot *slot); | ||
81 | 31 | ||
82 | static struct hotplug_slot_ops dummy_hotplug_slot_ops = { | 32 | static ssize_t legacy_show(struct kobject *kobj, struct attribute *attr, |
83 | .owner = THIS_MODULE, | 33 | char *buf) |
84 | .enable_slot = enable_slot, | ||
85 | .disable_slot = disable_slot, | ||
86 | }; | ||
87 | |||
88 | static void dummy_release(struct hotplug_slot *slot) | ||
89 | { | 34 | { |
90 | struct dummy_slot *dslot = slot->private; | 35 | struct legacy_slot *slot = container_of(kobj, typeof(*slot), kobj); |
91 | 36 | strcpy(buf, "1\n"); | |
92 | list_del(&dslot->node); | 37 | return 2; |
93 | kfree(dslot->slot->info); | ||
94 | kfree(dslot->slot); | ||
95 | pci_dev_put(dslot->dev); | ||
96 | kfree(dslot); | ||
97 | } | 38 | } |
98 | 39 | ||
99 | #define SLOT_NAME_SIZE 8 | 40 | static void remove_callback(void *data) |
100 | |||
101 | static int add_slot(struct pci_dev *dev) | ||
102 | { | 41 | { |
103 | struct dummy_slot *dslot; | 42 | pci_remove_bus_device((struct pci_dev *)data); |
104 | struct hotplug_slot *slot; | ||
105 | char name[SLOT_NAME_SIZE]; | ||
106 | int retval = -ENOMEM; | ||
107 | static int count = 1; | ||
108 | |||
109 | slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); | ||
110 | if (!slot) | ||
111 | goto error; | ||
112 | |||
113 | slot->info = kzalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); | ||
114 | if (!slot->info) | ||
115 | goto error_slot; | ||
116 | |||
117 | slot->info->power_status = 1; | ||
118 | slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; | ||
119 | slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; | ||
120 | |||
121 | dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL); | ||
122 | if (!dslot) | ||
123 | goto error_info; | ||
124 | |||
125 | if (dup_slots) | ||
126 | snprintf(name, SLOT_NAME_SIZE, "fake"); | ||
127 | else | ||
128 | snprintf(name, SLOT_NAME_SIZE, "fake%d", count++); | ||
129 | dbg("slot->name = %s\n", name); | ||
130 | slot->ops = &dummy_hotplug_slot_ops; | ||
131 | slot->release = &dummy_release; | ||
132 | slot->private = dslot; | ||
133 | |||
134 | retval = pci_hp_register(slot, dev->bus, PCI_SLOT(dev->devfn), name); | ||
135 | if (retval) { | ||
136 | err("pci_hp_register failed with error %d\n", retval); | ||
137 | goto error_dslot; | ||
138 | } | ||
139 | |||
140 | dbg("slot->name = %s\n", hotplug_slot_name(slot)); | ||
141 | dslot->slot = slot; | ||
142 | dslot->dev = pci_dev_get(dev); | ||
143 | list_add (&dslot->node, &slot_list); | ||
144 | return retval; | ||
145 | |||
146 | error_dslot: | ||
147 | kfree(dslot); | ||
148 | error_info: | ||
149 | kfree(slot->info); | ||
150 | error_slot: | ||
151 | kfree(slot); | ||
152 | error: | ||
153 | return retval; | ||
154 | } | 43 | } |
155 | 44 | ||
156 | static int __init pci_scan_buses(void) | 45 | static ssize_t legacy_store(struct kobject *kobj, struct attribute *attr, |
46 | const char *buf, size_t len) | ||
157 | { | 47 | { |
158 | struct pci_dev *dev = NULL; | 48 | struct legacy_slot *slot = container_of(kobj, typeof(*slot), kobj); |
159 | int lastslot = 0; | 49 | unsigned long val; |
160 | 50 | ||
161 | while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { | 51 | if (strict_strtoul(buf, 0, &val) < 0) |
162 | if (PCI_FUNC(dev->devfn) > 0 && | 52 | return -EINVAL; |
163 | lastslot == PCI_SLOT(dev->devfn)) | ||
164 | continue; | ||
165 | lastslot = PCI_SLOT(dev->devfn); | ||
166 | add_slot(dev); | ||
167 | } | ||
168 | 53 | ||
169 | return 0; | 54 | if (val) |
55 | pci_rescan_bus(slot->dev->bus); | ||
56 | else | ||
57 | sysfs_schedule_callback(&slot->dev->dev.kobj, remove_callback, | ||
58 | slot->dev, THIS_MODULE); | ||
59 | return len; | ||
170 | } | 60 | } |
171 | 61 | ||
172 | static void remove_slot(struct dummy_slot *dslot) | 62 | static struct attribute *legacy_attrs[] = { |
173 | { | 63 | &(struct attribute){ .name = "power", .mode = 0644 }, |
174 | int retval; | 64 | NULL, |
175 | 65 | }; | |
176 | dbg("removing slot %s\n", hotplug_slot_name(dslot->slot)); | ||
177 | retval = pci_hp_deregister(dslot->slot); | ||
178 | if (retval) | ||
179 | err("Problem unregistering a slot %s\n", | ||
180 | hotplug_slot_name(dslot->slot)); | ||
181 | } | ||
182 | 66 | ||
183 | /* called from the single-threaded workqueue handler to remove a slot */ | 67 | static void legacy_release(struct kobject *kobj) |
184 | static void remove_slot_worker(struct work_struct *work) | ||
185 | { | 68 | { |
186 | struct dummy_slot *dslot = | 69 | struct legacy_slot *slot = container_of(kobj, typeof(*slot), kobj); |
187 | container_of(work, struct dummy_slot, remove_work); | ||
188 | remove_slot(dslot); | ||
189 | } | ||
190 | 70 | ||
191 | /** | 71 | pci_dev_put(slot->dev); |
192 | * pci_rescan_slot - Rescan slot | 72 | kfree(slot); |
193 | * @temp: Device template. Should be set: bus and devfn. | ||
194 | * | ||
195 | * Tries hard not to re-enable already existing devices; | ||
196 | * also handles scanning of subfunctions. | ||
197 | */ | ||
198 | static int pci_rescan_slot(struct pci_dev *temp) | ||
199 | { | ||
200 | struct pci_bus *bus = temp->bus; | ||
201 | struct pci_dev *dev; | ||
202 | int func; | ||
203 | u8 hdr_type; | ||
204 | int count = 0; | ||
205 | |||
206 | if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { | ||
207 | temp->hdr_type = hdr_type & 0x7f; | ||
208 | if ((dev = pci_get_slot(bus, temp->devfn)) != NULL) | ||
209 | pci_dev_put(dev); | ||
210 | else { | ||
211 | dev = pci_scan_single_device(bus, temp->devfn); | ||
212 | if (dev) { | ||
213 | dbg("New device on %s function %x:%x\n", | ||
214 | bus->name, temp->devfn >> 3, | ||
215 | temp->devfn & 7); | ||
216 | count++; | ||
217 | } | ||
218 | } | ||
219 | /* multifunction device? */ | ||
220 | if (!(hdr_type & 0x80)) | ||
221 | return count; | ||
222 | |||
223 | /* continue scanning for other functions */ | ||
224 | for (func = 1, temp->devfn++; func < 8; func++, temp->devfn++) { | ||
225 | if (pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) | ||
226 | continue; | ||
227 | temp->hdr_type = hdr_type & 0x7f; | ||
228 | |||
229 | if ((dev = pci_get_slot(bus, temp->devfn)) != NULL) | ||
230 | pci_dev_put(dev); | ||
231 | else { | ||
232 | dev = pci_scan_single_device(bus, temp->devfn); | ||
233 | if (dev) { | ||
234 | dbg("New device on %s function %x:%x\n", | ||
235 | bus->name, temp->devfn >> 3, | ||
236 | temp->devfn & 7); | ||
237 | count++; | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | |||
243 | return count; | ||
244 | } | 73 | } |
245 | 74 | ||
75 | static struct kobj_type legacy_ktype = { | ||
76 | .sysfs_ops = &(struct sysfs_ops){ | ||
77 | .store = legacy_store, .show = legacy_show | ||
78 | }, | ||
79 | .release = &legacy_release, | ||
80 | .default_attrs = legacy_attrs, | ||
81 | }; | ||
246 | 82 | ||
247 | /** | 83 | static int legacy_add_slot(struct pci_dev *pdev) |
248 | * pci_rescan_bus - Rescan PCI bus | ||
249 | * @bus: the PCI bus to rescan | ||
250 | * | ||
251 | * Call pci_rescan_slot for each possible function of the bus. | ||
252 | */ | ||
253 | static void pci_rescan_bus(const struct pci_bus *bus) | ||
254 | { | 84 | { |
255 | unsigned int devfn; | 85 | struct legacy_slot *slot = kzalloc(sizeof(*slot), GFP_KERNEL); |
256 | struct pci_dev *dev; | ||
257 | int retval; | ||
258 | int found = 0; | ||
259 | dev = alloc_pci_dev(); | ||
260 | if (!dev) | ||
261 | return; | ||
262 | 86 | ||
263 | dev->bus = (struct pci_bus*)bus; | 87 | if (!slot) |
264 | dev->sysdata = bus->sysdata; | 88 | return -ENOMEM; |
265 | for (devfn = 0; devfn < 0x100; devfn += 8) { | ||
266 | dev->devfn = devfn; | ||
267 | found += pci_rescan_slot(dev); | ||
268 | } | ||
269 | |||
270 | if (found) { | ||
271 | pci_bus_assign_resources(bus); | ||
272 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
273 | /* Skip already-added devices */ | ||
274 | if (dev->is_added) | ||
275 | continue; | ||
276 | retval = pci_bus_add_device(dev); | ||
277 | if (retval) | ||
278 | dev_err(&dev->dev, | ||
279 | "Error adding device, continuing\n"); | ||
280 | else | ||
281 | add_slot(dev); | ||
282 | } | ||
283 | pci_bus_add_devices(bus); | ||
284 | } | ||
285 | kfree(dev); | ||
286 | } | ||
287 | 89 | ||
288 | /* recursively scan all buses */ | 90 | if (kobject_init_and_add(&slot->kobj, &legacy_ktype, |
289 | static void pci_rescan_buses(const struct list_head *list) | 91 | &pci_slots_kset->kobj, "%s", |
290 | { | 92 | dev_name(&pdev->dev))) { |
291 | const struct list_head *l; | 93 | dev_warn(&pdev->dev, "Failed to created legacy fake slot\n"); |
292 | list_for_each(l,list) { | 94 | return -EINVAL; |
293 | const struct pci_bus *b = pci_bus_b(l); | ||
294 | pci_rescan_bus(b); | ||
295 | pci_rescan_buses(&b->children); | ||
296 | } | 95 | } |
297 | } | 96 | slot->dev = pci_dev_get(pdev); |
298 | 97 | ||
299 | /* initiate rescan of all pci buses */ | 98 | list_add(&slot->list, &legacy_list); |
300 | static inline void pci_rescan(void) { | ||
301 | pci_rescan_buses(&pci_root_buses); | ||
302 | } | ||
303 | |||
304 | /* called from the single-threaded workqueue handler to rescan all pci buses */ | ||
305 | static void pci_rescan_worker(struct work_struct *work) | ||
306 | { | ||
307 | pci_rescan(); | ||
308 | } | ||
309 | 99 | ||
310 | static int enable_slot(struct hotplug_slot *hotplug_slot) | ||
311 | { | ||
312 | /* mis-use enable_slot for rescanning of the pci bus */ | ||
313 | cancel_work_sync(&pci_rescan_work); | ||
314 | queue_work(dummyphp_wq, &pci_rescan_work); | ||
315 | return 0; | 100 | return 0; |
316 | } | 101 | } |
317 | 102 | ||
318 | static int disable_slot(struct hotplug_slot *slot) | 103 | static int legacy_notify(struct notifier_block *nb, |
104 | unsigned long action, void *data) | ||
319 | { | 105 | { |
320 | struct dummy_slot *dslot; | 106 | struct pci_dev *pdev = to_pci_dev(data); |
321 | struct pci_dev *dev; | ||
322 | int func; | ||
323 | |||
324 | if (!slot) | ||
325 | return -ENODEV; | ||
326 | dslot = slot->private; | ||
327 | |||
328 | dbg("%s - physical_slot = %s\n", __func__, hotplug_slot_name(slot)); | ||
329 | 107 | ||
330 | for (func = 7; func >= 0; func--) { | 108 | if (action == BUS_NOTIFY_ADD_DEVICE) { |
331 | dev = pci_get_slot(dslot->dev->bus, dslot->dev->devfn + func); | 109 | legacy_add_slot(pdev); |
332 | if (!dev) | 110 | } else if (action == BUS_NOTIFY_DEL_DEVICE) { |
333 | continue; | 111 | struct legacy_slot *slot; |
334 | 112 | ||
335 | if (test_and_set_bit(0, &dslot->removed)) { | 113 | list_for_each_entry(slot, &legacy_list, list) |
336 | dbg("Slot already scheduled for removal\n"); | 114 | if (slot->dev == pdev) |
337 | pci_dev_put(dev); | 115 | goto found; |
338 | return -ENODEV; | ||
339 | } | ||
340 | 116 | ||
341 | /* remove the device from the pci core */ | 117 | dev_warn(&pdev->dev, "Missing legacy fake slot?"); |
342 | pci_remove_bus_device(dev); | 118 | return -ENODEV; |
343 | 119 | found: | |
344 | /* queue work item to blow away this sysfs entry and other | 120 | kobject_del(&slot->kobj); |
345 | * parts. | 121 | list_del(&slot->list); |
346 | */ | 122 | kobject_put(&slot->kobj); |
347 | INIT_WORK(&dslot->remove_work, remove_slot_worker); | ||
348 | queue_work(dummyphp_wq, &dslot->remove_work); | ||
349 | |||
350 | pci_dev_put(dev); | ||
351 | } | 123 | } |
124 | |||
352 | return 0; | 125 | return 0; |
353 | } | 126 | } |
354 | 127 | ||
355 | static void cleanup_slots (void) | 128 | static struct notifier_block legacy_notifier = { |
356 | { | 129 | .notifier_call = legacy_notify |
357 | struct list_head *tmp; | 130 | }; |
358 | struct list_head *next; | ||
359 | struct dummy_slot *dslot; | ||
360 | |||
361 | destroy_workqueue(dummyphp_wq); | ||
362 | list_for_each_safe (tmp, next, &slot_list) { | ||
363 | dslot = list_entry (tmp, struct dummy_slot, node); | ||
364 | remove_slot(dslot); | ||
365 | } | ||
366 | |||
367 | } | ||
368 | 131 | ||
369 | static int __init dummyphp_init(void) | 132 | static int __init init_legacy(void) |
370 | { | 133 | { |
371 | info(DRIVER_DESC "\n"); | 134 | struct pci_dev *pdev = NULL; |
372 | 135 | ||
373 | dummyphp_wq = create_singlethread_workqueue(MY_NAME); | 136 | /* Add existing devices */ |
374 | if (!dummyphp_wq) | 137 | while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) |
375 | return -ENOMEM; | 138 | legacy_add_slot(pdev); |
376 | 139 | ||
377 | return pci_scan_buses(); | 140 | /* Be alerted of any new ones */ |
141 | bus_register_notifier(&pci_bus_type, &legacy_notifier); | ||
142 | return 0; | ||
378 | } | 143 | } |
144 | module_init(init_legacy); | ||
379 | 145 | ||
380 | 146 | static void __exit remove_legacy(void) | |
381 | static void __exit dummyphp_exit(void) | ||
382 | { | 147 | { |
383 | cleanup_slots(); | 148 | struct legacy_slot *slot, *tmp; |
149 | |||
150 | bus_unregister_notifier(&pci_bus_type, &legacy_notifier); | ||
151 | |||
152 | list_for_each_entry_safe(slot, tmp, &legacy_list, list) { | ||
153 | list_del(&slot->list); | ||
154 | kobject_del(&slot->kobj); | ||
155 | kobject_put(&slot->kobj); | ||
156 | } | ||
384 | } | 157 | } |
158 | module_exit(remove_legacy); | ||
385 | 159 | ||
386 | module_init(dummyphp_init); | ||
387 | module_exit(dummyphp_exit); | ||
388 | 160 | ||
389 | MODULE_AUTHOR(DRIVER_AUTHOR); | 161 | MODULE_AUTHOR("Trent Piepho <xyzzy@speakeasy.org>"); |
390 | MODULE_DESCRIPTION(DRIVER_DESC); | 162 | MODULE_DESCRIPTION("Legacy version of the fakephp interface"); |
391 | MODULE_LICENSE("GPL"); | 163 | MODULE_LICENSE("GPL"); |
392 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
393 | MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); | ||
394 | module_param(dup_slots, bool, S_IRUGO | S_IWUSR); | ||
395 | MODULE_PARM_DESC(dup_slots, "Force duplicate slot names for debugging"); | ||
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 39ae37589fda..0a368547e633 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -46,10 +46,10 @@ extern int pciehp_force; | |||
46 | extern struct workqueue_struct *pciehp_wq; | 46 | extern struct workqueue_struct *pciehp_wq; |
47 | 47 | ||
48 | #define dbg(format, arg...) \ | 48 | #define dbg(format, arg...) \ |
49 | do { \ | 49 | do { \ |
50 | if (pciehp_debug) \ | 50 | if (pciehp_debug) \ |
51 | printk("%s: " format, MY_NAME , ## arg); \ | 51 | printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); \ |
52 | } while (0) | 52 | } while (0) |
53 | #define err(format, arg...) \ | 53 | #define err(format, arg...) \ |
54 | printk(KERN_ERR "%s: " format, MY_NAME , ## arg) | 54 | printk(KERN_ERR "%s: " format, MY_NAME , ## arg) |
55 | #define info(format, arg...) \ | 55 | #define info(format, arg...) \ |
@@ -60,7 +60,7 @@ extern struct workqueue_struct *pciehp_wq; | |||
60 | #define ctrl_dbg(ctrl, format, arg...) \ | 60 | #define ctrl_dbg(ctrl, format, arg...) \ |
61 | do { \ | 61 | do { \ |
62 | if (pciehp_debug) \ | 62 | if (pciehp_debug) \ |
63 | dev_printk(, &ctrl->pcie->device, \ | 63 | dev_printk(KERN_DEBUG, &ctrl->pcie->device, \ |
64 | format, ## arg); \ | 64 | format, ## arg); \ |
65 | } while (0) | 65 | } while (0) |
66 | #define ctrl_err(ctrl, format, arg...) \ | 66 | #define ctrl_err(ctrl, format, arg...) \ |
@@ -108,10 +108,11 @@ struct controller { | |||
108 | u32 slot_cap; | 108 | u32 slot_cap; |
109 | u8 cap_base; | 109 | u8 cap_base; |
110 | struct timer_list poll_timer; | 110 | struct timer_list poll_timer; |
111 | int cmd_busy; | 111 | unsigned int cmd_busy:1; |
112 | unsigned int no_cmd_complete:1; | 112 | unsigned int no_cmd_complete:1; |
113 | unsigned int link_active_reporting:1; | 113 | unsigned int link_active_reporting:1; |
114 | unsigned int notification_enabled:1; | 114 | unsigned int notification_enabled:1; |
115 | unsigned int power_fault_detected; | ||
115 | }; | 116 | }; |
116 | 117 | ||
117 | #define INT_BUTTON_IGNORE 0 | 118 | #define INT_BUTTON_IGNORE 0 |
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c index 438d795f9fe3..96048010e7d9 100644 --- a/drivers/pci/hotplug/pciehp_acpi.c +++ b/drivers/pci/hotplug/pciehp_acpi.c | |||
@@ -67,37 +67,27 @@ static int __init parse_detect_mode(void) | |||
67 | return PCIEHP_DETECT_DEFAULT; | 67 | return PCIEHP_DETECT_DEFAULT; |
68 | } | 68 | } |
69 | 69 | ||
70 | static struct pcie_port_service_id __initdata port_pci_ids[] = { | ||
71 | { | ||
72 | .vendor = PCI_ANY_ID, | ||
73 | .device = PCI_ANY_ID, | ||
74 | .port_type = PCIE_ANY_PORT, | ||
75 | .service_type = PCIE_PORT_SERVICE_HP, | ||
76 | .driver_data = 0, | ||
77 | }, { /* end: all zeroes */ } | ||
78 | }; | ||
79 | |||
80 | static int __initdata dup_slot_id; | 70 | static int __initdata dup_slot_id; |
81 | static int __initdata acpi_slot_detected; | 71 | static int __initdata acpi_slot_detected; |
82 | static struct list_head __initdata dummy_slots = LIST_HEAD_INIT(dummy_slots); | 72 | static struct list_head __initdata dummy_slots = LIST_HEAD_INIT(dummy_slots); |
83 | 73 | ||
84 | /* Dummy driver for dumplicate name detection */ | 74 | /* Dummy driver for dumplicate name detection */ |
85 | static int __init dummy_probe(struct pcie_device *dev, | 75 | static int __init dummy_probe(struct pcie_device *dev) |
86 | const struct pcie_port_service_id *id) | ||
87 | { | 76 | { |
88 | int pos; | 77 | int pos; |
89 | u32 slot_cap; | 78 | u32 slot_cap; |
90 | struct slot *slot, *tmp; | 79 | struct slot *slot, *tmp; |
91 | struct pci_dev *pdev = dev->port; | 80 | struct pci_dev *pdev = dev->port; |
92 | struct pci_bus *pbus = pdev->subordinate; | 81 | struct pci_bus *pbus = pdev->subordinate; |
93 | if (!(slot = kzalloc(sizeof(*slot), GFP_KERNEL))) | ||
94 | return -ENOMEM; | ||
95 | /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */ | 82 | /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */ |
96 | if (pciehp_get_hp_hw_control_from_firmware(pdev)) | 83 | if (pciehp_get_hp_hw_control_from_firmware(pdev)) |
97 | return -ENODEV; | 84 | return -ENODEV; |
98 | if (!(pos = pci_find_capability(pdev, PCI_CAP_ID_EXP))) | 85 | if (!(pos = pci_find_capability(pdev, PCI_CAP_ID_EXP))) |
99 | return -ENODEV; | 86 | return -ENODEV; |
100 | pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap); | 87 | pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap); |
88 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); | ||
89 | if (!slot) | ||
90 | return -ENOMEM; | ||
101 | slot->number = slot_cap >> 19; | 91 | slot->number = slot_cap >> 19; |
102 | list_for_each_entry(tmp, &dummy_slots, slot_list) { | 92 | list_for_each_entry(tmp, &dummy_slots, slot_list) { |
103 | if (tmp->number == slot->number) | 93 | if (tmp->number == slot->number) |
@@ -111,7 +101,8 @@ static int __init dummy_probe(struct pcie_device *dev, | |||
111 | 101 | ||
112 | static struct pcie_port_service_driver __initdata dummy_driver = { | 102 | static struct pcie_port_service_driver __initdata dummy_driver = { |
113 | .name = "pciehp_dummy", | 103 | .name = "pciehp_dummy", |
114 | .id_table = port_pci_ids, | 104 | .port_type = PCIE_ANY_PORT, |
105 | .service = PCIE_PORT_SERVICE_HP, | ||
115 | .probe = dummy_probe, | 106 | .probe = dummy_probe, |
116 | }; | 107 | }; |
117 | 108 | ||
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 681e3912b821..fb254b2454de 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -401,7 +401,7 @@ static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe | |||
401 | return 0; | 401 | return 0; |
402 | } | 402 | } |
403 | 403 | ||
404 | static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_id *id) | 404 | static int pciehp_probe(struct pcie_device *dev) |
405 | { | 405 | { |
406 | int rc; | 406 | int rc; |
407 | struct controller *ctrl; | 407 | struct controller *ctrl; |
@@ -475,7 +475,7 @@ static void pciehp_remove (struct pcie_device *dev) | |||
475 | } | 475 | } |
476 | 476 | ||
477 | #ifdef CONFIG_PM | 477 | #ifdef CONFIG_PM |
478 | static int pciehp_suspend (struct pcie_device *dev, pm_message_t state) | 478 | static int pciehp_suspend (struct pcie_device *dev) |
479 | { | 479 | { |
480 | dev_info(&dev->device, "%s ENTRY\n", __func__); | 480 | dev_info(&dev->device, "%s ENTRY\n", __func__); |
481 | return 0; | 481 | return 0; |
@@ -503,20 +503,12 @@ static int pciehp_resume (struct pcie_device *dev) | |||
503 | } | 503 | } |
504 | return 0; | 504 | return 0; |
505 | } | 505 | } |
506 | #endif | 506 | #endif /* PM */ |
507 | |||
508 | static struct pcie_port_service_id port_pci_ids[] = { { | ||
509 | .vendor = PCI_ANY_ID, | ||
510 | .device = PCI_ANY_ID, | ||
511 | .port_type = PCIE_ANY_PORT, | ||
512 | .service_type = PCIE_PORT_SERVICE_HP, | ||
513 | .driver_data = 0, | ||
514 | }, { /* end: all zeroes */ } | ||
515 | }; | ||
516 | 507 | ||
517 | static struct pcie_port_service_driver hpdriver_portdrv = { | 508 | static struct pcie_port_service_driver hpdriver_portdrv = { |
518 | .name = PCIE_MODULE_NAME, | 509 | .name = PCIE_MODULE_NAME, |
519 | .id_table = &port_pci_ids[0], | 510 | .port_type = PCIE_ANY_PORT, |
511 | .service = PCIE_PORT_SERVICE_HP, | ||
520 | 512 | ||
521 | .probe = pciehp_probe, | 513 | .probe = pciehp_probe, |
522 | .remove = pciehp_remove, | 514 | .remove = pciehp_remove, |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 7a16c6897bb9..07bd32151146 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -548,23 +548,21 @@ static int hpc_power_on_slot(struct slot * slot) | |||
548 | 548 | ||
549 | slot_cmd = POWER_ON; | 549 | slot_cmd = POWER_ON; |
550 | cmd_mask = PCI_EXP_SLTCTL_PCC; | 550 | cmd_mask = PCI_EXP_SLTCTL_PCC; |
551 | /* Enable detection that we turned off at slot power-off time */ | ||
552 | if (!pciehp_poll_mode) { | 551 | if (!pciehp_poll_mode) { |
553 | slot_cmd |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | | 552 | /* Enable power fault detection turned off at power off time */ |
554 | PCI_EXP_SLTCTL_PDCE); | 553 | slot_cmd |= PCI_EXP_SLTCTL_PFDE; |
555 | cmd_mask |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | | 554 | cmd_mask |= PCI_EXP_SLTCTL_PFDE; |
556 | PCI_EXP_SLTCTL_PDCE); | ||
557 | } | 555 | } |
558 | 556 | ||
559 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 557 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
560 | |||
561 | if (retval) { | 558 | if (retval) { |
562 | ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); | 559 | ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); |
563 | return -1; | 560 | return retval; |
564 | } | 561 | } |
565 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", | 562 | ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", |
566 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); | 563 | __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd); |
567 | 564 | ||
565 | ctrl->power_fault_detected = 0; | ||
568 | return retval; | 566 | return retval; |
569 | } | 567 | } |
570 | 568 | ||
@@ -621,18 +619,10 @@ static int hpc_power_off_slot(struct slot * slot) | |||
621 | 619 | ||
622 | slot_cmd = POWER_OFF; | 620 | slot_cmd = POWER_OFF; |
623 | cmd_mask = PCI_EXP_SLTCTL_PCC; | 621 | cmd_mask = PCI_EXP_SLTCTL_PCC; |
624 | /* | ||
625 | * If we get MRL or presence detect interrupts now, the isr | ||
626 | * will notice the sticky power-fault bit too and issue power | ||
627 | * indicator change commands. This will lead to an endless loop | ||
628 | * of command completions, since the power-fault bit remains on | ||
629 | * till the slot is powered on again. | ||
630 | */ | ||
631 | if (!pciehp_poll_mode) { | 622 | if (!pciehp_poll_mode) { |
632 | slot_cmd &= ~(PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | | 623 | /* Disable power fault detection */ |
633 | PCI_EXP_SLTCTL_PDCE); | 624 | slot_cmd &= ~PCI_EXP_SLTCTL_PFDE; |
634 | cmd_mask |= (PCI_EXP_SLTCTL_PFDE | PCI_EXP_SLTCTL_MRLSCE | | 625 | cmd_mask |= PCI_EXP_SLTCTL_PFDE; |
635 | PCI_EXP_SLTCTL_PDCE); | ||
636 | } | 626 | } |
637 | 627 | ||
638 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); | 628 | retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); |
@@ -672,10 +662,11 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
672 | detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | | 662 | detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | |
673 | PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | | 663 | PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | |
674 | PCI_EXP_SLTSTA_CC); | 664 | PCI_EXP_SLTSTA_CC); |
665 | detected &= ~intr_loc; | ||
675 | intr_loc |= detected; | 666 | intr_loc |= detected; |
676 | if (!intr_loc) | 667 | if (!intr_loc) |
677 | return IRQ_NONE; | 668 | return IRQ_NONE; |
678 | if (detected && pciehp_writew(ctrl, PCI_EXP_SLTSTA, detected)) { | 669 | if (detected && pciehp_writew(ctrl, PCI_EXP_SLTSTA, intr_loc)) { |
679 | ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS\n", | 670 | ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS\n", |
680 | __func__); | 671 | __func__); |
681 | return IRQ_NONE; | 672 | return IRQ_NONE; |
@@ -709,9 +700,10 @@ static irqreturn_t pcie_isr(int irq, void *dev_id) | |||
709 | pciehp_handle_presence_change(p_slot); | 700 | pciehp_handle_presence_change(p_slot); |
710 | 701 | ||
711 | /* Check Power Fault Detected */ | 702 | /* Check Power Fault Detected */ |
712 | if (intr_loc & PCI_EXP_SLTSTA_PFD) | 703 | if ((intr_loc & PCI_EXP_SLTSTA_PFD) && !ctrl->power_fault_detected) { |
704 | ctrl->power_fault_detected = 1; | ||
713 | pciehp_handle_power_fault(p_slot); | 705 | pciehp_handle_power_fault(p_slot); |
714 | 706 | } | |
715 | return IRQ_HANDLED; | 707 | return IRQ_HANDLED; |
716 | } | 708 | } |
717 | 709 | ||
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 6aba0b6cf2e0..974e924ca96d 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
@@ -48,10 +48,10 @@ extern int shpchp_debug; | |||
48 | extern struct workqueue_struct *shpchp_wq; | 48 | extern struct workqueue_struct *shpchp_wq; |
49 | 49 | ||
50 | #define dbg(format, arg...) \ | 50 | #define dbg(format, arg...) \ |
51 | do { \ | 51 | do { \ |
52 | if (shpchp_debug) \ | 52 | if (shpchp_debug) \ |
53 | printk("%s: " format, MY_NAME , ## arg); \ | 53 | printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); \ |
54 | } while (0) | 54 | } while (0) |
55 | #define err(format, arg...) \ | 55 | #define err(format, arg...) \ |
56 | printk(KERN_ERR "%s: " format, MY_NAME , ## arg) | 56 | printk(KERN_ERR "%s: " format, MY_NAME , ## arg) |
57 | #define info(format, arg...) \ | 57 | #define info(format, arg...) \ |
@@ -62,7 +62,7 @@ extern struct workqueue_struct *shpchp_wq; | |||
62 | #define ctrl_dbg(ctrl, format, arg...) \ | 62 | #define ctrl_dbg(ctrl, format, arg...) \ |
63 | do { \ | 63 | do { \ |
64 | if (shpchp_debug) \ | 64 | if (shpchp_debug) \ |
65 | dev_printk(, &ctrl->pci_dev->dev, \ | 65 | dev_printk(KERN_DEBUG, &ctrl->pci_dev->dev, \ |
66 | format, ## arg); \ | 66 | format, ## arg); \ |
67 | } while (0) | 67 | } while (0) |
68 | #define ctrl_err(ctrl, format, arg...) \ | 68 | #define ctrl_err(ctrl, format, arg...) \ |
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index 138f161becc0..aa315e52529b 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c | |||
@@ -137,7 +137,7 @@ int __ref shpchp_configure_device(struct slot *p_slot) | |||
137 | busnr)) | 137 | busnr)) |
138 | break; | 138 | break; |
139 | } | 139 | } |
140 | if (busnr >= end) { | 140 | if (busnr > end) { |
141 | ctrl_err(ctrl, | 141 | ctrl_err(ctrl, |
142 | "No free bus for hot-added bridge\n"); | 142 | "No free bus for hot-added bridge\n"); |
143 | pci_dev_put(dev); | 143 | pci_dev_put(dev); |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 49402c399232..9dbd5066acaf 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -1782,7 +1782,7 @@ static inline void iommu_prepare_isa(void) | |||
1782 | ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); | 1782 | ret = iommu_prepare_identity_map(pdev, 0, 16*1024*1024); |
1783 | 1783 | ||
1784 | if (ret) | 1784 | if (ret) |
1785 | printk("IOMMU: Failed to create 0-64M identity map, " | 1785 | printk(KERN_ERR "IOMMU: Failed to create 0-64M identity map, " |
1786 | "floppy might not work\n"); | 1786 | "floppy might not work\n"); |
1787 | 1787 | ||
1788 | } | 1788 | } |
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c new file mode 100644 index 000000000000..7227efc760db --- /dev/null +++ b/drivers/pci/iov.c | |||
@@ -0,0 +1,680 @@ | |||
1 | /* | ||
2 | * drivers/pci/iov.c | ||
3 | * | ||
4 | * Copyright (C) 2009 Intel Corporation, Yu Zhao <yu.zhao@intel.com> | ||
5 | * | ||
6 | * PCI Express I/O Virtualization (IOV) support. | ||
7 | * Single Root IOV 1.0 | ||
8 | */ | ||
9 | |||
10 | #include <linux/pci.h> | ||
11 | #include <linux/mutex.h> | ||
12 | #include <linux/string.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include "pci.h" | ||
15 | |||
16 | #define VIRTFN_ID_LEN 16 | ||
17 | |||
18 | static inline u8 virtfn_bus(struct pci_dev *dev, int id) | ||
19 | { | ||
20 | return dev->bus->number + ((dev->devfn + dev->sriov->offset + | ||
21 | dev->sriov->stride * id) >> 8); | ||
22 | } | ||
23 | |||
24 | static inline u8 virtfn_devfn(struct pci_dev *dev, int id) | ||
25 | { | ||
26 | return (dev->devfn + dev->sriov->offset + | ||
27 | dev->sriov->stride * id) & 0xff; | ||
28 | } | ||
29 | |||
30 | static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) | ||
31 | { | ||
32 | int rc; | ||
33 | struct pci_bus *child; | ||
34 | |||
35 | if (bus->number == busnr) | ||
36 | return bus; | ||
37 | |||
38 | child = pci_find_bus(pci_domain_nr(bus), busnr); | ||
39 | if (child) | ||
40 | return child; | ||
41 | |||
42 | child = pci_add_new_bus(bus, NULL, busnr); | ||
43 | if (!child) | ||
44 | return NULL; | ||
45 | |||
46 | child->subordinate = busnr; | ||
47 | child->dev.parent = bus->bridge; | ||
48 | rc = pci_bus_add_child(child); | ||
49 | if (rc) { | ||
50 | pci_remove_bus(child); | ||
51 | return NULL; | ||
52 | } | ||
53 | |||
54 | return child; | ||
55 | } | ||
56 | |||
57 | static void virtfn_remove_bus(struct pci_bus *bus, int busnr) | ||
58 | { | ||
59 | struct pci_bus *child; | ||
60 | |||
61 | if (bus->number == busnr) | ||
62 | return; | ||
63 | |||
64 | child = pci_find_bus(pci_domain_nr(bus), busnr); | ||
65 | BUG_ON(!child); | ||
66 | |||
67 | if (list_empty(&child->devices)) | ||
68 | pci_remove_bus(child); | ||
69 | } | ||
70 | |||
71 | static int virtfn_add(struct pci_dev *dev, int id, int reset) | ||
72 | { | ||
73 | int i; | ||
74 | int rc; | ||
75 | u64 size; | ||
76 | char buf[VIRTFN_ID_LEN]; | ||
77 | struct pci_dev *virtfn; | ||
78 | struct resource *res; | ||
79 | struct pci_sriov *iov = dev->sriov; | ||
80 | |||
81 | virtfn = alloc_pci_dev(); | ||
82 | if (!virtfn) | ||
83 | return -ENOMEM; | ||
84 | |||
85 | mutex_lock(&iov->dev->sriov->lock); | ||
86 | virtfn->bus = virtfn_add_bus(dev->bus, virtfn_bus(dev, id)); | ||
87 | if (!virtfn->bus) { | ||
88 | kfree(virtfn); | ||
89 | mutex_unlock(&iov->dev->sriov->lock); | ||
90 | return -ENOMEM; | ||
91 | } | ||
92 | virtfn->devfn = virtfn_devfn(dev, id); | ||
93 | virtfn->vendor = dev->vendor; | ||
94 | pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_DID, &virtfn->device); | ||
95 | pci_setup_device(virtfn); | ||
96 | virtfn->dev.parent = dev->dev.parent; | ||
97 | |||
98 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | ||
99 | res = dev->resource + PCI_IOV_RESOURCES + i; | ||
100 | if (!res->parent) | ||
101 | continue; | ||
102 | virtfn->resource[i].name = pci_name(virtfn); | ||
103 | virtfn->resource[i].flags = res->flags; | ||
104 | size = resource_size(res); | ||
105 | do_div(size, iov->total); | ||
106 | virtfn->resource[i].start = res->start + size * id; | ||
107 | virtfn->resource[i].end = virtfn->resource[i].start + size - 1; | ||
108 | rc = request_resource(res, &virtfn->resource[i]); | ||
109 | BUG_ON(rc); | ||
110 | } | ||
111 | |||
112 | if (reset) | ||
113 | pci_execute_reset_function(virtfn); | ||
114 | |||
115 | pci_device_add(virtfn, virtfn->bus); | ||
116 | mutex_unlock(&iov->dev->sriov->lock); | ||
117 | |||
118 | virtfn->physfn = pci_dev_get(dev); | ||
119 | virtfn->is_virtfn = 1; | ||
120 | |||
121 | rc = pci_bus_add_device(virtfn); | ||
122 | if (rc) | ||
123 | goto failed1; | ||
124 | sprintf(buf, "virtfn%u", id); | ||
125 | rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf); | ||
126 | if (rc) | ||
127 | goto failed1; | ||
128 | rc = sysfs_create_link(&virtfn->dev.kobj, &dev->dev.kobj, "physfn"); | ||
129 | if (rc) | ||
130 | goto failed2; | ||
131 | |||
132 | kobject_uevent(&virtfn->dev.kobj, KOBJ_CHANGE); | ||
133 | |||
134 | return 0; | ||
135 | |||
136 | failed2: | ||
137 | sysfs_remove_link(&dev->dev.kobj, buf); | ||
138 | failed1: | ||
139 | pci_dev_put(dev); | ||
140 | mutex_lock(&iov->dev->sriov->lock); | ||
141 | pci_remove_bus_device(virtfn); | ||
142 | virtfn_remove_bus(dev->bus, virtfn_bus(dev, id)); | ||
143 | mutex_unlock(&iov->dev->sriov->lock); | ||
144 | |||
145 | return rc; | ||
146 | } | ||
147 | |||
148 | static void virtfn_remove(struct pci_dev *dev, int id, int reset) | ||
149 | { | ||
150 | char buf[VIRTFN_ID_LEN]; | ||
151 | struct pci_bus *bus; | ||
152 | struct pci_dev *virtfn; | ||
153 | struct pci_sriov *iov = dev->sriov; | ||
154 | |||
155 | bus = pci_find_bus(pci_domain_nr(dev->bus), virtfn_bus(dev, id)); | ||
156 | if (!bus) | ||
157 | return; | ||
158 | |||
159 | virtfn = pci_get_slot(bus, virtfn_devfn(dev, id)); | ||
160 | if (!virtfn) | ||
161 | return; | ||
162 | |||
163 | pci_dev_put(virtfn); | ||
164 | |||
165 | if (reset) { | ||
166 | device_release_driver(&virtfn->dev); | ||
167 | pci_execute_reset_function(virtfn); | ||
168 | } | ||
169 | |||
170 | sprintf(buf, "virtfn%u", id); | ||
171 | sysfs_remove_link(&dev->dev.kobj, buf); | ||
172 | sysfs_remove_link(&virtfn->dev.kobj, "physfn"); | ||
173 | |||
174 | mutex_lock(&iov->dev->sriov->lock); | ||
175 | pci_remove_bus_device(virtfn); | ||
176 | virtfn_remove_bus(dev->bus, virtfn_bus(dev, id)); | ||
177 | mutex_unlock(&iov->dev->sriov->lock); | ||
178 | |||
179 | pci_dev_put(dev); | ||
180 | } | ||
181 | |||
182 | static int sriov_migration(struct pci_dev *dev) | ||
183 | { | ||
184 | u16 status; | ||
185 | struct pci_sriov *iov = dev->sriov; | ||
186 | |||
187 | if (!iov->nr_virtfn) | ||
188 | return 0; | ||
189 | |||
190 | if (!(iov->cap & PCI_SRIOV_CAP_VFM)) | ||
191 | return 0; | ||
192 | |||
193 | pci_read_config_word(dev, iov->pos + PCI_SRIOV_STATUS, &status); | ||
194 | if (!(status & PCI_SRIOV_STATUS_VFM)) | ||
195 | return 0; | ||
196 | |||
197 | schedule_work(&iov->mtask); | ||
198 | |||
199 | return 1; | ||
200 | } | ||
201 | |||
202 | static void sriov_migration_task(struct work_struct *work) | ||
203 | { | ||
204 | int i; | ||
205 | u8 state; | ||
206 | u16 status; | ||
207 | struct pci_sriov *iov = container_of(work, struct pci_sriov, mtask); | ||
208 | |||
209 | for (i = iov->initial; i < iov->nr_virtfn; i++) { | ||
210 | state = readb(iov->mstate + i); | ||
211 | if (state == PCI_SRIOV_VFM_MI) { | ||
212 | writeb(PCI_SRIOV_VFM_AV, iov->mstate + i); | ||
213 | state = readb(iov->mstate + i); | ||
214 | if (state == PCI_SRIOV_VFM_AV) | ||
215 | virtfn_add(iov->self, i, 1); | ||
216 | } else if (state == PCI_SRIOV_VFM_MO) { | ||
217 | virtfn_remove(iov->self, i, 1); | ||
218 | writeb(PCI_SRIOV_VFM_UA, iov->mstate + i); | ||
219 | state = readb(iov->mstate + i); | ||
220 | if (state == PCI_SRIOV_VFM_AV) | ||
221 | virtfn_add(iov->self, i, 0); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | pci_read_config_word(iov->self, iov->pos + PCI_SRIOV_STATUS, &status); | ||
226 | status &= ~PCI_SRIOV_STATUS_VFM; | ||
227 | pci_write_config_word(iov->self, iov->pos + PCI_SRIOV_STATUS, status); | ||
228 | } | ||
229 | |||
230 | static int sriov_enable_migration(struct pci_dev *dev, int nr_virtfn) | ||
231 | { | ||
232 | int bir; | ||
233 | u32 table; | ||
234 | resource_size_t pa; | ||
235 | struct pci_sriov *iov = dev->sriov; | ||
236 | |||
237 | if (nr_virtfn <= iov->initial) | ||
238 | return 0; | ||
239 | |||
240 | pci_read_config_dword(dev, iov->pos + PCI_SRIOV_VFM, &table); | ||
241 | bir = PCI_SRIOV_VFM_BIR(table); | ||
242 | if (bir > PCI_STD_RESOURCE_END) | ||
243 | return -EIO; | ||
244 | |||
245 | table = PCI_SRIOV_VFM_OFFSET(table); | ||
246 | if (table + nr_virtfn > pci_resource_len(dev, bir)) | ||
247 | return -EIO; | ||
248 | |||
249 | pa = pci_resource_start(dev, bir) + table; | ||
250 | iov->mstate = ioremap(pa, nr_virtfn); | ||
251 | if (!iov->mstate) | ||
252 | return -ENOMEM; | ||
253 | |||
254 | INIT_WORK(&iov->mtask, sriov_migration_task); | ||
255 | |||
256 | iov->ctrl |= PCI_SRIOV_CTRL_VFM | PCI_SRIOV_CTRL_INTR; | ||
257 | pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static void sriov_disable_migration(struct pci_dev *dev) | ||
263 | { | ||
264 | struct pci_sriov *iov = dev->sriov; | ||
265 | |||
266 | iov->ctrl &= ~(PCI_SRIOV_CTRL_VFM | PCI_SRIOV_CTRL_INTR); | ||
267 | pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); | ||
268 | |||
269 | cancel_work_sync(&iov->mtask); | ||
270 | iounmap(iov->mstate); | ||
271 | } | ||
272 | |||
273 | static int sriov_enable(struct pci_dev *dev, int nr_virtfn) | ||
274 | { | ||
275 | int rc; | ||
276 | int i, j; | ||
277 | int nres; | ||
278 | u16 offset, stride, initial; | ||
279 | struct resource *res; | ||
280 | struct pci_dev *pdev; | ||
281 | struct pci_sriov *iov = dev->sriov; | ||
282 | |||
283 | if (!nr_virtfn) | ||
284 | return 0; | ||
285 | |||
286 | if (iov->nr_virtfn) | ||
287 | return -EINVAL; | ||
288 | |||
289 | pci_read_config_word(dev, iov->pos + PCI_SRIOV_INITIAL_VF, &initial); | ||
290 | if (initial > iov->total || | ||
291 | (!(iov->cap & PCI_SRIOV_CAP_VFM) && (initial != iov->total))) | ||
292 | return -EIO; | ||
293 | |||
294 | if (nr_virtfn < 0 || nr_virtfn > iov->total || | ||
295 | (!(iov->cap & PCI_SRIOV_CAP_VFM) && (nr_virtfn > initial))) | ||
296 | return -EINVAL; | ||
297 | |||
298 | pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, nr_virtfn); | ||
299 | pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_OFFSET, &offset); | ||
300 | pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_STRIDE, &stride); | ||
301 | if (!offset || (nr_virtfn > 1 && !stride)) | ||
302 | return -EIO; | ||
303 | |||
304 | nres = 0; | ||
305 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | ||
306 | res = dev->resource + PCI_IOV_RESOURCES + i; | ||
307 | if (res->parent) | ||
308 | nres++; | ||
309 | } | ||
310 | if (nres != iov->nres) { | ||
311 | dev_err(&dev->dev, "not enough MMIO resources for SR-IOV\n"); | ||
312 | return -ENOMEM; | ||
313 | } | ||
314 | |||
315 | iov->offset = offset; | ||
316 | iov->stride = stride; | ||
317 | |||
318 | if (virtfn_bus(dev, nr_virtfn - 1) > dev->bus->subordinate) { | ||
319 | dev_err(&dev->dev, "SR-IOV: bus number out of range\n"); | ||
320 | return -ENOMEM; | ||
321 | } | ||
322 | |||
323 | if (iov->link != dev->devfn) { | ||
324 | pdev = pci_get_slot(dev->bus, iov->link); | ||
325 | if (!pdev) | ||
326 | return -ENODEV; | ||
327 | |||
328 | pci_dev_put(pdev); | ||
329 | |||
330 | if (!pdev->is_physfn) | ||
331 | return -ENODEV; | ||
332 | |||
333 | rc = sysfs_create_link(&dev->dev.kobj, | ||
334 | &pdev->dev.kobj, "dep_link"); | ||
335 | if (rc) | ||
336 | return rc; | ||
337 | } | ||
338 | |||
339 | iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE; | ||
340 | pci_block_user_cfg_access(dev); | ||
341 | pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); | ||
342 | msleep(100); | ||
343 | pci_unblock_user_cfg_access(dev); | ||
344 | |||
345 | iov->initial = initial; | ||
346 | if (nr_virtfn < initial) | ||
347 | initial = nr_virtfn; | ||
348 | |||
349 | for (i = 0; i < initial; i++) { | ||
350 | rc = virtfn_add(dev, i, 0); | ||
351 | if (rc) | ||
352 | goto failed; | ||
353 | } | ||
354 | |||
355 | if (iov->cap & PCI_SRIOV_CAP_VFM) { | ||
356 | rc = sriov_enable_migration(dev, nr_virtfn); | ||
357 | if (rc) | ||
358 | goto failed; | ||
359 | } | ||
360 | |||
361 | kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE); | ||
362 | iov->nr_virtfn = nr_virtfn; | ||
363 | |||
364 | return 0; | ||
365 | |||
366 | failed: | ||
367 | for (j = 0; j < i; j++) | ||
368 | virtfn_remove(dev, j, 0); | ||
369 | |||
370 | iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); | ||
371 | pci_block_user_cfg_access(dev); | ||
372 | pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); | ||
373 | ssleep(1); | ||
374 | pci_unblock_user_cfg_access(dev); | ||
375 | |||
376 | if (iov->link != dev->devfn) | ||
377 | sysfs_remove_link(&dev->dev.kobj, "dep_link"); | ||
378 | |||
379 | return rc; | ||
380 | } | ||
381 | |||
382 | static void sriov_disable(struct pci_dev *dev) | ||
383 | { | ||
384 | int i; | ||
385 | struct pci_sriov *iov = dev->sriov; | ||
386 | |||
387 | if (!iov->nr_virtfn) | ||
388 | return; | ||
389 | |||
390 | if (iov->cap & PCI_SRIOV_CAP_VFM) | ||
391 | sriov_disable_migration(dev); | ||
392 | |||
393 | for (i = 0; i < iov->nr_virtfn; i++) | ||
394 | virtfn_remove(dev, i, 0); | ||
395 | |||
396 | iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); | ||
397 | pci_block_user_cfg_access(dev); | ||
398 | pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); | ||
399 | ssleep(1); | ||
400 | pci_unblock_user_cfg_access(dev); | ||
401 | |||
402 | if (iov->link != dev->devfn) | ||
403 | sysfs_remove_link(&dev->dev.kobj, "dep_link"); | ||
404 | |||
405 | iov->nr_virtfn = 0; | ||
406 | } | ||
407 | |||
408 | static int sriov_init(struct pci_dev *dev, int pos) | ||
409 | { | ||
410 | int i; | ||
411 | int rc; | ||
412 | int nres; | ||
413 | u32 pgsz; | ||
414 | u16 ctrl, total, offset, stride; | ||
415 | struct pci_sriov *iov; | ||
416 | struct resource *res; | ||
417 | struct pci_dev *pdev; | ||
418 | |||
419 | if (dev->pcie_type != PCI_EXP_TYPE_RC_END && | ||
420 | dev->pcie_type != PCI_EXP_TYPE_ENDPOINT) | ||
421 | return -ENODEV; | ||
422 | |||
423 | pci_read_config_word(dev, pos + PCI_SRIOV_CTRL, &ctrl); | ||
424 | if (ctrl & PCI_SRIOV_CTRL_VFE) { | ||
425 | pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, 0); | ||
426 | ssleep(1); | ||
427 | } | ||
428 | |||
429 | pci_read_config_word(dev, pos + PCI_SRIOV_TOTAL_VF, &total); | ||
430 | if (!total) | ||
431 | return 0; | ||
432 | |||
433 | ctrl = 0; | ||
434 | list_for_each_entry(pdev, &dev->bus->devices, bus_list) | ||
435 | if (pdev->is_physfn) | ||
436 | goto found; | ||
437 | |||
438 | pdev = NULL; | ||
439 | if (pci_ari_enabled(dev->bus)) | ||
440 | ctrl |= PCI_SRIOV_CTRL_ARI; | ||
441 | |||
442 | found: | ||
443 | pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl); | ||
444 | pci_write_config_word(dev, pos + PCI_SRIOV_NUM_VF, total); | ||
445 | pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset); | ||
446 | pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride); | ||
447 | if (!offset || (total > 1 && !stride)) | ||
448 | return -EIO; | ||
449 | |||
450 | pci_read_config_dword(dev, pos + PCI_SRIOV_SUP_PGSIZE, &pgsz); | ||
451 | i = PAGE_SHIFT > 12 ? PAGE_SHIFT - 12 : 0; | ||
452 | pgsz &= ~((1 << i) - 1); | ||
453 | if (!pgsz) | ||
454 | return -EIO; | ||
455 | |||
456 | pgsz &= ~(pgsz - 1); | ||
457 | pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz); | ||
458 | |||
459 | nres = 0; | ||
460 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | ||
461 | res = dev->resource + PCI_IOV_RESOURCES + i; | ||
462 | i += __pci_read_base(dev, pci_bar_unknown, res, | ||
463 | pos + PCI_SRIOV_BAR + i * 4); | ||
464 | if (!res->flags) | ||
465 | continue; | ||
466 | if (resource_size(res) & (PAGE_SIZE - 1)) { | ||
467 | rc = -EIO; | ||
468 | goto failed; | ||
469 | } | ||
470 | res->end = res->start + resource_size(res) * total - 1; | ||
471 | nres++; | ||
472 | } | ||
473 | |||
474 | iov = kzalloc(sizeof(*iov), GFP_KERNEL); | ||
475 | if (!iov) { | ||
476 | rc = -ENOMEM; | ||
477 | goto failed; | ||
478 | } | ||
479 | |||
480 | iov->pos = pos; | ||
481 | iov->nres = nres; | ||
482 | iov->ctrl = ctrl; | ||
483 | iov->total = total; | ||
484 | iov->offset = offset; | ||
485 | iov->stride = stride; | ||
486 | iov->pgsz = pgsz; | ||
487 | iov->self = dev; | ||
488 | pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap); | ||
489 | pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link); | ||
490 | |||
491 | if (pdev) | ||
492 | iov->dev = pci_dev_get(pdev); | ||
493 | else { | ||
494 | iov->dev = dev; | ||
495 | mutex_init(&iov->lock); | ||
496 | } | ||
497 | |||
498 | dev->sriov = iov; | ||
499 | dev->is_physfn = 1; | ||
500 | |||
501 | return 0; | ||
502 | |||
503 | failed: | ||
504 | for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { | ||
505 | res = dev->resource + PCI_IOV_RESOURCES + i; | ||
506 | res->flags = 0; | ||
507 | } | ||
508 | |||
509 | return rc; | ||
510 | } | ||
511 | |||
512 | static void sriov_release(struct pci_dev *dev) | ||
513 | { | ||
514 | BUG_ON(dev->sriov->nr_virtfn); | ||
515 | |||
516 | if (dev == dev->sriov->dev) | ||
517 | mutex_destroy(&dev->sriov->lock); | ||
518 | else | ||
519 | pci_dev_put(dev->sriov->dev); | ||
520 | |||
521 | kfree(dev->sriov); | ||
522 | dev->sriov = NULL; | ||
523 | } | ||
524 | |||
525 | static void sriov_restore_state(struct pci_dev *dev) | ||
526 | { | ||
527 | int i; | ||
528 | u16 ctrl; | ||
529 | struct pci_sriov *iov = dev->sriov; | ||
530 | |||
531 | pci_read_config_word(dev, iov->pos + PCI_SRIOV_CTRL, &ctrl); | ||
532 | if (ctrl & PCI_SRIOV_CTRL_VFE) | ||
533 | return; | ||
534 | |||
535 | for (i = PCI_IOV_RESOURCES; i <= PCI_IOV_RESOURCE_END; i++) | ||
536 | pci_update_resource(dev, i); | ||
537 | |||
538 | pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz); | ||
539 | pci_write_config_word(dev, iov->pos + PCI_SRIOV_NUM_VF, iov->nr_virtfn); | ||
540 | pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); | ||
541 | if (iov->ctrl & PCI_SRIOV_CTRL_VFE) | ||
542 | msleep(100); | ||
543 | } | ||
544 | |||
545 | /** | ||
546 | * pci_iov_init - initialize the IOV capability | ||
547 | * @dev: the PCI device | ||
548 | * | ||
549 | * Returns 0 on success, or negative on failure. | ||
550 | */ | ||
551 | int pci_iov_init(struct pci_dev *dev) | ||
552 | { | ||
553 | int pos; | ||
554 | |||
555 | if (!dev->is_pcie) | ||
556 | return -ENODEV; | ||
557 | |||
558 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV); | ||
559 | if (pos) | ||
560 | return sriov_init(dev, pos); | ||
561 | |||
562 | return -ENODEV; | ||
563 | } | ||
564 | |||
565 | /** | ||
566 | * pci_iov_release - release resources used by the IOV capability | ||
567 | * @dev: the PCI device | ||
568 | */ | ||
569 | void pci_iov_release(struct pci_dev *dev) | ||
570 | { | ||
571 | if (dev->is_physfn) | ||
572 | sriov_release(dev); | ||
573 | } | ||
574 | |||
575 | /** | ||
576 | * pci_iov_resource_bar - get position of the SR-IOV BAR | ||
577 | * @dev: the PCI device | ||
578 | * @resno: the resource number | ||
579 | * @type: the BAR type to be filled in | ||
580 | * | ||
581 | * Returns position of the BAR encapsulated in the SR-IOV capability. | ||
582 | */ | ||
583 | int pci_iov_resource_bar(struct pci_dev *dev, int resno, | ||
584 | enum pci_bar_type *type) | ||
585 | { | ||
586 | if (resno < PCI_IOV_RESOURCES || resno > PCI_IOV_RESOURCE_END) | ||
587 | return 0; | ||
588 | |||
589 | BUG_ON(!dev->is_physfn); | ||
590 | |||
591 | *type = pci_bar_unknown; | ||
592 | |||
593 | return dev->sriov->pos + PCI_SRIOV_BAR + | ||
594 | 4 * (resno - PCI_IOV_RESOURCES); | ||
595 | } | ||
596 | |||
597 | /** | ||
598 | * pci_restore_iov_state - restore the state of the IOV capability | ||
599 | * @dev: the PCI device | ||
600 | */ | ||
601 | void pci_restore_iov_state(struct pci_dev *dev) | ||
602 | { | ||
603 | if (dev->is_physfn) | ||
604 | sriov_restore_state(dev); | ||
605 | } | ||
606 | |||
607 | /** | ||
608 | * pci_iov_bus_range - find bus range used by Virtual Function | ||
609 | * @bus: the PCI bus | ||
610 | * | ||
611 | * Returns max number of buses (exclude current one) used by Virtual | ||
612 | * Functions. | ||
613 | */ | ||
614 | int pci_iov_bus_range(struct pci_bus *bus) | ||
615 | { | ||
616 | int max = 0; | ||
617 | u8 busnr; | ||
618 | struct pci_dev *dev; | ||
619 | |||
620 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
621 | if (!dev->is_physfn) | ||
622 | continue; | ||
623 | busnr = virtfn_bus(dev, dev->sriov->total - 1); | ||
624 | if (busnr > max) | ||
625 | max = busnr; | ||
626 | } | ||
627 | |||
628 | return max ? max - bus->number : 0; | ||
629 | } | ||
630 | |||
631 | /** | ||
632 | * pci_enable_sriov - enable the SR-IOV capability | ||
633 | * @dev: the PCI device | ||
634 | * | ||
635 | * Returns 0 on success, or negative on failure. | ||
636 | */ | ||
637 | int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn) | ||
638 | { | ||
639 | might_sleep(); | ||
640 | |||
641 | if (!dev->is_physfn) | ||
642 | return -ENODEV; | ||
643 | |||
644 | return sriov_enable(dev, nr_virtfn); | ||
645 | } | ||
646 | EXPORT_SYMBOL_GPL(pci_enable_sriov); | ||
647 | |||
648 | /** | ||
649 | * pci_disable_sriov - disable the SR-IOV capability | ||
650 | * @dev: the PCI device | ||
651 | */ | ||
652 | void pci_disable_sriov(struct pci_dev *dev) | ||
653 | { | ||
654 | might_sleep(); | ||
655 | |||
656 | if (!dev->is_physfn) | ||
657 | return; | ||
658 | |||
659 | sriov_disable(dev); | ||
660 | } | ||
661 | EXPORT_SYMBOL_GPL(pci_disable_sriov); | ||
662 | |||
663 | /** | ||
664 | * pci_sriov_migration - notify SR-IOV core of Virtual Function Migration | ||
665 | * @dev: the PCI device | ||
666 | * | ||
667 | * Returns IRQ_HANDLED if the IRQ is handled, or IRQ_NONE if not. | ||
668 | * | ||
669 | * Physical Function driver is responsible to register IRQ handler using | ||
670 | * VF Migration Interrupt Message Number, and call this function when the | ||
671 | * interrupt is generated by the hardware. | ||
672 | */ | ||
673 | irqreturn_t pci_sriov_migration(struct pci_dev *dev) | ||
674 | { | ||
675 | if (!dev->is_physfn) | ||
676 | return IRQ_NONE; | ||
677 | |||
678 | return sriov_migration(dev) ? IRQ_HANDLED : IRQ_NONE; | ||
679 | } | ||
680 | EXPORT_SYMBOL_GPL(pci_sriov_migration); | ||
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index baba2eb5367d..6f2e6295e773 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -27,48 +27,53 @@ static int pci_msi_enable = 1; | |||
27 | 27 | ||
28 | /* Arch hooks */ | 28 | /* Arch hooks */ |
29 | 29 | ||
30 | int __attribute__ ((weak)) | 30 | #ifndef arch_msi_check_device |
31 | arch_msi_check_device(struct pci_dev *dev, int nvec, int type) | 31 | int arch_msi_check_device(struct pci_dev *dev, int nvec, int type) |
32 | { | 32 | { |
33 | return 0; | 33 | return 0; |
34 | } | 34 | } |
35 | #endif | ||
35 | 36 | ||
36 | int __attribute__ ((weak)) | 37 | #ifndef arch_setup_msi_irqs |
37 | arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry) | 38 | int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) |
38 | { | ||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | int __attribute__ ((weak)) | ||
43 | arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | ||
44 | { | 39 | { |
45 | struct msi_desc *entry; | 40 | struct msi_desc *entry; |
46 | int ret; | 41 | int ret; |
47 | 42 | ||
43 | /* | ||
44 | * If an architecture wants to support multiple MSI, it needs to | ||
45 | * override arch_setup_msi_irqs() | ||
46 | */ | ||
47 | if (type == PCI_CAP_ID_MSI && nvec > 1) | ||
48 | return 1; | ||
49 | |||
48 | list_for_each_entry(entry, &dev->msi_list, list) { | 50 | list_for_each_entry(entry, &dev->msi_list, list) { |
49 | ret = arch_setup_msi_irq(dev, entry); | 51 | ret = arch_setup_msi_irq(dev, entry); |
50 | if (ret) | 52 | if (ret < 0) |
51 | return ret; | 53 | return ret; |
54 | if (ret > 0) | ||
55 | return -ENOSPC; | ||
52 | } | 56 | } |
53 | 57 | ||
54 | return 0; | 58 | return 0; |
55 | } | 59 | } |
60 | #endif | ||
56 | 61 | ||
57 | void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq) | 62 | #ifndef arch_teardown_msi_irqs |
58 | { | 63 | void arch_teardown_msi_irqs(struct pci_dev *dev) |
59 | return; | ||
60 | } | ||
61 | |||
62 | void __attribute__ ((weak)) | ||
63 | arch_teardown_msi_irqs(struct pci_dev *dev) | ||
64 | { | 64 | { |
65 | struct msi_desc *entry; | 65 | struct msi_desc *entry; |
66 | 66 | ||
67 | list_for_each_entry(entry, &dev->msi_list, list) { | 67 | list_for_each_entry(entry, &dev->msi_list, list) { |
68 | if (entry->irq != 0) | 68 | int i, nvec; |
69 | arch_teardown_msi_irq(entry->irq); | 69 | if (entry->irq == 0) |
70 | continue; | ||
71 | nvec = 1 << entry->msi_attrib.multiple; | ||
72 | for (i = 0; i < nvec; i++) | ||
73 | arch_teardown_msi_irq(entry->irq + i); | ||
70 | } | 74 | } |
71 | } | 75 | } |
76 | #endif | ||
72 | 77 | ||
73 | static void __msi_set_enable(struct pci_dev *dev, int pos, int enable) | 78 | static void __msi_set_enable(struct pci_dev *dev, int pos, int enable) |
74 | { | 79 | { |
@@ -111,27 +116,14 @@ static inline __attribute_const__ u32 msi_mask(unsigned x) | |||
111 | return (1 << (1 << x)) - 1; | 116 | return (1 << (1 << x)) - 1; |
112 | } | 117 | } |
113 | 118 | ||
114 | static void msix_flush_writes(struct irq_desc *desc) | 119 | static inline __attribute_const__ u32 msi_capable_mask(u16 control) |
115 | { | 120 | { |
116 | struct msi_desc *entry; | 121 | return msi_mask((control >> 1) & 7); |
122 | } | ||
117 | 123 | ||
118 | entry = get_irq_desc_msi(desc); | 124 | static inline __attribute_const__ u32 msi_enabled_mask(u16 control) |
119 | BUG_ON(!entry || !entry->dev); | 125 | { |
120 | switch (entry->msi_attrib.type) { | 126 | return msi_mask((control >> 4) & 7); |
121 | case PCI_CAP_ID_MSI: | ||
122 | /* nothing to do */ | ||
123 | break; | ||
124 | case PCI_CAP_ID_MSIX: | ||
125 | { | ||
126 | int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + | ||
127 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; | ||
128 | readl(entry->mask_base + offset); | ||
129 | break; | ||
130 | } | ||
131 | default: | ||
132 | BUG(); | ||
133 | break; | ||
134 | } | ||
135 | } | 127 | } |
136 | 128 | ||
137 | /* | 129 | /* |
@@ -143,49 +135,71 @@ static void msix_flush_writes(struct irq_desc *desc) | |||
143 | * Returns 1 if it succeeded in masking the interrupt and 0 if the device | 135 | * Returns 1 if it succeeded in masking the interrupt and 0 if the device |
144 | * doesn't support MSI masking. | 136 | * doesn't support MSI masking. |
145 | */ | 137 | */ |
146 | static int msi_set_mask_bits(struct irq_desc *desc, u32 mask, u32 flag) | 138 | static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) |
147 | { | 139 | { |
148 | struct msi_desc *entry; | 140 | u32 mask_bits = desc->masked; |
149 | 141 | ||
150 | entry = get_irq_desc_msi(desc); | 142 | if (!desc->msi_attrib.maskbit) |
151 | BUG_ON(!entry || !entry->dev); | 143 | return; |
152 | switch (entry->msi_attrib.type) { | 144 | |
153 | case PCI_CAP_ID_MSI: | 145 | mask_bits &= ~mask; |
154 | if (entry->msi_attrib.maskbit) { | 146 | mask_bits |= flag; |
155 | int pos; | 147 | pci_write_config_dword(desc->dev, desc->mask_pos, mask_bits); |
156 | u32 mask_bits; | 148 | desc->masked = mask_bits; |
157 | 149 | } | |
158 | pos = (long)entry->mask_base; | 150 | |
159 | pci_read_config_dword(entry->dev, pos, &mask_bits); | 151 | /* |
160 | mask_bits &= ~(mask); | 152 | * This internal function does not flush PCI writes to the device. |
161 | mask_bits |= flag & mask; | 153 | * All users must ensure that they read from the device before either |
162 | pci_write_config_dword(entry->dev, pos, mask_bits); | 154 | * assuming that the device state is up to date, or returning out of this |
163 | } else { | 155 | * file. This saves a few milliseconds when initialising devices with lots |
164 | return 0; | 156 | * of MSI-X interrupts. |
165 | } | 157 | */ |
166 | break; | 158 | static void msix_mask_irq(struct msi_desc *desc, u32 flag) |
167 | case PCI_CAP_ID_MSIX: | 159 | { |
168 | { | 160 | u32 mask_bits = desc->masked; |
169 | int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + | 161 | unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + |
170 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; | 162 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; |
171 | writel(flag, entry->mask_base + offset); | 163 | mask_bits &= ~1; |
172 | readl(entry->mask_base + offset); | 164 | mask_bits |= flag; |
173 | break; | 165 | writel(mask_bits, desc->mask_base + offset); |
174 | } | 166 | desc->masked = mask_bits; |
175 | default: | 167 | } |
176 | BUG(); | 168 | |
177 | break; | 169 | static void msi_set_mask_bit(unsigned irq, u32 flag) |
170 | { | ||
171 | struct msi_desc *desc = get_irq_msi(irq); | ||
172 | |||
173 | if (desc->msi_attrib.is_msix) { | ||
174 | msix_mask_irq(desc, flag); | ||
175 | readl(desc->mask_base); /* Flush write to device */ | ||
176 | } else { | ||
177 | unsigned offset = irq - desc->dev->irq; | ||
178 | msi_mask_irq(desc, 1 << offset, flag << offset); | ||
178 | } | 179 | } |
179 | entry->msi_attrib.masked = !!flag; | 180 | } |
180 | return 1; | 181 | |
182 | void mask_msi_irq(unsigned int irq) | ||
183 | { | ||
184 | msi_set_mask_bit(irq, 1); | ||
185 | } | ||
186 | |||
187 | void unmask_msi_irq(unsigned int irq) | ||
188 | { | ||
189 | msi_set_mask_bit(irq, 0); | ||
181 | } | 190 | } |
182 | 191 | ||
183 | void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | 192 | void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) |
184 | { | 193 | { |
185 | struct msi_desc *entry = get_irq_desc_msi(desc); | 194 | struct msi_desc *entry = get_irq_desc_msi(desc); |
186 | switch(entry->msi_attrib.type) { | 195 | if (entry->msi_attrib.is_msix) { |
187 | case PCI_CAP_ID_MSI: | 196 | void __iomem *base = entry->mask_base + |
188 | { | 197 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; |
198 | |||
199 | msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | ||
200 | msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | ||
201 | msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET); | ||
202 | } else { | ||
189 | struct pci_dev *dev = entry->dev; | 203 | struct pci_dev *dev = entry->dev; |
190 | int pos = entry->msi_attrib.pos; | 204 | int pos = entry->msi_attrib.pos; |
191 | u16 data; | 205 | u16 data; |
@@ -201,21 +215,6 @@ void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | |||
201 | pci_read_config_word(dev, msi_data_reg(pos, 0), &data); | 215 | pci_read_config_word(dev, msi_data_reg(pos, 0), &data); |
202 | } | 216 | } |
203 | msg->data = data; | 217 | msg->data = data; |
204 | break; | ||
205 | } | ||
206 | case PCI_CAP_ID_MSIX: | ||
207 | { | ||
208 | void __iomem *base; | ||
209 | base = entry->mask_base + | ||
210 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; | ||
211 | |||
212 | msg->address_lo = readl(base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | ||
213 | msg->address_hi = readl(base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | ||
214 | msg->data = readl(base + PCI_MSIX_ENTRY_DATA_OFFSET); | ||
215 | break; | ||
216 | } | ||
217 | default: | ||
218 | BUG(); | ||
219 | } | 218 | } |
220 | } | 219 | } |
221 | 220 | ||
@@ -229,11 +228,25 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg) | |||
229 | void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | 228 | void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) |
230 | { | 229 | { |
231 | struct msi_desc *entry = get_irq_desc_msi(desc); | 230 | struct msi_desc *entry = get_irq_desc_msi(desc); |
232 | switch (entry->msi_attrib.type) { | 231 | if (entry->msi_attrib.is_msix) { |
233 | case PCI_CAP_ID_MSI: | 232 | void __iomem *base; |
234 | { | 233 | base = entry->mask_base + |
234 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; | ||
235 | |||
236 | writel(msg->address_lo, | ||
237 | base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | ||
238 | writel(msg->address_hi, | ||
239 | base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | ||
240 | writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET); | ||
241 | } else { | ||
235 | struct pci_dev *dev = entry->dev; | 242 | struct pci_dev *dev = entry->dev; |
236 | int pos = entry->msi_attrib.pos; | 243 | int pos = entry->msi_attrib.pos; |
244 | u16 msgctl; | ||
245 | |||
246 | pci_read_config_word(dev, msi_control_reg(pos), &msgctl); | ||
247 | msgctl &= ~PCI_MSI_FLAGS_QSIZE; | ||
248 | msgctl |= entry->msi_attrib.multiple << 4; | ||
249 | pci_write_config_word(dev, msi_control_reg(pos), msgctl); | ||
237 | 250 | ||
238 | pci_write_config_dword(dev, msi_lower_address_reg(pos), | 251 | pci_write_config_dword(dev, msi_lower_address_reg(pos), |
239 | msg->address_lo); | 252 | msg->address_lo); |
@@ -246,23 +259,6 @@ void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg) | |||
246 | pci_write_config_word(dev, msi_data_reg(pos, 0), | 259 | pci_write_config_word(dev, msi_data_reg(pos, 0), |
247 | msg->data); | 260 | msg->data); |
248 | } | 261 | } |
249 | break; | ||
250 | } | ||
251 | case PCI_CAP_ID_MSIX: | ||
252 | { | ||
253 | void __iomem *base; | ||
254 | base = entry->mask_base + | ||
255 | entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE; | ||
256 | |||
257 | writel(msg->address_lo, | ||
258 | base + PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET); | ||
259 | writel(msg->address_hi, | ||
260 | base + PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET); | ||
261 | writel(msg->data, base + PCI_MSIX_ENTRY_DATA_OFFSET); | ||
262 | break; | ||
263 | } | ||
264 | default: | ||
265 | BUG(); | ||
266 | } | 262 | } |
267 | entry->msg = *msg; | 263 | entry->msg = *msg; |
268 | } | 264 | } |
@@ -274,37 +270,18 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg) | |||
274 | write_msi_msg_desc(desc, msg); | 270 | write_msi_msg_desc(desc, msg); |
275 | } | 271 | } |
276 | 272 | ||
277 | void mask_msi_irq(unsigned int irq) | ||
278 | { | ||
279 | struct irq_desc *desc = irq_to_desc(irq); | ||
280 | |||
281 | msi_set_mask_bits(desc, 1, 1); | ||
282 | msix_flush_writes(desc); | ||
283 | } | ||
284 | |||
285 | void unmask_msi_irq(unsigned int irq) | ||
286 | { | ||
287 | struct irq_desc *desc = irq_to_desc(irq); | ||
288 | |||
289 | msi_set_mask_bits(desc, 1, 0); | ||
290 | msix_flush_writes(desc); | ||
291 | } | ||
292 | |||
293 | static int msi_free_irqs(struct pci_dev* dev); | 273 | static int msi_free_irqs(struct pci_dev* dev); |
294 | 274 | ||
295 | static struct msi_desc* alloc_msi_entry(void) | 275 | static struct msi_desc *alloc_msi_entry(struct pci_dev *dev) |
296 | { | 276 | { |
297 | struct msi_desc *entry; | 277 | struct msi_desc *desc = kzalloc(sizeof(*desc), GFP_KERNEL); |
298 | 278 | if (!desc) | |
299 | entry = kzalloc(sizeof(struct msi_desc), GFP_KERNEL); | ||
300 | if (!entry) | ||
301 | return NULL; | 279 | return NULL; |
302 | 280 | ||
303 | INIT_LIST_HEAD(&entry->list); | 281 | INIT_LIST_HEAD(&desc->list); |
304 | entry->irq = 0; | 282 | desc->dev = dev; |
305 | entry->dev = NULL; | ||
306 | 283 | ||
307 | return entry; | 284 | return desc; |
308 | } | 285 | } |
309 | 286 | ||
310 | static void pci_intx_for_msi(struct pci_dev *dev, int enable) | 287 | static void pci_intx_for_msi(struct pci_dev *dev, int enable) |
@@ -328,15 +305,11 @@ static void __pci_restore_msi_state(struct pci_dev *dev) | |||
328 | pci_intx_for_msi(dev, 0); | 305 | pci_intx_for_msi(dev, 0); |
329 | msi_set_enable(dev, 0); | 306 | msi_set_enable(dev, 0); |
330 | write_msi_msg(dev->irq, &entry->msg); | 307 | write_msi_msg(dev->irq, &entry->msg); |
331 | if (entry->msi_attrib.maskbit) { | ||
332 | struct irq_desc *desc = irq_to_desc(dev->irq); | ||
333 | msi_set_mask_bits(desc, entry->msi_attrib.maskbits_mask, | ||
334 | entry->msi_attrib.masked); | ||
335 | } | ||
336 | 308 | ||
337 | pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); | 309 | pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); |
310 | msi_mask_irq(entry, msi_capable_mask(control), entry->masked); | ||
338 | control &= ~PCI_MSI_FLAGS_QSIZE; | 311 | control &= ~PCI_MSI_FLAGS_QSIZE; |
339 | control |= PCI_MSI_FLAGS_ENABLE; | 312 | control |= (entry->msi_attrib.multiple << 4) | PCI_MSI_FLAGS_ENABLE; |
340 | pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); | 313 | pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); |
341 | } | 314 | } |
342 | 315 | ||
@@ -354,9 +327,8 @@ static void __pci_restore_msix_state(struct pci_dev *dev) | |||
354 | msix_set_enable(dev, 0); | 327 | msix_set_enable(dev, 0); |
355 | 328 | ||
356 | list_for_each_entry(entry, &dev->msi_list, list) { | 329 | list_for_each_entry(entry, &dev->msi_list, list) { |
357 | struct irq_desc *desc = irq_to_desc(entry->irq); | ||
358 | write_msi_msg(entry->irq, &entry->msg); | 330 | write_msi_msg(entry->irq, &entry->msg); |
359 | msi_set_mask_bits(desc, 1, entry->msi_attrib.masked); | 331 | msix_mask_irq(entry, entry->masked); |
360 | } | 332 | } |
361 | 333 | ||
362 | BUG_ON(list_empty(&dev->msi_list)); | 334 | BUG_ON(list_empty(&dev->msi_list)); |
@@ -378,52 +350,48 @@ EXPORT_SYMBOL_GPL(pci_restore_msi_state); | |||
378 | /** | 350 | /** |
379 | * msi_capability_init - configure device's MSI capability structure | 351 | * msi_capability_init - configure device's MSI capability structure |
380 | * @dev: pointer to the pci_dev data structure of MSI device function | 352 | * @dev: pointer to the pci_dev data structure of MSI device function |
353 | * @nvec: number of interrupts to allocate | ||
381 | * | 354 | * |
382 | * Setup the MSI capability structure of device function with a single | 355 | * Setup the MSI capability structure of the device with the requested |
383 | * MSI irq, regardless of device function is capable of handling | 356 | * number of interrupts. A return value of zero indicates the successful |
384 | * multiple messages. A return of zero indicates the successful setup | 357 | * setup of an entry with the new MSI irq. A negative return value indicates |
385 | * of an entry zero with the new MSI irq or non-zero for otherwise. | 358 | * an error, and a positive return value indicates the number of interrupts |
386 | **/ | 359 | * which could have been allocated. |
387 | static int msi_capability_init(struct pci_dev *dev) | 360 | */ |
361 | static int msi_capability_init(struct pci_dev *dev, int nvec) | ||
388 | { | 362 | { |
389 | struct msi_desc *entry; | 363 | struct msi_desc *entry; |
390 | int pos, ret; | 364 | int pos, ret; |
391 | u16 control; | 365 | u16 control; |
366 | unsigned mask; | ||
392 | 367 | ||
393 | msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */ | 368 | msi_set_enable(dev, 0); /* Ensure msi is disabled as I set it up */ |
394 | 369 | ||
395 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | 370 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); |
396 | pci_read_config_word(dev, msi_control_reg(pos), &control); | 371 | pci_read_config_word(dev, msi_control_reg(pos), &control); |
397 | /* MSI Entry Initialization */ | 372 | /* MSI Entry Initialization */ |
398 | entry = alloc_msi_entry(); | 373 | entry = alloc_msi_entry(dev); |
399 | if (!entry) | 374 | if (!entry) |
400 | return -ENOMEM; | 375 | return -ENOMEM; |
401 | 376 | ||
402 | entry->msi_attrib.type = PCI_CAP_ID_MSI; | 377 | entry->msi_attrib.is_msix = 0; |
403 | entry->msi_attrib.is_64 = is_64bit_address(control); | 378 | entry->msi_attrib.is_64 = is_64bit_address(control); |
404 | entry->msi_attrib.entry_nr = 0; | 379 | entry->msi_attrib.entry_nr = 0; |
405 | entry->msi_attrib.maskbit = is_mask_bit_support(control); | 380 | entry->msi_attrib.maskbit = is_mask_bit_support(control); |
406 | entry->msi_attrib.masked = 1; | ||
407 | entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ | 381 | entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ |
408 | entry->msi_attrib.pos = pos; | 382 | entry->msi_attrib.pos = pos; |
409 | entry->dev = dev; | 383 | |
410 | if (entry->msi_attrib.maskbit) { | 384 | entry->mask_pos = msi_mask_bits_reg(pos, entry->msi_attrib.is_64); |
411 | unsigned int base, maskbits, temp; | 385 | /* All MSIs are unmasked by default, Mask them all */ |
412 | 386 | if (entry->msi_attrib.maskbit) | |
413 | base = msi_mask_bits_reg(pos, entry->msi_attrib.is_64); | 387 | pci_read_config_dword(dev, entry->mask_pos, &entry->masked); |
414 | entry->mask_base = (void __iomem *)(long)base; | 388 | mask = msi_capable_mask(control); |
415 | 389 | msi_mask_irq(entry, mask, mask); | |
416 | /* All MSIs are unmasked by default, Mask them all */ | 390 | |
417 | pci_read_config_dword(dev, base, &maskbits); | ||
418 | temp = msi_mask((control & PCI_MSI_FLAGS_QMASK) >> 1); | ||
419 | maskbits |= temp; | ||
420 | pci_write_config_dword(dev, base, maskbits); | ||
421 | entry->msi_attrib.maskbits_mask = temp; | ||
422 | } | ||
423 | list_add_tail(&entry->list, &dev->msi_list); | 391 | list_add_tail(&entry->list, &dev->msi_list); |
424 | 392 | ||
425 | /* Configure MSI capability structure */ | 393 | /* Configure MSI capability structure */ |
426 | ret = arch_setup_msi_irqs(dev, 1, PCI_CAP_ID_MSI); | 394 | ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI); |
427 | if (ret) { | 395 | if (ret) { |
428 | msi_free_irqs(dev); | 396 | msi_free_irqs(dev); |
429 | return ret; | 397 | return ret; |
@@ -476,26 +444,28 @@ static int msix_capability_init(struct pci_dev *dev, | |||
476 | 444 | ||
477 | /* MSI-X Table Initialization */ | 445 | /* MSI-X Table Initialization */ |
478 | for (i = 0; i < nvec; i++) { | 446 | for (i = 0; i < nvec; i++) { |
479 | entry = alloc_msi_entry(); | 447 | entry = alloc_msi_entry(dev); |
480 | if (!entry) | 448 | if (!entry) |
481 | break; | 449 | break; |
482 | 450 | ||
483 | j = entries[i].entry; | 451 | j = entries[i].entry; |
484 | entry->msi_attrib.type = PCI_CAP_ID_MSIX; | 452 | entry->msi_attrib.is_msix = 1; |
485 | entry->msi_attrib.is_64 = 1; | 453 | entry->msi_attrib.is_64 = 1; |
486 | entry->msi_attrib.entry_nr = j; | 454 | entry->msi_attrib.entry_nr = j; |
487 | entry->msi_attrib.maskbit = 1; | ||
488 | entry->msi_attrib.masked = 1; | ||
489 | entry->msi_attrib.default_irq = dev->irq; | 455 | entry->msi_attrib.default_irq = dev->irq; |
490 | entry->msi_attrib.pos = pos; | 456 | entry->msi_attrib.pos = pos; |
491 | entry->dev = dev; | ||
492 | entry->mask_base = base; | 457 | entry->mask_base = base; |
458 | entry->masked = readl(base + j * PCI_MSIX_ENTRY_SIZE + | ||
459 | PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); | ||
460 | msix_mask_irq(entry, 1); | ||
493 | 461 | ||
494 | list_add_tail(&entry->list, &dev->msi_list); | 462 | list_add_tail(&entry->list, &dev->msi_list); |
495 | } | 463 | } |
496 | 464 | ||
497 | ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); | 465 | ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); |
498 | if (ret) { | 466 | if (ret < 0) { |
467 | /* If we had some success report the number of irqs | ||
468 | * we succeeded in setting up. */ | ||
499 | int avail = 0; | 469 | int avail = 0; |
500 | list_for_each_entry(entry, &dev->msi_list, list) { | 470 | list_for_each_entry(entry, &dev->msi_list, list) { |
501 | if (entry->irq != 0) { | 471 | if (entry->irq != 0) { |
@@ -503,14 +473,13 @@ static int msix_capability_init(struct pci_dev *dev, | |||
503 | } | 473 | } |
504 | } | 474 | } |
505 | 475 | ||
506 | msi_free_irqs(dev); | 476 | if (avail != 0) |
477 | ret = avail; | ||
478 | } | ||
507 | 479 | ||
508 | /* If we had some success report the number of irqs | 480 | if (ret) { |
509 | * we succeeded in setting up. | 481 | msi_free_irqs(dev); |
510 | */ | 482 | return ret; |
511 | if (avail == 0) | ||
512 | avail = ret; | ||
513 | return avail; | ||
514 | } | 483 | } |
515 | 484 | ||
516 | i = 0; | 485 | i = 0; |
@@ -575,39 +544,54 @@ static int pci_msi_check_device(struct pci_dev* dev, int nvec, int type) | |||
575 | } | 544 | } |
576 | 545 | ||
577 | /** | 546 | /** |
578 | * pci_enable_msi - configure device's MSI capability structure | 547 | * pci_enable_msi_block - configure device's MSI capability structure |
579 | * @dev: pointer to the pci_dev data structure of MSI device function | 548 | * @dev: device to configure |
549 | * @nvec: number of interrupts to configure | ||
580 | * | 550 | * |
581 | * Setup the MSI capability structure of device function with | 551 | * Allocate IRQs for a device with the MSI capability. |
582 | * a single MSI irq upon its software driver call to request for | 552 | * This function returns a negative errno if an error occurs. If it |
583 | * MSI mode enabled on its hardware device function. A return of zero | 553 | * is unable to allocate the number of interrupts requested, it returns |
584 | * indicates the successful setup of an entry zero with the new MSI | 554 | * the number of interrupts it might be able to allocate. If it successfully |
585 | * irq or non-zero for otherwise. | 555 | * allocates at least the number of interrupts requested, it returns 0 and |
586 | **/ | 556 | * updates the @dev's irq member to the lowest new interrupt number; the |
587 | int pci_enable_msi(struct pci_dev* dev) | 557 | * other interrupt numbers allocated to this device are consecutive. |
558 | */ | ||
559 | int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec) | ||
588 | { | 560 | { |
589 | int status; | 561 | int status, pos, maxvec; |
562 | u16 msgctl; | ||
590 | 563 | ||
591 | status = pci_msi_check_device(dev, 1, PCI_CAP_ID_MSI); | 564 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); |
565 | if (!pos) | ||
566 | return -EINVAL; | ||
567 | pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); | ||
568 | maxvec = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1); | ||
569 | if (nvec > maxvec) | ||
570 | return maxvec; | ||
571 | |||
572 | status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI); | ||
592 | if (status) | 573 | if (status) |
593 | return status; | 574 | return status; |
594 | 575 | ||
595 | WARN_ON(!!dev->msi_enabled); | 576 | WARN_ON(!!dev->msi_enabled); |
596 | 577 | ||
597 | /* Check whether driver already requested for MSI-X irqs */ | 578 | /* Check whether driver already requested MSI-X irqs */ |
598 | if (dev->msix_enabled) { | 579 | if (dev->msix_enabled) { |
599 | dev_info(&dev->dev, "can't enable MSI " | 580 | dev_info(&dev->dev, "can't enable MSI " |
600 | "(MSI-X already enabled)\n"); | 581 | "(MSI-X already enabled)\n"); |
601 | return -EINVAL; | 582 | return -EINVAL; |
602 | } | 583 | } |
603 | status = msi_capability_init(dev); | 584 | |
585 | status = msi_capability_init(dev, nvec); | ||
604 | return status; | 586 | return status; |
605 | } | 587 | } |
606 | EXPORT_SYMBOL(pci_enable_msi); | 588 | EXPORT_SYMBOL(pci_enable_msi_block); |
607 | 589 | ||
608 | void pci_msi_shutdown(struct pci_dev* dev) | 590 | void pci_msi_shutdown(struct pci_dev *dev) |
609 | { | 591 | { |
610 | struct msi_desc *entry; | 592 | struct msi_desc *desc; |
593 | u32 mask; | ||
594 | u16 ctrl; | ||
611 | 595 | ||
612 | if (!pci_msi_enable || !dev || !dev->msi_enabled) | 596 | if (!pci_msi_enable || !dev || !dev->msi_enabled) |
613 | return; | 597 | return; |
@@ -617,19 +601,15 @@ void pci_msi_shutdown(struct pci_dev* dev) | |||
617 | dev->msi_enabled = 0; | 601 | dev->msi_enabled = 0; |
618 | 602 | ||
619 | BUG_ON(list_empty(&dev->msi_list)); | 603 | BUG_ON(list_empty(&dev->msi_list)); |
620 | entry = list_entry(dev->msi_list.next, struct msi_desc, list); | 604 | desc = list_first_entry(&dev->msi_list, struct msi_desc, list); |
621 | /* Return the the pci reset with msi irqs unmasked */ | 605 | pci_read_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS, &ctrl); |
622 | if (entry->msi_attrib.maskbit) { | 606 | mask = msi_capable_mask(ctrl); |
623 | u32 mask = entry->msi_attrib.maskbits_mask; | 607 | msi_mask_irq(desc, mask, ~mask); |
624 | struct irq_desc *desc = irq_to_desc(dev->irq); | ||
625 | msi_set_mask_bits(desc, mask, ~mask); | ||
626 | } | ||
627 | if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) | ||
628 | return; | ||
629 | 608 | ||
630 | /* Restore dev->irq to its default pin-assertion irq */ | 609 | /* Restore dev->irq to its default pin-assertion irq */ |
631 | dev->irq = entry->msi_attrib.default_irq; | 610 | dev->irq = desc->msi_attrib.default_irq; |
632 | } | 611 | } |
612 | |||
633 | void pci_disable_msi(struct pci_dev* dev) | 613 | void pci_disable_msi(struct pci_dev* dev) |
634 | { | 614 | { |
635 | struct msi_desc *entry; | 615 | struct msi_desc *entry; |
@@ -640,7 +620,7 @@ void pci_disable_msi(struct pci_dev* dev) | |||
640 | pci_msi_shutdown(dev); | 620 | pci_msi_shutdown(dev); |
641 | 621 | ||
642 | entry = list_entry(dev->msi_list.next, struct msi_desc, list); | 622 | entry = list_entry(dev->msi_list.next, struct msi_desc, list); |
643 | if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) | 623 | if (entry->msi_attrib.is_msix) |
644 | return; | 624 | return; |
645 | 625 | ||
646 | msi_free_irqs(dev); | 626 | msi_free_irqs(dev); |
@@ -652,14 +632,18 @@ static int msi_free_irqs(struct pci_dev* dev) | |||
652 | struct msi_desc *entry, *tmp; | 632 | struct msi_desc *entry, *tmp; |
653 | 633 | ||
654 | list_for_each_entry(entry, &dev->msi_list, list) { | 634 | list_for_each_entry(entry, &dev->msi_list, list) { |
655 | if (entry->irq) | 635 | int i, nvec; |
656 | BUG_ON(irq_has_action(entry->irq)); | 636 | if (!entry->irq) |
637 | continue; | ||
638 | nvec = 1 << entry->msi_attrib.multiple; | ||
639 | for (i = 0; i < nvec; i++) | ||
640 | BUG_ON(irq_has_action(entry->irq + i)); | ||
657 | } | 641 | } |
658 | 642 | ||
659 | arch_teardown_msi_irqs(dev); | 643 | arch_teardown_msi_irqs(dev); |
660 | 644 | ||
661 | list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { | 645 | list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { |
662 | if (entry->msi_attrib.type == PCI_CAP_ID_MSIX) { | 646 | if (entry->msi_attrib.is_msix) { |
663 | writel(1, entry->mask_base + entry->msi_attrib.entry_nr | 647 | writel(1, entry->mask_base + entry->msi_attrib.entry_nr |
664 | * PCI_MSIX_ENTRY_SIZE | 648 | * PCI_MSIX_ENTRY_SIZE |
665 | + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); | 649 | + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); |
@@ -675,6 +659,23 @@ static int msi_free_irqs(struct pci_dev* dev) | |||
675 | } | 659 | } |
676 | 660 | ||
677 | /** | 661 | /** |
662 | * pci_msix_table_size - return the number of device's MSI-X table entries | ||
663 | * @dev: pointer to the pci_dev data structure of MSI-X device function | ||
664 | */ | ||
665 | int pci_msix_table_size(struct pci_dev *dev) | ||
666 | { | ||
667 | int pos; | ||
668 | u16 control; | ||
669 | |||
670 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | ||
671 | if (!pos) | ||
672 | return 0; | ||
673 | |||
674 | pci_read_config_word(dev, msi_control_reg(pos), &control); | ||
675 | return multi_msix_capable(control); | ||
676 | } | ||
677 | |||
678 | /** | ||
678 | * pci_enable_msix - configure device's MSI-X capability structure | 679 | * pci_enable_msix - configure device's MSI-X capability structure |
679 | * @dev: pointer to the pci_dev data structure of MSI-X device function | 680 | * @dev: pointer to the pci_dev data structure of MSI-X device function |
680 | * @entries: pointer to an array of MSI-X entries | 681 | * @entries: pointer to an array of MSI-X entries |
@@ -691,9 +692,8 @@ static int msi_free_irqs(struct pci_dev* dev) | |||
691 | **/ | 692 | **/ |
692 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | 693 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) |
693 | { | 694 | { |
694 | int status, pos, nr_entries; | 695 | int status, nr_entries; |
695 | int i, j; | 696 | int i, j; |
696 | u16 control; | ||
697 | 697 | ||
698 | if (!entries) | 698 | if (!entries) |
699 | return -EINVAL; | 699 | return -EINVAL; |
@@ -702,9 +702,7 @@ int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) | |||
702 | if (status) | 702 | if (status) |
703 | return status; | 703 | return status; |
704 | 704 | ||
705 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | 705 | nr_entries = pci_msix_table_size(dev); |
706 | pci_read_config_word(dev, msi_control_reg(pos), &control); | ||
707 | nr_entries = multi_msix_capable(control); | ||
708 | if (nvec > nr_entries) | 706 | if (nvec > nr_entries) |
709 | return -EINVAL; | 707 | return -EINVAL; |
710 | 708 | ||
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index 3898f5237144..71f4df2ef654 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h | |||
@@ -20,14 +20,8 @@ | |||
20 | #define msi_mask_bits_reg(base, is64bit) \ | 20 | #define msi_mask_bits_reg(base, is64bit) \ |
21 | ( (is64bit == 1) ? base+PCI_MSI_MASK_BIT : base+PCI_MSI_MASK_BIT-4) | 21 | ( (is64bit == 1) ? base+PCI_MSI_MASK_BIT : base+PCI_MSI_MASK_BIT-4) |
22 | #define msi_disable(control) control &= ~PCI_MSI_FLAGS_ENABLE | 22 | #define msi_disable(control) control &= ~PCI_MSI_FLAGS_ENABLE |
23 | #define multi_msi_capable(control) \ | ||
24 | (1 << ((control & PCI_MSI_FLAGS_QMASK) >> 1)) | ||
25 | #define multi_msi_enable(control, num) \ | ||
26 | control |= (((num >> 1) << 4) & PCI_MSI_FLAGS_QSIZE); | ||
27 | #define is_64bit_address(control) (!!(control & PCI_MSI_FLAGS_64BIT)) | 23 | #define is_64bit_address(control) (!!(control & PCI_MSI_FLAGS_64BIT)) |
28 | #define is_mask_bit_support(control) (!!(control & PCI_MSI_FLAGS_MASKBIT)) | 24 | #define is_mask_bit_support(control) (!!(control & PCI_MSI_FLAGS_MASKBIT)) |
29 | #define msi_enable(control, num) multi_msi_enable(control, num); \ | ||
30 | control |= PCI_MSI_FLAGS_ENABLE | ||
31 | 25 | ||
32 | #define msix_table_offset_reg(base) (base + 0x04) | 26 | #define msix_table_offset_reg(base) (base + 0x04) |
33 | #define msix_pba_offset_reg(base) (base + 0x08) | 27 | #define msix_pba_offset_reg(base) (base + 0x08) |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index deea8a187eb8..fac5eddcefd2 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -18,221 +18,6 @@ | |||
18 | #include <linux/pci-acpi.h> | 18 | #include <linux/pci-acpi.h> |
19 | #include "pci.h" | 19 | #include "pci.h" |
20 | 20 | ||
21 | struct acpi_osc_data { | ||
22 | acpi_handle handle; | ||
23 | u32 support_set; | ||
24 | u32 control_set; | ||
25 | u32 control_query; | ||
26 | int is_queried; | ||
27 | struct list_head sibiling; | ||
28 | }; | ||
29 | static LIST_HEAD(acpi_osc_data_list); | ||
30 | |||
31 | struct acpi_osc_args { | ||
32 | u32 capbuf[3]; | ||
33 | }; | ||
34 | |||
35 | static DEFINE_MUTEX(pci_acpi_lock); | ||
36 | |||
37 | static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) | ||
38 | { | ||
39 | struct acpi_osc_data *data; | ||
40 | |||
41 | list_for_each_entry(data, &acpi_osc_data_list, sibiling) { | ||
42 | if (data->handle == handle) | ||
43 | return data; | ||
44 | } | ||
45 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
46 | if (!data) | ||
47 | return NULL; | ||
48 | INIT_LIST_HEAD(&data->sibiling); | ||
49 | data->handle = handle; | ||
50 | list_add_tail(&data->sibiling, &acpi_osc_data_list); | ||
51 | return data; | ||
52 | } | ||
53 | |||
54 | static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, | ||
55 | 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; | ||
56 | |||
57 | static acpi_status acpi_run_osc(acpi_handle handle, | ||
58 | struct acpi_osc_args *osc_args, u32 *retval) | ||
59 | { | ||
60 | acpi_status status; | ||
61 | struct acpi_object_list input; | ||
62 | union acpi_object in_params[4]; | ||
63 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
64 | union acpi_object *out_obj; | ||
65 | u32 errors, flags = osc_args->capbuf[OSC_QUERY_TYPE]; | ||
66 | |||
67 | /* Setting up input parameters */ | ||
68 | input.count = 4; | ||
69 | input.pointer = in_params; | ||
70 | in_params[0].type = ACPI_TYPE_BUFFER; | ||
71 | in_params[0].buffer.length = 16; | ||
72 | in_params[0].buffer.pointer = OSC_UUID; | ||
73 | in_params[1].type = ACPI_TYPE_INTEGER; | ||
74 | in_params[1].integer.value = 1; | ||
75 | in_params[2].type = ACPI_TYPE_INTEGER; | ||
76 | in_params[2].integer.value = 3; | ||
77 | in_params[3].type = ACPI_TYPE_BUFFER; | ||
78 | in_params[3].buffer.length = 12; | ||
79 | in_params[3].buffer.pointer = (u8 *)osc_args->capbuf; | ||
80 | |||
81 | status = acpi_evaluate_object(handle, "_OSC", &input, &output); | ||
82 | if (ACPI_FAILURE(status)) | ||
83 | return status; | ||
84 | |||
85 | if (!output.length) | ||
86 | return AE_NULL_OBJECT; | ||
87 | |||
88 | out_obj = output.pointer; | ||
89 | if (out_obj->type != ACPI_TYPE_BUFFER) { | ||
90 | printk(KERN_DEBUG "Evaluate _OSC returns wrong type\n"); | ||
91 | status = AE_TYPE; | ||
92 | goto out_kfree; | ||
93 | } | ||
94 | /* Need to ignore the bit0 in result code */ | ||
95 | errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0); | ||
96 | if (errors) { | ||
97 | if (errors & OSC_REQUEST_ERROR) | ||
98 | printk(KERN_DEBUG "_OSC request fails\n"); | ||
99 | if (errors & OSC_INVALID_UUID_ERROR) | ||
100 | printk(KERN_DEBUG "_OSC invalid UUID\n"); | ||
101 | if (errors & OSC_INVALID_REVISION_ERROR) | ||
102 | printk(KERN_DEBUG "_OSC invalid revision\n"); | ||
103 | if (errors & OSC_CAPABILITIES_MASK_ERROR) { | ||
104 | if (flags & OSC_QUERY_ENABLE) | ||
105 | goto out_success; | ||
106 | printk(KERN_DEBUG "_OSC FW not grant req. control\n"); | ||
107 | status = AE_SUPPORT; | ||
108 | goto out_kfree; | ||
109 | } | ||
110 | status = AE_ERROR; | ||
111 | goto out_kfree; | ||
112 | } | ||
113 | out_success: | ||
114 | *retval = *((u32 *)(out_obj->buffer.pointer + 8)); | ||
115 | status = AE_OK; | ||
116 | |||
117 | out_kfree: | ||
118 | kfree(output.pointer); | ||
119 | return status; | ||
120 | } | ||
121 | |||
122 | static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data) | ||
123 | { | ||
124 | acpi_status status; | ||
125 | u32 support_set, result; | ||
126 | struct acpi_osc_args osc_args; | ||
127 | |||
128 | /* do _OSC query for all possible controls */ | ||
129 | support_set = osc_data->support_set | (flags & OSC_SUPPORT_MASKS); | ||
130 | osc_args.capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; | ||
131 | osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set; | ||
132 | osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; | ||
133 | |||
134 | status = acpi_run_osc(osc_data->handle, &osc_args, &result); | ||
135 | if (ACPI_SUCCESS(status)) { | ||
136 | osc_data->support_set = support_set; | ||
137 | osc_data->control_query = result; | ||
138 | osc_data->is_queried = 1; | ||
139 | } | ||
140 | |||
141 | return status; | ||
142 | } | ||
143 | |||
144 | /* | ||
145 | * pci_acpi_osc_support: Invoke _OSC indicating support for the given feature | ||
146 | * @flags: Bitmask of flags to support | ||
147 | * | ||
148 | * See the ACPI spec for the definition of the flags | ||
149 | */ | ||
150 | int pci_acpi_osc_support(acpi_handle handle, u32 flags) | ||
151 | { | ||
152 | acpi_status status; | ||
153 | acpi_handle tmp; | ||
154 | struct acpi_osc_data *osc_data; | ||
155 | int rc = 0; | ||
156 | |||
157 | status = acpi_get_handle(handle, "_OSC", &tmp); | ||
158 | if (ACPI_FAILURE(status)) | ||
159 | return -ENOTTY; | ||
160 | |||
161 | mutex_lock(&pci_acpi_lock); | ||
162 | osc_data = acpi_get_osc_data(handle); | ||
163 | if (!osc_data) { | ||
164 | printk(KERN_ERR "acpi osc data array is full\n"); | ||
165 | rc = -ENOMEM; | ||
166 | goto out; | ||
167 | } | ||
168 | |||
169 | __acpi_query_osc(flags, osc_data); | ||
170 | out: | ||
171 | mutex_unlock(&pci_acpi_lock); | ||
172 | return rc; | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * pci_osc_control_set - commit requested control to Firmware | ||
177 | * @handle: acpi_handle for the target ACPI object | ||
178 | * @flags: driver's requested control bits | ||
179 | * | ||
180 | * Attempt to take control from Firmware on requested control bits. | ||
181 | **/ | ||
182 | acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) | ||
183 | { | ||
184 | acpi_status status; | ||
185 | u32 control_req, control_set, result; | ||
186 | acpi_handle tmp; | ||
187 | struct acpi_osc_data *osc_data; | ||
188 | struct acpi_osc_args osc_args; | ||
189 | |||
190 | status = acpi_get_handle(handle, "_OSC", &tmp); | ||
191 | if (ACPI_FAILURE(status)) | ||
192 | return status; | ||
193 | |||
194 | mutex_lock(&pci_acpi_lock); | ||
195 | osc_data = acpi_get_osc_data(handle); | ||
196 | if (!osc_data) { | ||
197 | printk(KERN_ERR "acpi osc data array is full\n"); | ||
198 | status = AE_ERROR; | ||
199 | goto out; | ||
200 | } | ||
201 | |||
202 | control_req = (flags & OSC_CONTROL_MASKS); | ||
203 | if (!control_req) { | ||
204 | status = AE_TYPE; | ||
205 | goto out; | ||
206 | } | ||
207 | |||
208 | /* No need to evaluate _OSC if the control was already granted. */ | ||
209 | if ((osc_data->control_set & control_req) == control_req) | ||
210 | goto out; | ||
211 | |||
212 | if (!osc_data->is_queried) { | ||
213 | status = __acpi_query_osc(osc_data->support_set, osc_data); | ||
214 | if (ACPI_FAILURE(status)) | ||
215 | goto out; | ||
216 | } | ||
217 | |||
218 | if ((osc_data->control_query & control_req) != control_req) { | ||
219 | status = AE_SUPPORT; | ||
220 | goto out; | ||
221 | } | ||
222 | |||
223 | control_set = osc_data->control_set | control_req; | ||
224 | osc_args.capbuf[OSC_QUERY_TYPE] = 0; | ||
225 | osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set; | ||
226 | osc_args.capbuf[OSC_CONTROL_TYPE] = control_set; | ||
227 | status = acpi_run_osc(handle, &osc_args, &result); | ||
228 | if (ACPI_SUCCESS(status)) | ||
229 | osc_data->control_set = result; | ||
230 | out: | ||
231 | mutex_unlock(&pci_acpi_lock); | ||
232 | return status; | ||
233 | } | ||
234 | EXPORT_SYMBOL(pci_osc_control_set); | ||
235 | |||
236 | /* | 21 | /* |
237 | * _SxD returns the D-state with the highest power | 22 | * _SxD returns the D-state with the highest power |
238 | * (lowest D-state number) supported in the S-state "x". | 23 | * (lowest D-state number) supported in the S-state "x". |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 267de88551c9..c0cbbb5a245e 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -99,6 +99,52 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) | |||
99 | } | 99 | } |
100 | static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); | 100 | static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); |
101 | 101 | ||
102 | /** | ||
103 | * store_remove_id - remove a PCI device ID from this driver | ||
104 | * @driver: target device driver | ||
105 | * @buf: buffer for scanning device ID data | ||
106 | * @count: input size | ||
107 | * | ||
108 | * Removes a dynamic pci device ID to this driver. | ||
109 | */ | ||
110 | static ssize_t | ||
111 | store_remove_id(struct device_driver *driver, const char *buf, size_t count) | ||
112 | { | ||
113 | struct pci_dynid *dynid, *n; | ||
114 | struct pci_driver *pdrv = to_pci_driver(driver); | ||
115 | __u32 vendor, device, subvendor = PCI_ANY_ID, | ||
116 | subdevice = PCI_ANY_ID, class = 0, class_mask = 0; | ||
117 | int fields = 0; | ||
118 | int retval = -ENODEV; | ||
119 | |||
120 | fields = sscanf(buf, "%x %x %x %x %x %x", | ||
121 | &vendor, &device, &subvendor, &subdevice, | ||
122 | &class, &class_mask); | ||
123 | if (fields < 2) | ||
124 | return -EINVAL; | ||
125 | |||
126 | spin_lock(&pdrv->dynids.lock); | ||
127 | list_for_each_entry_safe(dynid, n, &pdrv->dynids.list, node) { | ||
128 | struct pci_device_id *id = &dynid->id; | ||
129 | if ((id->vendor == vendor) && | ||
130 | (id->device == device) && | ||
131 | (subvendor == PCI_ANY_ID || id->subvendor == subvendor) && | ||
132 | (subdevice == PCI_ANY_ID || id->subdevice == subdevice) && | ||
133 | !((id->class ^ class) & class_mask)) { | ||
134 | list_del(&dynid->node); | ||
135 | kfree(dynid); | ||
136 | retval = 0; | ||
137 | break; | ||
138 | } | ||
139 | } | ||
140 | spin_unlock(&pdrv->dynids.lock); | ||
141 | |||
142 | if (retval) | ||
143 | return retval; | ||
144 | return count; | ||
145 | } | ||
146 | static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); | ||
147 | |||
102 | static void | 148 | static void |
103 | pci_free_dynids(struct pci_driver *drv) | 149 | pci_free_dynids(struct pci_driver *drv) |
104 | { | 150 | { |
@@ -125,6 +171,20 @@ static void pci_remove_newid_file(struct pci_driver *drv) | |||
125 | { | 171 | { |
126 | driver_remove_file(&drv->driver, &driver_attr_new_id); | 172 | driver_remove_file(&drv->driver, &driver_attr_new_id); |
127 | } | 173 | } |
174 | |||
175 | static int | ||
176 | pci_create_removeid_file(struct pci_driver *drv) | ||
177 | { | ||
178 | int error = 0; | ||
179 | if (drv->probe != NULL) | ||
180 | error = driver_create_file(&drv->driver,&driver_attr_remove_id); | ||
181 | return error; | ||
182 | } | ||
183 | |||
184 | static void pci_remove_removeid_file(struct pci_driver *drv) | ||
185 | { | ||
186 | driver_remove_file(&drv->driver, &driver_attr_remove_id); | ||
187 | } | ||
128 | #else /* !CONFIG_HOTPLUG */ | 188 | #else /* !CONFIG_HOTPLUG */ |
129 | static inline void pci_free_dynids(struct pci_driver *drv) {} | 189 | static inline void pci_free_dynids(struct pci_driver *drv) {} |
130 | static inline int pci_create_newid_file(struct pci_driver *drv) | 190 | static inline int pci_create_newid_file(struct pci_driver *drv) |
@@ -132,6 +192,11 @@ static inline int pci_create_newid_file(struct pci_driver *drv) | |||
132 | return 0; | 192 | return 0; |
133 | } | 193 | } |
134 | static inline void pci_remove_newid_file(struct pci_driver *drv) {} | 194 | static inline void pci_remove_newid_file(struct pci_driver *drv) {} |
195 | static inline int pci_create_removeid_file(struct pci_driver *drv) | ||
196 | { | ||
197 | return 0; | ||
198 | } | ||
199 | static inline void pci_remove_removeid_file(struct pci_driver *drv) {} | ||
135 | #endif | 200 | #endif |
136 | 201 | ||
137 | /** | 202 | /** |
@@ -899,13 +964,23 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner, | |||
899 | /* register with core */ | 964 | /* register with core */ |
900 | error = driver_register(&drv->driver); | 965 | error = driver_register(&drv->driver); |
901 | if (error) | 966 | if (error) |
902 | return error; | 967 | goto out; |
903 | 968 | ||
904 | error = pci_create_newid_file(drv); | 969 | error = pci_create_newid_file(drv); |
905 | if (error) | 970 | if (error) |
906 | driver_unregister(&drv->driver); | 971 | goto out_newid; |
907 | 972 | ||
973 | error = pci_create_removeid_file(drv); | ||
974 | if (error) | ||
975 | goto out_removeid; | ||
976 | out: | ||
908 | return error; | 977 | return error; |
978 | |||
979 | out_removeid: | ||
980 | pci_remove_newid_file(drv); | ||
981 | out_newid: | ||
982 | driver_unregister(&drv->driver); | ||
983 | goto out; | ||
909 | } | 984 | } |
910 | 985 | ||
911 | /** | 986 | /** |
@@ -921,6 +996,7 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner, | |||
921 | void | 996 | void |
922 | pci_unregister_driver(struct pci_driver *drv) | 997 | pci_unregister_driver(struct pci_driver *drv) |
923 | { | 998 | { |
999 | pci_remove_removeid_file(drv); | ||
924 | pci_remove_newid_file(drv); | 1000 | pci_remove_newid_file(drv); |
925 | driver_unregister(&drv->driver); | 1001 | driver_unregister(&drv->driver); |
926 | pci_free_dynids(drv); | 1002 | pci_free_dynids(drv); |
@@ -1020,6 +1096,7 @@ struct bus_type pci_bus_type = { | |||
1020 | .remove = pci_device_remove, | 1096 | .remove = pci_device_remove, |
1021 | .shutdown = pci_device_shutdown, | 1097 | .shutdown = pci_device_shutdown, |
1022 | .dev_attrs = pci_dev_attrs, | 1098 | .dev_attrs = pci_dev_attrs, |
1099 | .bus_attrs = pci_bus_attrs, | ||
1023 | .pm = PCI_PM_OPS_PTR, | 1100 | .pm = PCI_PM_OPS_PTR, |
1024 | }; | 1101 | }; |
1025 | 1102 | ||
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index dfc4e0ddf241..e9a8706a6401 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -219,6 +219,83 @@ msi_bus_store(struct device *dev, struct device_attribute *attr, | |||
219 | return count; | 219 | return count; |
220 | } | 220 | } |
221 | 221 | ||
222 | #ifdef CONFIG_HOTPLUG | ||
223 | static DEFINE_MUTEX(pci_remove_rescan_mutex); | ||
224 | static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf, | ||
225 | size_t count) | ||
226 | { | ||
227 | unsigned long val; | ||
228 | struct pci_bus *b = NULL; | ||
229 | |||
230 | if (strict_strtoul(buf, 0, &val) < 0) | ||
231 | return -EINVAL; | ||
232 | |||
233 | if (val) { | ||
234 | mutex_lock(&pci_remove_rescan_mutex); | ||
235 | while ((b = pci_find_next_bus(b)) != NULL) | ||
236 | pci_rescan_bus(b); | ||
237 | mutex_unlock(&pci_remove_rescan_mutex); | ||
238 | } | ||
239 | return count; | ||
240 | } | ||
241 | |||
242 | struct bus_attribute pci_bus_attrs[] = { | ||
243 | __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store), | ||
244 | __ATTR_NULL | ||
245 | }; | ||
246 | |||
247 | static ssize_t | ||
248 | dev_rescan_store(struct device *dev, struct device_attribute *attr, | ||
249 | const char *buf, size_t count) | ||
250 | { | ||
251 | unsigned long val; | ||
252 | struct pci_dev *pdev = to_pci_dev(dev); | ||
253 | |||
254 | if (strict_strtoul(buf, 0, &val) < 0) | ||
255 | return -EINVAL; | ||
256 | |||
257 | if (val) { | ||
258 | mutex_lock(&pci_remove_rescan_mutex); | ||
259 | pci_rescan_bus(pdev->bus); | ||
260 | mutex_unlock(&pci_remove_rescan_mutex); | ||
261 | } | ||
262 | return count; | ||
263 | } | ||
264 | |||
265 | static void remove_callback(struct device *dev) | ||
266 | { | ||
267 | struct pci_dev *pdev = to_pci_dev(dev); | ||
268 | |||
269 | mutex_lock(&pci_remove_rescan_mutex); | ||
270 | pci_remove_bus_device(pdev); | ||
271 | mutex_unlock(&pci_remove_rescan_mutex); | ||
272 | } | ||
273 | |||
274 | static ssize_t | ||
275 | remove_store(struct device *dev, struct device_attribute *dummy, | ||
276 | const char *buf, size_t count) | ||
277 | { | ||
278 | int ret = 0; | ||
279 | unsigned long val; | ||
280 | struct pci_dev *pdev = to_pci_dev(dev); | ||
281 | |||
282 | if (strict_strtoul(buf, 0, &val) < 0) | ||
283 | return -EINVAL; | ||
284 | |||
285 | if (pci_is_root_bus(pdev->bus)) | ||
286 | return -EBUSY; | ||
287 | |||
288 | /* An attribute cannot be unregistered by one of its own methods, | ||
289 | * so we have to use this roundabout approach. | ||
290 | */ | ||
291 | if (val) | ||
292 | ret = device_schedule_callback(dev, remove_callback); | ||
293 | if (ret) | ||
294 | count = ret; | ||
295 | return count; | ||
296 | } | ||
297 | #endif | ||
298 | |||
222 | struct device_attribute pci_dev_attrs[] = { | 299 | struct device_attribute pci_dev_attrs[] = { |
223 | __ATTR_RO(resource), | 300 | __ATTR_RO(resource), |
224 | __ATTR_RO(vendor), | 301 | __ATTR_RO(vendor), |
@@ -237,10 +314,25 @@ struct device_attribute pci_dev_attrs[] = { | |||
237 | __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), | 314 | __ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), |
238 | broken_parity_status_show,broken_parity_status_store), | 315 | broken_parity_status_show,broken_parity_status_store), |
239 | __ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store), | 316 | __ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store), |
317 | #ifdef CONFIG_HOTPLUG | ||
318 | __ATTR(remove, (S_IWUSR|S_IWGRP), NULL, remove_store), | ||
319 | __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_rescan_store), | ||
320 | #endif | ||
240 | __ATTR_NULL, | 321 | __ATTR_NULL, |
241 | }; | 322 | }; |
242 | 323 | ||
243 | static ssize_t | 324 | static ssize_t |
325 | boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
326 | { | ||
327 | struct pci_dev *pdev = to_pci_dev(dev); | ||
328 | |||
329 | return sprintf(buf, "%u\n", | ||
330 | !!(pdev->resource[PCI_ROM_RESOURCE].flags & | ||
331 | IORESOURCE_ROM_SHADOW)); | ||
332 | } | ||
333 | struct device_attribute vga_attr = __ATTR_RO(boot_vga); | ||
334 | |||
335 | static ssize_t | ||
244 | pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, | 336 | pci_read_config(struct kobject *kobj, struct bin_attribute *bin_attr, |
245 | char *buf, loff_t off, size_t count) | 337 | char *buf, loff_t off, size_t count) |
246 | { | 338 | { |
@@ -493,6 +585,19 @@ pci_mmap_legacy_io(struct kobject *kobj, struct bin_attribute *attr, | |||
493 | } | 585 | } |
494 | 586 | ||
495 | /** | 587 | /** |
588 | * pci_adjust_legacy_attr - adjustment of legacy file attributes | ||
589 | * @b: bus to create files under | ||
590 | * @mmap_type: I/O port or memory | ||
591 | * | ||
592 | * Stub implementation. Can be overridden by arch if necessary. | ||
593 | */ | ||
594 | void __weak | ||
595 | pci_adjust_legacy_attr(struct pci_bus *b, enum pci_mmap_state mmap_type) | ||
596 | { | ||
597 | return; | ||
598 | } | ||
599 | |||
600 | /** | ||
496 | * pci_create_legacy_files - create legacy I/O port and memory files | 601 | * pci_create_legacy_files - create legacy I/O port and memory files |
497 | * @b: bus to create files under | 602 | * @b: bus to create files under |
498 | * | 603 | * |
@@ -518,6 +623,7 @@ void pci_create_legacy_files(struct pci_bus *b) | |||
518 | b->legacy_io->read = pci_read_legacy_io; | 623 | b->legacy_io->read = pci_read_legacy_io; |
519 | b->legacy_io->write = pci_write_legacy_io; | 624 | b->legacy_io->write = pci_write_legacy_io; |
520 | b->legacy_io->mmap = pci_mmap_legacy_io; | 625 | b->legacy_io->mmap = pci_mmap_legacy_io; |
626 | pci_adjust_legacy_attr(b, pci_mmap_io); | ||
521 | error = device_create_bin_file(&b->dev, b->legacy_io); | 627 | error = device_create_bin_file(&b->dev, b->legacy_io); |
522 | if (error) | 628 | if (error) |
523 | goto legacy_io_err; | 629 | goto legacy_io_err; |
@@ -528,6 +634,7 @@ void pci_create_legacy_files(struct pci_bus *b) | |||
528 | b->legacy_mem->size = 1024*1024; | 634 | b->legacy_mem->size = 1024*1024; |
529 | b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR; | 635 | b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR; |
530 | b->legacy_mem->mmap = pci_mmap_legacy_mem; | 636 | b->legacy_mem->mmap = pci_mmap_legacy_mem; |
637 | pci_adjust_legacy_attr(b, pci_mmap_mem); | ||
531 | error = device_create_bin_file(&b->dev, b->legacy_mem); | 638 | error = device_create_bin_file(&b->dev, b->legacy_mem); |
532 | if (error) | 639 | if (error) |
533 | goto legacy_mem_err; | 640 | goto legacy_mem_err; |
@@ -719,8 +826,8 @@ static int pci_create_resource_files(struct pci_dev *pdev) | |||
719 | return 0; | 826 | return 0; |
720 | } | 827 | } |
721 | #else /* !HAVE_PCI_MMAP */ | 828 | #else /* !HAVE_PCI_MMAP */ |
722 | static inline int pci_create_resource_files(struct pci_dev *dev) { return 0; } | 829 | int __weak pci_create_resource_files(struct pci_dev *dev) { return 0; } |
723 | static inline void pci_remove_resource_files(struct pci_dev *dev) { return; } | 830 | void __weak pci_remove_resource_files(struct pci_dev *dev) { return; } |
724 | #endif /* HAVE_PCI_MMAP */ | 831 | #endif /* HAVE_PCI_MMAP */ |
725 | 832 | ||
726 | /** | 833 | /** |
@@ -884,18 +991,27 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) | |||
884 | pdev->rom_attr = attr; | 991 | pdev->rom_attr = attr; |
885 | } | 992 | } |
886 | 993 | ||
994 | if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) { | ||
995 | retval = device_create_file(&pdev->dev, &vga_attr); | ||
996 | if (retval) | ||
997 | goto err_rom_file; | ||
998 | } | ||
999 | |||
887 | /* add platform-specific attributes */ | 1000 | /* add platform-specific attributes */ |
888 | retval = pcibios_add_platform_entries(pdev); | 1001 | retval = pcibios_add_platform_entries(pdev); |
889 | if (retval) | 1002 | if (retval) |
890 | goto err_rom_file; | 1003 | goto err_vga_file; |
891 | 1004 | ||
892 | /* add sysfs entries for various capabilities */ | 1005 | /* add sysfs entries for various capabilities */ |
893 | retval = pci_create_capabilities_sysfs(pdev); | 1006 | retval = pci_create_capabilities_sysfs(pdev); |
894 | if (retval) | 1007 | if (retval) |
895 | goto err_rom_file; | 1008 | goto err_vga_file; |
896 | 1009 | ||
897 | return 0; | 1010 | return 0; |
898 | 1011 | ||
1012 | err_vga_file: | ||
1013 | if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) | ||
1014 | device_remove_file(&pdev->dev, &vga_attr); | ||
899 | err_rom_file: | 1015 | err_rom_file: |
900 | if (rom_size) { | 1016 | if (rom_size) { |
901 | sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); | 1017 | sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 0195066251e5..fe7ac2cea7c9 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/pm_wakeup.h> | 20 | #include <linux/pm_wakeup.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ | 22 | #include <asm/dma.h> /* isa_dma_bridge_buggy */ |
23 | #include <linux/device.h> | ||
24 | #include <asm/setup.h> | ||
23 | #include "pci.h" | 25 | #include "pci.h" |
24 | 26 | ||
25 | unsigned int pci_pm_d3_delay = PCI_PM_D3_WAIT; | 27 | unsigned int pci_pm_d3_delay = PCI_PM_D3_WAIT; |
@@ -677,6 +679,8 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) | |||
677 | 679 | ||
678 | EXPORT_SYMBOL(pci_choose_state); | 680 | EXPORT_SYMBOL(pci_choose_state); |
679 | 681 | ||
682 | #define PCI_EXP_SAVE_REGS 7 | ||
683 | |||
680 | static int pci_save_pcie_state(struct pci_dev *dev) | 684 | static int pci_save_pcie_state(struct pci_dev *dev) |
681 | { | 685 | { |
682 | int pos, i = 0; | 686 | int pos, i = 0; |
@@ -689,7 +693,7 @@ static int pci_save_pcie_state(struct pci_dev *dev) | |||
689 | 693 | ||
690 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); | 694 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP); |
691 | if (!save_state) { | 695 | if (!save_state) { |
692 | dev_err(&dev->dev, "buffer not found in %s\n", __FUNCTION__); | 696 | dev_err(&dev->dev, "buffer not found in %s\n", __func__); |
693 | return -ENOMEM; | 697 | return -ENOMEM; |
694 | } | 698 | } |
695 | cap = (u16 *)&save_state->data[0]; | 699 | cap = (u16 *)&save_state->data[0]; |
@@ -698,6 +702,9 @@ static int pci_save_pcie_state(struct pci_dev *dev) | |||
698 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]); | 702 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]); |
699 | pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); | 703 | pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]); |
700 | pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); | 704 | pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]); |
705 | pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]); | ||
706 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]); | ||
707 | pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]); | ||
701 | 708 | ||
702 | return 0; | 709 | return 0; |
703 | } | 710 | } |
@@ -718,6 +725,9 @@ static void pci_restore_pcie_state(struct pci_dev *dev) | |||
718 | pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]); | 725 | pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]); |
719 | pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]); | 726 | pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]); |
720 | pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]); | 727 | pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]); |
728 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]); | ||
729 | pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]); | ||
730 | pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]); | ||
721 | } | 731 | } |
722 | 732 | ||
723 | 733 | ||
@@ -732,7 +742,7 @@ static int pci_save_pcix_state(struct pci_dev *dev) | |||
732 | 742 | ||
733 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX); | 743 | save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX); |
734 | if (!save_state) { | 744 | if (!save_state) { |
735 | dev_err(&dev->dev, "buffer not found in %s\n", __FUNCTION__); | 745 | dev_err(&dev->dev, "buffer not found in %s\n", __func__); |
736 | return -ENOMEM; | 746 | return -ENOMEM; |
737 | } | 747 | } |
738 | 748 | ||
@@ -805,6 +815,7 @@ pci_restore_state(struct pci_dev *dev) | |||
805 | } | 815 | } |
806 | pci_restore_pcix_state(dev); | 816 | pci_restore_pcix_state(dev); |
807 | pci_restore_msi_state(dev); | 817 | pci_restore_msi_state(dev); |
818 | pci_restore_iov_state(dev); | ||
808 | 819 | ||
809 | return 0; | 820 | return 0; |
810 | } | 821 | } |
@@ -1401,7 +1412,8 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev) | |||
1401 | { | 1412 | { |
1402 | int error; | 1413 | int error; |
1403 | 1414 | ||
1404 | error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_EXP, 4 * sizeof(u16)); | 1415 | error = pci_add_cap_save_buffer(dev, PCI_CAP_ID_EXP, |
1416 | PCI_EXP_SAVE_REGS * sizeof(u16)); | ||
1405 | if (error) | 1417 | if (error) |
1406 | dev_err(&dev->dev, | 1418 | dev_err(&dev->dev, |
1407 | "unable to preallocate PCI Express save buffer\n"); | 1419 | "unable to preallocate PCI Express save buffer\n"); |
@@ -1472,7 +1484,7 @@ pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge) | |||
1472 | if (!pin) | 1484 | if (!pin) |
1473 | return -1; | 1485 | return -1; |
1474 | 1486 | ||
1475 | while (dev->bus->self) { | 1487 | while (dev->bus->parent) { |
1476 | pin = pci_swizzle_interrupt_pin(dev, pin); | 1488 | pin = pci_swizzle_interrupt_pin(dev, pin); |
1477 | dev = dev->bus->self; | 1489 | dev = dev->bus->self; |
1478 | } | 1490 | } |
@@ -1492,7 +1504,7 @@ u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp) | |||
1492 | { | 1504 | { |
1493 | u8 pin = *pinp; | 1505 | u8 pin = *pinp; |
1494 | 1506 | ||
1495 | while (dev->bus->self) { | 1507 | while (dev->bus->parent) { |
1496 | pin = pci_swizzle_interrupt_pin(dev, pin); | 1508 | pin = pci_swizzle_interrupt_pin(dev, pin); |
1497 | dev = dev->bus->self; | 1509 | dev = dev->bus->self; |
1498 | } | 1510 | } |
@@ -2016,18 +2028,24 @@ static int __pcie_flr(struct pci_dev *dev, int probe) | |||
2016 | pci_block_user_cfg_access(dev); | 2028 | pci_block_user_cfg_access(dev); |
2017 | 2029 | ||
2018 | /* Wait for Transaction Pending bit clean */ | 2030 | /* Wait for Transaction Pending bit clean */ |
2031 | pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); | ||
2032 | if (!(status & PCI_EXP_DEVSTA_TRPND)) | ||
2033 | goto transaction_done; | ||
2034 | |||
2019 | msleep(100); | 2035 | msleep(100); |
2020 | pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); | 2036 | pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); |
2021 | if (status & PCI_EXP_DEVSTA_TRPND) { | 2037 | if (!(status & PCI_EXP_DEVSTA_TRPND)) |
2022 | dev_info(&dev->dev, "Busy after 100ms while trying to reset; " | 2038 | goto transaction_done; |
2039 | |||
2040 | dev_info(&dev->dev, "Busy after 100ms while trying to reset; " | ||
2023 | "sleeping for 1 second\n"); | 2041 | "sleeping for 1 second\n"); |
2024 | ssleep(1); | 2042 | ssleep(1); |
2025 | pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); | 2043 | pci_read_config_word(dev, exppos + PCI_EXP_DEVSTA, &status); |
2026 | if (status & PCI_EXP_DEVSTA_TRPND) | 2044 | if (status & PCI_EXP_DEVSTA_TRPND) |
2027 | dev_info(&dev->dev, "Still busy after 1s; " | 2045 | dev_info(&dev->dev, "Still busy after 1s; " |
2028 | "proceeding with reset anyway\n"); | 2046 | "proceeding with reset anyway\n"); |
2029 | } | ||
2030 | 2047 | ||
2048 | transaction_done: | ||
2031 | pci_write_config_word(dev, exppos + PCI_EXP_DEVCTL, | 2049 | pci_write_config_word(dev, exppos + PCI_EXP_DEVCTL, |
2032 | PCI_EXP_DEVCTL_BCR_FLR); | 2050 | PCI_EXP_DEVCTL_BCR_FLR); |
2033 | mdelay(100); | 2051 | mdelay(100); |
@@ -2054,18 +2072,24 @@ static int __pci_af_flr(struct pci_dev *dev, int probe) | |||
2054 | pci_block_user_cfg_access(dev); | 2072 | pci_block_user_cfg_access(dev); |
2055 | 2073 | ||
2056 | /* Wait for Transaction Pending bit clean */ | 2074 | /* Wait for Transaction Pending bit clean */ |
2075 | pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status); | ||
2076 | if (!(status & PCI_AF_STATUS_TP)) | ||
2077 | goto transaction_done; | ||
2078 | |||
2057 | msleep(100); | 2079 | msleep(100); |
2058 | pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status); | 2080 | pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status); |
2059 | if (status & PCI_AF_STATUS_TP) { | 2081 | if (!(status & PCI_AF_STATUS_TP)) |
2060 | dev_info(&dev->dev, "Busy after 100ms while trying to" | 2082 | goto transaction_done; |
2061 | " reset; sleeping for 1 second\n"); | 2083 | |
2062 | ssleep(1); | 2084 | dev_info(&dev->dev, "Busy after 100ms while trying to" |
2063 | pci_read_config_byte(dev, | 2085 | " reset; sleeping for 1 second\n"); |
2064 | cappos + PCI_AF_STATUS, &status); | 2086 | ssleep(1); |
2065 | if (status & PCI_AF_STATUS_TP) | 2087 | pci_read_config_byte(dev, cappos + PCI_AF_STATUS, &status); |
2066 | dev_info(&dev->dev, "Still busy after 1s; " | 2088 | if (status & PCI_AF_STATUS_TP) |
2067 | "proceeding with reset anyway\n"); | 2089 | dev_info(&dev->dev, "Still busy after 1s; " |
2068 | } | 2090 | "proceeding with reset anyway\n"); |
2091 | |||
2092 | transaction_done: | ||
2069 | pci_write_config_byte(dev, cappos + PCI_AF_CTRL, PCI_AF_CTRL_FLR); | 2093 | pci_write_config_byte(dev, cappos + PCI_AF_CTRL, PCI_AF_CTRL_FLR); |
2070 | mdelay(100); | 2094 | mdelay(100); |
2071 | 2095 | ||
@@ -2334,18 +2358,140 @@ int pci_select_bars(struct pci_dev *dev, unsigned long flags) | |||
2334 | */ | 2358 | */ |
2335 | int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type) | 2359 | int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type) |
2336 | { | 2360 | { |
2361 | int reg; | ||
2362 | |||
2337 | if (resno < PCI_ROM_RESOURCE) { | 2363 | if (resno < PCI_ROM_RESOURCE) { |
2338 | *type = pci_bar_unknown; | 2364 | *type = pci_bar_unknown; |
2339 | return PCI_BASE_ADDRESS_0 + 4 * resno; | 2365 | return PCI_BASE_ADDRESS_0 + 4 * resno; |
2340 | } else if (resno == PCI_ROM_RESOURCE) { | 2366 | } else if (resno == PCI_ROM_RESOURCE) { |
2341 | *type = pci_bar_mem32; | 2367 | *type = pci_bar_mem32; |
2342 | return dev->rom_base_reg; | 2368 | return dev->rom_base_reg; |
2369 | } else if (resno < PCI_BRIDGE_RESOURCES) { | ||
2370 | /* device specific resource */ | ||
2371 | reg = pci_iov_resource_bar(dev, resno, type); | ||
2372 | if (reg) | ||
2373 | return reg; | ||
2343 | } | 2374 | } |
2344 | 2375 | ||
2345 | dev_err(&dev->dev, "BAR: invalid resource #%d\n", resno); | 2376 | dev_err(&dev->dev, "BAR: invalid resource #%d\n", resno); |
2346 | return 0; | 2377 | return 0; |
2347 | } | 2378 | } |
2348 | 2379 | ||
2380 | #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE | ||
2381 | static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0}; | ||
2382 | spinlock_t resource_alignment_lock = SPIN_LOCK_UNLOCKED; | ||
2383 | |||
2384 | /** | ||
2385 | * pci_specified_resource_alignment - get resource alignment specified by user. | ||
2386 | * @dev: the PCI device to get | ||
2387 | * | ||
2388 | * RETURNS: Resource alignment if it is specified. | ||
2389 | * Zero if it is not specified. | ||
2390 | */ | ||
2391 | resource_size_t pci_specified_resource_alignment(struct pci_dev *dev) | ||
2392 | { | ||
2393 | int seg, bus, slot, func, align_order, count; | ||
2394 | resource_size_t align = 0; | ||
2395 | char *p; | ||
2396 | |||
2397 | spin_lock(&resource_alignment_lock); | ||
2398 | p = resource_alignment_param; | ||
2399 | while (*p) { | ||
2400 | count = 0; | ||
2401 | if (sscanf(p, "%d%n", &align_order, &count) == 1 && | ||
2402 | p[count] == '@') { | ||
2403 | p += count + 1; | ||
2404 | } else { | ||
2405 | align_order = -1; | ||
2406 | } | ||
2407 | if (sscanf(p, "%x:%x:%x.%x%n", | ||
2408 | &seg, &bus, &slot, &func, &count) != 4) { | ||
2409 | seg = 0; | ||
2410 | if (sscanf(p, "%x:%x.%x%n", | ||
2411 | &bus, &slot, &func, &count) != 3) { | ||
2412 | /* Invalid format */ | ||
2413 | printk(KERN_ERR "PCI: Can't parse resource_alignment parameter: %s\n", | ||
2414 | p); | ||
2415 | break; | ||
2416 | } | ||
2417 | } | ||
2418 | p += count; | ||
2419 | if (seg == pci_domain_nr(dev->bus) && | ||
2420 | bus == dev->bus->number && | ||
2421 | slot == PCI_SLOT(dev->devfn) && | ||
2422 | func == PCI_FUNC(dev->devfn)) { | ||
2423 | if (align_order == -1) { | ||
2424 | align = PAGE_SIZE; | ||
2425 | } else { | ||
2426 | align = 1 << align_order; | ||
2427 | } | ||
2428 | /* Found */ | ||
2429 | break; | ||
2430 | } | ||
2431 | if (*p != ';' && *p != ',') { | ||
2432 | /* End of param or invalid format */ | ||
2433 | break; | ||
2434 | } | ||
2435 | p++; | ||
2436 | } | ||
2437 | spin_unlock(&resource_alignment_lock); | ||
2438 | return align; | ||
2439 | } | ||
2440 | |||
2441 | /** | ||
2442 | * pci_is_reassigndev - check if specified PCI is target device to reassign | ||
2443 | * @dev: the PCI device to check | ||
2444 | * | ||
2445 | * RETURNS: non-zero for PCI device is a target device to reassign, | ||
2446 | * or zero is not. | ||
2447 | */ | ||
2448 | int pci_is_reassigndev(struct pci_dev *dev) | ||
2449 | { | ||
2450 | return (pci_specified_resource_alignment(dev) != 0); | ||
2451 | } | ||
2452 | |||
2453 | ssize_t pci_set_resource_alignment_param(const char *buf, size_t count) | ||
2454 | { | ||
2455 | if (count > RESOURCE_ALIGNMENT_PARAM_SIZE - 1) | ||
2456 | count = RESOURCE_ALIGNMENT_PARAM_SIZE - 1; | ||
2457 | spin_lock(&resource_alignment_lock); | ||
2458 | strncpy(resource_alignment_param, buf, count); | ||
2459 | resource_alignment_param[count] = '\0'; | ||
2460 | spin_unlock(&resource_alignment_lock); | ||
2461 | return count; | ||
2462 | } | ||
2463 | |||
2464 | ssize_t pci_get_resource_alignment_param(char *buf, size_t size) | ||
2465 | { | ||
2466 | size_t count; | ||
2467 | spin_lock(&resource_alignment_lock); | ||
2468 | count = snprintf(buf, size, "%s", resource_alignment_param); | ||
2469 | spin_unlock(&resource_alignment_lock); | ||
2470 | return count; | ||
2471 | } | ||
2472 | |||
2473 | static ssize_t pci_resource_alignment_show(struct bus_type *bus, char *buf) | ||
2474 | { | ||
2475 | return pci_get_resource_alignment_param(buf, PAGE_SIZE); | ||
2476 | } | ||
2477 | |||
2478 | static ssize_t pci_resource_alignment_store(struct bus_type *bus, | ||
2479 | const char *buf, size_t count) | ||
2480 | { | ||
2481 | return pci_set_resource_alignment_param(buf, count); | ||
2482 | } | ||
2483 | |||
2484 | BUS_ATTR(resource_alignment, 0644, pci_resource_alignment_show, | ||
2485 | pci_resource_alignment_store); | ||
2486 | |||
2487 | static int __init pci_resource_alignment_sysfs_init(void) | ||
2488 | { | ||
2489 | return bus_create_file(&pci_bus_type, | ||
2490 | &bus_attr_resource_alignment); | ||
2491 | } | ||
2492 | |||
2493 | late_initcall(pci_resource_alignment_sysfs_init); | ||
2494 | |||
2349 | static void __devinit pci_no_domains(void) | 2495 | static void __devinit pci_no_domains(void) |
2350 | { | 2496 | { |
2351 | #ifdef CONFIG_PCI_DOMAINS | 2497 | #ifdef CONFIG_PCI_DOMAINS |
@@ -2394,6 +2540,9 @@ static int __init pci_setup(char *str) | |||
2394 | pci_cardbus_io_size = memparse(str + 9, &str); | 2540 | pci_cardbus_io_size = memparse(str + 9, &str); |
2395 | } else if (!strncmp(str, "cbmemsize=", 10)) { | 2541 | } else if (!strncmp(str, "cbmemsize=", 10)) { |
2396 | pci_cardbus_mem_size = memparse(str + 10, &str); | 2542 | pci_cardbus_mem_size = memparse(str + 10, &str); |
2543 | } else if (!strncmp(str, "resource_alignment=", 19)) { | ||
2544 | pci_set_resource_alignment_param(str + 19, | ||
2545 | strlen(str + 19)); | ||
2397 | } else { | 2546 | } else { |
2398 | printk(KERN_ERR "PCI: Unknown option `%s'\n", | 2547 | printk(KERN_ERR "PCI: Unknown option `%s'\n", |
2399 | str); | 2548 | str); |
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 149fff65891f..d03f6b99f292 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -1,6 +1,8 @@ | |||
1 | #ifndef DRIVERS_PCI_H | 1 | #ifndef DRIVERS_PCI_H |
2 | #define DRIVERS_PCI_H | 2 | #define DRIVERS_PCI_H |
3 | 3 | ||
4 | #include <linux/workqueue.h> | ||
5 | |||
4 | #define PCI_CFG_SPACE_SIZE 256 | 6 | #define PCI_CFG_SPACE_SIZE 256 |
5 | #define PCI_CFG_SPACE_EXP_SIZE 4096 | 7 | #define PCI_CFG_SPACE_EXP_SIZE 4096 |
6 | 8 | ||
@@ -135,6 +137,12 @@ extern int pcie_mch_quirk; | |||
135 | extern struct device_attribute pci_dev_attrs[]; | 137 | extern struct device_attribute pci_dev_attrs[]; |
136 | extern struct device_attribute dev_attr_cpuaffinity; | 138 | extern struct device_attribute dev_attr_cpuaffinity; |
137 | extern struct device_attribute dev_attr_cpulistaffinity; | 139 | extern struct device_attribute dev_attr_cpulistaffinity; |
140 | #ifdef CONFIG_HOTPLUG | ||
141 | extern struct bus_attribute pci_bus_attrs[]; | ||
142 | #else | ||
143 | #define pci_bus_attrs NULL | ||
144 | #endif | ||
145 | |||
138 | 146 | ||
139 | /** | 147 | /** |
140 | * pci_match_one_device - Tell if a PCI device structure has a matching | 148 | * pci_match_one_device - Tell if a PCI device structure has a matching |
@@ -177,6 +185,7 @@ enum pci_bar_type { | |||
177 | pci_bar_mem64, /* A 64-bit memory BAR */ | 185 | pci_bar_mem64, /* A 64-bit memory BAR */ |
178 | }; | 186 | }; |
179 | 187 | ||
188 | extern int pci_setup_device(struct pci_dev *dev); | ||
180 | extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, | 189 | extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, |
181 | struct resource *res, unsigned int reg); | 190 | struct resource *res, unsigned int reg); |
182 | extern int pci_resource_bar(struct pci_dev *dev, int resno, | 191 | extern int pci_resource_bar(struct pci_dev *dev, int resno, |
@@ -194,4 +203,60 @@ static inline int pci_ari_enabled(struct pci_bus *bus) | |||
194 | return bus->self && bus->self->ari_enabled; | 203 | return bus->self && bus->self->ari_enabled; |
195 | } | 204 | } |
196 | 205 | ||
206 | #ifdef CONFIG_PCI_QUIRKS | ||
207 | extern int pci_is_reassigndev(struct pci_dev *dev); | ||
208 | resource_size_t pci_specified_resource_alignment(struct pci_dev *dev); | ||
209 | extern void pci_disable_bridge_window(struct pci_dev *dev); | ||
210 | #endif | ||
211 | |||
212 | /* Single Root I/O Virtualization */ | ||
213 | struct pci_sriov { | ||
214 | int pos; /* capability position */ | ||
215 | int nres; /* number of resources */ | ||
216 | u32 cap; /* SR-IOV Capabilities */ | ||
217 | u16 ctrl; /* SR-IOV Control */ | ||
218 | u16 total; /* total VFs associated with the PF */ | ||
219 | u16 initial; /* initial VFs associated with the PF */ | ||
220 | u16 nr_virtfn; /* number of VFs available */ | ||
221 | u16 offset; /* first VF Routing ID offset */ | ||
222 | u16 stride; /* following VF stride */ | ||
223 | u32 pgsz; /* page size for BAR alignment */ | ||
224 | u8 link; /* Function Dependency Link */ | ||
225 | struct pci_dev *dev; /* lowest numbered PF */ | ||
226 | struct pci_dev *self; /* this PF */ | ||
227 | struct mutex lock; /* lock for VF bus */ | ||
228 | struct work_struct mtask; /* VF Migration task */ | ||
229 | u8 __iomem *mstate; /* VF Migration State Array */ | ||
230 | }; | ||
231 | |||
232 | #ifdef CONFIG_PCI_IOV | ||
233 | extern int pci_iov_init(struct pci_dev *dev); | ||
234 | extern void pci_iov_release(struct pci_dev *dev); | ||
235 | extern int pci_iov_resource_bar(struct pci_dev *dev, int resno, | ||
236 | enum pci_bar_type *type); | ||
237 | extern void pci_restore_iov_state(struct pci_dev *dev); | ||
238 | extern int pci_iov_bus_range(struct pci_bus *bus); | ||
239 | #else | ||
240 | static inline int pci_iov_init(struct pci_dev *dev) | ||
241 | { | ||
242 | return -ENODEV; | ||
243 | } | ||
244 | static inline void pci_iov_release(struct pci_dev *dev) | ||
245 | |||
246 | { | ||
247 | } | ||
248 | static inline int pci_iov_resource_bar(struct pci_dev *dev, int resno, | ||
249 | enum pci_bar_type *type) | ||
250 | { | ||
251 | return 0; | ||
252 | } | ||
253 | static inline void pci_restore_iov_state(struct pci_dev *dev) | ||
254 | { | ||
255 | } | ||
256 | static inline int pci_iov_bus_range(struct pci_bus *bus) | ||
257 | { | ||
258 | return 0; | ||
259 | } | ||
260 | #endif /* CONFIG_PCI_IOV */ | ||
261 | |||
197 | #endif /* DRIVERS_PCI_H */ | 262 | #endif /* DRIVERS_PCI_H */ |
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index e390707661dd..32ade5af927e 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c | |||
@@ -38,30 +38,13 @@ MODULE_AUTHOR(DRIVER_AUTHOR); | |||
38 | MODULE_DESCRIPTION(DRIVER_DESC); | 38 | MODULE_DESCRIPTION(DRIVER_DESC); |
39 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | 40 | ||
41 | static int __devinit aer_probe (struct pcie_device *dev, | 41 | static int __devinit aer_probe (struct pcie_device *dev); |
42 | const struct pcie_port_service_id *id ); | ||
43 | static void aer_remove(struct pcie_device *dev); | 42 | static void aer_remove(struct pcie_device *dev); |
44 | static int aer_suspend(struct pcie_device *dev, pm_message_t state) | ||
45 | {return 0;} | ||
46 | static int aer_resume(struct pcie_device *dev) {return 0;} | ||
47 | static pci_ers_result_t aer_error_detected(struct pci_dev *dev, | 43 | static pci_ers_result_t aer_error_detected(struct pci_dev *dev, |
48 | enum pci_channel_state error); | 44 | enum pci_channel_state error); |
49 | static void aer_error_resume(struct pci_dev *dev); | 45 | static void aer_error_resume(struct pci_dev *dev); |
50 | static pci_ers_result_t aer_root_reset(struct pci_dev *dev); | 46 | static pci_ers_result_t aer_root_reset(struct pci_dev *dev); |
51 | 47 | ||
52 | /* | ||
53 | * PCI Express bus's AER Root service driver data structure | ||
54 | */ | ||
55 | static struct pcie_port_service_id aer_id[] = { | ||
56 | { | ||
57 | .vendor = PCI_ANY_ID, | ||
58 | .device = PCI_ANY_ID, | ||
59 | .port_type = PCIE_RC_PORT, | ||
60 | .service_type = PCIE_PORT_SERVICE_AER, | ||
61 | }, | ||
62 | { /* end: all zeroes */ } | ||
63 | }; | ||
64 | |||
65 | static struct pci_error_handlers aer_error_handlers = { | 48 | static struct pci_error_handlers aer_error_handlers = { |
66 | .error_detected = aer_error_detected, | 49 | .error_detected = aer_error_detected, |
67 | .resume = aer_error_resume, | 50 | .resume = aer_error_resume, |
@@ -69,14 +52,12 @@ static struct pci_error_handlers aer_error_handlers = { | |||
69 | 52 | ||
70 | static struct pcie_port_service_driver aerdriver = { | 53 | static struct pcie_port_service_driver aerdriver = { |
71 | .name = "aer", | 54 | .name = "aer", |
72 | .id_table = &aer_id[0], | 55 | .port_type = PCIE_ANY_PORT, |
56 | .service = PCIE_PORT_SERVICE_AER, | ||
73 | 57 | ||
74 | .probe = aer_probe, | 58 | .probe = aer_probe, |
75 | .remove = aer_remove, | 59 | .remove = aer_remove, |
76 | 60 | ||
77 | .suspend = aer_suspend, | ||
78 | .resume = aer_resume, | ||
79 | |||
80 | .err_handler = &aer_error_handlers, | 61 | .err_handler = &aer_error_handlers, |
81 | 62 | ||
82 | .reset_link = aer_root_reset, | 63 | .reset_link = aer_root_reset, |
@@ -207,8 +188,7 @@ static void aer_remove(struct pcie_device *dev) | |||
207 | * | 188 | * |
208 | * Invoked when PCI Express bus loads AER service driver. | 189 | * Invoked when PCI Express bus loads AER service driver. |
209 | **/ | 190 | **/ |
210 | static int __devinit aer_probe (struct pcie_device *dev, | 191 | static int __devinit aer_probe (struct pcie_device *dev) |
211 | const struct pcie_port_service_id *id ) | ||
212 | { | 192 | { |
213 | int status; | 193 | int status; |
214 | struct aer_rpc *rpc; | 194 | struct aer_rpc *rpc; |
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index ebce26c37049..8edb2f300e8f 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c | |||
@@ -38,7 +38,7 @@ int aer_osc_setup(struct pcie_device *pciedev) | |||
38 | 38 | ||
39 | handle = acpi_find_root_bridge_handle(pdev); | 39 | handle = acpi_find_root_bridge_handle(pdev); |
40 | if (handle) { | 40 | if (handle) { |
41 | status = pci_osc_control_set(handle, | 41 | status = acpi_pci_osc_control_set(handle, |
42 | OSC_PCI_EXPRESS_AER_CONTROL | | 42 | OSC_PCI_EXPRESS_AER_CONTROL | |
43 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | 43 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); |
44 | } | 44 | } |
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 382575007382..307452f30035 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
@@ -351,21 +351,21 @@ static int find_aer_service_iter(struct device *device, void *data) | |||
351 | { | 351 | { |
352 | struct device_driver *driver; | 352 | struct device_driver *driver; |
353 | struct pcie_port_service_driver *service_driver; | 353 | struct pcie_port_service_driver *service_driver; |
354 | struct pcie_device *pcie_dev; | ||
355 | struct find_aer_service_data *result; | 354 | struct find_aer_service_data *result; |
356 | 355 | ||
357 | result = (struct find_aer_service_data *) data; | 356 | result = (struct find_aer_service_data *) data; |
358 | 357 | ||
359 | if (device->bus == &pcie_port_bus_type) { | 358 | if (device->bus == &pcie_port_bus_type) { |
360 | pcie_dev = to_pcie_device(device); | 359 | struct pcie_port_data *port_data; |
361 | if (pcie_dev->id.port_type == PCIE_SW_DOWNSTREAM_PORT) | 360 | |
361 | port_data = pci_get_drvdata(to_pcie_device(device)->port); | ||
362 | if (port_data->port_type == PCIE_SW_DOWNSTREAM_PORT) | ||
362 | result->is_downstream = 1; | 363 | result->is_downstream = 1; |
363 | 364 | ||
364 | driver = device->driver; | 365 | driver = device->driver; |
365 | if (driver) { | 366 | if (driver) { |
366 | service_driver = to_service_driver(driver); | 367 | service_driver = to_service_driver(driver); |
367 | if (service_driver->id_table->service_type == | 368 | if (service_driver->service == PCIE_PORT_SERVICE_AER) { |
368 | PCIE_PORT_SERVICE_AER) { | ||
369 | result->aer_driver = service_driver; | 369 | result->aer_driver = service_driver; |
370 | return 1; | 370 | return 1; |
371 | } | 371 | } |
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index 2529f3f2ea5a..17ad53868f9f 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h | |||
@@ -25,19 +25,21 @@ | |||
25 | #define PCIE_CAPABILITIES_REG 0x2 | 25 | #define PCIE_CAPABILITIES_REG 0x2 |
26 | #define PCIE_SLOT_CAPABILITIES_REG 0x14 | 26 | #define PCIE_SLOT_CAPABILITIES_REG 0x14 |
27 | #define PCIE_PORT_DEVICE_MAXSERVICES 4 | 27 | #define PCIE_PORT_DEVICE_MAXSERVICES 4 |
28 | #define PCIE_PORT_MSI_VECTOR_MASK 0x1f | ||
29 | /* | ||
30 | * According to the PCI Express Base Specification 2.0, the indices of the MSI-X | ||
31 | * table entires used by port services must not exceed 31 | ||
32 | */ | ||
33 | #define PCIE_PORT_MAX_MSIX_ENTRIES 32 | ||
28 | 34 | ||
29 | #define get_descriptor_id(type, service) (((type - 4) << 4) | service) | 35 | #define get_descriptor_id(type, service) (((type - 4) << 4) | service) |
30 | 36 | ||
31 | struct pcie_port_device_ext { | ||
32 | int interrupt_mode; /* [0:INTx | 1:MSI | 2:MSI-X] */ | ||
33 | }; | ||
34 | |||
35 | extern struct bus_type pcie_port_bus_type; | 37 | extern struct bus_type pcie_port_bus_type; |
36 | extern int pcie_port_device_probe(struct pci_dev *dev); | 38 | extern int pcie_port_device_probe(struct pci_dev *dev); |
37 | extern int pcie_port_device_register(struct pci_dev *dev); | 39 | extern int pcie_port_device_register(struct pci_dev *dev); |
38 | #ifdef CONFIG_PM | 40 | #ifdef CONFIG_PM |
39 | extern int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state); | 41 | extern int pcie_port_device_suspend(struct device *dev); |
40 | extern int pcie_port_device_resume(struct pci_dev *dev); | 42 | extern int pcie_port_device_resume(struct device *dev); |
41 | #endif | 43 | #endif |
42 | extern void pcie_port_device_remove(struct pci_dev *dev); | 44 | extern void pcie_port_device_remove(struct pci_dev *dev); |
43 | extern int __must_check pcie_port_bus_register(void); | 45 | extern int __must_check pcie_port_bus_register(void); |
diff --git a/drivers/pci/pcie/portdrv_bus.c b/drivers/pci/pcie/portdrv_bus.c index eec89b767f9f..ef3a4eeaebb4 100644 --- a/drivers/pci/pcie/portdrv_bus.c +++ b/drivers/pci/pcie/portdrv_bus.c | |||
@@ -26,20 +26,22 @@ EXPORT_SYMBOL_GPL(pcie_port_bus_type); | |||
26 | static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) | 26 | static int pcie_port_bus_match(struct device *dev, struct device_driver *drv) |
27 | { | 27 | { |
28 | struct pcie_device *pciedev; | 28 | struct pcie_device *pciedev; |
29 | struct pcie_port_data *port_data; | ||
29 | struct pcie_port_service_driver *driver; | 30 | struct pcie_port_service_driver *driver; |
30 | 31 | ||
31 | if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type) | 32 | if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type) |
32 | return 0; | 33 | return 0; |
33 | 34 | ||
34 | pciedev = to_pcie_device(dev); | 35 | pciedev = to_pcie_device(dev); |
35 | driver = to_service_driver(drv); | 36 | driver = to_service_driver(drv); |
36 | if ( (driver->id_table->vendor != PCI_ANY_ID && | 37 | |
37 | driver->id_table->vendor != pciedev->id.vendor) || | 38 | if (driver->service != pciedev->service) |
38 | (driver->id_table->device != PCI_ANY_ID && | 39 | return 0; |
39 | driver->id_table->device != pciedev->id.device) || | 40 | |
40 | (driver->id_table->port_type != PCIE_ANY_PORT && | 41 | port_data = pci_get_drvdata(pciedev->port); |
41 | driver->id_table->port_type != pciedev->id.port_type) || | 42 | |
42 | driver->id_table->service_type != pciedev->id.service_type ) | 43 | if (driver->port_type != PCIE_ANY_PORT |
44 | && driver->port_type != port_data->port_type) | ||
43 | return 0; | 45 | return 0; |
44 | 46 | ||
45 | return 1; | 47 | return 1; |
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 8b3f8c18032f..e39982503863 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c | |||
@@ -15,10 +15,9 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/pcieport_if.h> | 16 | #include <linux/pcieport_if.h> |
17 | 17 | ||
18 | #include "../pci.h" | ||
18 | #include "portdrv.h" | 19 | #include "portdrv.h" |
19 | 20 | ||
20 | extern int pcie_mch_quirk; /* MSI-quirk Indicator */ | ||
21 | |||
22 | /** | 21 | /** |
23 | * release_pcie_device - free PCI Express port service device structure | 22 | * release_pcie_device - free PCI Express port service device structure |
24 | * @dev: Port service device to release | 23 | * @dev: Port service device to release |
@@ -31,26 +30,150 @@ static void release_pcie_device(struct device *dev) | |||
31 | kfree(to_pcie_device(dev)); | 30 | kfree(to_pcie_device(dev)); |
32 | } | 31 | } |
33 | 32 | ||
34 | static int is_msi_quirked(struct pci_dev *dev) | 33 | /** |
34 | * pcie_port_msix_add_entry - add entry to given array of MSI-X entries | ||
35 | * @entries: Array of MSI-X entries | ||
36 | * @new_entry: Index of the entry to add to the array | ||
37 | * @nr_entries: Number of entries aleady in the array | ||
38 | * | ||
39 | * Return value: Position of the added entry in the array | ||
40 | */ | ||
41 | static int pcie_port_msix_add_entry( | ||
42 | struct msix_entry *entries, int new_entry, int nr_entries) | ||
35 | { | 43 | { |
36 | int port_type, quirk = 0; | 44 | int j; |
45 | |||
46 | for (j = 0; j < nr_entries; j++) | ||
47 | if (entries[j].entry == new_entry) | ||
48 | return j; | ||
49 | |||
50 | entries[j].entry = new_entry; | ||
51 | return j; | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * pcie_port_enable_msix - try to set up MSI-X as interrupt mode for given port | ||
56 | * @dev: PCI Express port to handle | ||
57 | * @vectors: Array of interrupt vectors to populate | ||
58 | * @mask: Bitmask of port capabilities returned by get_port_device_capability() | ||
59 | * | ||
60 | * Return value: 0 on success, error code on failure | ||
61 | */ | ||
62 | static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask) | ||
63 | { | ||
64 | struct msix_entry *msix_entries; | ||
65 | int idx[PCIE_PORT_DEVICE_MAXSERVICES]; | ||
66 | int nr_entries, status, pos, i, nvec; | ||
37 | u16 reg16; | 67 | u16 reg16; |
68 | u32 reg32; | ||
38 | 69 | ||
39 | pci_read_config_word(dev, | 70 | nr_entries = pci_msix_table_size(dev); |
40 | pci_find_capability(dev, PCI_CAP_ID_EXP) + | 71 | if (!nr_entries) |
41 | PCIE_CAPABILITIES_REG, ®16); | 72 | return -EINVAL; |
42 | port_type = (reg16 >> 4) & PORT_TYPE_MASK; | 73 | if (nr_entries > PCIE_PORT_MAX_MSIX_ENTRIES) |
43 | switch(port_type) { | 74 | nr_entries = PCIE_PORT_MAX_MSIX_ENTRIES; |
44 | case PCIE_RC_PORT: | 75 | |
45 | if (pcie_mch_quirk == 1) | 76 | msix_entries = kzalloc(sizeof(*msix_entries) * nr_entries, GFP_KERNEL); |
46 | quirk = 1; | 77 | if (!msix_entries) |
47 | break; | 78 | return -ENOMEM; |
48 | case PCIE_SW_UPSTREAM_PORT: | 79 | |
49 | case PCIE_SW_DOWNSTREAM_PORT: | 80 | /* |
50 | default: | 81 | * Allocate as many entries as the port wants, so that we can check |
51 | break; | 82 | * which of them will be useful. Moreover, if nr_entries is correctly |
83 | * equal to the number of entries this port actually uses, we'll happily | ||
84 | * go through without any tricks. | ||
85 | */ | ||
86 | for (i = 0; i < nr_entries; i++) | ||
87 | msix_entries[i].entry = i; | ||
88 | |||
89 | status = pci_enable_msix(dev, msix_entries, nr_entries); | ||
90 | if (status) | ||
91 | goto Exit; | ||
92 | |||
93 | for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) | ||
94 | idx[i] = -1; | ||
95 | status = -EIO; | ||
96 | nvec = 0; | ||
97 | |||
98 | if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP)) { | ||
99 | int entry; | ||
100 | |||
101 | /* | ||
102 | * The code below follows the PCI Express Base Specification 2.0 | ||
103 | * stating in Section 6.1.6 that "PME and Hot-Plug Event | ||
104 | * interrupts (when both are implemented) always share the same | ||
105 | * MSI or MSI-X vector, as indicated by the Interrupt Message | ||
106 | * Number field in the PCI Express Capabilities register", where | ||
107 | * according to Section 7.8.2 of the specification "For MSI-X, | ||
108 | * the value in this field indicates which MSI-X Table entry is | ||
109 | * used to generate the interrupt message." | ||
110 | */ | ||
111 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | ||
112 | pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, ®16); | ||
113 | entry = (reg16 >> 9) & PCIE_PORT_MSI_VECTOR_MASK; | ||
114 | if (entry >= nr_entries) | ||
115 | goto Error; | ||
116 | |||
117 | i = pcie_port_msix_add_entry(msix_entries, entry, nvec); | ||
118 | if (i == nvec) | ||
119 | nvec++; | ||
120 | |||
121 | idx[PCIE_PORT_SERVICE_PME_SHIFT] = i; | ||
122 | idx[PCIE_PORT_SERVICE_HP_SHIFT] = i; | ||
123 | } | ||
124 | |||
125 | if (mask & PCIE_PORT_SERVICE_AER) { | ||
126 | int entry; | ||
127 | |||
128 | /* | ||
129 | * The code below follows Section 7.10.10 of the PCI Express | ||
130 | * Base Specification 2.0 stating that bits 31-27 of the Root | ||
131 | * Error Status Register contain a value indicating which of the | ||
132 | * MSI/MSI-X vectors assigned to the port is going to be used | ||
133 | * for AER, where "For MSI-X, the value in this register | ||
134 | * indicates which MSI-X Table entry is used to generate the | ||
135 | * interrupt message." | ||
136 | */ | ||
137 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | ||
138 | pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, ®32); | ||
139 | entry = reg32 >> 27; | ||
140 | if (entry >= nr_entries) | ||
141 | goto Error; | ||
142 | |||
143 | i = pcie_port_msix_add_entry(msix_entries, entry, nvec); | ||
144 | if (i == nvec) | ||
145 | nvec++; | ||
146 | |||
147 | idx[PCIE_PORT_SERVICE_AER_SHIFT] = i; | ||
52 | } | 148 | } |
53 | return quirk; | 149 | |
150 | /* | ||
151 | * If nvec is equal to the allocated number of entries, we can just use | ||
152 | * what we have. Otherwise, the port has some extra entries not for the | ||
153 | * services we know and we need to work around that. | ||
154 | */ | ||
155 | if (nvec == nr_entries) { | ||
156 | status = 0; | ||
157 | } else { | ||
158 | /* Drop the temporary MSI-X setup */ | ||
159 | pci_disable_msix(dev); | ||
160 | |||
161 | /* Now allocate the MSI-X vectors for real */ | ||
162 | status = pci_enable_msix(dev, msix_entries, nvec); | ||
163 | if (status) | ||
164 | goto Exit; | ||
165 | } | ||
166 | |||
167 | for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) | ||
168 | vectors[i] = idx[i] >= 0 ? msix_entries[idx[i]].vector : -1; | ||
169 | |||
170 | Exit: | ||
171 | kfree(msix_entries); | ||
172 | return status; | ||
173 | |||
174 | Error: | ||
175 | pci_disable_msix(dev); | ||
176 | goto Exit; | ||
54 | } | 177 | } |
55 | 178 | ||
56 | /** | 179 | /** |
@@ -64,47 +187,32 @@ static int is_msi_quirked(struct pci_dev *dev) | |||
64 | */ | 187 | */ |
65 | static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask) | 188 | static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask) |
66 | { | 189 | { |
67 | int i, pos, nvec, status = -EINVAL; | 190 | struct pcie_port_data *port_data = pci_get_drvdata(dev); |
68 | int interrupt_mode = PCIE_PORT_INTx_MODE; | 191 | int irq, interrupt_mode = PCIE_PORT_NO_IRQ; |
192 | int i; | ||
69 | 193 | ||
70 | /* Set INTx as default */ | ||
71 | for (i = 0, nvec = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) { | ||
72 | if (mask & (1 << i)) | ||
73 | nvec++; | ||
74 | vectors[i] = dev->irq; | ||
75 | } | ||
76 | |||
77 | /* Check MSI quirk */ | 194 | /* Check MSI quirk */ |
78 | if (is_msi_quirked(dev)) | 195 | if (port_data->port_type == PCIE_RC_PORT && pcie_mch_quirk) |
79 | return interrupt_mode; | 196 | goto Fallback; |
80 | 197 | ||
81 | /* Select MSI-X over MSI if supported */ | 198 | /* Try to use MSI-X if supported */ |
82 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | 199 | if (!pcie_port_enable_msix(dev, vectors, mask)) |
83 | if (pos) { | 200 | return PCIE_PORT_MSIX_MODE; |
84 | struct msix_entry msix_entries[PCIE_PORT_DEVICE_MAXSERVICES] = | 201 | |
85 | {{0, 0}, {0, 1}, {0, 2}, {0, 3}}; | 202 | /* We're not going to use MSI-X, so try MSI and fall back to INTx */ |
86 | status = pci_enable_msix(dev, msix_entries, nvec); | 203 | if (!pci_enable_msi(dev)) |
87 | if (!status) { | 204 | interrupt_mode = PCIE_PORT_MSI_MODE; |
88 | int j = 0; | 205 | |
89 | 206 | Fallback: | |
90 | interrupt_mode = PCIE_PORT_MSIX_MODE; | 207 | if (interrupt_mode == PCIE_PORT_NO_IRQ && dev->pin) |
91 | for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) { | 208 | interrupt_mode = PCIE_PORT_INTx_MODE; |
92 | if (mask & (1 << i)) | 209 | |
93 | vectors[i] = msix_entries[j++].vector; | 210 | irq = interrupt_mode != PCIE_PORT_NO_IRQ ? dev->irq : -1; |
94 | } | 211 | for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) |
95 | } | 212 | vectors[i] = irq; |
96 | } | 213 | |
97 | if (status) { | 214 | vectors[PCIE_PORT_SERVICE_VC_SHIFT] = -1; |
98 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | 215 | |
99 | if (pos) { | ||
100 | status = pci_enable_msi(dev); | ||
101 | if (!status) { | ||
102 | interrupt_mode = PCIE_PORT_MSI_MODE; | ||
103 | for (i = 0;i < PCIE_PORT_DEVICE_MAXSERVICES;i++) | ||
104 | vectors[i] = dev->irq; | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | return interrupt_mode; | 216 | return interrupt_mode; |
109 | } | 217 | } |
110 | 218 | ||
@@ -132,13 +240,11 @@ static int get_port_device_capability(struct pci_dev *dev) | |||
132 | pos + PCIE_SLOT_CAPABILITIES_REG, ®32); | 240 | pos + PCIE_SLOT_CAPABILITIES_REG, ®32); |
133 | if (reg32 & SLOT_HP_CAPABLE_MASK) | 241 | if (reg32 & SLOT_HP_CAPABLE_MASK) |
134 | services |= PCIE_PORT_SERVICE_HP; | 242 | services |= PCIE_PORT_SERVICE_HP; |
135 | } | 243 | } |
136 | /* PME Capable - root port capability */ | 244 | /* AER capable */ |
137 | if (((reg16 >> 4) & PORT_TYPE_MASK) == PCIE_RC_PORT) | ||
138 | services |= PCIE_PORT_SERVICE_PME; | ||
139 | |||
140 | if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) | 245 | if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) |
141 | services |= PCIE_PORT_SERVICE_AER; | 246 | services |= PCIE_PORT_SERVICE_AER; |
247 | /* VC support */ | ||
142 | if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC)) | 248 | if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC)) |
143 | services |= PCIE_PORT_SERVICE_VC; | 249 | services |= PCIE_PORT_SERVICE_VC; |
144 | 250 | ||
@@ -152,20 +258,17 @@ static int get_port_device_capability(struct pci_dev *dev) | |||
152 | * @port_type: Type of the port | 258 | * @port_type: Type of the port |
153 | * @service_type: Type of service to associate with the service device | 259 | * @service_type: Type of service to associate with the service device |
154 | * @irq: Interrupt vector to associate with the service device | 260 | * @irq: Interrupt vector to associate with the service device |
155 | * @irq_mode: Interrupt mode of the service (INTx, MSI-X, MSI) | ||
156 | */ | 261 | */ |
157 | static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev, | 262 | static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev, |
158 | int port_type, int service_type, int irq, int irq_mode) | 263 | int service_type, int irq) |
159 | { | 264 | { |
265 | struct pcie_port_data *port_data = pci_get_drvdata(parent); | ||
160 | struct device *device; | 266 | struct device *device; |
267 | int port_type = port_data->port_type; | ||
161 | 268 | ||
162 | dev->port = parent; | 269 | dev->port = parent; |
163 | dev->interrupt_mode = irq_mode; | ||
164 | dev->irq = irq; | 270 | dev->irq = irq; |
165 | dev->id.vendor = parent->vendor; | 271 | dev->service = service_type; |
166 | dev->id.device = parent->device; | ||
167 | dev->id.port_type = port_type; | ||
168 | dev->id.service_type = (1 << service_type); | ||
169 | 272 | ||
170 | /* Initialize generic device interface */ | 273 | /* Initialize generic device interface */ |
171 | device = &dev->device; | 274 | device = &dev->device; |
@@ -185,10 +288,9 @@ static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev, | |||
185 | * @port_type: Type of the port | 288 | * @port_type: Type of the port |
186 | * @service_type: Type of service to associate with the service device | 289 | * @service_type: Type of service to associate with the service device |
187 | * @irq: Interrupt vector to associate with the service device | 290 | * @irq: Interrupt vector to associate with the service device |
188 | * @irq_mode: Interrupt mode of the service (INTx, MSI-X, MSI) | ||
189 | */ | 291 | */ |
190 | static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, | 292 | static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, |
191 | int port_type, int service_type, int irq, int irq_mode) | 293 | int service_type, int irq) |
192 | { | 294 | { |
193 | struct pcie_device *device; | 295 | struct pcie_device *device; |
194 | 296 | ||
@@ -196,7 +298,7 @@ static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, | |||
196 | if (!device) | 298 | if (!device) |
197 | return NULL; | 299 | return NULL; |
198 | 300 | ||
199 | pcie_device_init(parent, device, port_type, service_type, irq,irq_mode); | 301 | pcie_device_init(parent, device, service_type, irq); |
200 | return device; | 302 | return device; |
201 | } | 303 | } |
202 | 304 | ||
@@ -230,63 +332,90 @@ int pcie_port_device_probe(struct pci_dev *dev) | |||
230 | */ | 332 | */ |
231 | int pcie_port_device_register(struct pci_dev *dev) | 333 | int pcie_port_device_register(struct pci_dev *dev) |
232 | { | 334 | { |
233 | struct pcie_port_device_ext *p_ext; | 335 | struct pcie_port_data *port_data; |
234 | int status, type, capabilities, irq_mode, i; | 336 | int status, capabilities, irq_mode, i, nr_serv; |
235 | int vectors[PCIE_PORT_DEVICE_MAXSERVICES]; | 337 | int vectors[PCIE_PORT_DEVICE_MAXSERVICES]; |
236 | u16 reg16; | 338 | u16 reg16; |
237 | 339 | ||
238 | /* Allocate port device extension */ | 340 | port_data = kzalloc(sizeof(*port_data), GFP_KERNEL); |
239 | if (!(p_ext = kmalloc(sizeof(struct pcie_port_device_ext), GFP_KERNEL))) | 341 | if (!port_data) |
240 | return -ENOMEM; | 342 | return -ENOMEM; |
241 | 343 | pci_set_drvdata(dev, port_data); | |
242 | pci_set_drvdata(dev, p_ext); | ||
243 | 344 | ||
244 | /* Get port type */ | 345 | /* Get port type */ |
245 | pci_read_config_word(dev, | 346 | pci_read_config_word(dev, |
246 | pci_find_capability(dev, PCI_CAP_ID_EXP) + | 347 | pci_find_capability(dev, PCI_CAP_ID_EXP) + |
247 | PCIE_CAPABILITIES_REG, ®16); | 348 | PCIE_CAPABILITIES_REG, ®16); |
248 | type = (reg16 >> 4) & PORT_TYPE_MASK; | 349 | port_data->port_type = (reg16 >> 4) & PORT_TYPE_MASK; |
249 | 350 | ||
250 | /* Now get port services */ | ||
251 | capabilities = get_port_device_capability(dev); | 351 | capabilities = get_port_device_capability(dev); |
352 | /* Root ports are capable of generating PME too */ | ||
353 | if (port_data->port_type == PCIE_RC_PORT) | ||
354 | capabilities |= PCIE_PORT_SERVICE_PME; | ||
355 | |||
252 | irq_mode = assign_interrupt_mode(dev, vectors, capabilities); | 356 | irq_mode = assign_interrupt_mode(dev, vectors, capabilities); |
253 | p_ext->interrupt_mode = irq_mode; | 357 | if (irq_mode == PCIE_PORT_NO_IRQ) { |
358 | /* | ||
359 | * Don't use service devices that require interrupts if there is | ||
360 | * no way to generate them. | ||
361 | */ | ||
362 | if (!(capabilities & PCIE_PORT_SERVICE_VC)) { | ||
363 | status = -ENODEV; | ||
364 | goto Error; | ||
365 | } | ||
366 | capabilities = PCIE_PORT_SERVICE_VC; | ||
367 | } | ||
368 | port_data->port_irq_mode = irq_mode; | ||
369 | |||
370 | status = pci_enable_device(dev); | ||
371 | if (status) | ||
372 | goto Error; | ||
373 | pci_set_master(dev); | ||
254 | 374 | ||
255 | /* Allocate child services if any */ | 375 | /* Allocate child services if any */ |
256 | for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) { | 376 | for (i = 0, nr_serv = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) { |
257 | struct pcie_device *child; | 377 | struct pcie_device *child; |
378 | int service = 1 << i; | ||
379 | |||
380 | if (!(capabilities & service)) | ||
381 | continue; | ||
258 | 382 | ||
259 | if (capabilities & (1 << i)) { | 383 | child = alloc_pcie_device(dev, service, vectors[i]); |
260 | child = alloc_pcie_device( | 384 | if (!child) |
261 | dev, /* parent */ | 385 | continue; |
262 | type, /* port type */ | 386 | |
263 | i, /* service type */ | 387 | status = device_register(&child->device); |
264 | vectors[i], /* irq */ | 388 | if (status) { |
265 | irq_mode /* interrupt mode */); | 389 | kfree(child); |
266 | if (child) { | 390 | continue; |
267 | status = device_register(&child->device); | ||
268 | if (status) { | ||
269 | kfree(child); | ||
270 | continue; | ||
271 | } | ||
272 | get_device(&child->device); | ||
273 | } | ||
274 | } | 391 | } |
392 | |||
393 | get_device(&child->device); | ||
394 | nr_serv++; | ||
395 | } | ||
396 | if (!nr_serv) { | ||
397 | pci_disable_device(dev); | ||
398 | status = -ENODEV; | ||
399 | goto Error; | ||
275 | } | 400 | } |
401 | |||
276 | return 0; | 402 | return 0; |
403 | |||
404 | Error: | ||
405 | kfree(port_data); | ||
406 | return status; | ||
277 | } | 407 | } |
278 | 408 | ||
279 | #ifdef CONFIG_PM | 409 | #ifdef CONFIG_PM |
280 | static int suspend_iter(struct device *dev, void *data) | 410 | static int suspend_iter(struct device *dev, void *data) |
281 | { | 411 | { |
282 | struct pcie_port_service_driver *service_driver; | 412 | struct pcie_port_service_driver *service_driver; |
283 | pm_message_t state = * (pm_message_t *) data; | ||
284 | 413 | ||
285 | if ((dev->bus == &pcie_port_bus_type) && | 414 | if ((dev->bus == &pcie_port_bus_type) && |
286 | (dev->driver)) { | 415 | (dev->driver)) { |
287 | service_driver = to_service_driver(dev->driver); | 416 | service_driver = to_service_driver(dev->driver); |
288 | if (service_driver->suspend) | 417 | if (service_driver->suspend) |
289 | service_driver->suspend(to_pcie_device(dev), state); | 418 | service_driver->suspend(to_pcie_device(dev)); |
290 | } | 419 | } |
291 | return 0; | 420 | return 0; |
292 | } | 421 | } |
@@ -294,11 +423,10 @@ static int suspend_iter(struct device *dev, void *data) | |||
294 | /** | 423 | /** |
295 | * pcie_port_device_suspend - suspend port services associated with a PCIe port | 424 | * pcie_port_device_suspend - suspend port services associated with a PCIe port |
296 | * @dev: PCI Express port to handle | 425 | * @dev: PCI Express port to handle |
297 | * @state: Representation of system power management transition in progress | ||
298 | */ | 426 | */ |
299 | int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state) | 427 | int pcie_port_device_suspend(struct device *dev) |
300 | { | 428 | { |
301 | return device_for_each_child(&dev->dev, &state, suspend_iter); | 429 | return device_for_each_child(dev, NULL, suspend_iter); |
302 | } | 430 | } |
303 | 431 | ||
304 | static int resume_iter(struct device *dev, void *data) | 432 | static int resume_iter(struct device *dev, void *data) |
@@ -318,24 +446,17 @@ static int resume_iter(struct device *dev, void *data) | |||
318 | * pcie_port_device_suspend - resume port services associated with a PCIe port | 446 | * pcie_port_device_suspend - resume port services associated with a PCIe port |
319 | * @dev: PCI Express port to handle | 447 | * @dev: PCI Express port to handle |
320 | */ | 448 | */ |
321 | int pcie_port_device_resume(struct pci_dev *dev) | 449 | int pcie_port_device_resume(struct device *dev) |
322 | { | 450 | { |
323 | return device_for_each_child(&dev->dev, NULL, resume_iter); | 451 | return device_for_each_child(dev, NULL, resume_iter); |
324 | } | 452 | } |
325 | #endif | 453 | #endif /* PM */ |
326 | 454 | ||
327 | static int remove_iter(struct device *dev, void *data) | 455 | static int remove_iter(struct device *dev, void *data) |
328 | { | 456 | { |
329 | struct pcie_port_service_driver *service_driver; | ||
330 | |||
331 | if (dev->bus == &pcie_port_bus_type) { | 457 | if (dev->bus == &pcie_port_bus_type) { |
332 | if (dev->driver) { | 458 | put_device(dev); |
333 | service_driver = to_service_driver(dev->driver); | 459 | device_unregister(dev); |
334 | if (service_driver->remove) | ||
335 | service_driver->remove(to_pcie_device(dev)); | ||
336 | } | ||
337 | *(unsigned long*)data = (unsigned long)dev; | ||
338 | return 1; | ||
339 | } | 460 | } |
340 | return 0; | 461 | return 0; |
341 | } | 462 | } |
@@ -349,25 +470,21 @@ static int remove_iter(struct device *dev, void *data) | |||
349 | */ | 470 | */ |
350 | void pcie_port_device_remove(struct pci_dev *dev) | 471 | void pcie_port_device_remove(struct pci_dev *dev) |
351 | { | 472 | { |
352 | struct device *device; | 473 | struct pcie_port_data *port_data = pci_get_drvdata(dev); |
353 | unsigned long device_addr; | ||
354 | int interrupt_mode = PCIE_PORT_INTx_MODE; | ||
355 | int status; | ||
356 | 474 | ||
357 | do { | 475 | device_for_each_child(&dev->dev, NULL, remove_iter); |
358 | status = device_for_each_child(&dev->dev, &device_addr, remove_iter); | 476 | pci_disable_device(dev); |
359 | if (status) { | 477 | |
360 | device = (struct device*)device_addr; | 478 | switch (port_data->port_irq_mode) { |
361 | interrupt_mode = (to_pcie_device(device))->interrupt_mode; | 479 | case PCIE_PORT_MSIX_MODE: |
362 | put_device(device); | ||
363 | device_unregister(device); | ||
364 | } | ||
365 | } while (status); | ||
366 | /* Switch to INTx by default if MSI enabled */ | ||
367 | if (interrupt_mode == PCIE_PORT_MSIX_MODE) | ||
368 | pci_disable_msix(dev); | 480 | pci_disable_msix(dev); |
369 | else if (interrupt_mode == PCIE_PORT_MSI_MODE) | 481 | break; |
482 | case PCIE_PORT_MSI_MODE: | ||
370 | pci_disable_msi(dev); | 483 | pci_disable_msi(dev); |
484 | break; | ||
485 | } | ||
486 | |||
487 | kfree(port_data); | ||
371 | } | 488 | } |
372 | 489 | ||
373 | /** | 490 | /** |
@@ -392,7 +509,7 @@ static int pcie_port_probe_service(struct device *dev) | |||
392 | return -ENODEV; | 509 | return -ENODEV; |
393 | 510 | ||
394 | pciedev = to_pcie_device(dev); | 511 | pciedev = to_pcie_device(dev); |
395 | status = driver->probe(pciedev, driver->id_table); | 512 | status = driver->probe(pciedev); |
396 | if (!status) { | 513 | if (!status) { |
397 | dev_printk(KERN_DEBUG, dev, "service driver %s loaded\n", | 514 | dev_printk(KERN_DEBUG, dev, "service driver %s loaded\n", |
398 | driver->name); | 515 | driver->name); |
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 5ea566e20b37..b924e2463f85 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c | |||
@@ -32,11 +32,6 @@ MODULE_LICENSE("GPL"); | |||
32 | /* global data */ | 32 | /* global data */ |
33 | static const char device_name[] = "pcieport-driver"; | 33 | static const char device_name[] = "pcieport-driver"; |
34 | 34 | ||
35 | static int pcie_portdrv_save_config(struct pci_dev *dev) | ||
36 | { | ||
37 | return pci_save_state(dev); | ||
38 | } | ||
39 | |||
40 | static int pcie_portdrv_restore_config(struct pci_dev *dev) | 35 | static int pcie_portdrv_restore_config(struct pci_dev *dev) |
41 | { | 36 | { |
42 | int retval; | 37 | int retval; |
@@ -49,21 +44,21 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev) | |||
49 | } | 44 | } |
50 | 45 | ||
51 | #ifdef CONFIG_PM | 46 | #ifdef CONFIG_PM |
52 | static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state) | 47 | static struct dev_pm_ops pcie_portdrv_pm_ops = { |
53 | { | 48 | .suspend = pcie_port_device_suspend, |
54 | return pcie_port_device_suspend(dev, state); | 49 | .resume = pcie_port_device_resume, |
50 | .freeze = pcie_port_device_suspend, | ||
51 | .thaw = pcie_port_device_resume, | ||
52 | .poweroff = pcie_port_device_suspend, | ||
53 | .restore = pcie_port_device_resume, | ||
54 | }; | ||
55 | 55 | ||
56 | } | 56 | #define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops) |
57 | 57 | ||
58 | static int pcie_portdrv_resume(struct pci_dev *dev) | 58 | #else /* !PM */ |
59 | { | 59 | |
60 | pci_set_master(dev); | 60 | #define PCIE_PORTDRV_PM_OPS NULL |
61 | return pcie_port_device_resume(dev); | 61 | #endif /* !PM */ |
62 | } | ||
63 | #else | ||
64 | #define pcie_portdrv_suspend NULL | ||
65 | #define pcie_portdrv_resume NULL | ||
66 | #endif | ||
67 | 62 | ||
68 | /* | 63 | /* |
69 | * pcie_portdrv_probe - Probe PCI-Express port devices | 64 | * pcie_portdrv_probe - Probe PCI-Express port devices |
@@ -82,20 +77,15 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev, | |||
82 | if (status) | 77 | if (status) |
83 | return status; | 78 | return status; |
84 | 79 | ||
85 | if (pci_enable_device(dev) < 0) | ||
86 | return -ENODEV; | ||
87 | |||
88 | pci_set_master(dev); | ||
89 | if (!dev->irq && dev->pin) { | 80 | if (!dev->irq && dev->pin) { |
90 | dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; " | 81 | dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; " |
91 | "check vendor BIOS\n", dev->vendor, dev->device); | 82 | "check vendor BIOS\n", dev->vendor, dev->device); |
92 | } | 83 | } |
93 | if (pcie_port_device_register(dev)) { | 84 | status = pcie_port_device_register(dev); |
94 | pci_disable_device(dev); | 85 | if (status) |
95 | return -ENOMEM; | 86 | return status; |
96 | } | ||
97 | 87 | ||
98 | pcie_portdrv_save_config(dev); | 88 | pci_save_state(dev); |
99 | 89 | ||
100 | return 0; | 90 | return 0; |
101 | } | 91 | } |
@@ -104,7 +94,6 @@ static void pcie_portdrv_remove (struct pci_dev *dev) | |||
104 | { | 94 | { |
105 | pcie_port_device_remove(dev); | 95 | pcie_port_device_remove(dev); |
106 | pci_disable_device(dev); | 96 | pci_disable_device(dev); |
107 | kfree(pci_get_drvdata(dev)); | ||
108 | } | 97 | } |
109 | 98 | ||
110 | static int error_detected_iter(struct device *device, void *data) | 99 | static int error_detected_iter(struct device *device, void *data) |
@@ -278,10 +267,9 @@ static struct pci_driver pcie_portdriver = { | |||
278 | .probe = pcie_portdrv_probe, | 267 | .probe = pcie_portdrv_probe, |
279 | .remove = pcie_portdrv_remove, | 268 | .remove = pcie_portdrv_remove, |
280 | 269 | ||
281 | .suspend = pcie_portdrv_suspend, | ||
282 | .resume = pcie_portdrv_resume, | ||
283 | |||
284 | .err_handler = &pcie_portdrv_err_handler, | 270 | .err_handler = &pcie_portdrv_err_handler, |
271 | |||
272 | .driver.pm = PCIE_PORTDRV_PM_OPS, | ||
285 | }; | 273 | }; |
286 | 274 | ||
287 | static int __init pcie_portdrv_init(void) | 275 | static int __init pcie_portdrv_init(void) |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 55ec44a27e89..e2f3dd098cfa 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -287,7 +287,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) | |||
287 | struct resource *res; | 287 | struct resource *res; |
288 | int i; | 288 | int i; |
289 | 289 | ||
290 | if (!dev) /* It's a host bus, nothing to read */ | 290 | if (!child->parent) /* It's a host bus, nothing to read */ |
291 | return; | 291 | return; |
292 | 292 | ||
293 | if (dev->transparent) { | 293 | if (dev->transparent) { |
@@ -511,21 +511,21 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, | |||
511 | 511 | ||
512 | /* | 512 | /* |
513 | * If we already got to this bus through a different bridge, | 513 | * If we already got to this bus through a different bridge, |
514 | * ignore it. This can happen with the i450NX chipset. | 514 | * don't re-add it. This can happen with the i450NX chipset. |
515 | * | ||
516 | * However, we continue to descend down the hierarchy and | ||
517 | * scan remaining child buses. | ||
515 | */ | 518 | */ |
516 | if (pci_find_bus(pci_domain_nr(bus), busnr)) { | 519 | child = pci_find_bus(pci_domain_nr(bus), busnr); |
517 | dev_info(&dev->dev, "bus %04x:%02x already known\n", | 520 | if (!child) { |
518 | pci_domain_nr(bus), busnr); | 521 | child = pci_add_new_bus(bus, dev, busnr); |
519 | goto out; | 522 | if (!child) |
523 | goto out; | ||
524 | child->primary = buses & 0xFF; | ||
525 | child->subordinate = (buses >> 16) & 0xFF; | ||
526 | child->bridge_ctl = bctl; | ||
520 | } | 527 | } |
521 | 528 | ||
522 | child = pci_add_new_bus(bus, dev, busnr); | ||
523 | if (!child) | ||
524 | goto out; | ||
525 | child->primary = buses & 0xFF; | ||
526 | child->subordinate = (buses >> 16) & 0xFF; | ||
527 | child->bridge_ctl = bctl; | ||
528 | |||
529 | cmax = pci_scan_child_bus(child); | 529 | cmax = pci_scan_child_bus(child); |
530 | if (cmax > max) | 530 | if (cmax > max) |
531 | max = cmax; | 531 | max = cmax; |
@@ -674,6 +674,19 @@ static void pci_read_irq(struct pci_dev *dev) | |||
674 | dev->irq = irq; | 674 | dev->irq = irq; |
675 | } | 675 | } |
676 | 676 | ||
677 | static void set_pcie_port_type(struct pci_dev *pdev) | ||
678 | { | ||
679 | int pos; | ||
680 | u16 reg16; | ||
681 | |||
682 | pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); | ||
683 | if (!pos) | ||
684 | return; | ||
685 | pdev->is_pcie = 1; | ||
686 | pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); | ||
687 | pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; | ||
688 | } | ||
689 | |||
677 | #define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) | 690 | #define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) |
678 | 691 | ||
679 | /** | 692 | /** |
@@ -683,12 +696,33 @@ static void pci_read_irq(struct pci_dev *dev) | |||
683 | * Initialize the device structure with information about the device's | 696 | * Initialize the device structure with information about the device's |
684 | * vendor,class,memory and IO-space addresses,IRQ lines etc. | 697 | * vendor,class,memory and IO-space addresses,IRQ lines etc. |
685 | * Called at initialisation of the PCI subsystem and by CardBus services. | 698 | * Called at initialisation of the PCI subsystem and by CardBus services. |
686 | * Returns 0 on success and -1 if unknown type of device (not normal, bridge | 699 | * Returns 0 on success and negative if unknown type of device (not normal, |
687 | * or CardBus). | 700 | * bridge or CardBus). |
688 | */ | 701 | */ |
689 | static int pci_setup_device(struct pci_dev * dev) | 702 | int pci_setup_device(struct pci_dev *dev) |
690 | { | 703 | { |
691 | u32 class; | 704 | u32 class; |
705 | u8 hdr_type; | ||
706 | struct pci_slot *slot; | ||
707 | |||
708 | if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type)) | ||
709 | return -EIO; | ||
710 | |||
711 | dev->sysdata = dev->bus->sysdata; | ||
712 | dev->dev.parent = dev->bus->bridge; | ||
713 | dev->dev.bus = &pci_bus_type; | ||
714 | dev->hdr_type = hdr_type & 0x7f; | ||
715 | dev->multifunction = !!(hdr_type & 0x80); | ||
716 | dev->error_state = pci_channel_io_normal; | ||
717 | set_pcie_port_type(dev); | ||
718 | |||
719 | list_for_each_entry(slot, &dev->bus->slots, list) | ||
720 | if (PCI_SLOT(dev->devfn) == slot->number) | ||
721 | dev->slot = slot; | ||
722 | |||
723 | /* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer) | ||
724 | set this higher, assuming the system even supports it. */ | ||
725 | dev->dma_mask = 0xffffffff; | ||
692 | 726 | ||
693 | dev_set_name(&dev->dev, "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus), | 727 | dev_set_name(&dev->dev, "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus), |
694 | dev->bus->number, PCI_SLOT(dev->devfn), | 728 | dev->bus->number, PCI_SLOT(dev->devfn), |
@@ -703,12 +737,14 @@ static int pci_setup_device(struct pci_dev * dev) | |||
703 | dev_dbg(&dev->dev, "found [%04x:%04x] class %06x header type %02x\n", | 737 | dev_dbg(&dev->dev, "found [%04x:%04x] class %06x header type %02x\n", |
704 | dev->vendor, dev->device, class, dev->hdr_type); | 738 | dev->vendor, dev->device, class, dev->hdr_type); |
705 | 739 | ||
740 | /* need to have dev->class ready */ | ||
741 | dev->cfg_size = pci_cfg_space_size(dev); | ||
742 | |||
706 | /* "Unknown power state" */ | 743 | /* "Unknown power state" */ |
707 | dev->current_state = PCI_UNKNOWN; | 744 | dev->current_state = PCI_UNKNOWN; |
708 | 745 | ||
709 | /* Early fixups, before probing the BARs */ | 746 | /* Early fixups, before probing the BARs */ |
710 | pci_fixup_device(pci_fixup_early, dev); | 747 | pci_fixup_device(pci_fixup_early, dev); |
711 | class = dev->class >> 8; | ||
712 | 748 | ||
713 | switch (dev->hdr_type) { /* header type */ | 749 | switch (dev->hdr_type) { /* header type */ |
714 | case PCI_HEADER_TYPE_NORMAL: /* standard header */ | 750 | case PCI_HEADER_TYPE_NORMAL: /* standard header */ |
@@ -770,7 +806,7 @@ static int pci_setup_device(struct pci_dev * dev) | |||
770 | default: /* unknown header */ | 806 | default: /* unknown header */ |
771 | dev_err(&dev->dev, "unknown header type %02x, " | 807 | dev_err(&dev->dev, "unknown header type %02x, " |
772 | "ignoring device\n", dev->hdr_type); | 808 | "ignoring device\n", dev->hdr_type); |
773 | return -1; | 809 | return -EIO; |
774 | 810 | ||
775 | bad: | 811 | bad: |
776 | dev_err(&dev->dev, "ignoring class %02x (doesn't match header " | 812 | dev_err(&dev->dev, "ignoring class %02x (doesn't match header " |
@@ -785,6 +821,7 @@ static int pci_setup_device(struct pci_dev * dev) | |||
785 | static void pci_release_capabilities(struct pci_dev *dev) | 821 | static void pci_release_capabilities(struct pci_dev *dev) |
786 | { | 822 | { |
787 | pci_vpd_release(dev); | 823 | pci_vpd_release(dev); |
824 | pci_iov_release(dev); | ||
788 | } | 825 | } |
789 | 826 | ||
790 | /** | 827 | /** |
@@ -803,19 +840,6 @@ static void pci_release_dev(struct device *dev) | |||
803 | kfree(pci_dev); | 840 | kfree(pci_dev); |
804 | } | 841 | } |
805 | 842 | ||
806 | static void set_pcie_port_type(struct pci_dev *pdev) | ||
807 | { | ||
808 | int pos; | ||
809 | u16 reg16; | ||
810 | |||
811 | pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); | ||
812 | if (!pos) | ||
813 | return; | ||
814 | pdev->is_pcie = 1; | ||
815 | pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); | ||
816 | pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; | ||
817 | } | ||
818 | |||
819 | /** | 843 | /** |
820 | * pci_cfg_space_size - get the configuration space size of the PCI device. | 844 | * pci_cfg_space_size - get the configuration space size of the PCI device. |
821 | * @dev: PCI device | 845 | * @dev: PCI device |
@@ -847,6 +871,11 @@ int pci_cfg_space_size(struct pci_dev *dev) | |||
847 | { | 871 | { |
848 | int pos; | 872 | int pos; |
849 | u32 status; | 873 | u32 status; |
874 | u16 class; | ||
875 | |||
876 | class = dev->class >> 8; | ||
877 | if (class == PCI_CLASS_BRIDGE_HOST) | ||
878 | return pci_cfg_space_size_ext(dev); | ||
850 | 879 | ||
851 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | 880 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); |
852 | if (!pos) { | 881 | if (!pos) { |
@@ -891,9 +920,7 @@ EXPORT_SYMBOL(alloc_pci_dev); | |||
891 | static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) | 920 | static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) |
892 | { | 921 | { |
893 | struct pci_dev *dev; | 922 | struct pci_dev *dev; |
894 | struct pci_slot *slot; | ||
895 | u32 l; | 923 | u32 l; |
896 | u8 hdr_type; | ||
897 | int delay = 1; | 924 | int delay = 1; |
898 | 925 | ||
899 | if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l)) | 926 | if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l)) |
@@ -920,34 +947,16 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) | |||
920 | } | 947 | } |
921 | } | 948 | } |
922 | 949 | ||
923 | if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type)) | ||
924 | return NULL; | ||
925 | |||
926 | dev = alloc_pci_dev(); | 950 | dev = alloc_pci_dev(); |
927 | if (!dev) | 951 | if (!dev) |
928 | return NULL; | 952 | return NULL; |
929 | 953 | ||
930 | dev->bus = bus; | 954 | dev->bus = bus; |
931 | dev->sysdata = bus->sysdata; | ||
932 | dev->dev.parent = bus->bridge; | ||
933 | dev->dev.bus = &pci_bus_type; | ||
934 | dev->devfn = devfn; | 955 | dev->devfn = devfn; |
935 | dev->hdr_type = hdr_type & 0x7f; | ||
936 | dev->multifunction = !!(hdr_type & 0x80); | ||
937 | dev->vendor = l & 0xffff; | 956 | dev->vendor = l & 0xffff; |
938 | dev->device = (l >> 16) & 0xffff; | 957 | dev->device = (l >> 16) & 0xffff; |
939 | dev->cfg_size = pci_cfg_space_size(dev); | ||
940 | dev->error_state = pci_channel_io_normal; | ||
941 | set_pcie_port_type(dev); | ||
942 | |||
943 | list_for_each_entry(slot, &bus->slots, list) | ||
944 | if (PCI_SLOT(devfn) == slot->number) | ||
945 | dev->slot = slot; | ||
946 | 958 | ||
947 | /* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer) | 959 | if (pci_setup_device(dev)) { |
948 | set this higher, assuming the system even supports it. */ | ||
949 | dev->dma_mask = 0xffffffff; | ||
950 | if (pci_setup_device(dev) < 0) { | ||
951 | kfree(dev); | 960 | kfree(dev); |
952 | return NULL; | 961 | return NULL; |
953 | } | 962 | } |
@@ -972,6 +981,9 @@ static void pci_init_capabilities(struct pci_dev *dev) | |||
972 | 981 | ||
973 | /* Alternative Routing-ID Forwarding */ | 982 | /* Alternative Routing-ID Forwarding */ |
974 | pci_enable_ari(dev); | 983 | pci_enable_ari(dev); |
984 | |||
985 | /* Single Root I/O Virtualization */ | ||
986 | pci_iov_init(dev); | ||
975 | } | 987 | } |
976 | 988 | ||
977 | void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) | 989 | void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) |
@@ -1006,6 +1018,12 @@ struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn) | |||
1006 | { | 1018 | { |
1007 | struct pci_dev *dev; | 1019 | struct pci_dev *dev; |
1008 | 1020 | ||
1021 | dev = pci_get_slot(bus, devfn); | ||
1022 | if (dev) { | ||
1023 | pci_dev_put(dev); | ||
1024 | return dev; | ||
1025 | } | ||
1026 | |||
1009 | dev = pci_scan_device(bus, devfn); | 1027 | dev = pci_scan_device(bus, devfn); |
1010 | if (!dev) | 1028 | if (!dev) |
1011 | return NULL; | 1029 | return NULL; |
@@ -1024,35 +1042,27 @@ EXPORT_SYMBOL(pci_scan_single_device); | |||
1024 | * Scan a PCI slot on the specified PCI bus for devices, adding | 1042 | * Scan a PCI slot on the specified PCI bus for devices, adding |
1025 | * discovered devices to the @bus->devices list. New devices | 1043 | * discovered devices to the @bus->devices list. New devices |
1026 | * will not have is_added set. | 1044 | * will not have is_added set. |
1045 | * | ||
1046 | * Returns the number of new devices found. | ||
1027 | */ | 1047 | */ |
1028 | int pci_scan_slot(struct pci_bus *bus, int devfn) | 1048 | int pci_scan_slot(struct pci_bus *bus, int devfn) |
1029 | { | 1049 | { |
1030 | int func, nr = 0; | 1050 | int fn, nr = 0; |
1031 | int scan_all_fns; | 1051 | struct pci_dev *dev; |
1032 | |||
1033 | scan_all_fns = pcibios_scan_all_fns(bus, devfn); | ||
1034 | |||
1035 | for (func = 0; func < 8; func++, devfn++) { | ||
1036 | struct pci_dev *dev; | ||
1037 | |||
1038 | dev = pci_scan_single_device(bus, devfn); | ||
1039 | if (dev) { | ||
1040 | nr++; | ||
1041 | 1052 | ||
1042 | /* | 1053 | dev = pci_scan_single_device(bus, devfn); |
1043 | * If this is a single function device, | 1054 | if (dev && !dev->is_added) /* new device? */ |
1044 | * don't scan past the first function. | 1055 | nr++; |
1045 | */ | 1056 | |
1046 | if (!dev->multifunction) { | 1057 | if ((dev && dev->multifunction) || |
1047 | if (func > 0) { | 1058 | (!dev && pcibios_scan_all_fns(bus, devfn))) { |
1048 | dev->multifunction = 1; | 1059 | for (fn = 1; fn < 8; fn++) { |
1049 | } else { | 1060 | dev = pci_scan_single_device(bus, devfn + fn); |
1050 | break; | 1061 | if (dev) { |
1051 | } | 1062 | if (!dev->is_added) |
1063 | nr++; | ||
1064 | dev->multifunction = 1; | ||
1052 | } | 1065 | } |
1053 | } else { | ||
1054 | if (func == 0 && !scan_all_fns) | ||
1055 | break; | ||
1056 | } | 1066 | } |
1057 | } | 1067 | } |
1058 | 1068 | ||
@@ -1074,12 +1084,21 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) | |||
1074 | for (devfn = 0; devfn < 0x100; devfn += 8) | 1084 | for (devfn = 0; devfn < 0x100; devfn += 8) |
1075 | pci_scan_slot(bus, devfn); | 1085 | pci_scan_slot(bus, devfn); |
1076 | 1086 | ||
1087 | /* Reserve buses for SR-IOV capability. */ | ||
1088 | max += pci_iov_bus_range(bus); | ||
1089 | |||
1077 | /* | 1090 | /* |
1078 | * After performing arch-dependent fixup of the bus, look behind | 1091 | * After performing arch-dependent fixup of the bus, look behind |
1079 | * all PCI-to-PCI bridges on this bus. | 1092 | * all PCI-to-PCI bridges on this bus. |
1080 | */ | 1093 | */ |
1081 | pr_debug("PCI: Fixups for bus %04x:%02x\n", pci_domain_nr(bus), bus->number); | 1094 | if (!bus->is_added) { |
1082 | pcibios_fixup_bus(bus); | 1095 | pr_debug("PCI: Fixups for bus %04x:%02x\n", |
1096 | pci_domain_nr(bus), bus->number); | ||
1097 | pcibios_fixup_bus(bus); | ||
1098 | if (pci_is_root_bus(bus)) | ||
1099 | bus->is_added = 1; | ||
1100 | } | ||
1101 | |||
1083 | for (pass=0; pass < 2; pass++) | 1102 | for (pass=0; pass < 2; pass++) |
1084 | list_for_each_entry(dev, &bus->devices, bus_list) { | 1103 | list_for_each_entry(dev, &bus->devices, bus_list) { |
1085 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | 1104 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || |
@@ -1114,7 +1133,7 @@ struct pci_bus * pci_create_bus(struct device *parent, | |||
1114 | if (!b) | 1133 | if (!b) |
1115 | return NULL; | 1134 | return NULL; |
1116 | 1135 | ||
1117 | dev = kmalloc(sizeof(*dev), GFP_KERNEL); | 1136 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
1118 | if (!dev){ | 1137 | if (!dev){ |
1119 | kfree(b); | 1138 | kfree(b); |
1120 | return NULL; | 1139 | return NULL; |
@@ -1133,7 +1152,6 @@ struct pci_bus * pci_create_bus(struct device *parent, | |||
1133 | list_add_tail(&b->node, &pci_root_buses); | 1152 | list_add_tail(&b->node, &pci_root_buses); |
1134 | up_write(&pci_bus_sem); | 1153 | up_write(&pci_bus_sem); |
1135 | 1154 | ||
1136 | memset(dev, 0, sizeof(*dev)); | ||
1137 | dev->parent = parent; | 1155 | dev->parent = parent; |
1138 | dev->release = pci_release_bus_bridge_dev; | 1156 | dev->release = pci_release_bus_bridge_dev; |
1139 | dev_set_name(dev, "pci%04x:%02x", pci_domain_nr(b), bus); | 1157 | dev_set_name(dev, "pci%04x:%02x", pci_domain_nr(b), bus); |
@@ -1193,6 +1211,38 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, | |||
1193 | EXPORT_SYMBOL(pci_scan_bus_parented); | 1211 | EXPORT_SYMBOL(pci_scan_bus_parented); |
1194 | 1212 | ||
1195 | #ifdef CONFIG_HOTPLUG | 1213 | #ifdef CONFIG_HOTPLUG |
1214 | /** | ||
1215 | * pci_rescan_bus - scan a PCI bus for devices. | ||
1216 | * @bus: PCI bus to scan | ||
1217 | * | ||
1218 | * Scan a PCI bus and child buses for new devices, adds them, | ||
1219 | * and enables them. | ||
1220 | * | ||
1221 | * Returns the max number of subordinate bus discovered. | ||
1222 | */ | ||
1223 | unsigned int __devinit pci_rescan_bus(struct pci_bus *bus) | ||
1224 | { | ||
1225 | unsigned int max; | ||
1226 | struct pci_dev *dev; | ||
1227 | |||
1228 | max = pci_scan_child_bus(bus); | ||
1229 | |||
1230 | down_read(&pci_bus_sem); | ||
1231 | list_for_each_entry(dev, &bus->devices, bus_list) | ||
1232 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | ||
1233 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) | ||
1234 | if (dev->subordinate) | ||
1235 | pci_bus_size_bridges(dev->subordinate); | ||
1236 | up_read(&pci_bus_sem); | ||
1237 | |||
1238 | pci_bus_assign_resources(bus); | ||
1239 | pci_enable_bridges(bus); | ||
1240 | pci_bus_add_devices(bus); | ||
1241 | |||
1242 | return max; | ||
1243 | } | ||
1244 | EXPORT_SYMBOL_GPL(pci_rescan_bus); | ||
1245 | |||
1196 | EXPORT_SYMBOL(pci_add_new_bus); | 1246 | EXPORT_SYMBOL(pci_add_new_bus); |
1197 | EXPORT_SYMBOL(pci_scan_slot); | 1247 | EXPORT_SYMBOL(pci_scan_slot); |
1198 | EXPORT_SYMBOL(pci_scan_bridge); | 1248 | EXPORT_SYMBOL(pci_scan_bridge); |
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 92b9efe9bcaf..9b2f0d96900d 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/kallsyms.h> | 24 | #include <linux/kallsyms.h> |
25 | #include <linux/dmi.h> | 25 | #include <linux/dmi.h> |
26 | #include <linux/pci-aspm.h> | 26 | #include <linux/pci-aspm.h> |
27 | #include <linux/ioport.h> | ||
27 | #include "pci.h" | 28 | #include "pci.h" |
28 | 29 | ||
29 | int isa_dma_bridge_buggy; | 30 | int isa_dma_bridge_buggy; |
@@ -34,6 +35,65 @@ int pcie_mch_quirk; | |||
34 | EXPORT_SYMBOL(pcie_mch_quirk); | 35 | EXPORT_SYMBOL(pcie_mch_quirk); |
35 | 36 | ||
36 | #ifdef CONFIG_PCI_QUIRKS | 37 | #ifdef CONFIG_PCI_QUIRKS |
38 | /* | ||
39 | * This quirk function disables the device and releases resources | ||
40 | * which is specified by kernel's boot parameter 'pci=resource_alignment='. | ||
41 | * It also rounds up size to specified alignment. | ||
42 | * Later on, the kernel will assign page-aligned memory resource back | ||
43 | * to that device. | ||
44 | */ | ||
45 | static void __devinit quirk_resource_alignment(struct pci_dev *dev) | ||
46 | { | ||
47 | int i; | ||
48 | struct resource *r; | ||
49 | resource_size_t align, size; | ||
50 | |||
51 | if (!pci_is_reassigndev(dev)) | ||
52 | return; | ||
53 | |||
54 | if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL && | ||
55 | (dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) { | ||
56 | dev_warn(&dev->dev, | ||
57 | "Can't reassign resources to host bridge.\n"); | ||
58 | return; | ||
59 | } | ||
60 | |||
61 | dev_info(&dev->dev, "Disabling device and release resources.\n"); | ||
62 | pci_disable_device(dev); | ||
63 | |||
64 | align = pci_specified_resource_alignment(dev); | ||
65 | for (i=0; i < PCI_BRIDGE_RESOURCES; i++) { | ||
66 | r = &dev->resource[i]; | ||
67 | if (!(r->flags & IORESOURCE_MEM)) | ||
68 | continue; | ||
69 | size = resource_size(r); | ||
70 | if (size < align) { | ||
71 | size = align; | ||
72 | dev_info(&dev->dev, | ||
73 | "Rounding up size of resource #%d to %#llx.\n", | ||
74 | i, (unsigned long long)size); | ||
75 | } | ||
76 | r->end = size - 1; | ||
77 | r->start = 0; | ||
78 | } | ||
79 | /* Need to disable bridge's resource window, | ||
80 | * to enable the kernel to reassign new resource | ||
81 | * window later on. | ||
82 | */ | ||
83 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && | ||
84 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
85 | for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) { | ||
86 | r = &dev->resource[i]; | ||
87 | if (!(r->flags & IORESOURCE_MEM)) | ||
88 | continue; | ||
89 | r->end = resource_size(r) - 1; | ||
90 | r->start = 0; | ||
91 | } | ||
92 | pci_disable_bridge_window(dev); | ||
93 | } | ||
94 | } | ||
95 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_resource_alignment); | ||
96 | |||
37 | /* The Mellanox Tavor device gives false positive parity errors | 97 | /* The Mellanox Tavor device gives false positive parity errors |
38 | * Mark this device with a broken_parity_status, to allow | 98 | * Mark this device with a broken_parity_status, to allow |
39 | * PCI scanning code to "skip" this now blacklisted device. | 99 | * PCI scanning code to "skip" this now blacklisted device. |
@@ -1126,10 +1186,15 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) | |||
1126 | * its on-board VGA controller */ | 1186 | * its on-board VGA controller */ |
1127 | asus_hides_smbus = 1; | 1187 | asus_hides_smbus = 1; |
1128 | } | 1188 | } |
1129 | else if (dev->device == PCI_DEVICE_ID_INTEL_82845G_IG) | 1189 | else if (dev->device == PCI_DEVICE_ID_INTEL_82801DB_2) |
1130 | switch(dev->subsystem_device) { | 1190 | switch(dev->subsystem_device) { |
1131 | case 0x00b8: /* Compaq Evo D510 CMT */ | 1191 | case 0x00b8: /* Compaq Evo D510 CMT */ |
1132 | case 0x00b9: /* Compaq Evo D510 SFF */ | 1192 | case 0x00b9: /* Compaq Evo D510 SFF */ |
1193 | /* Motherboard doesn't have Host bridge | ||
1194 | * subvendor/subdevice IDs and on-board VGA | ||
1195 | * controller is disabled if an AGP card is | ||
1196 | * inserted, therefore checking USB UHCI | ||
1197 | * Controller #1 */ | ||
1133 | asus_hides_smbus = 1; | 1198 | asus_hides_smbus = 1; |
1134 | } | 1199 | } |
1135 | else if (dev->device == PCI_DEVICE_ID_INTEL_82815_CGC) | 1200 | else if (dev->device == PCI_DEVICE_ID_INTEL_82815_CGC) |
@@ -1154,7 +1219,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, as | |||
1154 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge); | 1219 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge); |
1155 | 1220 | ||
1156 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3, asus_hides_smbus_hostbridge); | 1221 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3, asus_hides_smbus_hostbridge); |
1157 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_IG, asus_hides_smbus_hostbridge); | 1222 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_2, asus_hides_smbus_hostbridge); |
1158 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC, asus_hides_smbus_hostbridge); | 1223 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC, asus_hides_smbus_hostbridge); |
1159 | 1224 | ||
1160 | static void asus_hides_smbus_lpc(struct pci_dev *dev) | 1225 | static void asus_hides_smbus_lpc(struct pci_dev *dev) |
@@ -1664,9 +1729,13 @@ static void __devinit quirk_netmos(struct pci_dev *dev) | |||
1664 | * of parallel ports and <S> is the number of serial ports. | 1729 | * of parallel ports and <S> is the number of serial ports. |
1665 | */ | 1730 | */ |
1666 | switch (dev->device) { | 1731 | switch (dev->device) { |
1732 | case PCI_DEVICE_ID_NETMOS_9835: | ||
1733 | /* Well, this rule doesn't hold for the following 9835 device */ | ||
1734 | if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && | ||
1735 | dev->subsystem_device == 0x0299) | ||
1736 | return; | ||
1667 | case PCI_DEVICE_ID_NETMOS_9735: | 1737 | case PCI_DEVICE_ID_NETMOS_9735: |
1668 | case PCI_DEVICE_ID_NETMOS_9745: | 1738 | case PCI_DEVICE_ID_NETMOS_9745: |
1669 | case PCI_DEVICE_ID_NETMOS_9835: | ||
1670 | case PCI_DEVICE_ID_NETMOS_9845: | 1739 | case PCI_DEVICE_ID_NETMOS_9845: |
1671 | case PCI_DEVICE_ID_NETMOS_9855: | 1740 | case PCI_DEVICE_ID_NETMOS_9855: |
1672 | if ((dev->class >> 8) == PCI_CLASS_COMMUNICATION_SERIAL && | 1741 | if ((dev->class >> 8) == PCI_CLASS_COMMUNICATION_SERIAL && |
@@ -2078,6 +2147,92 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, | |||
2078 | PCI_DEVICE_ID_NVIDIA_NVENET_15, | 2147 | PCI_DEVICE_ID_NVIDIA_NVENET_15, |
2079 | nvenet_msi_disable); | 2148 | nvenet_msi_disable); |
2080 | 2149 | ||
2150 | static int __devinit ht_check_msi_mapping(struct pci_dev *dev) | ||
2151 | { | ||
2152 | int pos, ttl = 48; | ||
2153 | int found = 0; | ||
2154 | |||
2155 | /* check if there is HT MSI cap or enabled on this device */ | ||
2156 | pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING); | ||
2157 | while (pos && ttl--) { | ||
2158 | u8 flags; | ||
2159 | |||
2160 | if (found < 1) | ||
2161 | found = 1; | ||
2162 | if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, | ||
2163 | &flags) == 0) { | ||
2164 | if (flags & HT_MSI_FLAGS_ENABLE) { | ||
2165 | if (found < 2) { | ||
2166 | found = 2; | ||
2167 | break; | ||
2168 | } | ||
2169 | } | ||
2170 | } | ||
2171 | pos = pci_find_next_ht_capability(dev, pos, | ||
2172 | HT_CAPTYPE_MSI_MAPPING); | ||
2173 | } | ||
2174 | |||
2175 | return found; | ||
2176 | } | ||
2177 | |||
2178 | static int __devinit host_bridge_with_leaf(struct pci_dev *host_bridge) | ||
2179 | { | ||
2180 | struct pci_dev *dev; | ||
2181 | int pos; | ||
2182 | int i, dev_no; | ||
2183 | int found = 0; | ||
2184 | |||
2185 | dev_no = host_bridge->devfn >> 3; | ||
2186 | for (i = dev_no + 1; i < 0x20; i++) { | ||
2187 | dev = pci_get_slot(host_bridge->bus, PCI_DEVFN(i, 0)); | ||
2188 | if (!dev) | ||
2189 | continue; | ||
2190 | |||
2191 | /* found next host bridge ?*/ | ||
2192 | pos = pci_find_ht_capability(dev, HT_CAPTYPE_SLAVE); | ||
2193 | if (pos != 0) { | ||
2194 | pci_dev_put(dev); | ||
2195 | break; | ||
2196 | } | ||
2197 | |||
2198 | if (ht_check_msi_mapping(dev)) { | ||
2199 | found = 1; | ||
2200 | pci_dev_put(dev); | ||
2201 | break; | ||
2202 | } | ||
2203 | pci_dev_put(dev); | ||
2204 | } | ||
2205 | |||
2206 | return found; | ||
2207 | } | ||
2208 | |||
2209 | #define PCI_HT_CAP_SLAVE_CTRL0 4 /* link control */ | ||
2210 | #define PCI_HT_CAP_SLAVE_CTRL1 8 /* link control to */ | ||
2211 | |||
2212 | static int __devinit is_end_of_ht_chain(struct pci_dev *dev) | ||
2213 | { | ||
2214 | int pos, ctrl_off; | ||
2215 | int end = 0; | ||
2216 | u16 flags, ctrl; | ||
2217 | |||
2218 | pos = pci_find_ht_capability(dev, HT_CAPTYPE_SLAVE); | ||
2219 | |||
2220 | if (!pos) | ||
2221 | goto out; | ||
2222 | |||
2223 | pci_read_config_word(dev, pos + PCI_CAP_FLAGS, &flags); | ||
2224 | |||
2225 | ctrl_off = ((flags >> 10) & 1) ? | ||
2226 | PCI_HT_CAP_SLAVE_CTRL0 : PCI_HT_CAP_SLAVE_CTRL1; | ||
2227 | pci_read_config_word(dev, pos + ctrl_off, &ctrl); | ||
2228 | |||
2229 | if (ctrl & (1 << 6)) | ||
2230 | end = 1; | ||
2231 | |||
2232 | out: | ||
2233 | return end; | ||
2234 | } | ||
2235 | |||
2081 | static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev) | 2236 | static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev) |
2082 | { | 2237 | { |
2083 | struct pci_dev *host_bridge; | 2238 | struct pci_dev *host_bridge; |
@@ -2102,6 +2257,11 @@ static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev) | |||
2102 | if (!found) | 2257 | if (!found) |
2103 | return; | 2258 | return; |
2104 | 2259 | ||
2260 | /* don't enable end_device/host_bridge with leaf directly here */ | ||
2261 | if (host_bridge == dev && is_end_of_ht_chain(host_bridge) && | ||
2262 | host_bridge_with_leaf(host_bridge)) | ||
2263 | goto out; | ||
2264 | |||
2105 | /* root did that ! */ | 2265 | /* root did that ! */ |
2106 | if (msi_ht_cap_enabled(host_bridge)) | 2266 | if (msi_ht_cap_enabled(host_bridge)) |
2107 | goto out; | 2267 | goto out; |
@@ -2132,44 +2292,12 @@ static void __devinit ht_disable_msi_mapping(struct pci_dev *dev) | |||
2132 | } | 2292 | } |
2133 | } | 2293 | } |
2134 | 2294 | ||
2135 | static int __devinit ht_check_msi_mapping(struct pci_dev *dev) | 2295 | static void __devinit __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all) |
2136 | { | ||
2137 | int pos, ttl = 48; | ||
2138 | int found = 0; | ||
2139 | |||
2140 | /* check if there is HT MSI cap or enabled on this device */ | ||
2141 | pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING); | ||
2142 | while (pos && ttl--) { | ||
2143 | u8 flags; | ||
2144 | |||
2145 | if (found < 1) | ||
2146 | found = 1; | ||
2147 | if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, | ||
2148 | &flags) == 0) { | ||
2149 | if (flags & HT_MSI_FLAGS_ENABLE) { | ||
2150 | if (found < 2) { | ||
2151 | found = 2; | ||
2152 | break; | ||
2153 | } | ||
2154 | } | ||
2155 | } | ||
2156 | pos = pci_find_next_ht_capability(dev, pos, | ||
2157 | HT_CAPTYPE_MSI_MAPPING); | ||
2158 | } | ||
2159 | |||
2160 | return found; | ||
2161 | } | ||
2162 | |||
2163 | static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) | ||
2164 | { | 2296 | { |
2165 | struct pci_dev *host_bridge; | 2297 | struct pci_dev *host_bridge; |
2166 | int pos; | 2298 | int pos; |
2167 | int found; | 2299 | int found; |
2168 | 2300 | ||
2169 | /* Enabling HT MSI mapping on this device breaks MCP51 */ | ||
2170 | if (dev->device == 0x270) | ||
2171 | return; | ||
2172 | |||
2173 | /* check if there is HT MSI cap or enabled on this device */ | 2301 | /* check if there is HT MSI cap or enabled on this device */ |
2174 | found = ht_check_msi_mapping(dev); | 2302 | found = ht_check_msi_mapping(dev); |
2175 | 2303 | ||
@@ -2193,7 +2321,10 @@ static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) | |||
2193 | /* Host bridge is to HT */ | 2321 | /* Host bridge is to HT */ |
2194 | if (found == 1) { | 2322 | if (found == 1) { |
2195 | /* it is not enabled, try to enable it */ | 2323 | /* it is not enabled, try to enable it */ |
2196 | nv_ht_enable_msi_mapping(dev); | 2324 | if (all) |
2325 | ht_enable_msi_mapping(dev); | ||
2326 | else | ||
2327 | nv_ht_enable_msi_mapping(dev); | ||
2197 | } | 2328 | } |
2198 | return; | 2329 | return; |
2199 | } | 2330 | } |
@@ -2205,8 +2336,20 @@ static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) | |||
2205 | /* Host bridge is not to HT, disable HT MSI mapping on this device */ | 2336 | /* Host bridge is not to HT, disable HT MSI mapping on this device */ |
2206 | ht_disable_msi_mapping(dev); | 2337 | ht_disable_msi_mapping(dev); |
2207 | } | 2338 | } |
2208 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk); | 2339 | |
2209 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk); | 2340 | static void __devinit nv_msi_ht_cap_quirk_all(struct pci_dev *dev) |
2341 | { | ||
2342 | return __nv_msi_ht_cap_quirk(dev, 1); | ||
2343 | } | ||
2344 | |||
2345 | static void __devinit nv_msi_ht_cap_quirk_leaf(struct pci_dev *dev) | ||
2346 | { | ||
2347 | return __nv_msi_ht_cap_quirk(dev, 0); | ||
2348 | } | ||
2349 | |||
2350 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk_leaf); | ||
2351 | |||
2352 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk_all); | ||
2210 | 2353 | ||
2211 | static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev) | 2354 | static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev) |
2212 | { | 2355 | { |
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index 042e08924421..86503c14ce7e 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c | |||
@@ -71,6 +71,9 @@ void pci_remove_bus(struct pci_bus *pci_bus) | |||
71 | down_write(&pci_bus_sem); | 71 | down_write(&pci_bus_sem); |
72 | list_del(&pci_bus->node); | 72 | list_del(&pci_bus->node); |
73 | up_write(&pci_bus_sem); | 73 | up_write(&pci_bus_sem); |
74 | if (!pci_bus->is_added) | ||
75 | return; | ||
76 | |||
74 | pci_remove_legacy_files(pci_bus); | 77 | pci_remove_legacy_files(pci_bus); |
75 | device_remove_file(&pci_bus->dev, &dev_attr_cpuaffinity); | 78 | device_remove_file(&pci_bus->dev, &dev_attr_cpuaffinity); |
76 | device_remove_file(&pci_bus->dev, &dev_attr_cpulistaffinity); | 79 | device_remove_file(&pci_bus->dev, &dev_attr_cpulistaffinity); |
@@ -92,6 +95,7 @@ EXPORT_SYMBOL(pci_remove_bus); | |||
92 | */ | 95 | */ |
93 | void pci_remove_bus_device(struct pci_dev *dev) | 96 | void pci_remove_bus_device(struct pci_dev *dev) |
94 | { | 97 | { |
98 | pci_stop_bus_device(dev); | ||
95 | if (dev->subordinate) { | 99 | if (dev->subordinate) { |
96 | struct pci_bus *b = dev->subordinate; | 100 | struct pci_bus *b = dev->subordinate; |
97 | 101 | ||
diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 5af8bd538149..710d4ea69568 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c | |||
@@ -29,7 +29,7 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev) | |||
29 | if (pdev->is_pcie) | 29 | if (pdev->is_pcie) |
30 | return NULL; | 30 | return NULL; |
31 | while (1) { | 31 | while (1) { |
32 | if (!pdev->bus->self) | 32 | if (!pdev->bus->parent) |
33 | break; | 33 | break; |
34 | pdev = pdev->bus->self; | 34 | pdev = pdev->bus->self; |
35 | /* a p2p bridge */ | 35 | /* a p2p bridge */ |
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 704608945780..334285a8e237 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | 28 | ||
29 | 29 | ||
30 | static void pbus_assign_resources_sorted(struct pci_bus *bus) | 30 | static void pbus_assign_resources_sorted(const struct pci_bus *bus) |
31 | { | 31 | { |
32 | struct pci_dev *dev; | 32 | struct pci_dev *dev; |
33 | struct resource *res; | 33 | struct resource *res; |
@@ -144,6 +144,9 @@ static void pci_setup_bridge(struct pci_bus *bus) | |||
144 | struct pci_bus_region region; | 144 | struct pci_bus_region region; |
145 | u32 l, bu, lu, io_upper16; | 145 | u32 l, bu, lu, io_upper16; |
146 | 146 | ||
147 | if (!pci_is_root_bus(bus) && bus->is_added) | ||
148 | return; | ||
149 | |||
147 | dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n", | 150 | dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n", |
148 | pci_domain_nr(bus), bus->number); | 151 | pci_domain_nr(bus), bus->number); |
149 | 152 | ||
@@ -495,7 +498,7 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus) | |||
495 | } | 498 | } |
496 | EXPORT_SYMBOL(pci_bus_size_bridges); | 499 | EXPORT_SYMBOL(pci_bus_size_bridges); |
497 | 500 | ||
498 | void __ref pci_bus_assign_resources(struct pci_bus *bus) | 501 | void __ref pci_bus_assign_resources(const struct pci_bus *bus) |
499 | { | 502 | { |
500 | struct pci_bus *b; | 503 | struct pci_bus *b; |
501 | struct pci_dev *dev; | 504 | struct pci_dev *dev; |
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 32e8d88a4619..3039fcb86afc 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c | |||
@@ -120,6 +120,21 @@ int pci_claim_resource(struct pci_dev *dev, int resource) | |||
120 | return err; | 120 | return err; |
121 | } | 121 | } |
122 | 122 | ||
123 | #ifdef CONFIG_PCI_QUIRKS | ||
124 | void pci_disable_bridge_window(struct pci_dev *dev) | ||
125 | { | ||
126 | dev_dbg(&dev->dev, "Disabling bridge window.\n"); | ||
127 | |||
128 | /* MMIO Base/Limit */ | ||
129 | pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0); | ||
130 | |||
131 | /* Prefetchable MMIO Base/Limit */ | ||
132 | pci_write_config_dword(dev, PCI_PREF_LIMIT_UPPER32, 0); | ||
133 | pci_write_config_dword(dev, PCI_PREF_MEMORY_BASE, 0x0000fff0); | ||
134 | pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff); | ||
135 | } | ||
136 | #endif /* CONFIG_PCI_QUIRKS */ | ||
137 | |||
123 | int pci_assign_resource(struct pci_dev *dev, int resno) | 138 | int pci_assign_resource(struct pci_dev *dev, int resno) |
124 | { | 139 | { |
125 | struct pci_bus *bus = dev->bus; | 140 | struct pci_bus *bus = dev->bus; |
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index 5a8ccb4f604d..21189447e545 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/pci/slot.c | 2 | * drivers/pci/slot.c |
3 | * Copyright (C) 2006 Matthew Wilcox <matthew@wil.cx> | 3 | * Copyright (C) 2006 Matthew Wilcox <matthew@wil.cx> |
4 | * Copyright (C) 2006-2008 Hewlett-Packard Development Company, L.P. | 4 | * Copyright (C) 2006-2009 Hewlett-Packard Development Company, L.P. |
5 | * Alex Chiang <achiang@hp.com> | 5 | * Alex Chiang <achiang@hp.com> |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/kobject.h> | 8 | #include <linux/kobject.h> |
@@ -52,8 +52,8 @@ static void pci_slot_release(struct kobject *kobj) | |||
52 | struct pci_dev *dev; | 52 | struct pci_dev *dev; |
53 | struct pci_slot *slot = to_pci_slot(kobj); | 53 | struct pci_slot *slot = to_pci_slot(kobj); |
54 | 54 | ||
55 | pr_debug("%s: releasing pci_slot on %x:%d\n", __func__, | 55 | dev_dbg(&slot->bus->dev, "dev %02x, released physical slot %s\n", |
56 | slot->bus->number, slot->number); | 56 | slot->number, pci_slot_name(slot)); |
57 | 57 | ||
58 | list_for_each_entry(dev, &slot->bus->devices, bus_list) | 58 | list_for_each_entry(dev, &slot->bus->devices, bus_list) |
59 | if (PCI_SLOT(dev->devfn) == slot->number) | 59 | if (PCI_SLOT(dev->devfn) == slot->number) |
@@ -248,9 +248,8 @@ placeholder: | |||
248 | if (PCI_SLOT(dev->devfn) == slot_nr) | 248 | if (PCI_SLOT(dev->devfn) == slot_nr) |
249 | dev->slot = slot; | 249 | dev->slot = slot; |
250 | 250 | ||
251 | /* Don't care if debug printk has a -1 for slot_nr */ | 251 | dev_dbg(&parent->dev, "dev %02x, created physical slot %s\n", |
252 | pr_debug("%s: created pci_slot on %04x:%02x:%02x\n", | 252 | slot_nr, pci_slot_name(slot)); |
253 | __func__, pci_domain_nr(parent), parent->number, slot_nr); | ||
254 | 253 | ||
255 | out: | 254 | out: |
256 | kfree(slot_name); | 255 | kfree(slot_name); |
@@ -299,9 +298,8 @@ EXPORT_SYMBOL_GPL(pci_renumber_slot); | |||
299 | */ | 298 | */ |
300 | void pci_destroy_slot(struct pci_slot *slot) | 299 | void pci_destroy_slot(struct pci_slot *slot) |
301 | { | 300 | { |
302 | pr_debug("%s: dec refcount to %d on %04x:%02x:%02x\n", __func__, | 301 | dev_dbg(&slot->bus->dev, "dev %02x, dec refcount to %d\n", |
303 | atomic_read(&slot->kobj.kref.refcount) - 1, | 302 | slot->number, atomic_read(&slot->kobj.kref.refcount) - 1); |
304 | pci_domain_nr(slot->bus), slot->bus->number, slot->number); | ||
305 | 303 | ||
306 | down_write(&pci_bus_sem); | 304 | down_write(&pci_bus_sem); |
307 | kobject_put(&slot->kobj); | 305 | kobject_put(&slot->kobj); |
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c index d63f26e666a4..ba1f7497e4b9 100644 --- a/drivers/platform/x86/asus_acpi.c +++ b/drivers/platform/x86/asus_acpi.c | |||
@@ -987,7 +987,6 @@ asus_proc_add(char *name, proc_writefunc *writefunc, | |||
987 | proc->write_proc = writefunc; | 987 | proc->write_proc = writefunc; |
988 | proc->read_proc = readfunc; | 988 | proc->read_proc = readfunc; |
989 | proc->data = acpi_driver_data(device); | 989 | proc->data = acpi_driver_data(device); |
990 | proc->owner = THIS_MODULE; | ||
991 | proc->uid = asus_uid; | 990 | proc->uid = asus_uid; |
992 | proc->gid = asus_gid; | 991 | proc->gid = asus_gid; |
993 | return 0; | 992 | return 0; |
@@ -1020,7 +1019,6 @@ static int asus_hotk_add_fs(struct acpi_device *device) | |||
1020 | if (proc) { | 1019 | if (proc) { |
1021 | proc->read_proc = proc_read_info; | 1020 | proc->read_proc = proc_read_info; |
1022 | proc->data = acpi_driver_data(device); | 1021 | proc->data = acpi_driver_data(device); |
1023 | proc->owner = THIS_MODULE; | ||
1024 | proc->uid = asus_uid; | 1022 | proc->uid = asus_uid; |
1025 | proc->gid = asus_gid; | 1023 | proc->gid = asus_gid; |
1026 | } else { | 1024 | } else { |
@@ -1436,7 +1434,6 @@ static int __init asus_acpi_init(void) | |||
1436 | printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n"); | 1434 | printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n"); |
1437 | return -ENODEV; | 1435 | return -ENODEV; |
1438 | } | 1436 | } |
1439 | asus_proc_dir->owner = THIS_MODULE; | ||
1440 | 1437 | ||
1441 | result = acpi_bus_register_driver(&asus_hotk_driver); | 1438 | result = acpi_bus_register_driver(&asus_hotk_driver); |
1442 | if (result < 0) { | 1439 | if (result < 0) { |
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 16e11c2ee19a..af9f43021172 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c | |||
@@ -103,7 +103,7 @@ static void parse_da_table(const struct dmi_header *dm) | |||
103 | da_num_tokens += tokens; | 103 | da_num_tokens += tokens; |
104 | } | 104 | } |
105 | 105 | ||
106 | static void find_tokens(const struct dmi_header *dm) | 106 | static void find_tokens(const struct dmi_header *dm, void *dummy) |
107 | { | 107 | { |
108 | switch (dm->type) { | 108 | switch (dm->type) { |
109 | case 0xd4: /* Indexed IO */ | 109 | case 0xd4: /* Indexed IO */ |
@@ -356,7 +356,7 @@ static int __init dell_init(void) | |||
356 | if (!dmi_check_system(dell_device_table)) | 356 | if (!dmi_check_system(dell_device_table)) |
357 | return -ENODEV; | 357 | return -ENODEV; |
358 | 358 | ||
359 | dmi_walk(find_tokens); | 359 | dmi_walk(find_tokens, NULL); |
360 | 360 | ||
361 | if (!da_tokens) { | 361 | if (!da_tokens) { |
362 | printk(KERN_INFO "dell-laptop: Unable to find dmi tokens\n"); | 362 | printk(KERN_INFO "dell-laptop: Unable to find dmi tokens\n"); |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index d2433204a40c..3dad27a385d3 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -6992,7 +6992,6 @@ static int __init ibm_init(struct ibm_init_struct *iibm) | |||
6992 | ret = -ENODEV; | 6992 | ret = -ENODEV; |
6993 | goto err_out; | 6993 | goto err_out; |
6994 | } | 6994 | } |
6995 | entry->owner = THIS_MODULE; | ||
6996 | entry->data = ibm; | 6995 | entry->data = ibm; |
6997 | entry->read_proc = &dispatch_procfs_read; | 6996 | entry->read_proc = &dispatch_procfs_read; |
6998 | if (ibm->write) | 6997 | if (ibm->write) |
@@ -7405,7 +7404,6 @@ static int __init thinkpad_acpi_module_init(void) | |||
7405 | thinkpad_acpi_module_exit(); | 7404 | thinkpad_acpi_module_exit(); |
7406 | return -ENODEV; | 7405 | return -ENODEV; |
7407 | } | 7406 | } |
7408 | proc_dir->owner = THIS_MODULE; | ||
7409 | 7407 | ||
7410 | ret = platform_driver_register(&tpacpi_pdriver); | 7408 | ret = platform_driver_register(&tpacpi_pdriver); |
7411 | if (ret) { | 7409 | if (ret) { |
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 40e60fc2e596..9f187265db8e 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c | |||
@@ -679,8 +679,6 @@ static acpi_status __init add_device(void) | |||
679 | toshiba_proc_dir, | 679 | toshiba_proc_dir, |
680 | (read_proc_t *) dispatch_read, | 680 | (read_proc_t *) dispatch_read, |
681 | item); | 681 | item); |
682 | if (proc) | ||
683 | proc->owner = THIS_MODULE; | ||
684 | if (proc && item->write_func) | 682 | if (proc && item->write_func) |
685 | proc->write_proc = (write_proc_t *) dispatch_write; | 683 | proc->write_proc = (write_proc_t *) dispatch_write; |
686 | } | 684 | } |
@@ -772,7 +770,6 @@ static int __init toshiba_acpi_init(void) | |||
772 | toshiba_acpi_exit(); | 770 | toshiba_acpi_exit(); |
773 | return -ENODEV; | 771 | return -ENODEV; |
774 | } else { | 772 | } else { |
775 | toshiba_proc_dir->owner = THIS_MODULE; | ||
776 | status = add_device(); | 773 | status = add_device(); |
777 | if (ACPI_FAILURE(status)) { | 774 | if (ACPI_FAILURE(status)) { |
778 | toshiba_acpi_exit(); | 775 | toshiba_acpi_exit(); |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 81450fbd8b12..09d5cd33a3f6 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -129,13 +129,14 @@ comment "I2C RTC drivers" | |||
129 | if I2C | 129 | if I2C |
130 | 130 | ||
131 | config RTC_DRV_DS1307 | 131 | config RTC_DRV_DS1307 |
132 | tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00" | 132 | tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025" |
133 | help | 133 | help |
134 | If you say yes here you get support for various compatible RTC | 134 | If you say yes here you get support for various compatible RTC |
135 | chips (often with battery backup) connected with I2C. This driver | 135 | chips (often with battery backup) connected with I2C. This driver |
136 | should handle DS1307, DS1337, DS1338, DS1339, DS1340, ST M41T00, | 136 | should handle DS1307, DS1337, DS1338, DS1339, DS1340, ST M41T00, |
137 | and probably other chips. In some cases the RTC must already | 137 | EPSON RX-8025 and probably other chips. In some cases the RTC |
138 | have been initialized (by manufacturing or a bootloader). | 138 | must already have been initialized (by manufacturing or a |
139 | bootloader). | ||
139 | 140 | ||
140 | The first seven registers on these chips hold an RTC, and other | 141 | The first seven registers on these chips hold an RTC, and other |
141 | registers may add features such as NVRAM, a trickle charger for | 142 | registers may add features such as NVRAM, a trickle charger for |
@@ -440,6 +441,16 @@ config RTC_DRV_DS1742 | |||
440 | This driver can also be built as a module. If so, the module | 441 | This driver can also be built as a module. If so, the module |
441 | will be called rtc-ds1742. | 442 | will be called rtc-ds1742. |
442 | 443 | ||
444 | config RTC_DRV_EFI | ||
445 | tristate "EFI RTC" | ||
446 | depends on IA64 | ||
447 | help | ||
448 | If you say yes here you will get support for the EFI | ||
449 | Real Time Clock. | ||
450 | |||
451 | This driver can also be built as a module. If so, the module | ||
452 | will be called rtc-efi. | ||
453 | |||
443 | config RTC_DRV_STK17TA8 | 454 | config RTC_DRV_STK17TA8 |
444 | tristate "Simtek STK17TA8" | 455 | tristate "Simtek STK17TA8" |
445 | depends on RTC_CLASS | 456 | depends on RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 0e697aa51caa..e7b09986d26e 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -36,6 +36,7 @@ obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | |||
36 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 36 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
37 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | 37 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o |
38 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o | 38 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o |
39 | obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o | ||
39 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o | 40 | obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o |
40 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o | 41 | obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o |
41 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o | 42 | obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o |
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 7e5155e88ac7..2c4a65302a9d 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2005 James Chapman (ds1337 core) | 4 | * Copyright (C) 2005 James Chapman (ds1337 core) |
5 | * Copyright (C) 2006 David Brownell | 5 | * Copyright (C) 2006 David Brownell |
6 | * Copyright (C) 2009 Matthias Fuchs (rx8025 support) | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -31,6 +32,7 @@ enum ds_type { | |||
31 | ds_1339, | 32 | ds_1339, |
32 | ds_1340, | 33 | ds_1340, |
33 | m41t00, | 34 | m41t00, |
35 | rx_8025, | ||
34 | // rs5c372 too? different address... | 36 | // rs5c372 too? different address... |
35 | }; | 37 | }; |
36 | 38 | ||
@@ -83,6 +85,12 @@ enum ds_type { | |||
83 | #define DS1339_REG_ALARM1_SECS 0x07 | 85 | #define DS1339_REG_ALARM1_SECS 0x07 |
84 | #define DS1339_REG_TRICKLE 0x10 | 86 | #define DS1339_REG_TRICKLE 0x10 |
85 | 87 | ||
88 | #define RX8025_REG_CTRL1 0x0e | ||
89 | # define RX8025_BIT_2412 0x20 | ||
90 | #define RX8025_REG_CTRL2 0x0f | ||
91 | # define RX8025_BIT_PON 0x10 | ||
92 | # define RX8025_BIT_VDET 0x40 | ||
93 | # define RX8025_BIT_XST 0x20 | ||
86 | 94 | ||
87 | 95 | ||
88 | struct ds1307 { | 96 | struct ds1307 { |
@@ -94,6 +102,10 @@ struct ds1307 { | |||
94 | struct i2c_client *client; | 102 | struct i2c_client *client; |
95 | struct rtc_device *rtc; | 103 | struct rtc_device *rtc; |
96 | struct work_struct work; | 104 | struct work_struct work; |
105 | s32 (*read_block_data)(struct i2c_client *client, u8 command, | ||
106 | u8 length, u8 *values); | ||
107 | s32 (*write_block_data)(struct i2c_client *client, u8 command, | ||
108 | u8 length, const u8 *values); | ||
97 | }; | 109 | }; |
98 | 110 | ||
99 | struct chip_desc { | 111 | struct chip_desc { |
@@ -117,6 +129,8 @@ static const struct chip_desc chips[] = { | |||
117 | [ds_1340] = { | 129 | [ds_1340] = { |
118 | }, | 130 | }, |
119 | [m41t00] = { | 131 | [m41t00] = { |
132 | }, | ||
133 | [rx_8025] = { | ||
120 | }, }; | 134 | }, }; |
121 | 135 | ||
122 | static const struct i2c_device_id ds1307_id[] = { | 136 | static const struct i2c_device_id ds1307_id[] = { |
@@ -126,12 +140,86 @@ static const struct i2c_device_id ds1307_id[] = { | |||
126 | { "ds1339", ds_1339 }, | 140 | { "ds1339", ds_1339 }, |
127 | { "ds1340", ds_1340 }, | 141 | { "ds1340", ds_1340 }, |
128 | { "m41t00", m41t00 }, | 142 | { "m41t00", m41t00 }, |
143 | { "rx8025", rx_8025 }, | ||
129 | { } | 144 | { } |
130 | }; | 145 | }; |
131 | MODULE_DEVICE_TABLE(i2c, ds1307_id); | 146 | MODULE_DEVICE_TABLE(i2c, ds1307_id); |
132 | 147 | ||
133 | /*----------------------------------------------------------------------*/ | 148 | /*----------------------------------------------------------------------*/ |
134 | 149 | ||
150 | #define BLOCK_DATA_MAX_TRIES 10 | ||
151 | |||
152 | static s32 ds1307_read_block_data_once(struct i2c_client *client, u8 command, | ||
153 | u8 length, u8 *values) | ||
154 | { | ||
155 | s32 i, data; | ||
156 | |||
157 | for (i = 0; i < length; i++) { | ||
158 | data = i2c_smbus_read_byte_data(client, command + i); | ||
159 | if (data < 0) | ||
160 | return data; | ||
161 | values[i] = data; | ||
162 | } | ||
163 | return i; | ||
164 | } | ||
165 | |||
166 | static s32 ds1307_read_block_data(struct i2c_client *client, u8 command, | ||
167 | u8 length, u8 *values) | ||
168 | { | ||
169 | u8 oldvalues[I2C_SMBUS_BLOCK_MAX]; | ||
170 | s32 ret; | ||
171 | int tries = 0; | ||
172 | |||
173 | dev_dbg(&client->dev, "ds1307_read_block_data (length=%d)\n", length); | ||
174 | ret = ds1307_read_block_data_once(client, command, length, values); | ||
175 | if (ret < 0) | ||
176 | return ret; | ||
177 | do { | ||
178 | if (++tries > BLOCK_DATA_MAX_TRIES) { | ||
179 | dev_err(&client->dev, | ||
180 | "ds1307_read_block_data failed\n"); | ||
181 | return -EIO; | ||
182 | } | ||
183 | memcpy(oldvalues, values, length); | ||
184 | ret = ds1307_read_block_data_once(client, command, length, | ||
185 | values); | ||
186 | if (ret < 0) | ||
187 | return ret; | ||
188 | } while (memcmp(oldvalues, values, length)); | ||
189 | return length; | ||
190 | } | ||
191 | |||
192 | static s32 ds1307_write_block_data(struct i2c_client *client, u8 command, | ||
193 | u8 length, const u8 *values) | ||
194 | { | ||
195 | u8 currvalues[I2C_SMBUS_BLOCK_MAX]; | ||
196 | int tries = 0; | ||
197 | |||
198 | dev_dbg(&client->dev, "ds1307_write_block_data (length=%d)\n", length); | ||
199 | do { | ||
200 | s32 i, ret; | ||
201 | |||
202 | if (++tries > BLOCK_DATA_MAX_TRIES) { | ||
203 | dev_err(&client->dev, | ||
204 | "ds1307_write_block_data failed\n"); | ||
205 | return -EIO; | ||
206 | } | ||
207 | for (i = 0; i < length; i++) { | ||
208 | ret = i2c_smbus_write_byte_data(client, command + i, | ||
209 | values[i]); | ||
210 | if (ret < 0) | ||
211 | return ret; | ||
212 | } | ||
213 | ret = ds1307_read_block_data_once(client, command, length, | ||
214 | currvalues); | ||
215 | if (ret < 0) | ||
216 | return ret; | ||
217 | } while (memcmp(currvalues, values, length)); | ||
218 | return length; | ||
219 | } | ||
220 | |||
221 | /*----------------------------------------------------------------------*/ | ||
222 | |||
135 | /* | 223 | /* |
136 | * The IRQ logic includes a "real" handler running in IRQ context just | 224 | * The IRQ logic includes a "real" handler running in IRQ context just |
137 | * long enough to schedule this workqueue entry. We need a task context | 225 | * long enough to schedule this workqueue entry. We need a task context |
@@ -202,7 +290,7 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) | |||
202 | int tmp; | 290 | int tmp; |
203 | 291 | ||
204 | /* read the RTC date and time registers all at once */ | 292 | /* read the RTC date and time registers all at once */ |
205 | tmp = i2c_smbus_read_i2c_block_data(ds1307->client, | 293 | tmp = ds1307->read_block_data(ds1307->client, |
206 | DS1307_REG_SECS, 7, ds1307->regs); | 294 | DS1307_REG_SECS, 7, ds1307->regs); |
207 | if (tmp != 7) { | 295 | if (tmp != 7) { |
208 | dev_err(dev, "%s error %d\n", "read", tmp); | 296 | dev_err(dev, "%s error %d\n", "read", tmp); |
@@ -279,7 +367,7 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) | |||
279 | "write", buf[0], buf[1], buf[2], buf[3], | 367 | "write", buf[0], buf[1], buf[2], buf[3], |
280 | buf[4], buf[5], buf[6]); | 368 | buf[4], buf[5], buf[6]); |
281 | 369 | ||
282 | result = i2c_smbus_write_i2c_block_data(ds1307->client, 0, 7, buf); | 370 | result = ds1307->write_block_data(ds1307->client, 0, 7, buf); |
283 | if (result < 0) { | 371 | if (result < 0) { |
284 | dev_err(dev, "%s error %d\n", "write", result); | 372 | dev_err(dev, "%s error %d\n", "write", result); |
285 | return result; | 373 | return result; |
@@ -297,7 +385,7 @@ static int ds1337_read_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
297 | return -EINVAL; | 385 | return -EINVAL; |
298 | 386 | ||
299 | /* read all ALARM1, ALARM2, and status registers at once */ | 387 | /* read all ALARM1, ALARM2, and status registers at once */ |
300 | ret = i2c_smbus_read_i2c_block_data(client, | 388 | ret = ds1307->read_block_data(client, |
301 | DS1339_REG_ALARM1_SECS, 9, ds1307->regs); | 389 | DS1339_REG_ALARM1_SECS, 9, ds1307->regs); |
302 | if (ret != 9) { | 390 | if (ret != 9) { |
303 | dev_err(dev, "%s error %d\n", "alarm read", ret); | 391 | dev_err(dev, "%s error %d\n", "alarm read", ret); |
@@ -356,7 +444,7 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
356 | t->enabled, t->pending); | 444 | t->enabled, t->pending); |
357 | 445 | ||
358 | /* read current status of both alarms and the chip */ | 446 | /* read current status of both alarms and the chip */ |
359 | ret = i2c_smbus_read_i2c_block_data(client, | 447 | ret = ds1307->read_block_data(client, |
360 | DS1339_REG_ALARM1_SECS, 9, buf); | 448 | DS1339_REG_ALARM1_SECS, 9, buf); |
361 | if (ret != 9) { | 449 | if (ret != 9) { |
362 | dev_err(dev, "%s error %d\n", "alarm write", ret); | 450 | dev_err(dev, "%s error %d\n", "alarm write", ret); |
@@ -391,7 +479,7 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
391 | } | 479 | } |
392 | buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I); | 480 | buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I); |
393 | 481 | ||
394 | ret = i2c_smbus_write_i2c_block_data(client, | 482 | ret = ds1307->write_block_data(client, |
395 | DS1339_REG_ALARM1_SECS, 9, buf); | 483 | DS1339_REG_ALARM1_SECS, 9, buf); |
396 | if (ret < 0) { | 484 | if (ret < 0) { |
397 | dev_err(dev, "can't set alarm time\n"); | 485 | dev_err(dev, "can't set alarm time\n"); |
@@ -479,7 +567,7 @@ ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | |||
479 | if (unlikely(!count)) | 567 | if (unlikely(!count)) |
480 | return count; | 568 | return count; |
481 | 569 | ||
482 | result = i2c_smbus_read_i2c_block_data(client, 8 + off, count, buf); | 570 | result = ds1307->read_block_data(client, 8 + off, count, buf); |
483 | if (result < 0) | 571 | if (result < 0) |
484 | dev_err(&client->dev, "%s error %d\n", "nvram read", result); | 572 | dev_err(&client->dev, "%s error %d\n", "nvram read", result); |
485 | return result; | 573 | return result; |
@@ -490,9 +578,11 @@ ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | |||
490 | char *buf, loff_t off, size_t count) | 578 | char *buf, loff_t off, size_t count) |
491 | { | 579 | { |
492 | struct i2c_client *client; | 580 | struct i2c_client *client; |
581 | struct ds1307 *ds1307; | ||
493 | int result; | 582 | int result; |
494 | 583 | ||
495 | client = kobj_to_i2c_client(kobj); | 584 | client = kobj_to_i2c_client(kobj); |
585 | ds1307 = i2c_get_clientdata(client); | ||
496 | 586 | ||
497 | if (unlikely(off >= NVRAM_SIZE)) | 587 | if (unlikely(off >= NVRAM_SIZE)) |
498 | return -EFBIG; | 588 | return -EFBIG; |
@@ -501,7 +591,7 @@ ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | |||
501 | if (unlikely(!count)) | 591 | if (unlikely(!count)) |
502 | return count; | 592 | return count; |
503 | 593 | ||
504 | result = i2c_smbus_write_i2c_block_data(client, 8 + off, count, buf); | 594 | result = ds1307->write_block_data(client, 8 + off, count, buf); |
505 | if (result < 0) { | 595 | if (result < 0) { |
506 | dev_err(&client->dev, "%s error %d\n", "nvram write", result); | 596 | dev_err(&client->dev, "%s error %d\n", "nvram write", result); |
507 | return result; | 597 | return result; |
@@ -535,9 +625,8 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
535 | int want_irq = false; | 625 | int want_irq = false; |
536 | unsigned char *buf; | 626 | unsigned char *buf; |
537 | 627 | ||
538 | if (!i2c_check_functionality(adapter, | 628 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA) |
539 | I2C_FUNC_SMBUS_WRITE_BYTE_DATA | | 629 | && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) |
540 | I2C_FUNC_SMBUS_I2C_BLOCK)) | ||
541 | return -EIO; | 630 | return -EIO; |
542 | 631 | ||
543 | if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL))) | 632 | if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL))) |
@@ -547,6 +636,13 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
547 | i2c_set_clientdata(client, ds1307); | 636 | i2c_set_clientdata(client, ds1307); |
548 | ds1307->type = id->driver_data; | 637 | ds1307->type = id->driver_data; |
549 | buf = ds1307->regs; | 638 | buf = ds1307->regs; |
639 | if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { | ||
640 | ds1307->read_block_data = i2c_smbus_read_i2c_block_data; | ||
641 | ds1307->write_block_data = i2c_smbus_write_i2c_block_data; | ||
642 | } else { | ||
643 | ds1307->read_block_data = ds1307_read_block_data; | ||
644 | ds1307->write_block_data = ds1307_write_block_data; | ||
645 | } | ||
550 | 646 | ||
551 | switch (ds1307->type) { | 647 | switch (ds1307->type) { |
552 | case ds_1337: | 648 | case ds_1337: |
@@ -557,7 +653,7 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
557 | want_irq = true; | 653 | want_irq = true; |
558 | } | 654 | } |
559 | /* get registers that the "rtc" read below won't read... */ | 655 | /* get registers that the "rtc" read below won't read... */ |
560 | tmp = i2c_smbus_read_i2c_block_data(ds1307->client, | 656 | tmp = ds1307->read_block_data(ds1307->client, |
561 | DS1337_REG_CONTROL, 2, buf); | 657 | DS1337_REG_CONTROL, 2, buf); |
562 | if (tmp != 2) { | 658 | if (tmp != 2) { |
563 | pr_debug("read error %d\n", tmp); | 659 | pr_debug("read error %d\n", tmp); |
@@ -589,13 +685,79 @@ static int __devinit ds1307_probe(struct i2c_client *client, | |||
589 | dev_warn(&client->dev, "SET TIME!\n"); | 685 | dev_warn(&client->dev, "SET TIME!\n"); |
590 | } | 686 | } |
591 | break; | 687 | break; |
688 | |||
689 | case rx_8025: | ||
690 | tmp = i2c_smbus_read_i2c_block_data(ds1307->client, | ||
691 | RX8025_REG_CTRL1 << 4 | 0x08, 2, buf); | ||
692 | if (tmp != 2) { | ||
693 | pr_debug("read error %d\n", tmp); | ||
694 | err = -EIO; | ||
695 | goto exit_free; | ||
696 | } | ||
697 | |||
698 | /* oscillator off? turn it on, so clock can tick. */ | ||
699 | if (!(ds1307->regs[1] & RX8025_BIT_XST)) { | ||
700 | ds1307->regs[1] |= RX8025_BIT_XST; | ||
701 | i2c_smbus_write_byte_data(client, | ||
702 | RX8025_REG_CTRL2 << 4 | 0x08, | ||
703 | ds1307->regs[1]); | ||
704 | dev_warn(&client->dev, | ||
705 | "oscillator stop detected - SET TIME!\n"); | ||
706 | } | ||
707 | |||
708 | if (ds1307->regs[1] & RX8025_BIT_PON) { | ||
709 | ds1307->regs[1] &= ~RX8025_BIT_PON; | ||
710 | i2c_smbus_write_byte_data(client, | ||
711 | RX8025_REG_CTRL2 << 4 | 0x08, | ||
712 | ds1307->regs[1]); | ||
713 | dev_warn(&client->dev, "power-on detected\n"); | ||
714 | } | ||
715 | |||
716 | if (ds1307->regs[1] & RX8025_BIT_VDET) { | ||
717 | ds1307->regs[1] &= ~RX8025_BIT_VDET; | ||
718 | i2c_smbus_write_byte_data(client, | ||
719 | RX8025_REG_CTRL2 << 4 | 0x08, | ||
720 | ds1307->regs[1]); | ||
721 | dev_warn(&client->dev, "voltage drop detected\n"); | ||
722 | } | ||
723 | |||
724 | /* make sure we are running in 24hour mode */ | ||
725 | if (!(ds1307->regs[0] & RX8025_BIT_2412)) { | ||
726 | u8 hour; | ||
727 | |||
728 | /* switch to 24 hour mode */ | ||
729 | i2c_smbus_write_byte_data(client, | ||
730 | RX8025_REG_CTRL1 << 4 | 0x08, | ||
731 | ds1307->regs[0] | | ||
732 | RX8025_BIT_2412); | ||
733 | |||
734 | tmp = i2c_smbus_read_i2c_block_data(ds1307->client, | ||
735 | RX8025_REG_CTRL1 << 4 | 0x08, 2, buf); | ||
736 | if (tmp != 2) { | ||
737 | pr_debug("read error %d\n", tmp); | ||
738 | err = -EIO; | ||
739 | goto exit_free; | ||
740 | } | ||
741 | |||
742 | /* correct hour */ | ||
743 | hour = bcd2bin(ds1307->regs[DS1307_REG_HOUR]); | ||
744 | if (hour == 12) | ||
745 | hour = 0; | ||
746 | if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM) | ||
747 | hour += 12; | ||
748 | |||
749 | i2c_smbus_write_byte_data(client, | ||
750 | DS1307_REG_HOUR << 4 | 0x08, | ||
751 | hour); | ||
752 | } | ||
753 | break; | ||
592 | default: | 754 | default: |
593 | break; | 755 | break; |
594 | } | 756 | } |
595 | 757 | ||
596 | read_rtc: | 758 | read_rtc: |
597 | /* read RTC registers */ | 759 | /* read RTC registers */ |
598 | tmp = i2c_smbus_read_i2c_block_data(ds1307->client, 0, 8, buf); | 760 | tmp = ds1307->read_block_data(ds1307->client, 0, 8, buf); |
599 | if (tmp != 8) { | 761 | if (tmp != 8) { |
600 | pr_debug("read error %d\n", tmp); | 762 | pr_debug("read error %d\n", tmp); |
601 | err = -EIO; | 763 | err = -EIO; |
@@ -649,6 +811,7 @@ read_rtc: | |||
649 | dev_warn(&client->dev, "SET TIME!\n"); | 811 | dev_warn(&client->dev, "SET TIME!\n"); |
650 | } | 812 | } |
651 | break; | 813 | break; |
814 | case rx_8025: | ||
652 | case ds_1337: | 815 | case ds_1337: |
653 | case ds_1339: | 816 | case ds_1339: |
654 | break; | 817 | break; |
@@ -662,6 +825,8 @@ read_rtc: | |||
662 | * systems that will run through year 2100. | 825 | * systems that will run through year 2100. |
663 | */ | 826 | */ |
664 | break; | 827 | break; |
828 | case rx_8025: | ||
829 | break; | ||
665 | default: | 830 | default: |
666 | if (!(tmp & DS1307_BIT_12HR)) | 831 | if (!(tmp & DS1307_BIT_12HR)) |
667 | break; | 832 | break; |
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index a5b0fc09f0c6..4d32e328f6cd 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c | |||
@@ -222,16 +222,16 @@ static int ds1374_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
222 | rtc_tm_to_time(&alarm->time, &new_alarm); | 222 | rtc_tm_to_time(&alarm->time, &new_alarm); |
223 | rtc_tm_to_time(&now, &itime); | 223 | rtc_tm_to_time(&now, &itime); |
224 | 224 | ||
225 | new_alarm -= itime; | ||
226 | |||
227 | /* This can happen due to races, in addition to dates that are | 225 | /* This can happen due to races, in addition to dates that are |
228 | * truly in the past. To avoid requiring the caller to check for | 226 | * truly in the past. To avoid requiring the caller to check for |
229 | * races, dates in the past are assumed to be in the recent past | 227 | * races, dates in the past are assumed to be in the recent past |
230 | * (i.e. not something that we'd rather the caller know about via | 228 | * (i.e. not something that we'd rather the caller know about via |
231 | * an error), and the alarm is set to go off as soon as possible. | 229 | * an error), and the alarm is set to go off as soon as possible. |
232 | */ | 230 | */ |
233 | if (new_alarm <= 0) | 231 | if (time_before_eq(new_alarm, itime)) |
234 | new_alarm = 1; | 232 | new_alarm = 1; |
233 | else | ||
234 | new_alarm -= itime; | ||
235 | 235 | ||
236 | mutex_lock(&ds1374->mutex); | 236 | mutex_lock(&ds1374->mutex); |
237 | 237 | ||
diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c new file mode 100644 index 000000000000..550292304b0f --- /dev/null +++ b/drivers/rtc/rtc-efi.c | |||
@@ -0,0 +1,235 @@ | |||
1 | /* | ||
2 | * rtc-efi: RTC Class Driver for EFI-based systems | ||
3 | * | ||
4 | * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. | ||
5 | * | ||
6 | * Author: dann frazier <dannf@hp.com> | ||
7 | * Based on efirtc.c by Stephane Eranian | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/time.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/rtc.h> | ||
21 | #include <linux/efi.h> | ||
22 | |||
23 | #define EFI_ISDST (EFI_TIME_ADJUST_DAYLIGHT|EFI_TIME_IN_DAYLIGHT) | ||
24 | /* | ||
25 | * EFI Epoch is 1/1/1998 | ||
26 | */ | ||
27 | #define EFI_RTC_EPOCH 1998 | ||
28 | |||
29 | /* | ||
30 | * returns day of the year [0-365] | ||
31 | */ | ||
32 | static inline int | ||
33 | compute_yday(efi_time_t *eft) | ||
34 | { | ||
35 | /* efi_time_t.month is in the [1-12] so, we need -1 */ | ||
36 | return rtc_year_days(eft->day - 1, eft->month - 1, eft->year); | ||
37 | } | ||
38 | /* | ||
39 | * returns day of the week [0-6] 0=Sunday | ||
40 | * | ||
41 | * Don't try to provide a year that's before 1998, please ! | ||
42 | */ | ||
43 | static int | ||
44 | compute_wday(efi_time_t *eft) | ||
45 | { | ||
46 | int y; | ||
47 | int ndays = 0; | ||
48 | |||
49 | if (eft->year < 1998) { | ||
50 | printk(KERN_ERR "efirtc: EFI year < 1998, invalid date\n"); | ||
51 | return -1; | ||
52 | } | ||
53 | |||
54 | for (y = EFI_RTC_EPOCH; y < eft->year; y++) | ||
55 | ndays += 365 + (is_leap_year(y) ? 1 : 0); | ||
56 | |||
57 | ndays += compute_yday(eft); | ||
58 | |||
59 | /* | ||
60 | * 4=1/1/1998 was a Thursday | ||
61 | */ | ||
62 | return (ndays + 4) % 7; | ||
63 | } | ||
64 | |||
65 | static void | ||
66 | convert_to_efi_time(struct rtc_time *wtime, efi_time_t *eft) | ||
67 | { | ||
68 | eft->year = wtime->tm_year + 1900; | ||
69 | eft->month = wtime->tm_mon + 1; | ||
70 | eft->day = wtime->tm_mday; | ||
71 | eft->hour = wtime->tm_hour; | ||
72 | eft->minute = wtime->tm_min; | ||
73 | eft->second = wtime->tm_sec; | ||
74 | eft->nanosecond = 0; | ||
75 | eft->daylight = wtime->tm_isdst ? EFI_ISDST : 0; | ||
76 | eft->timezone = EFI_UNSPECIFIED_TIMEZONE; | ||
77 | } | ||
78 | |||
79 | static void | ||
80 | convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime) | ||
81 | { | ||
82 | memset(wtime, 0, sizeof(*wtime)); | ||
83 | wtime->tm_sec = eft->second; | ||
84 | wtime->tm_min = eft->minute; | ||
85 | wtime->tm_hour = eft->hour; | ||
86 | wtime->tm_mday = eft->day; | ||
87 | wtime->tm_mon = eft->month - 1; | ||
88 | wtime->tm_year = eft->year - 1900; | ||
89 | |||
90 | /* day of the week [0-6], Sunday=0 */ | ||
91 | wtime->tm_wday = compute_wday(eft); | ||
92 | |||
93 | /* day in the year [1-365]*/ | ||
94 | wtime->tm_yday = compute_yday(eft); | ||
95 | |||
96 | |||
97 | switch (eft->daylight & EFI_ISDST) { | ||
98 | case EFI_ISDST: | ||
99 | wtime->tm_isdst = 1; | ||
100 | break; | ||
101 | case EFI_TIME_ADJUST_DAYLIGHT: | ||
102 | wtime->tm_isdst = 0; | ||
103 | break; | ||
104 | default: | ||
105 | wtime->tm_isdst = -1; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static int efi_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | ||
110 | { | ||
111 | efi_time_t eft; | ||
112 | efi_status_t status; | ||
113 | |||
114 | /* | ||
115 | * As of EFI v1.10, this call always returns an unsupported status | ||
116 | */ | ||
117 | status = efi.get_wakeup_time((efi_bool_t *)&wkalrm->enabled, | ||
118 | (efi_bool_t *)&wkalrm->pending, &eft); | ||
119 | |||
120 | if (status != EFI_SUCCESS) | ||
121 | return -EINVAL; | ||
122 | |||
123 | convert_from_efi_time(&eft, &wkalrm->time); | ||
124 | |||
125 | return rtc_valid_tm(&wkalrm->time); | ||
126 | } | ||
127 | |||
128 | static int efi_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) | ||
129 | { | ||
130 | efi_time_t eft; | ||
131 | efi_status_t status; | ||
132 | |||
133 | convert_to_efi_time(&wkalrm->time, &eft); | ||
134 | |||
135 | /* | ||
136 | * XXX Fixme: | ||
137 | * As of EFI 0.92 with the firmware I have on my | ||
138 | * machine this call does not seem to work quite | ||
139 | * right | ||
140 | * | ||
141 | * As of v1.10, this call always returns an unsupported status | ||
142 | */ | ||
143 | status = efi.set_wakeup_time((efi_bool_t)wkalrm->enabled, &eft); | ||
144 | |||
145 | printk(KERN_WARNING "write status is %d\n", (int)status); | ||
146 | |||
147 | return status == EFI_SUCCESS ? 0 : -EINVAL; | ||
148 | } | ||
149 | |||
150 | static int efi_read_time(struct device *dev, struct rtc_time *tm) | ||
151 | { | ||
152 | efi_status_t status; | ||
153 | efi_time_t eft; | ||
154 | efi_time_cap_t cap; | ||
155 | |||
156 | status = efi.get_time(&eft, &cap); | ||
157 | |||
158 | if (status != EFI_SUCCESS) { | ||
159 | /* should never happen */ | ||
160 | printk(KERN_ERR "efitime: can't read time\n"); | ||
161 | return -EINVAL; | ||
162 | } | ||
163 | |||
164 | convert_from_efi_time(&eft, tm); | ||
165 | |||
166 | return rtc_valid_tm(tm); | ||
167 | } | ||
168 | |||
169 | static int efi_set_time(struct device *dev, struct rtc_time *tm) | ||
170 | { | ||
171 | efi_status_t status; | ||
172 | efi_time_t eft; | ||
173 | |||
174 | convert_to_efi_time(tm, &eft); | ||
175 | |||
176 | status = efi.set_time(&eft); | ||
177 | |||
178 | return status == EFI_SUCCESS ? 0 : -EINVAL; | ||
179 | } | ||
180 | |||
181 | static const struct rtc_class_ops efi_rtc_ops = { | ||
182 | .read_time = efi_read_time, | ||
183 | .set_time = efi_set_time, | ||
184 | .read_alarm = efi_read_alarm, | ||
185 | .set_alarm = efi_set_alarm, | ||
186 | }; | ||
187 | |||
188 | static int __init efi_rtc_probe(struct platform_device *dev) | ||
189 | { | ||
190 | struct rtc_device *rtc; | ||
191 | |||
192 | rtc = rtc_device_register("rtc-efi", &dev->dev, &efi_rtc_ops, | ||
193 | THIS_MODULE); | ||
194 | if (IS_ERR(rtc)) | ||
195 | return PTR_ERR(rtc); | ||
196 | |||
197 | platform_set_drvdata(dev, rtc); | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int __exit efi_rtc_remove(struct platform_device *dev) | ||
203 | { | ||
204 | struct rtc_device *rtc = platform_get_drvdata(dev); | ||
205 | |||
206 | rtc_device_unregister(rtc); | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static struct platform_driver efi_rtc_driver = { | ||
212 | .driver = { | ||
213 | .name = "rtc-efi", | ||
214 | .owner = THIS_MODULE, | ||
215 | }, | ||
216 | .probe = efi_rtc_probe, | ||
217 | .remove = __exit_p(efi_rtc_remove), | ||
218 | }; | ||
219 | |||
220 | static int __init efi_rtc_init(void) | ||
221 | { | ||
222 | return platform_driver_probe(&efi_rtc_driver, efi_rtc_probe); | ||
223 | } | ||
224 | |||
225 | static void __exit efi_rtc_exit(void) | ||
226 | { | ||
227 | platform_driver_unregister(&efi_rtc_driver); | ||
228 | } | ||
229 | |||
230 | module_init(efi_rtc_init); | ||
231 | module_exit(efi_rtc_exit); | ||
232 | |||
233 | MODULE_AUTHOR("dann frazier <dannf@hp.com>"); | ||
234 | MODULE_LICENSE("GPL"); | ||
235 | MODULE_DESCRIPTION("EFI RTC driver"); | ||
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index dd70bf73ce9d..773851f338b8 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c | |||
@@ -26,14 +26,13 @@ static const unsigned short rtc_ydays[2][13] = { | |||
26 | }; | 26 | }; |
27 | 27 | ||
28 | #define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) | 28 | #define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400) |
29 | #define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400)) | ||
30 | 29 | ||
31 | /* | 30 | /* |
32 | * The number of days in the month. | 31 | * The number of days in the month. |
33 | */ | 32 | */ |
34 | int rtc_month_days(unsigned int month, unsigned int year) | 33 | int rtc_month_days(unsigned int month, unsigned int year) |
35 | { | 34 | { |
36 | return rtc_days_in_month[month] + (LEAP_YEAR(year) && month == 1); | 35 | return rtc_days_in_month[month] + (is_leap_year(year) && month == 1); |
37 | } | 36 | } |
38 | EXPORT_SYMBOL(rtc_month_days); | 37 | EXPORT_SYMBOL(rtc_month_days); |
39 | 38 | ||
@@ -42,7 +41,7 @@ EXPORT_SYMBOL(rtc_month_days); | |||
42 | */ | 41 | */ |
43 | int rtc_year_days(unsigned int day, unsigned int month, unsigned int year) | 42 | int rtc_year_days(unsigned int day, unsigned int month, unsigned int year) |
44 | { | 43 | { |
45 | return rtc_ydays[LEAP_YEAR(year)][month] + day-1; | 44 | return rtc_ydays[is_leap_year(year)][month] + day-1; |
46 | } | 45 | } |
47 | EXPORT_SYMBOL(rtc_year_days); | 46 | EXPORT_SYMBOL(rtc_year_days); |
48 | 47 | ||
@@ -66,7 +65,7 @@ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) | |||
66 | - LEAPS_THRU_END_OF(1970 - 1); | 65 | - LEAPS_THRU_END_OF(1970 - 1); |
67 | if (days < 0) { | 66 | if (days < 0) { |
68 | year -= 1; | 67 | year -= 1; |
69 | days += 365 + LEAP_YEAR(year); | 68 | days += 365 + is_leap_year(year); |
70 | } | 69 | } |
71 | tm->tm_year = year - 1900; | 70 | tm->tm_year = year - 1900; |
72 | tm->tm_yday = days + 1; | 71 | tm->tm_yday = days + 1; |
diff --git a/drivers/rtc/rtc-parisc.c b/drivers/rtc/rtc-parisc.c index c6bfa6fe1a2a..b966f56da976 100644 --- a/drivers/rtc/rtc-parisc.c +++ b/drivers/rtc/rtc-parisc.c | |||
@@ -7,41 +7,25 @@ | |||
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <linux/time.h> | 8 | #include <linux/time.h> |
9 | #include <linux/platform_device.h> | 9 | #include <linux/platform_device.h> |
10 | #include <linux/rtc.h> | ||
10 | 11 | ||
11 | #include <asm/rtc.h> | 12 | #include <asm/rtc.h> |
12 | 13 | ||
13 | /* as simple as can be, and no simpler. */ | ||
14 | struct parisc_rtc { | ||
15 | struct rtc_device *rtc; | ||
16 | spinlock_t lock; | ||
17 | }; | ||
18 | |||
19 | static int parisc_get_time(struct device *dev, struct rtc_time *tm) | 14 | static int parisc_get_time(struct device *dev, struct rtc_time *tm) |
20 | { | 15 | { |
21 | struct parisc_rtc *p = dev_get_drvdata(dev); | 16 | unsigned long ret; |
22 | unsigned long flags, ret; | ||
23 | 17 | ||
24 | spin_lock_irqsave(&p->lock, flags); | ||
25 | ret = get_rtc_time(tm); | 18 | ret = get_rtc_time(tm); |
26 | spin_unlock_irqrestore(&p->lock, flags); | ||
27 | 19 | ||
28 | if (ret & RTC_BATT_BAD) | 20 | if (ret & RTC_BATT_BAD) |
29 | return -EOPNOTSUPP; | 21 | return -EOPNOTSUPP; |
30 | 22 | ||
31 | return 0; | 23 | return rtc_valid_tm(tm); |
32 | } | 24 | } |
33 | 25 | ||
34 | static int parisc_set_time(struct device *dev, struct rtc_time *tm) | 26 | static int parisc_set_time(struct device *dev, struct rtc_time *tm) |
35 | { | 27 | { |
36 | struct parisc_rtc *p = dev_get_drvdata(dev); | 28 | if (set_rtc_time(tm) < 0) |
37 | unsigned long flags; | ||
38 | int ret; | ||
39 | |||
40 | spin_lock_irqsave(&p->lock, flags); | ||
41 | ret = set_rtc_time(tm); | ||
42 | spin_unlock_irqrestore(&p->lock, flags); | ||
43 | |||
44 | if (ret < 0) | ||
45 | return -EOPNOTSUPP; | 29 | return -EOPNOTSUPP; |
46 | 30 | ||
47 | return 0; | 31 | return 0; |
@@ -52,35 +36,25 @@ static const struct rtc_class_ops parisc_rtc_ops = { | |||
52 | .set_time = parisc_set_time, | 36 | .set_time = parisc_set_time, |
53 | }; | 37 | }; |
54 | 38 | ||
55 | static int __devinit parisc_rtc_probe(struct platform_device *dev) | 39 | static int __init parisc_rtc_probe(struct platform_device *dev) |
56 | { | 40 | { |
57 | struct parisc_rtc *p; | 41 | struct rtc_device *rtc; |
58 | |||
59 | p = kzalloc(sizeof (*p), GFP_KERNEL); | ||
60 | if (!p) | ||
61 | return -ENOMEM; | ||
62 | |||
63 | spin_lock_init(&p->lock); | ||
64 | 42 | ||
65 | p->rtc = rtc_device_register("rtc-parisc", &dev->dev, &parisc_rtc_ops, | 43 | rtc = rtc_device_register("rtc-parisc", &dev->dev, &parisc_rtc_ops, |
66 | THIS_MODULE); | 44 | THIS_MODULE); |
67 | if (IS_ERR(p->rtc)) { | 45 | if (IS_ERR(rtc)) |
68 | int err = PTR_ERR(p->rtc); | 46 | return PTR_ERR(rtc); |
69 | kfree(p); | ||
70 | return err; | ||
71 | } | ||
72 | 47 | ||
73 | platform_set_drvdata(dev, p); | 48 | platform_set_drvdata(dev, rtc); |
74 | 49 | ||
75 | return 0; | 50 | return 0; |
76 | } | 51 | } |
77 | 52 | ||
78 | static int __devexit parisc_rtc_remove(struct platform_device *dev) | 53 | static int __exit parisc_rtc_remove(struct platform_device *dev) |
79 | { | 54 | { |
80 | struct parisc_rtc *p = platform_get_drvdata(dev); | 55 | struct rtc_device *rtc = platform_get_drvdata(dev); |
81 | 56 | ||
82 | rtc_device_unregister(p->rtc); | 57 | rtc_device_unregister(rtc); |
83 | kfree(p); | ||
84 | 58 | ||
85 | return 0; | 59 | return 0; |
86 | } | 60 | } |
@@ -96,7 +70,7 @@ static struct platform_driver parisc_rtc_driver = { | |||
96 | 70 | ||
97 | static int __init parisc_rtc_init(void) | 71 | static int __init parisc_rtc_init(void) |
98 | { | 72 | { |
99 | return platform_driver_register(&parisc_rtc_driver); | 73 | return platform_driver_probe(&parisc_rtc_driver, parisc_rtc_probe); |
100 | } | 74 | } |
101 | 75 | ||
102 | static void __exit parisc_rtc_fini(void) | 76 | static void __exit parisc_rtc_fini(void) |
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c index 0c6257a034ff..c086fc30a84c 100644 --- a/drivers/rtc/rtc-proc.c +++ b/drivers/rtc/rtc-proc.c | |||
@@ -105,14 +105,8 @@ static const struct file_operations rtc_proc_fops = { | |||
105 | 105 | ||
106 | void rtc_proc_add_device(struct rtc_device *rtc) | 106 | void rtc_proc_add_device(struct rtc_device *rtc) |
107 | { | 107 | { |
108 | if (rtc->id == 0) { | 108 | if (rtc->id == 0) |
109 | struct proc_dir_entry *ent; | 109 | proc_create_data("driver/rtc", 0, NULL, &rtc_proc_fops, rtc); |
110 | |||
111 | ent = proc_create_data("driver/rtc", 0, NULL, | ||
112 | &rtc_proc_fops, rtc); | ||
113 | if (ent) | ||
114 | ent->owner = rtc->owner; | ||
115 | } | ||
116 | } | 110 | } |
117 | 111 | ||
118 | void rtc_proc_del_device(struct rtc_device *rtc) | 112 | void rtc_proc_del_device(struct rtc_device *rtc) |
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index 14d4f036a768..66955cc9c746 100644 --- a/drivers/rtc/rtc-v3020.c +++ b/drivers/rtc/rtc-v3020.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/rtc-v3020.h> | 28 | #include <linux/rtc-v3020.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | 30 | ||
31 | #include <asm/io.h> | 31 | #include <linux/io.h> |
32 | 32 | ||
33 | #undef DEBUG | 33 | #undef DEBUG |
34 | 34 | ||
@@ -63,7 +63,7 @@ static void v3020_set_reg(struct v3020 *chip, unsigned char address, | |||
63 | 63 | ||
64 | static unsigned char v3020_get_reg(struct v3020 *chip, unsigned char address) | 64 | static unsigned char v3020_get_reg(struct v3020 *chip, unsigned char address) |
65 | { | 65 | { |
66 | unsigned int data=0; | 66 | unsigned int data = 0; |
67 | int i; | 67 | int i; |
68 | 68 | ||
69 | for (i = 0; i < 4; i++) { | 69 | for (i = 0; i < 4; i++) { |
@@ -106,16 +106,14 @@ static int v3020_read_time(struct device *dev, struct rtc_time *dt) | |||
106 | tmp = v3020_get_reg(chip, V3020_YEAR); | 106 | tmp = v3020_get_reg(chip, V3020_YEAR); |
107 | dt->tm_year = bcd2bin(tmp)+100; | 107 | dt->tm_year = bcd2bin(tmp)+100; |
108 | 108 | ||
109 | #ifdef DEBUG | 109 | dev_dbg(dev, "\n%s : Read RTC values\n", __func__); |
110 | printk("\n%s : Read RTC values\n",__func__); | 110 | dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour); |
111 | printk("tm_hour: %i\n",dt->tm_hour); | 111 | dev_dbg(dev, "tm_min : %i\n", dt->tm_min); |
112 | printk("tm_min : %i\n",dt->tm_min); | 112 | dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec); |
113 | printk("tm_sec : %i\n",dt->tm_sec); | 113 | dev_dbg(dev, "tm_year: %i\n", dt->tm_year); |
114 | printk("tm_year: %i\n",dt->tm_year); | 114 | dev_dbg(dev, "tm_mon : %i\n", dt->tm_mon); |
115 | printk("tm_mon : %i\n",dt->tm_mon); | 115 | dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday); |
116 | printk("tm_mday: %i\n",dt->tm_mday); | 116 | dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday); |
117 | printk("tm_wday: %i\n",dt->tm_wday); | ||
118 | #endif | ||
119 | 117 | ||
120 | return 0; | 118 | return 0; |
121 | } | 119 | } |
@@ -125,15 +123,13 @@ static int v3020_set_time(struct device *dev, struct rtc_time *dt) | |||
125 | { | 123 | { |
126 | struct v3020 *chip = dev_get_drvdata(dev); | 124 | struct v3020 *chip = dev_get_drvdata(dev); |
127 | 125 | ||
128 | #ifdef DEBUG | 126 | dev_dbg(dev, "\n%s : Setting RTC values\n", __func__); |
129 | printk("\n%s : Setting RTC values\n",__func__); | 127 | dev_dbg(dev, "tm_sec : %i\n", dt->tm_sec); |
130 | printk("tm_sec : %i\n",dt->tm_sec); | 128 | dev_dbg(dev, "tm_min : %i\n", dt->tm_min); |
131 | printk("tm_min : %i\n",dt->tm_min); | 129 | dev_dbg(dev, "tm_hour: %i\n", dt->tm_hour); |
132 | printk("tm_hour: %i\n",dt->tm_hour); | 130 | dev_dbg(dev, "tm_mday: %i\n", dt->tm_mday); |
133 | printk("tm_mday: %i\n",dt->tm_mday); | 131 | dev_dbg(dev, "tm_wday: %i\n", dt->tm_wday); |
134 | printk("tm_wday: %i\n",dt->tm_wday); | 132 | dev_dbg(dev, "tm_year: %i\n", dt->tm_year); |
135 | printk("tm_year: %i\n",dt->tm_year); | ||
136 | #endif | ||
137 | 133 | ||
138 | /* Write all the values to ram... */ | 134 | /* Write all the values to ram... */ |
139 | v3020_set_reg(chip, V3020_SECONDS, bin2bcd(dt->tm_sec)); | 135 | v3020_set_reg(chip, V3020_SECONDS, bin2bcd(dt->tm_sec)); |
@@ -191,7 +187,7 @@ static int rtc_probe(struct platform_device *pdev) | |||
191 | /* Test chip by doing a write/read sequence | 187 | /* Test chip by doing a write/read sequence |
192 | * to the chip ram */ | 188 | * to the chip ram */ |
193 | v3020_set_reg(chip, V3020_SECONDS, 0x33); | 189 | v3020_set_reg(chip, V3020_SECONDS, 0x33); |
194 | if(v3020_get_reg(chip, V3020_SECONDS) != 0x33) { | 190 | if (v3020_get_reg(chip, V3020_SECONDS) != 0x33) { |
195 | retval = -ENODEV; | 191 | retval = -ENODEV; |
196 | goto err_io; | 192 | goto err_io; |
197 | } | 193 | } |
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c index 5c5e3aa91385..c91edc572eb6 100644 --- a/drivers/rtc/rtc-wm8350.c +++ b/drivers/rtc/rtc-wm8350.c | |||
@@ -122,7 +122,7 @@ static int wm8350_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
122 | do { | 122 | do { |
123 | rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); | 123 | rtc_ctrl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); |
124 | schedule_timeout_uninterruptible(msecs_to_jiffies(1)); | 124 | schedule_timeout_uninterruptible(msecs_to_jiffies(1)); |
125 | } while (retries-- && !(rtc_ctrl & WM8350_RTC_STS)); | 125 | } while (--retries && !(rtc_ctrl & WM8350_RTC_STS)); |
126 | 126 | ||
127 | if (!retries) { | 127 | if (!retries) { |
128 | dev_err(dev, "timed out on set confirmation\n"); | 128 | dev_err(dev, "timed out on set confirmation\n"); |
@@ -236,6 +236,17 @@ static int wm8350_rtc_start_alarm(struct wm8350 *wm8350) | |||
236 | return 0; | 236 | return 0; |
237 | } | 237 | } |
238 | 238 | ||
239 | static int wm8350_rtc_alarm_irq_enable(struct device *dev, | ||
240 | unsigned int enabled) | ||
241 | { | ||
242 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | ||
243 | |||
244 | if (enabled) | ||
245 | return wm8350_rtc_start_alarm(wm8350); | ||
246 | else | ||
247 | return wm8350_rtc_stop_alarm(wm8350); | ||
248 | } | ||
249 | |||
239 | static int wm8350_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | 250 | static int wm8350_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) |
240 | { | 251 | { |
241 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | 252 | struct wm8350 *wm8350 = dev_get_drvdata(dev); |
@@ -291,30 +302,15 @@ static int wm8350_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
291 | return ret; | 302 | return ret; |
292 | } | 303 | } |
293 | 304 | ||
294 | /* | 305 | static int wm8350_rtc_update_irq_enable(struct device *dev, |
295 | * Handle commands from user-space | 306 | unsigned int enabled) |
296 | */ | ||
297 | static int wm8350_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
298 | unsigned long arg) | ||
299 | { | 307 | { |
300 | struct wm8350 *wm8350 = dev_get_drvdata(dev); | 308 | struct wm8350 *wm8350 = dev_get_drvdata(dev); |
301 | 309 | ||
302 | switch (cmd) { | 310 | if (enabled) |
303 | case RTC_AIE_OFF: | ||
304 | return wm8350_rtc_stop_alarm(wm8350); | ||
305 | case RTC_AIE_ON: | ||
306 | return wm8350_rtc_start_alarm(wm8350); | ||
307 | |||
308 | case RTC_UIE_OFF: | ||
309 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | ||
310 | break; | ||
311 | case RTC_UIE_ON: | ||
312 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); | 311 | wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); |
313 | break; | 312 | else |
314 | 313 | wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); | |
315 | default: | ||
316 | return -ENOIOCTLCMD; | ||
317 | } | ||
318 | 314 | ||
319 | return 0; | 315 | return 0; |
320 | } | 316 | } |
@@ -345,11 +341,12 @@ static void wm8350_rtc_update_handler(struct wm8350 *wm8350, int irq, | |||
345 | } | 341 | } |
346 | 342 | ||
347 | static const struct rtc_class_ops wm8350_rtc_ops = { | 343 | static const struct rtc_class_ops wm8350_rtc_ops = { |
348 | .ioctl = wm8350_rtc_ioctl, | ||
349 | .read_time = wm8350_rtc_readtime, | 344 | .read_time = wm8350_rtc_readtime, |
350 | .set_time = wm8350_rtc_settime, | 345 | .set_time = wm8350_rtc_settime, |
351 | .read_alarm = wm8350_rtc_readalarm, | 346 | .read_alarm = wm8350_rtc_readalarm, |
352 | .set_alarm = wm8350_rtc_setalarm, | 347 | .set_alarm = wm8350_rtc_setalarm, |
348 | .alarm_irq_enable = wm8350_rtc_alarm_irq_enable, | ||
349 | .update_irq_enable = wm8350_rtc_update_irq_enable, | ||
353 | }; | 350 | }; |
354 | 351 | ||
355 | #ifdef CONFIG_PM | 352 | #ifdef CONFIG_PM |
@@ -440,7 +437,7 @@ static int wm8350_rtc_probe(struct platform_device *pdev) | |||
440 | do { | 437 | do { |
441 | timectl = wm8350_reg_read(wm8350, | 438 | timectl = wm8350_reg_read(wm8350, |
442 | WM8350_RTC_TIME_CONTROL); | 439 | WM8350_RTC_TIME_CONTROL); |
443 | } while (timectl & WM8350_RTC_STS && retries--); | 440 | } while (timectl & WM8350_RTC_STS && --retries); |
444 | 441 | ||
445 | if (retries == 0) { | 442 | if (retries == 0) { |
446 | dev_err(&pdev->dev, "failed to start: timeout\n"); | 443 | dev_err(&pdev->dev, "failed to start: timeout\n"); |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 2fd64e5a9ab2..0570794ccf1c 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -2363,6 +2363,7 @@ int dasd_generic_notify(struct ccw_device *cdev, int event) | |||
2363 | ret = 0; | 2363 | ret = 0; |
2364 | switch (event) { | 2364 | switch (event) { |
2365 | case CIO_GONE: | 2365 | case CIO_GONE: |
2366 | case CIO_BOXED: | ||
2366 | case CIO_NO_PATH: | 2367 | case CIO_NO_PATH: |
2367 | /* First of all call extended error reporting. */ | 2368 | /* First of all call extended error reporting. */ |
2368 | dasd_eer_write(device, NULL, DASD_EER_NOPATH); | 2369 | dasd_eer_write(device, NULL, DASD_EER_NOPATH); |
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 2080ba6a69b0..654daa3cdfda 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c | |||
@@ -320,7 +320,6 @@ dasd_proc_init(void) | |||
320 | dasd_proc_root_entry = proc_mkdir("dasd", NULL); | 320 | dasd_proc_root_entry = proc_mkdir("dasd", NULL); |
321 | if (!dasd_proc_root_entry) | 321 | if (!dasd_proc_root_entry) |
322 | goto out_nodasd; | 322 | goto out_nodasd; |
323 | dasd_proc_root_entry->owner = THIS_MODULE; | ||
324 | dasd_devices_entry = proc_create("devices", | 323 | dasd_devices_entry = proc_create("devices", |
325 | S_IFREG | S_IRUGO | S_IWUSR, | 324 | S_IFREG | S_IRUGO | S_IWUSR, |
326 | dasd_proc_root_entry, | 325 | dasd_proc_root_entry, |
@@ -334,7 +333,6 @@ dasd_proc_init(void) | |||
334 | goto out_nostatistics; | 333 | goto out_nostatistics; |
335 | dasd_statistics_entry->read_proc = dasd_statistics_read; | 334 | dasd_statistics_entry->read_proc = dasd_statistics_read; |
336 | dasd_statistics_entry->write_proc = dasd_statistics_write; | 335 | dasd_statistics_entry->write_proc = dasd_statistics_write; |
337 | dasd_statistics_entry->owner = THIS_MODULE; | ||
338 | return 0; | 336 | return 0; |
339 | 337 | ||
340 | out_nostatistics: | 338 | out_nostatistics: |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index c4d2f667a2f6..35441fa16be1 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -310,8 +310,6 @@ static void ccw_device_remove_orphan_cb(struct work_struct *work) | |||
310 | put_device(&cdev->dev); | 310 | put_device(&cdev->dev); |
311 | } | 311 | } |
312 | 312 | ||
313 | static void ccw_device_call_sch_unregister(struct work_struct *work); | ||
314 | |||
315 | static void | 313 | static void |
316 | ccw_device_remove_disconnected(struct ccw_device *cdev) | 314 | ccw_device_remove_disconnected(struct ccw_device *cdev) |
317 | { | 315 | { |
@@ -335,11 +333,10 @@ ccw_device_remove_disconnected(struct ccw_device *cdev) | |||
335 | spin_unlock_irqrestore(cdev->ccwlock, flags); | 333 | spin_unlock_irqrestore(cdev->ccwlock, flags); |
336 | PREPARE_WORK(&cdev->private->kick_work, | 334 | PREPARE_WORK(&cdev->private->kick_work, |
337 | ccw_device_remove_orphan_cb); | 335 | ccw_device_remove_orphan_cb); |
336 | queue_work(slow_path_wq, &cdev->private->kick_work); | ||
338 | } else | 337 | } else |
339 | /* Deregister subchannel, which will kill the ccw device. */ | 338 | /* Deregister subchannel, which will kill the ccw device. */ |
340 | PREPARE_WORK(&cdev->private->kick_work, | 339 | ccw_device_schedule_sch_unregister(cdev); |
341 | ccw_device_call_sch_unregister); | ||
342 | queue_work(slow_path_wq, &cdev->private->kick_work); | ||
343 | } | 340 | } |
344 | 341 | ||
345 | /** | 342 | /** |
@@ -471,7 +468,7 @@ static int online_store_recog_and_online(struct ccw_device *cdev) | |||
471 | int ret; | 468 | int ret; |
472 | 469 | ||
473 | /* Do device recognition, if needed. */ | 470 | /* Do device recognition, if needed. */ |
474 | if (cdev->id.cu_type == 0) { | 471 | if (cdev->private->state == DEV_STATE_BOXED) { |
475 | ret = ccw_device_recognition(cdev); | 472 | ret = ccw_device_recognition(cdev); |
476 | if (ret) { | 473 | if (ret) { |
477 | CIO_MSG_EVENT(0, "Couldn't start recognition " | 474 | CIO_MSG_EVENT(0, "Couldn't start recognition " |
@@ -482,17 +479,21 @@ static int online_store_recog_and_online(struct ccw_device *cdev) | |||
482 | } | 479 | } |
483 | wait_event(cdev->private->wait_q, | 480 | wait_event(cdev->private->wait_q, |
484 | cdev->private->flags.recog_done); | 481 | cdev->private->flags.recog_done); |
482 | if (cdev->private->state != DEV_STATE_OFFLINE) | ||
483 | /* recognition failed */ | ||
484 | return -EAGAIN; | ||
485 | } | 485 | } |
486 | if (cdev->drv && cdev->drv->set_online) | 486 | if (cdev->drv && cdev->drv->set_online) |
487 | ccw_device_set_online(cdev); | 487 | ccw_device_set_online(cdev); |
488 | return 0; | 488 | return 0; |
489 | } | 489 | } |
490 | |||
490 | static int online_store_handle_online(struct ccw_device *cdev, int force) | 491 | static int online_store_handle_online(struct ccw_device *cdev, int force) |
491 | { | 492 | { |
492 | int ret; | 493 | int ret; |
493 | 494 | ||
494 | ret = online_store_recog_and_online(cdev); | 495 | ret = online_store_recog_and_online(cdev); |
495 | if (ret) | 496 | if (ret && !force) |
496 | return ret; | 497 | return ret; |
497 | if (force && cdev->private->state == DEV_STATE_BOXED) { | 498 | if (force && cdev->private->state == DEV_STATE_BOXED) { |
498 | ret = ccw_device_stlck(cdev); | 499 | ret = ccw_device_stlck(cdev); |
@@ -500,7 +501,9 @@ static int online_store_handle_online(struct ccw_device *cdev, int force) | |||
500 | return ret; | 501 | return ret; |
501 | if (cdev->id.cu_type == 0) | 502 | if (cdev->id.cu_type == 0) |
502 | cdev->private->state = DEV_STATE_NOT_OPER; | 503 | cdev->private->state = DEV_STATE_NOT_OPER; |
503 | online_store_recog_and_online(cdev); | 504 | ret = online_store_recog_and_online(cdev); |
505 | if (ret) | ||
506 | return ret; | ||
504 | } | 507 | } |
505 | return 0; | 508 | return 0; |
506 | } | 509 | } |
@@ -512,7 +515,11 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, | |||
512 | int force, ret; | 515 | int force, ret; |
513 | unsigned long i; | 516 | unsigned long i; |
514 | 517 | ||
515 | if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0) | 518 | if ((cdev->private->state != DEV_STATE_OFFLINE && |
519 | cdev->private->state != DEV_STATE_ONLINE && | ||
520 | cdev->private->state != DEV_STATE_BOXED && | ||
521 | cdev->private->state != DEV_STATE_DISCONNECTED) || | ||
522 | atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0) | ||
516 | return -EAGAIN; | 523 | return -EAGAIN; |
517 | 524 | ||
518 | if (cdev->drv && !try_module_get(cdev->drv->owner)) { | 525 | if (cdev->drv && !try_module_get(cdev->drv->owner)) { |
@@ -1014,6 +1021,13 @@ static void ccw_device_call_sch_unregister(struct work_struct *work) | |||
1014 | put_device(&sch->dev); | 1021 | put_device(&sch->dev); |
1015 | } | 1022 | } |
1016 | 1023 | ||
1024 | void ccw_device_schedule_sch_unregister(struct ccw_device *cdev) | ||
1025 | { | ||
1026 | PREPARE_WORK(&cdev->private->kick_work, | ||
1027 | ccw_device_call_sch_unregister); | ||
1028 | queue_work(slow_path_wq, &cdev->private->kick_work); | ||
1029 | } | ||
1030 | |||
1017 | /* | 1031 | /* |
1018 | * subchannel recognition done. Called from the state machine. | 1032 | * subchannel recognition done. Called from the state machine. |
1019 | */ | 1033 | */ |
@@ -1025,19 +1039,17 @@ io_subchannel_recog_done(struct ccw_device *cdev) | |||
1025 | return; | 1039 | return; |
1026 | } | 1040 | } |
1027 | switch (cdev->private->state) { | 1041 | switch (cdev->private->state) { |
1042 | case DEV_STATE_BOXED: | ||
1043 | /* Device did not respond in time. */ | ||
1028 | case DEV_STATE_NOT_OPER: | 1044 | case DEV_STATE_NOT_OPER: |
1029 | cdev->private->flags.recog_done = 1; | 1045 | cdev->private->flags.recog_done = 1; |
1030 | /* Remove device found not operational. */ | 1046 | /* Remove device found not operational. */ |
1031 | if (!get_device(&cdev->dev)) | 1047 | if (!get_device(&cdev->dev)) |
1032 | break; | 1048 | break; |
1033 | PREPARE_WORK(&cdev->private->kick_work, | 1049 | ccw_device_schedule_sch_unregister(cdev); |
1034 | ccw_device_call_sch_unregister); | ||
1035 | queue_work(slow_path_wq, &cdev->private->kick_work); | ||
1036 | if (atomic_dec_and_test(&ccw_device_init_count)) | 1050 | if (atomic_dec_and_test(&ccw_device_init_count)) |
1037 | wake_up(&ccw_device_init_wq); | 1051 | wake_up(&ccw_device_init_wq); |
1038 | break; | 1052 | break; |
1039 | case DEV_STATE_BOXED: | ||
1040 | /* Device did not respond in time. */ | ||
1041 | case DEV_STATE_OFFLINE: | 1053 | case DEV_STATE_OFFLINE: |
1042 | /* | 1054 | /* |
1043 | * We can't register the device in interrupt context so | 1055 | * We can't register the device in interrupt context so |
@@ -1551,8 +1563,7 @@ static int purge_fn(struct device *dev, void *data) | |||
1551 | goto out; | 1563 | goto out; |
1552 | CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", priv->dev_id.ssid, | 1564 | CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", priv->dev_id.ssid, |
1553 | priv->dev_id.devno); | 1565 | priv->dev_id.devno); |
1554 | PREPARE_WORK(&cdev->private->kick_work, ccw_device_call_sch_unregister); | 1566 | ccw_device_schedule_sch_unregister(cdev); |
1555 | queue_work(slow_path_wq, &cdev->private->kick_work); | ||
1556 | 1567 | ||
1557 | out: | 1568 | out: |
1558 | /* Abort loop in case of pending signal. */ | 1569 | /* Abort loop in case of pending signal. */ |
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 85e01846ca65..f1cbbd94ad4e 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h | |||
@@ -87,6 +87,7 @@ int ccw_device_is_orphan(struct ccw_device *); | |||
87 | int ccw_device_recognition(struct ccw_device *); | 87 | int ccw_device_recognition(struct ccw_device *); |
88 | int ccw_device_online(struct ccw_device *); | 88 | int ccw_device_online(struct ccw_device *); |
89 | int ccw_device_offline(struct ccw_device *); | 89 | int ccw_device_offline(struct ccw_device *); |
90 | void ccw_device_schedule_sch_unregister(struct ccw_device *); | ||
90 | int ccw_purge_blacklisted(void); | 91 | int ccw_purge_blacklisted(void); |
91 | 92 | ||
92 | /* Function prototypes for device status and basic sense stuff. */ | 93 | /* Function prototypes for device status and basic sense stuff. */ |
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 87b4bfca080f..e46049261561 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -256,13 +256,12 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) | |||
256 | old_lpm = 0; | 256 | old_lpm = 0; |
257 | if (sch->lpm != old_lpm) | 257 | if (sch->lpm != old_lpm) |
258 | __recover_lost_chpids(sch, old_lpm); | 258 | __recover_lost_chpids(sch, old_lpm); |
259 | if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) { | 259 | if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID && |
260 | if (state == DEV_STATE_NOT_OPER) { | 260 | (state == DEV_STATE_NOT_OPER || state == DEV_STATE_BOXED)) { |
261 | cdev->private->flags.recog_done = 1; | 261 | cdev->private->flags.recog_done = 1; |
262 | cdev->private->state = DEV_STATE_DISCONNECTED; | 262 | cdev->private->state = DEV_STATE_DISCONNECTED; |
263 | return; | 263 | wake_up(&cdev->private->wait_q); |
264 | } | 264 | return; |
265 | /* Boxed devices don't need extra treatment. */ | ||
266 | } | 265 | } |
267 | notify = 0; | 266 | notify = 0; |
268 | same_dev = 0; /* Keep the compiler quiet... */ | 267 | same_dev = 0; /* Keep the compiler quiet... */ |
@@ -274,7 +273,7 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) | |||
274 | sch->schid.ssid, sch->schid.sch_no); | 273 | sch->schid.ssid, sch->schid.sch_no); |
275 | break; | 274 | break; |
276 | case DEV_STATE_OFFLINE: | 275 | case DEV_STATE_OFFLINE: |
277 | if (cdev->private->state == DEV_STATE_DISCONNECTED_SENSE_ID) { | 276 | if (cdev->online) { |
278 | same_dev = ccw_device_handle_oper(cdev); | 277 | same_dev = ccw_device_handle_oper(cdev); |
279 | notify = 1; | 278 | notify = 1; |
280 | } | 279 | } |
@@ -307,12 +306,17 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) | |||
307 | " subchannel 0.%x.%04x\n", | 306 | " subchannel 0.%x.%04x\n", |
308 | cdev->private->dev_id.devno, | 307 | cdev->private->dev_id.devno, |
309 | sch->schid.ssid, sch->schid.sch_no); | 308 | sch->schid.ssid, sch->schid.sch_no); |
309 | if (cdev->id.cu_type != 0) { /* device was recognized before */ | ||
310 | cdev->private->flags.recog_done = 1; | ||
311 | cdev->private->state = DEV_STATE_BOXED; | ||
312 | wake_up(&cdev->private->wait_q); | ||
313 | return; | ||
314 | } | ||
310 | break; | 315 | break; |
311 | } | 316 | } |
312 | cdev->private->state = state; | 317 | cdev->private->state = state; |
313 | io_subchannel_recog_done(cdev); | 318 | io_subchannel_recog_done(cdev); |
314 | if (state != DEV_STATE_NOT_OPER) | 319 | wake_up(&cdev->private->wait_q); |
315 | wake_up(&cdev->private->wait_q); | ||
316 | } | 320 | } |
317 | 321 | ||
318 | /* | 322 | /* |
@@ -390,10 +394,13 @@ ccw_device_done(struct ccw_device *cdev, int state) | |||
390 | 394 | ||
391 | cdev->private->state = state; | 395 | cdev->private->state = state; |
392 | 396 | ||
393 | 397 | if (state == DEV_STATE_BOXED) { | |
394 | if (state == DEV_STATE_BOXED) | ||
395 | CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n", | 398 | CIO_MSG_EVENT(0, "Boxed device %04x on subchannel %04x\n", |
396 | cdev->private->dev_id.devno, sch->schid.sch_no); | 399 | cdev->private->dev_id.devno, sch->schid.sch_no); |
400 | if (cdev->online && !ccw_device_notify(cdev, CIO_BOXED)) | ||
401 | ccw_device_schedule_sch_unregister(cdev); | ||
402 | cdev->private->flags.donotify = 0; | ||
403 | } | ||
397 | 404 | ||
398 | if (cdev->private->flags.donotify) { | 405 | if (cdev->private->flags.donotify) { |
399 | cdev->private->flags.donotify = 0; | 406 | cdev->private->flags.donotify = 0; |
diff --git a/drivers/s390/net/qeth_core_offl.c b/drivers/s390/net/qeth_core_offl.c deleted file mode 100644 index e69de29bb2d1..000000000000 --- a/drivers/s390/net/qeth_core_offl.c +++ /dev/null | |||
diff --git a/drivers/s390/net/qeth_core_offl.h b/drivers/s390/net/qeth_core_offl.h deleted file mode 100644 index e69de29bb2d1..000000000000 --- a/drivers/s390/net/qeth_core_offl.h +++ /dev/null | |||
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 1fe1e2eda512..cfb0dcb6e3ff 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -176,6 +176,11 @@ static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event) | |||
176 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, | 176 | zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, |
177 | "ccnoti4", NULL); | 177 | "ccnoti4", NULL); |
178 | break; | 178 | break; |
179 | case CIO_BOXED: | ||
180 | dev_warn(&adapter->ccw_device->dev, | ||
181 | "The ccw device did not respond in time.\n"); | ||
182 | zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti5", NULL); | ||
183 | break; | ||
179 | } | 184 | } |
180 | return 1; | 185 | return 1; |
181 | } | 186 | } |
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 099b5455bbce..b13481369642 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c | |||
@@ -596,8 +596,6 @@ int __init scsi_init_devinfo(void) | |||
596 | error = -ENOMEM; | 596 | error = -ENOMEM; |
597 | goto out; | 597 | goto out; |
598 | } | 598 | } |
599 | |||
600 | p->owner = THIS_MODULE; | ||
601 | #endif /* CONFIG_SCSI_PROC_FS */ | 599 | #endif /* CONFIG_SCSI_PROC_FS */ |
602 | 600 | ||
603 | out: | 601 | out: |
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index 82f7b2dd08a2..77fbddb507fd 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c | |||
@@ -115,8 +115,6 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht) | |||
115 | if (!sht->proc_dir) | 115 | if (!sht->proc_dir) |
116 | printk(KERN_ERR "%s: proc_mkdir failed for %s\n", | 116 | printk(KERN_ERR "%s: proc_mkdir failed for %s\n", |
117 | __func__, sht->proc_name); | 117 | __func__, sht->proc_name); |
118 | else | ||
119 | sht->proc_dir->owner = sht->module; | ||
120 | } | 118 | } |
121 | mutex_unlock(&global_host_template_mutex); | 119 | mutex_unlock(&global_host_template_mutex); |
122 | } | 120 | } |
@@ -163,7 +161,6 @@ void scsi_proc_host_add(struct Scsi_Host *shost) | |||
163 | } | 161 | } |
164 | 162 | ||
165 | p->write_proc = proc_scsi_write_proc; | 163 | p->write_proc = proc_scsi_write_proc; |
166 | p->owner = sht->module; | ||
167 | } | 164 | } |
168 | 165 | ||
169 | /** | 166 | /** |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 42f4e66fccaf..b0bb29d804ae 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/console.h> | 29 | #include <linux/console.h> |
30 | #include <linux/proc_fs.h> | ||
31 | #include <linux/seq_file.h> | ||
30 | #include <linux/serial_core.h> | 32 | #include <linux/serial_core.h> |
31 | #include <linux/smp_lock.h> | 33 | #include <linux/smp_lock.h> |
32 | #include <linux/device.h> | 34 | #include <linux/device.h> |
@@ -1682,20 +1684,20 @@ static const char *uart_type(struct uart_port *port) | |||
1682 | 1684 | ||
1683 | #ifdef CONFIG_PROC_FS | 1685 | #ifdef CONFIG_PROC_FS |
1684 | 1686 | ||
1685 | static int uart_line_info(char *buf, struct uart_driver *drv, int i) | 1687 | static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i) |
1686 | { | 1688 | { |
1687 | struct uart_state *state = drv->state + i; | 1689 | struct uart_state *state = drv->state + i; |
1688 | int pm_state; | 1690 | int pm_state; |
1689 | struct uart_port *port = state->port; | 1691 | struct uart_port *port = state->port; |
1690 | char stat_buf[32]; | 1692 | char stat_buf[32]; |
1691 | unsigned int status; | 1693 | unsigned int status; |
1692 | int mmio, ret; | 1694 | int mmio; |
1693 | 1695 | ||
1694 | if (!port) | 1696 | if (!port) |
1695 | return 0; | 1697 | return; |
1696 | 1698 | ||
1697 | mmio = port->iotype >= UPIO_MEM; | 1699 | mmio = port->iotype >= UPIO_MEM; |
1698 | ret = sprintf(buf, "%d: uart:%s %s%08llX irq:%d", | 1700 | seq_printf(m, "%d: uart:%s %s%08llX irq:%d", |
1699 | port->line, uart_type(port), | 1701 | port->line, uart_type(port), |
1700 | mmio ? "mmio:0x" : "port:", | 1702 | mmio ? "mmio:0x" : "port:", |
1701 | mmio ? (unsigned long long)port->mapbase | 1703 | mmio ? (unsigned long long)port->mapbase |
@@ -1703,8 +1705,8 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i) | |||
1703 | port->irq); | 1705 | port->irq); |
1704 | 1706 | ||
1705 | if (port->type == PORT_UNKNOWN) { | 1707 | if (port->type == PORT_UNKNOWN) { |
1706 | strcat(buf, "\n"); | 1708 | seq_putc(m, '\n'); |
1707 | return ret + 1; | 1709 | return; |
1708 | } | 1710 | } |
1709 | 1711 | ||
1710 | if (capable(CAP_SYS_ADMIN)) { | 1712 | if (capable(CAP_SYS_ADMIN)) { |
@@ -1719,19 +1721,19 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i) | |||
1719 | uart_change_pm(state, pm_state); | 1721 | uart_change_pm(state, pm_state); |
1720 | mutex_unlock(&state->mutex); | 1722 | mutex_unlock(&state->mutex); |
1721 | 1723 | ||
1722 | ret += sprintf(buf + ret, " tx:%d rx:%d", | 1724 | seq_printf(m, " tx:%d rx:%d", |
1723 | port->icount.tx, port->icount.rx); | 1725 | port->icount.tx, port->icount.rx); |
1724 | if (port->icount.frame) | 1726 | if (port->icount.frame) |
1725 | ret += sprintf(buf + ret, " fe:%d", | 1727 | seq_printf(m, " fe:%d", |
1726 | port->icount.frame); | 1728 | port->icount.frame); |
1727 | if (port->icount.parity) | 1729 | if (port->icount.parity) |
1728 | ret += sprintf(buf + ret, " pe:%d", | 1730 | seq_printf(m, " pe:%d", |
1729 | port->icount.parity); | 1731 | port->icount.parity); |
1730 | if (port->icount.brk) | 1732 | if (port->icount.brk) |
1731 | ret += sprintf(buf + ret, " brk:%d", | 1733 | seq_printf(m, " brk:%d", |
1732 | port->icount.brk); | 1734 | port->icount.brk); |
1733 | if (port->icount.overrun) | 1735 | if (port->icount.overrun) |
1734 | ret += sprintf(buf + ret, " oe:%d", | 1736 | seq_printf(m, " oe:%d", |
1735 | port->icount.overrun); | 1737 | port->icount.overrun); |
1736 | 1738 | ||
1737 | #define INFOBIT(bit, str) \ | 1739 | #define INFOBIT(bit, str) \ |
@@ -1753,45 +1755,39 @@ static int uart_line_info(char *buf, struct uart_driver *drv, int i) | |||
1753 | STATBIT(TIOCM_RNG, "|RI"); | 1755 | STATBIT(TIOCM_RNG, "|RI"); |
1754 | if (stat_buf[0]) | 1756 | if (stat_buf[0]) |
1755 | stat_buf[0] = ' '; | 1757 | stat_buf[0] = ' '; |
1756 | strcat(stat_buf, "\n"); | ||
1757 | 1758 | ||
1758 | ret += sprintf(buf + ret, stat_buf); | 1759 | seq_puts(m, stat_buf); |
1759 | } else { | ||
1760 | strcat(buf, "\n"); | ||
1761 | ret++; | ||
1762 | } | 1760 | } |
1761 | seq_putc(m, '\n'); | ||
1763 | #undef STATBIT | 1762 | #undef STATBIT |
1764 | #undef INFOBIT | 1763 | #undef INFOBIT |
1765 | return ret; | ||
1766 | } | 1764 | } |
1767 | 1765 | ||
1768 | static int uart_read_proc(char *page, char **start, off_t off, | 1766 | static int uart_proc_show(struct seq_file *m, void *v) |
1769 | int count, int *eof, void *data) | ||
1770 | { | 1767 | { |
1771 | struct tty_driver *ttydrv = data; | 1768 | struct tty_driver *ttydrv = m->private; |
1772 | struct uart_driver *drv = ttydrv->driver_state; | 1769 | struct uart_driver *drv = ttydrv->driver_state; |
1773 | int i, len = 0, l; | 1770 | int i; |
1774 | off_t begin = 0; | ||
1775 | 1771 | ||
1776 | len += sprintf(page, "serinfo:1.0 driver%s%s revision:%s\n", | 1772 | seq_printf(m, "serinfo:1.0 driver%s%s revision:%s\n", |
1777 | "", "", ""); | 1773 | "", "", ""); |
1778 | for (i = 0; i < drv->nr && len < PAGE_SIZE - 96; i++) { | 1774 | for (i = 0; i < drv->nr; i++) |
1779 | l = uart_line_info(page + len, drv, i); | 1775 | uart_line_info(m, drv, i); |
1780 | len += l; | 1776 | return 0; |
1781 | if (len + begin > off + count) | ||
1782 | goto done; | ||
1783 | if (len + begin < off) { | ||
1784 | begin += len; | ||
1785 | len = 0; | ||
1786 | } | ||
1787 | } | ||
1788 | *eof = 1; | ||
1789 | done: | ||
1790 | if (off >= len + begin) | ||
1791 | return 0; | ||
1792 | *start = page + (off - begin); | ||
1793 | return (count < begin + len - off) ? count : (begin + len - off); | ||
1794 | } | 1777 | } |
1778 | |||
1779 | static int uart_proc_open(struct inode *inode, struct file *file) | ||
1780 | { | ||
1781 | return single_open(file, uart_proc_show, PDE(inode)->data); | ||
1782 | } | ||
1783 | |||
1784 | static const struct file_operations uart_proc_fops = { | ||
1785 | .owner = THIS_MODULE, | ||
1786 | .open = uart_proc_open, | ||
1787 | .read = seq_read, | ||
1788 | .llseek = seq_lseek, | ||
1789 | .release = single_release, | ||
1790 | }; | ||
1795 | #endif | 1791 | #endif |
1796 | 1792 | ||
1797 | #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL) | 1793 | #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL) |
@@ -2299,7 +2295,7 @@ static const struct tty_operations uart_ops = { | |||
2299 | .break_ctl = uart_break_ctl, | 2295 | .break_ctl = uart_break_ctl, |
2300 | .wait_until_sent= uart_wait_until_sent, | 2296 | .wait_until_sent= uart_wait_until_sent, |
2301 | #ifdef CONFIG_PROC_FS | 2297 | #ifdef CONFIG_PROC_FS |
2302 | .read_proc = uart_read_proc, | 2298 | .proc_fops = &uart_proc_fops, |
2303 | #endif | 2299 | #endif |
2304 | .tiocmget = uart_tiocmget, | 2300 | .tiocmget = uart_tiocmget, |
2305 | .tiocmset = uart_tiocmset, | 2301 | .tiocmset = uart_tiocmset, |
diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c index 44a2b46ccb79..f4573a96af24 100644 --- a/drivers/spi/spi_mpc83xx.c +++ b/drivers/spi/spi_mpc83xx.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/errno.h> | ||
18 | #include <linux/err.h> | ||
17 | #include <linux/completion.h> | 19 | #include <linux/completion.h> |
18 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
19 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
@@ -23,7 +25,13 @@ | |||
23 | #include <linux/spi/spi_bitbang.h> | 25 | #include <linux/spi/spi_bitbang.h> |
24 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
25 | #include <linux/fsl_devices.h> | 27 | #include <linux/fsl_devices.h> |
28 | #include <linux/of.h> | ||
29 | #include <linux/of_platform.h> | ||
30 | #include <linux/gpio.h> | ||
31 | #include <linux/of_gpio.h> | ||
32 | #include <linux/of_spi.h> | ||
26 | 33 | ||
34 | #include <sysdev/fsl_soc.h> | ||
27 | #include <asm/irq.h> | 35 | #include <asm/irq.h> |
28 | #include <asm/io.h> | 36 | #include <asm/io.h> |
29 | 37 | ||
@@ -79,7 +87,7 @@ struct mpc83xx_spi { | |||
79 | u32(*get_tx) (struct mpc83xx_spi *); | 87 | u32(*get_tx) (struct mpc83xx_spi *); |
80 | 88 | ||
81 | unsigned int count; | 89 | unsigned int count; |
82 | int irq; | 90 | unsigned int irq; |
83 | 91 | ||
84 | unsigned nsecs; /* (clock cycle time)/2 */ | 92 | unsigned nsecs; /* (clock cycle time)/2 */ |
85 | 93 | ||
@@ -89,9 +97,6 @@ struct mpc83xx_spi { | |||
89 | 97 | ||
90 | bool qe_mode; | 98 | bool qe_mode; |
91 | 99 | ||
92 | void (*activate_cs) (u8 cs, u8 polarity); | ||
93 | void (*deactivate_cs) (u8 cs, u8 polarity); | ||
94 | |||
95 | u8 busy; | 100 | u8 busy; |
96 | 101 | ||
97 | struct workqueue_struct *workqueue; | 102 | struct workqueue_struct *workqueue; |
@@ -123,6 +128,7 @@ static inline u32 mpc83xx_spi_read_reg(__be32 __iomem * reg) | |||
123 | } | 128 | } |
124 | 129 | ||
125 | #define MPC83XX_SPI_RX_BUF(type) \ | 130 | #define MPC83XX_SPI_RX_BUF(type) \ |
131 | static \ | ||
126 | void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \ | 132 | void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \ |
127 | { \ | 133 | { \ |
128 | type * rx = mpc83xx_spi->rx; \ | 134 | type * rx = mpc83xx_spi->rx; \ |
@@ -131,6 +137,7 @@ void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \ | |||
131 | } | 137 | } |
132 | 138 | ||
133 | #define MPC83XX_SPI_TX_BUF(type) \ | 139 | #define MPC83XX_SPI_TX_BUF(type) \ |
140 | static \ | ||
134 | u32 mpc83xx_spi_tx_buf_##type(struct mpc83xx_spi *mpc83xx_spi) \ | 141 | u32 mpc83xx_spi_tx_buf_##type(struct mpc83xx_spi *mpc83xx_spi) \ |
135 | { \ | 142 | { \ |
136 | u32 data; \ | 143 | u32 data; \ |
@@ -151,15 +158,14 @@ MPC83XX_SPI_TX_BUF(u32) | |||
151 | 158 | ||
152 | static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) | 159 | static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) |
153 | { | 160 | { |
154 | struct mpc83xx_spi *mpc83xx_spi; | 161 | struct mpc83xx_spi *mpc83xx_spi = spi_master_get_devdata(spi->master); |
155 | u8 pol = spi->mode & SPI_CS_HIGH ? 1 : 0; | 162 | struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data; |
163 | bool pol = spi->mode & SPI_CS_HIGH; | ||
156 | struct spi_mpc83xx_cs *cs = spi->controller_state; | 164 | struct spi_mpc83xx_cs *cs = spi->controller_state; |
157 | 165 | ||
158 | mpc83xx_spi = spi_master_get_devdata(spi->master); | ||
159 | |||
160 | if (value == BITBANG_CS_INACTIVE) { | 166 | if (value == BITBANG_CS_INACTIVE) { |
161 | if (mpc83xx_spi->deactivate_cs) | 167 | if (pdata->cs_control) |
162 | mpc83xx_spi->deactivate_cs(spi->chip_select, pol); | 168 | pdata->cs_control(spi, !pol); |
163 | } | 169 | } |
164 | 170 | ||
165 | if (value == BITBANG_CS_ACTIVE) { | 171 | if (value == BITBANG_CS_ACTIVE) { |
@@ -172,7 +178,7 @@ static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) | |||
172 | 178 | ||
173 | if (cs->hw_mode != regval) { | 179 | if (cs->hw_mode != regval) { |
174 | unsigned long flags; | 180 | unsigned long flags; |
175 | void *tmp_ptr = &mpc83xx_spi->base->mode; | 181 | __be32 __iomem *mode = &mpc83xx_spi->base->mode; |
176 | 182 | ||
177 | regval = cs->hw_mode; | 183 | regval = cs->hw_mode; |
178 | /* Turn off IRQs locally to minimize time that | 184 | /* Turn off IRQs locally to minimize time that |
@@ -180,12 +186,12 @@ static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) | |||
180 | */ | 186 | */ |
181 | local_irq_save(flags); | 187 | local_irq_save(flags); |
182 | /* Turn off SPI unit prior changing mode */ | 188 | /* Turn off SPI unit prior changing mode */ |
183 | mpc83xx_spi_write_reg(tmp_ptr, regval & ~SPMODE_ENABLE); | 189 | mpc83xx_spi_write_reg(mode, regval & ~SPMODE_ENABLE); |
184 | mpc83xx_spi_write_reg(tmp_ptr, regval); | 190 | mpc83xx_spi_write_reg(mode, regval); |
185 | local_irq_restore(flags); | 191 | local_irq_restore(flags); |
186 | } | 192 | } |
187 | if (mpc83xx_spi->activate_cs) | 193 | if (pdata->cs_control) |
188 | mpc83xx_spi->activate_cs(spi->chip_select, pol); | 194 | pdata->cs_control(spi, pol); |
189 | } | 195 | } |
190 | } | 196 | } |
191 | 197 | ||
@@ -284,7 +290,7 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
284 | regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode); | 290 | regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode); |
285 | if (cs->hw_mode != regval) { | 291 | if (cs->hw_mode != regval) { |
286 | unsigned long flags; | 292 | unsigned long flags; |
287 | void *tmp_ptr = &mpc83xx_spi->base->mode; | 293 | __be32 __iomem *mode = &mpc83xx_spi->base->mode; |
288 | 294 | ||
289 | regval = cs->hw_mode; | 295 | regval = cs->hw_mode; |
290 | /* Turn off IRQs locally to minimize time | 296 | /* Turn off IRQs locally to minimize time |
@@ -292,8 +298,8 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) | |||
292 | */ | 298 | */ |
293 | local_irq_save(flags); | 299 | local_irq_save(flags); |
294 | /* Turn off SPI unit prior changing mode */ | 300 | /* Turn off SPI unit prior changing mode */ |
295 | mpc83xx_spi_write_reg(tmp_ptr, regval & ~SPMODE_ENABLE); | 301 | mpc83xx_spi_write_reg(mode, regval & ~SPMODE_ENABLE); |
296 | mpc83xx_spi_write_reg(tmp_ptr, regval); | 302 | mpc83xx_spi_write_reg(mode, regval); |
297 | local_irq_restore(flags); | 303 | local_irq_restore(flags); |
298 | } | 304 | } |
299 | return 0; | 305 | return 0; |
@@ -483,7 +489,7 @@ static int mpc83xx_spi_setup(struct spi_device *spi) | |||
483 | return 0; | 489 | return 0; |
484 | } | 490 | } |
485 | 491 | ||
486 | irqreturn_t mpc83xx_spi_irq(s32 irq, void *context_data) | 492 | static irqreturn_t mpc83xx_spi_irq(s32 irq, void *context_data) |
487 | { | 493 | { |
488 | struct mpc83xx_spi *mpc83xx_spi = context_data; | 494 | struct mpc83xx_spi *mpc83xx_spi = context_data; |
489 | u32 event; | 495 | u32 event; |
@@ -545,43 +551,28 @@ static void mpc83xx_spi_cleanup(struct spi_device *spi) | |||
545 | kfree(spi->controller_state); | 551 | kfree(spi->controller_state); |
546 | } | 552 | } |
547 | 553 | ||
548 | static int __init mpc83xx_spi_probe(struct platform_device *dev) | 554 | static struct spi_master * __devinit |
555 | mpc83xx_spi_probe(struct device *dev, struct resource *mem, unsigned int irq) | ||
549 | { | 556 | { |
557 | struct fsl_spi_platform_data *pdata = dev->platform_data; | ||
550 | struct spi_master *master; | 558 | struct spi_master *master; |
551 | struct mpc83xx_spi *mpc83xx_spi; | 559 | struct mpc83xx_spi *mpc83xx_spi; |
552 | struct fsl_spi_platform_data *pdata; | ||
553 | struct resource *r; | ||
554 | u32 regval; | 560 | u32 regval; |
555 | int ret = 0; | 561 | int ret = 0; |
556 | 562 | ||
557 | /* Get resources(memory, IRQ) associated with the device */ | 563 | master = spi_alloc_master(dev, sizeof(struct mpc83xx_spi)); |
558 | master = spi_alloc_master(&dev->dev, sizeof(struct mpc83xx_spi)); | ||
559 | |||
560 | if (master == NULL) { | 564 | if (master == NULL) { |
561 | ret = -ENOMEM; | 565 | ret = -ENOMEM; |
562 | goto err; | 566 | goto err; |
563 | } | 567 | } |
564 | 568 | ||
565 | platform_set_drvdata(dev, master); | 569 | dev_set_drvdata(dev, master); |
566 | pdata = dev->dev.platform_data; | ||
567 | 570 | ||
568 | if (pdata == NULL) { | ||
569 | ret = -ENODEV; | ||
570 | goto free_master; | ||
571 | } | ||
572 | |||
573 | r = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
574 | if (r == NULL) { | ||
575 | ret = -ENODEV; | ||
576 | goto free_master; | ||
577 | } | ||
578 | master->setup = mpc83xx_spi_setup; | 571 | master->setup = mpc83xx_spi_setup; |
579 | master->transfer = mpc83xx_spi_transfer; | 572 | master->transfer = mpc83xx_spi_transfer; |
580 | master->cleanup = mpc83xx_spi_cleanup; | 573 | master->cleanup = mpc83xx_spi_cleanup; |
581 | 574 | ||
582 | mpc83xx_spi = spi_master_get_devdata(master); | 575 | mpc83xx_spi = spi_master_get_devdata(master); |
583 | mpc83xx_spi->activate_cs = pdata->activate_cs; | ||
584 | mpc83xx_spi->deactivate_cs = pdata->deactivate_cs; | ||
585 | mpc83xx_spi->qe_mode = pdata->qe_mode; | 576 | mpc83xx_spi->qe_mode = pdata->qe_mode; |
586 | mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8; | 577 | mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8; |
587 | mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8; | 578 | mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8; |
@@ -596,18 +587,13 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) | |||
596 | 587 | ||
597 | init_completion(&mpc83xx_spi->done); | 588 | init_completion(&mpc83xx_spi->done); |
598 | 589 | ||
599 | mpc83xx_spi->base = ioremap(r->start, r->end - r->start + 1); | 590 | mpc83xx_spi->base = ioremap(mem->start, mem->end - mem->start + 1); |
600 | if (mpc83xx_spi->base == NULL) { | 591 | if (mpc83xx_spi->base == NULL) { |
601 | ret = -ENOMEM; | 592 | ret = -ENOMEM; |
602 | goto put_master; | 593 | goto put_master; |
603 | } | 594 | } |
604 | 595 | ||
605 | mpc83xx_spi->irq = platform_get_irq(dev, 0); | 596 | mpc83xx_spi->irq = irq; |
606 | |||
607 | if (mpc83xx_spi->irq < 0) { | ||
608 | ret = -ENXIO; | ||
609 | goto unmap_io; | ||
610 | } | ||
611 | 597 | ||
612 | /* Register for SPI Interrupt */ | 598 | /* Register for SPI Interrupt */ |
613 | ret = request_irq(mpc83xx_spi->irq, mpc83xx_spi_irq, | 599 | ret = request_irq(mpc83xx_spi->irq, mpc83xx_spi_irq, |
@@ -649,9 +635,9 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) | |||
649 | 635 | ||
650 | printk(KERN_INFO | 636 | printk(KERN_INFO |
651 | "%s: MPC83xx SPI Controller driver at 0x%p (irq = %d)\n", | 637 | "%s: MPC83xx SPI Controller driver at 0x%p (irq = %d)\n", |
652 | dev_name(&dev->dev), mpc83xx_spi->base, mpc83xx_spi->irq); | 638 | dev_name(dev), mpc83xx_spi->base, mpc83xx_spi->irq); |
653 | 639 | ||
654 | return ret; | 640 | return master; |
655 | 641 | ||
656 | unreg_master: | 642 | unreg_master: |
657 | destroy_workqueue(mpc83xx_spi->workqueue); | 643 | destroy_workqueue(mpc83xx_spi->workqueue); |
@@ -661,18 +647,16 @@ unmap_io: | |||
661 | iounmap(mpc83xx_spi->base); | 647 | iounmap(mpc83xx_spi->base); |
662 | put_master: | 648 | put_master: |
663 | spi_master_put(master); | 649 | spi_master_put(master); |
664 | free_master: | ||
665 | kfree(master); | ||
666 | err: | 650 | err: |
667 | return ret; | 651 | return ERR_PTR(ret); |
668 | } | 652 | } |
669 | 653 | ||
670 | static int __exit mpc83xx_spi_remove(struct platform_device *dev) | 654 | static int __devexit mpc83xx_spi_remove(struct device *dev) |
671 | { | 655 | { |
672 | struct mpc83xx_spi *mpc83xx_spi; | 656 | struct mpc83xx_spi *mpc83xx_spi; |
673 | struct spi_master *master; | 657 | struct spi_master *master; |
674 | 658 | ||
675 | master = platform_get_drvdata(dev); | 659 | master = dev_get_drvdata(dev); |
676 | mpc83xx_spi = spi_master_get_devdata(master); | 660 | mpc83xx_spi = spi_master_get_devdata(master); |
677 | 661 | ||
678 | flush_workqueue(mpc83xx_spi->workqueue); | 662 | flush_workqueue(mpc83xx_spi->workqueue); |
@@ -685,23 +669,293 @@ static int __exit mpc83xx_spi_remove(struct platform_device *dev) | |||
685 | return 0; | 669 | return 0; |
686 | } | 670 | } |
687 | 671 | ||
672 | struct mpc83xx_spi_probe_info { | ||
673 | struct fsl_spi_platform_data pdata; | ||
674 | int *gpios; | ||
675 | bool *alow_flags; | ||
676 | }; | ||
677 | |||
678 | static struct mpc83xx_spi_probe_info * | ||
679 | to_of_pinfo(struct fsl_spi_platform_data *pdata) | ||
680 | { | ||
681 | return container_of(pdata, struct mpc83xx_spi_probe_info, pdata); | ||
682 | } | ||
683 | |||
684 | static void mpc83xx_spi_cs_control(struct spi_device *spi, bool on) | ||
685 | { | ||
686 | struct device *dev = spi->dev.parent; | ||
687 | struct mpc83xx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data); | ||
688 | u16 cs = spi->chip_select; | ||
689 | int gpio = pinfo->gpios[cs]; | ||
690 | bool alow = pinfo->alow_flags[cs]; | ||
691 | |||
692 | gpio_set_value(gpio, on ^ alow); | ||
693 | } | ||
694 | |||
695 | static int of_mpc83xx_spi_get_chipselects(struct device *dev) | ||
696 | { | ||
697 | struct device_node *np = dev_archdata_get_node(&dev->archdata); | ||
698 | struct fsl_spi_platform_data *pdata = dev->platform_data; | ||
699 | struct mpc83xx_spi_probe_info *pinfo = to_of_pinfo(pdata); | ||
700 | unsigned int ngpios; | ||
701 | int i = 0; | ||
702 | int ret; | ||
703 | |||
704 | ngpios = of_gpio_count(np); | ||
705 | if (!ngpios) { | ||
706 | /* | ||
707 | * SPI w/o chip-select line. One SPI device is still permitted | ||
708 | * though. | ||
709 | */ | ||
710 | pdata->max_chipselect = 1; | ||
711 | return 0; | ||
712 | } | ||
713 | |||
714 | pinfo->gpios = kmalloc(ngpios * sizeof(pinfo->gpios), GFP_KERNEL); | ||
715 | if (!pinfo->gpios) | ||
716 | return -ENOMEM; | ||
717 | memset(pinfo->gpios, -1, ngpios * sizeof(pinfo->gpios)); | ||
718 | |||
719 | pinfo->alow_flags = kzalloc(ngpios * sizeof(pinfo->alow_flags), | ||
720 | GFP_KERNEL); | ||
721 | if (!pinfo->alow_flags) { | ||
722 | ret = -ENOMEM; | ||
723 | goto err_alloc_flags; | ||
724 | } | ||
725 | |||
726 | for (; i < ngpios; i++) { | ||
727 | int gpio; | ||
728 | enum of_gpio_flags flags; | ||
729 | |||
730 | gpio = of_get_gpio_flags(np, i, &flags); | ||
731 | if (!gpio_is_valid(gpio)) { | ||
732 | dev_err(dev, "invalid gpio #%d: %d\n", i, gpio); | ||
733 | goto err_loop; | ||
734 | } | ||
735 | |||
736 | ret = gpio_request(gpio, dev_name(dev)); | ||
737 | if (ret) { | ||
738 | dev_err(dev, "can't request gpio #%d: %d\n", i, ret); | ||
739 | goto err_loop; | ||
740 | } | ||
741 | |||
742 | pinfo->gpios[i] = gpio; | ||
743 | pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW; | ||
744 | |||
745 | ret = gpio_direction_output(pinfo->gpios[i], | ||
746 | pinfo->alow_flags[i]); | ||
747 | if (ret) { | ||
748 | dev_err(dev, "can't set output direction for gpio " | ||
749 | "#%d: %d\n", i, ret); | ||
750 | goto err_loop; | ||
751 | } | ||
752 | } | ||
753 | |||
754 | pdata->max_chipselect = ngpios; | ||
755 | pdata->cs_control = mpc83xx_spi_cs_control; | ||
756 | |||
757 | return 0; | ||
758 | |||
759 | err_loop: | ||
760 | while (i >= 0) { | ||
761 | if (gpio_is_valid(pinfo->gpios[i])) | ||
762 | gpio_free(pinfo->gpios[i]); | ||
763 | i--; | ||
764 | } | ||
765 | |||
766 | kfree(pinfo->alow_flags); | ||
767 | pinfo->alow_flags = NULL; | ||
768 | err_alloc_flags: | ||
769 | kfree(pinfo->gpios); | ||
770 | pinfo->gpios = NULL; | ||
771 | return ret; | ||
772 | } | ||
773 | |||
774 | static int of_mpc83xx_spi_free_chipselects(struct device *dev) | ||
775 | { | ||
776 | struct fsl_spi_platform_data *pdata = dev->platform_data; | ||
777 | struct mpc83xx_spi_probe_info *pinfo = to_of_pinfo(pdata); | ||
778 | int i; | ||
779 | |||
780 | if (!pinfo->gpios) | ||
781 | return 0; | ||
782 | |||
783 | for (i = 0; i < pdata->max_chipselect; i++) { | ||
784 | if (gpio_is_valid(pinfo->gpios[i])) | ||
785 | gpio_free(pinfo->gpios[i]); | ||
786 | } | ||
787 | |||
788 | kfree(pinfo->gpios); | ||
789 | kfree(pinfo->alow_flags); | ||
790 | return 0; | ||
791 | } | ||
792 | |||
793 | static int __devinit of_mpc83xx_spi_probe(struct of_device *ofdev, | ||
794 | const struct of_device_id *ofid) | ||
795 | { | ||
796 | struct device *dev = &ofdev->dev; | ||
797 | struct device_node *np = ofdev->node; | ||
798 | struct mpc83xx_spi_probe_info *pinfo; | ||
799 | struct fsl_spi_platform_data *pdata; | ||
800 | struct spi_master *master; | ||
801 | struct resource mem; | ||
802 | struct resource irq; | ||
803 | const void *prop; | ||
804 | int ret = -ENOMEM; | ||
805 | |||
806 | pinfo = kzalloc(sizeof(*pinfo), GFP_KERNEL); | ||
807 | if (!pinfo) | ||
808 | return -ENOMEM; | ||
809 | |||
810 | pdata = &pinfo->pdata; | ||
811 | dev->platform_data = pdata; | ||
812 | |||
813 | /* Allocate bus num dynamically. */ | ||
814 | pdata->bus_num = -1; | ||
815 | |||
816 | /* SPI controller is either clocked from QE or SoC clock. */ | ||
817 | pdata->sysclk = get_brgfreq(); | ||
818 | if (pdata->sysclk == -1) { | ||
819 | pdata->sysclk = fsl_get_sys_freq(); | ||
820 | if (pdata->sysclk == -1) { | ||
821 | ret = -ENODEV; | ||
822 | goto err_clk; | ||
823 | } | ||
824 | } | ||
825 | |||
826 | prop = of_get_property(np, "mode", NULL); | ||
827 | if (prop && !strcmp(prop, "cpu-qe")) | ||
828 | pdata->qe_mode = 1; | ||
829 | |||
830 | ret = of_mpc83xx_spi_get_chipselects(dev); | ||
831 | if (ret) | ||
832 | goto err; | ||
833 | |||
834 | ret = of_address_to_resource(np, 0, &mem); | ||
835 | if (ret) | ||
836 | goto err; | ||
837 | |||
838 | ret = of_irq_to_resource(np, 0, &irq); | ||
839 | if (!ret) { | ||
840 | ret = -EINVAL; | ||
841 | goto err; | ||
842 | } | ||
843 | |||
844 | master = mpc83xx_spi_probe(dev, &mem, irq.start); | ||
845 | if (IS_ERR(master)) { | ||
846 | ret = PTR_ERR(master); | ||
847 | goto err; | ||
848 | } | ||
849 | |||
850 | of_register_spi_devices(master, np); | ||
851 | |||
852 | return 0; | ||
853 | |||
854 | err: | ||
855 | of_mpc83xx_spi_free_chipselects(dev); | ||
856 | err_clk: | ||
857 | kfree(pinfo); | ||
858 | return ret; | ||
859 | } | ||
860 | |||
861 | static int __devexit of_mpc83xx_spi_remove(struct of_device *ofdev) | ||
862 | { | ||
863 | int ret; | ||
864 | |||
865 | ret = mpc83xx_spi_remove(&ofdev->dev); | ||
866 | if (ret) | ||
867 | return ret; | ||
868 | of_mpc83xx_spi_free_chipselects(&ofdev->dev); | ||
869 | return 0; | ||
870 | } | ||
871 | |||
872 | static const struct of_device_id of_mpc83xx_spi_match[] = { | ||
873 | { .compatible = "fsl,spi" }, | ||
874 | {}, | ||
875 | }; | ||
876 | MODULE_DEVICE_TABLE(of, of_mpc83xx_spi_match); | ||
877 | |||
878 | static struct of_platform_driver of_mpc83xx_spi_driver = { | ||
879 | .name = "mpc83xx_spi", | ||
880 | .match_table = of_mpc83xx_spi_match, | ||
881 | .probe = of_mpc83xx_spi_probe, | ||
882 | .remove = __devexit_p(of_mpc83xx_spi_remove), | ||
883 | }; | ||
884 | |||
885 | #ifdef CONFIG_MPC832x_RDB | ||
886 | /* | ||
887 | * XXX XXX XXX | ||
888 | * This is "legacy" platform driver, was used by the MPC8323E-RDB boards | ||
889 | * only. The driver should go away soon, since newer MPC8323E-RDB's device | ||
890 | * tree can work with OpenFirmware driver. But for now we support old trees | ||
891 | * as well. | ||
892 | */ | ||
893 | static int __devinit plat_mpc83xx_spi_probe(struct platform_device *pdev) | ||
894 | { | ||
895 | struct resource *mem; | ||
896 | unsigned int irq; | ||
897 | struct spi_master *master; | ||
898 | |||
899 | if (!pdev->dev.platform_data) | ||
900 | return -EINVAL; | ||
901 | |||
902 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
903 | if (!mem) | ||
904 | return -EINVAL; | ||
905 | |||
906 | irq = platform_get_irq(pdev, 0); | ||
907 | if (!irq) | ||
908 | return -EINVAL; | ||
909 | |||
910 | master = mpc83xx_spi_probe(&pdev->dev, mem, irq); | ||
911 | if (IS_ERR(master)) | ||
912 | return PTR_ERR(master); | ||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | static int __devexit plat_mpc83xx_spi_remove(struct platform_device *pdev) | ||
917 | { | ||
918 | return mpc83xx_spi_remove(&pdev->dev); | ||
919 | } | ||
920 | |||
688 | MODULE_ALIAS("platform:mpc83xx_spi"); | 921 | MODULE_ALIAS("platform:mpc83xx_spi"); |
689 | static struct platform_driver mpc83xx_spi_driver = { | 922 | static struct platform_driver mpc83xx_spi_driver = { |
690 | .remove = __exit_p(mpc83xx_spi_remove), | 923 | .probe = plat_mpc83xx_spi_probe, |
924 | .remove = __exit_p(plat_mpc83xx_spi_remove), | ||
691 | .driver = { | 925 | .driver = { |
692 | .name = "mpc83xx_spi", | 926 | .name = "mpc83xx_spi", |
693 | .owner = THIS_MODULE, | 927 | .owner = THIS_MODULE, |
694 | }, | 928 | }, |
695 | }; | 929 | }; |
696 | 930 | ||
931 | static bool legacy_driver_failed; | ||
932 | |||
933 | static void __init legacy_driver_register(void) | ||
934 | { | ||
935 | legacy_driver_failed = platform_driver_register(&mpc83xx_spi_driver); | ||
936 | } | ||
937 | |||
938 | static void __exit legacy_driver_unregister(void) | ||
939 | { | ||
940 | if (legacy_driver_failed) | ||
941 | return; | ||
942 | platform_driver_unregister(&mpc83xx_spi_driver); | ||
943 | } | ||
944 | #else | ||
945 | static void __init legacy_driver_register(void) {} | ||
946 | static void __exit legacy_driver_unregister(void) {} | ||
947 | #endif /* CONFIG_MPC832x_RDB */ | ||
948 | |||
697 | static int __init mpc83xx_spi_init(void) | 949 | static int __init mpc83xx_spi_init(void) |
698 | { | 950 | { |
699 | return platform_driver_probe(&mpc83xx_spi_driver, mpc83xx_spi_probe); | 951 | legacy_driver_register(); |
952 | return of_register_platform_driver(&of_mpc83xx_spi_driver); | ||
700 | } | 953 | } |
701 | 954 | ||
702 | static void __exit mpc83xx_spi_exit(void) | 955 | static void __exit mpc83xx_spi_exit(void) |
703 | { | 956 | { |
704 | platform_driver_unregister(&mpc83xx_spi_driver); | 957 | of_unregister_platform_driver(&of_mpc83xx_spi_driver); |
958 | legacy_driver_unregister(); | ||
705 | } | 959 | } |
706 | 960 | ||
707 | module_init(mpc83xx_spi_init); | 961 | module_init(mpc83xx_spi_init); |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 742a5bc44be8..2a70563bbee1 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/tty_flip.h> | 26 | #include <linux/tty_flip.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/moduleparam.h> | 28 | #include <linux/moduleparam.h> |
29 | #include <linux/seq_file.h> | ||
29 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
30 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
31 | #include <linux/list.h> | 32 | #include <linux/list.h> |
@@ -421,57 +422,52 @@ static int serial_break(struct tty_struct *tty, int break_state) | |||
421 | return 0; | 422 | return 0; |
422 | } | 423 | } |
423 | 424 | ||
424 | static int serial_read_proc(char *page, char **start, off_t off, int count, | 425 | static int serial_proc_show(struct seq_file *m, void *v) |
425 | int *eof, void *data) | ||
426 | { | 426 | { |
427 | struct usb_serial *serial; | 427 | struct usb_serial *serial; |
428 | int length = 0; | ||
429 | int i; | 428 | int i; |
430 | off_t begin = 0; | ||
431 | char tmp[40]; | 429 | char tmp[40]; |
432 | 430 | ||
433 | dbg("%s", __func__); | 431 | dbg("%s", __func__); |
434 | length += sprintf(page, "usbserinfo:1.0 driver:2.0\n"); | 432 | seq_puts(m, "usbserinfo:1.0 driver:2.0\n"); |
435 | for (i = 0; i < SERIAL_TTY_MINORS && length < PAGE_SIZE; ++i) { | 433 | for (i = 0; i < SERIAL_TTY_MINORS; ++i) { |
436 | serial = usb_serial_get_by_index(i); | 434 | serial = usb_serial_get_by_index(i); |
437 | if (serial == NULL) | 435 | if (serial == NULL) |
438 | continue; | 436 | continue; |
439 | 437 | ||
440 | length += sprintf(page+length, "%d:", i); | 438 | seq_printf(m, "%d:", i); |
441 | if (serial->type->driver.owner) | 439 | if (serial->type->driver.owner) |
442 | length += sprintf(page+length, " module:%s", | 440 | seq_printf(m, " module:%s", |
443 | module_name(serial->type->driver.owner)); | 441 | module_name(serial->type->driver.owner)); |
444 | length += sprintf(page+length, " name:\"%s\"", | 442 | seq_printf(m, " name:\"%s\"", |
445 | serial->type->description); | 443 | serial->type->description); |
446 | length += sprintf(page+length, " vendor:%04x product:%04x", | 444 | seq_printf(m, " vendor:%04x product:%04x", |
447 | le16_to_cpu(serial->dev->descriptor.idVendor), | 445 | le16_to_cpu(serial->dev->descriptor.idVendor), |
448 | le16_to_cpu(serial->dev->descriptor.idProduct)); | 446 | le16_to_cpu(serial->dev->descriptor.idProduct)); |
449 | length += sprintf(page+length, " num_ports:%d", | 447 | seq_printf(m, " num_ports:%d", serial->num_ports); |
450 | serial->num_ports); | 448 | seq_printf(m, " port:%d", i - serial->minor + 1); |
451 | length += sprintf(page+length, " port:%d", | ||
452 | i - serial->minor + 1); | ||
453 | usb_make_path(serial->dev, tmp, sizeof(tmp)); | 449 | usb_make_path(serial->dev, tmp, sizeof(tmp)); |
454 | length += sprintf(page+length, " path:%s", tmp); | 450 | seq_printf(m, " path:%s", tmp); |
455 | 451 | ||
456 | length += sprintf(page+length, "\n"); | 452 | seq_putc(m, '\n'); |
457 | if ((length + begin) > (off + count)) { | ||
458 | usb_serial_put(serial); | ||
459 | goto done; | ||
460 | } | ||
461 | if ((length + begin) < off) { | ||
462 | begin += length; | ||
463 | length = 0; | ||
464 | } | ||
465 | usb_serial_put(serial); | 453 | usb_serial_put(serial); |
466 | } | 454 | } |
467 | *eof = 1; | 455 | return 0; |
468 | done: | ||
469 | if (off >= (length + begin)) | ||
470 | return 0; | ||
471 | *start = page + (off-begin); | ||
472 | return (count < begin+length-off) ? count : begin+length-off; | ||
473 | } | 456 | } |
474 | 457 | ||
458 | static int serial_proc_open(struct inode *inode, struct file *file) | ||
459 | { | ||
460 | return single_open(file, serial_proc_show, NULL); | ||
461 | } | ||
462 | |||
463 | static const struct file_operations serial_proc_fops = { | ||
464 | .owner = THIS_MODULE, | ||
465 | .open = serial_proc_open, | ||
466 | .read = seq_read, | ||
467 | .llseek = seq_lseek, | ||
468 | .release = single_release, | ||
469 | }; | ||
470 | |||
475 | static int serial_tiocmget(struct tty_struct *tty, struct file *file) | 471 | static int serial_tiocmget(struct tty_struct *tty, struct file *file) |
476 | { | 472 | { |
477 | struct usb_serial_port *port = tty->driver_data; | 473 | struct usb_serial_port *port = tty->driver_data; |
@@ -1113,9 +1109,9 @@ static const struct tty_operations serial_ops = { | |||
1113 | .unthrottle = serial_unthrottle, | 1109 | .unthrottle = serial_unthrottle, |
1114 | .break_ctl = serial_break, | 1110 | .break_ctl = serial_break, |
1115 | .chars_in_buffer = serial_chars_in_buffer, | 1111 | .chars_in_buffer = serial_chars_in_buffer, |
1116 | .read_proc = serial_read_proc, | ||
1117 | .tiocmget = serial_tiocmget, | 1112 | .tiocmget = serial_tiocmget, |
1118 | .tiocmset = serial_tiocmset, | 1113 | .tiocmset = serial_tiocmset, |
1114 | .proc_fops = &serial_proc_fops, | ||
1119 | }; | 1115 | }; |
1120 | 1116 | ||
1121 | struct tty_driver *usb_serial_tty_driver; | 1117 | struct tty_driver *usb_serial_tty_driver; |
diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index 7f907fb23b8a..0b17824b0eb5 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c | |||
@@ -471,9 +471,11 @@ int __init mc68x328fb_init(void) | |||
471 | fb_info.pseudo_palette = &mc68x328fb_pseudo_palette; | 471 | fb_info.pseudo_palette = &mc68x328fb_pseudo_palette; |
472 | fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; | 472 | fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; |
473 | 473 | ||
474 | fb_alloc_cmap(&fb_info.cmap, 256, 0); | 474 | if (fb_alloc_cmap(&fb_info.cmap, 256, 0)) |
475 | return -ENOMEM; | ||
475 | 476 | ||
476 | if (register_framebuffer(&fb_info) < 0) { | 477 | if (register_framebuffer(&fb_info) < 0) { |
478 | fb_dealloc_cmap(&fb_info.cmap); | ||
477 | return -EINVAL; | 479 | return -EINVAL; |
478 | } | 480 | } |
479 | 481 | ||
@@ -494,6 +496,7 @@ module_init(mc68x328fb_init); | |||
494 | static void __exit mc68x328fb_cleanup(void) | 496 | static void __exit mc68x328fb_cleanup(void) |
495 | { | 497 | { |
496 | unregister_framebuffer(&fb_info); | 498 | unregister_framebuffer(&fb_info); |
499 | fb_dealloc_cmap(&fb_info.cmap); | ||
497 | } | 500 | } |
498 | 501 | ||
499 | module_exit(mc68x328fb_cleanup); | 502 | module_exit(mc68x328fb_cleanup); |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 41c27a44bd82..ffe2f2796e29 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -1597,32 +1597,8 @@ config FB_VT8623 | |||
1597 | Driver for CastleRock integrated graphics core in the | 1597 | Driver for CastleRock integrated graphics core in the |
1598 | VIA VT8623 [Apollo CLE266] chipset. | 1598 | VIA VT8623 [Apollo CLE266] chipset. |
1599 | 1599 | ||
1600 | config FB_CYBLA | ||
1601 | tristate "Cyberblade/i1 support" | ||
1602 | depends on FB && PCI && X86_32 && !64BIT | ||
1603 | select FB_CFB_IMAGEBLIT | ||
1604 | ---help--- | ||
1605 | This driver is supposed to support the Trident Cyberblade/i1 | ||
1606 | graphics core integrated in the VIA VT8601A North Bridge, | ||
1607 | also known as VIA Apollo PLE133. | ||
1608 | |||
1609 | Status: | ||
1610 | - Developed, tested and working on EPIA 5000 and EPIA 800. | ||
1611 | - Does work reliable on all systems with CRT/LCD connected to | ||
1612 | normal VGA ports. | ||
1613 | - Should work on systems that do use the internal LCD port, but | ||
1614 | this is absolutely not tested. | ||
1615 | |||
1616 | Character imageblit, copyarea and rectangle fill are hw accelerated, | ||
1617 | ypan scrolling is used by default. | ||
1618 | |||
1619 | Please do read <file:Documentation/fb/cyblafb/*>. | ||
1620 | |||
1621 | To compile this driver as a module, choose M here: the | ||
1622 | module will be called cyblafb. | ||
1623 | |||
1624 | config FB_TRIDENT | 1600 | config FB_TRIDENT |
1625 | tristate "Trident support" | 1601 | tristate "Trident/CyberXXX/CyberBlade support" |
1626 | depends on FB && PCI | 1602 | depends on FB && PCI |
1627 | select FB_CFB_FILLRECT | 1603 | select FB_CFB_FILLRECT |
1628 | select FB_CFB_COPYAREA | 1604 | select FB_CFB_COPYAREA |
@@ -1633,21 +1609,14 @@ config FB_TRIDENT | |||
1633 | and Blade XP. | 1609 | and Blade XP. |
1634 | There are also integrated versions of these chips called CyberXXXX, | 1610 | There are also integrated versions of these chips called CyberXXXX, |
1635 | CyberImage or CyberBlade. These chips are mostly found in laptops | 1611 | CyberImage or CyberBlade. These chips are mostly found in laptops |
1636 | but also on some motherboards. For more information, read | 1612 | but also on some motherboards including early VIA EPIA motherboards. |
1637 | <file:Documentation/fb/tridentfb.txt> | 1613 | For more information, read <file:Documentation/fb/tridentfb.txt> |
1638 | 1614 | ||
1639 | Say Y if you have such a graphics board. | 1615 | Say Y if you have such a graphics board. |
1640 | 1616 | ||
1641 | To compile this driver as a module, choose M here: the | 1617 | To compile this driver as a module, choose M here: the |
1642 | module will be called tridentfb. | 1618 | module will be called tridentfb. |
1643 | 1619 | ||
1644 | config FB_TRIDENT_ACCEL | ||
1645 | bool "Trident Acceleration functions (EXPERIMENTAL)" | ||
1646 | depends on FB_TRIDENT && EXPERIMENTAL | ||
1647 | ---help--- | ||
1648 | This will compile the Trident frame buffer device with | ||
1649 | acceleration functions. | ||
1650 | |||
1651 | config FB_ARK | 1620 | config FB_ARK |
1652 | tristate "ARK 2000PV support" | 1621 | tristate "ARK 2000PV support" |
1653 | depends on FB && PCI | 1622 | depends on FB && PCI |
@@ -1920,6 +1889,30 @@ config FB_TMIO_ACCELL | |||
1920 | depends on FB_TMIO | 1889 | depends on FB_TMIO |
1921 | default y | 1890 | default y |
1922 | 1891 | ||
1892 | config FB_S3C | ||
1893 | tristate "Samsung S3C framebuffer support" | ||
1894 | depends on FB && ARCH_S3C64XX | ||
1895 | select FB_CFB_FILLRECT | ||
1896 | select FB_CFB_COPYAREA | ||
1897 | select FB_CFB_IMAGEBLIT | ||
1898 | ---help--- | ||
1899 | Frame buffer driver for the built-in FB controller in the Samsung | ||
1900 | SoC line from the S3C2443 onwards, including the S3C2416, S3C2450, | ||
1901 | and the S3C64XX series such as the S3C6400 and S3C6410. | ||
1902 | |||
1903 | These chips all have the same basic framebuffer design with the | ||
1904 | actual capabilities depending on the chip. For instance the S3C6400 | ||
1905 | and S3C6410 support 4 hardware windows whereas the S3C24XX series | ||
1906 | currently only have two. | ||
1907 | |||
1908 | Currently the support is only for the S3C6400 and S3C6410 SoCs. | ||
1909 | |||
1910 | config FB_S3C_DEBUG_REGWRITE | ||
1911 | bool "Debug register writes" | ||
1912 | depends on FB_S3C | ||
1913 | ---help--- | ||
1914 | Show all register writes via printk(KERN_DEBUG) | ||
1915 | |||
1923 | config FB_S3C2410 | 1916 | config FB_S3C2410 |
1924 | tristate "S3C2410 LCD framebuffer support" | 1917 | tristate "S3C2410 LCD framebuffer support" |
1925 | depends on FB && ARCH_S3C2410 | 1918 | depends on FB && ARCH_S3C2410 |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index bb265eca7d57..0dbd6c68d76b 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -76,6 +76,7 @@ obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \ | |||
76 | atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o | 76 | atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o |
77 | obj-$(CONFIG_FB_MAC) += macfb.o | 77 | obj-$(CONFIG_FB_MAC) += macfb.o |
78 | obj-$(CONFIG_FB_HECUBA) += hecubafb.o | 78 | obj-$(CONFIG_FB_HECUBA) += hecubafb.o |
79 | obj-$(CONFIG_FB_N411) += n411.o | ||
79 | obj-$(CONFIG_FB_HGA) += hgafb.o | 80 | obj-$(CONFIG_FB_HGA) += hgafb.o |
80 | obj-$(CONFIG_FB_XVR500) += sunxvr500.o | 81 | obj-$(CONFIG_FB_XVR500) += sunxvr500.o |
81 | obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o | 82 | obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o |
@@ -110,6 +111,7 @@ obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o | |||
110 | obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o | 111 | obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o |
111 | obj-$(CONFIG_FB_SH7760) += sh7760fb.o | 112 | obj-$(CONFIG_FB_SH7760) += sh7760fb.o |
112 | obj-$(CONFIG_FB_IMX) += imxfb.o | 113 | obj-$(CONFIG_FB_IMX) += imxfb.o |
114 | obj-$(CONFIG_FB_S3C) += s3c-fb.o | ||
113 | obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o | 115 | obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o |
114 | obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o | 116 | obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o |
115 | obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o | 117 | obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o |
diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 4e046fed1380..61050ab14128 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c | |||
@@ -408,7 +408,9 @@ static int clcdfb_register(struct clcd_fb *fb) | |||
408 | /* | 408 | /* |
409 | * Allocate colourmap. | 409 | * Allocate colourmap. |
410 | */ | 410 | */ |
411 | fb_alloc_cmap(&fb->fb.cmap, 256, 0); | 411 | ret = fb_alloc_cmap(&fb->fb.cmap, 256, 0); |
412 | if (ret) | ||
413 | goto unmap; | ||
412 | 414 | ||
413 | /* | 415 | /* |
414 | * Ensure interrupts are disabled. | 416 | * Ensure interrupts are disabled. |
@@ -426,6 +428,8 @@ static int clcdfb_register(struct clcd_fb *fb) | |||
426 | 428 | ||
427 | printk(KERN_ERR "CLCD: cannot register framebuffer (%d)\n", ret); | 429 | printk(KERN_ERR "CLCD: cannot register framebuffer (%d)\n", ret); |
428 | 430 | ||
431 | fb_dealloc_cmap(&fb->fb.cmap); | ||
432 | unmap: | ||
429 | iounmap(fb->regs); | 433 | iounmap(fb->regs); |
430 | free_clk: | 434 | free_clk: |
431 | clk_put(fb->clk); | 435 | clk_put(fb->clk); |
@@ -485,6 +489,8 @@ static int clcdfb_remove(struct amba_device *dev) | |||
485 | 489 | ||
486 | clcdfb_disable(fb); | 490 | clcdfb_disable(fb); |
487 | unregister_framebuffer(&fb->fb); | 491 | unregister_framebuffer(&fb->fb); |
492 | if (fb->fb.cmap.len) | ||
493 | fb_dealloc_cmap(&fb->fb.cmap); | ||
488 | iounmap(fb->regs); | 494 | iounmap(fb->regs); |
489 | clk_put(fb->clk); | 495 | clk_put(fb->clk); |
490 | 496 | ||
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 100f23661465..82bedd7f7789 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c | |||
@@ -2437,7 +2437,9 @@ default_chipset: | |||
2437 | goto amifb_error; | 2437 | goto amifb_error; |
2438 | } | 2438 | } |
2439 | 2439 | ||
2440 | fb_alloc_cmap(&fb_info.cmap, 1<<fb_info.var.bits_per_pixel, 0); | 2440 | err = fb_alloc_cmap(&fb_info.cmap, 1<<fb_info.var.bits_per_pixel, 0); |
2441 | if (err) | ||
2442 | goto amifb_error; | ||
2441 | 2443 | ||
2442 | if (register_framebuffer(&fb_info) < 0) { | 2444 | if (register_framebuffer(&fb_info) < 0) { |
2443 | err = -EINVAL; | 2445 | err = -EINVAL; |
@@ -2456,7 +2458,8 @@ amifb_error: | |||
2456 | 2458 | ||
2457 | static void amifb_deinit(void) | 2459 | static void amifb_deinit(void) |
2458 | { | 2460 | { |
2459 | fb_dealloc_cmap(&fb_info.cmap); | 2461 | if (fb_info.cmap.len) |
2462 | fb_dealloc_cmap(&fb_info.cmap); | ||
2460 | chipfree(); | 2463 | chipfree(); |
2461 | if (videomemory) | 2464 | if (videomemory) |
2462 | iounmap((void*)videomemory); | 2465 | iounmap((void*)videomemory); |
diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c index 314d18694b6a..d583bea608fd 100644 --- a/drivers/video/arkfb.c +++ b/drivers/video/arkfb.c | |||
@@ -470,7 +470,7 @@ static void ark_dac_read_regs(void *data, u8 *code, int count) | |||
470 | 470 | ||
471 | while (count != 0) | 471 | while (count != 0) |
472 | { | 472 | { |
473 | vga_wseq(NULL, 0x1C, regval | (code[0] & 4) ? 0x80 : 0); | 473 | vga_wseq(NULL, 0x1C, regval | (code[0] & 4 ? 0x80 : 0)); |
474 | code[1] = vga_r(NULL, dac_regs[code[0] & 3]); | 474 | code[1] = vga_r(NULL, dac_regs[code[0] & 3]); |
475 | count--; | 475 | count--; |
476 | code += 2; | 476 | code += 2; |
@@ -485,7 +485,7 @@ static void ark_dac_write_regs(void *data, u8 *code, int count) | |||
485 | 485 | ||
486 | while (count != 0) | 486 | while (count != 0) |
487 | { | 487 | { |
488 | vga_wseq(NULL, 0x1C, regval | (code[0] & 4) ? 0x80 : 0); | 488 | vga_wseq(NULL, 0x1C, regval | (code[0] & 4 ? 0x80 : 0)); |
489 | vga_w(NULL, dac_regs[code[0] & 3], code[1]); | 489 | vga_w(NULL, dac_regs[code[0] & 3], code[1]); |
490 | count--; | 490 | count--; |
491 | code += 2; | 491 | code += 2; |
diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index 1fd22f460b0f..1a1f946d8fef 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c | |||
@@ -505,19 +505,27 @@ static struct fb_var_screeninfo asiliantfb_var __devinitdata = { | |||
505 | .vsync_len = 2, | 505 | .vsync_len = 2, |
506 | }; | 506 | }; |
507 | 507 | ||
508 | static void __devinit init_asiliant(struct fb_info *p, unsigned long addr) | 508 | static int __devinit init_asiliant(struct fb_info *p, unsigned long addr) |
509 | { | 509 | { |
510 | int err; | ||
511 | |||
510 | p->fix = asiliantfb_fix; | 512 | p->fix = asiliantfb_fix; |
511 | p->fix.smem_start = addr; | 513 | p->fix.smem_start = addr; |
512 | p->var = asiliantfb_var; | 514 | p->var = asiliantfb_var; |
513 | p->fbops = &asiliantfb_ops; | 515 | p->fbops = &asiliantfb_ops; |
514 | p->flags = FBINFO_DEFAULT; | 516 | p->flags = FBINFO_DEFAULT; |
515 | 517 | ||
516 | fb_alloc_cmap(&p->cmap, 256, 0); | 518 | err = fb_alloc_cmap(&p->cmap, 256, 0); |
519 | if (err) { | ||
520 | printk(KERN_ERR "C&T 69000 fb failed to alloc cmap memory\n"); | ||
521 | return err; | ||
522 | } | ||
517 | 523 | ||
518 | if (register_framebuffer(p) < 0) { | 524 | err = register_framebuffer(p); |
525 | if (err < 0) { | ||
519 | printk(KERN_ERR "C&T 69000 framebuffer failed to register\n"); | 526 | printk(KERN_ERR "C&T 69000 framebuffer failed to register\n"); |
520 | return; | 527 | fb_dealloc_cmap(&p->cmap); |
528 | return err; | ||
521 | } | 529 | } |
522 | 530 | ||
523 | printk(KERN_INFO "fb%d: Asiliant 69000 frame buffer (%dK RAM detected)\n", | 531 | printk(KERN_INFO "fb%d: Asiliant 69000 frame buffer (%dK RAM detected)\n", |
@@ -532,6 +540,7 @@ asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) | |||
532 | { | 540 | { |
533 | unsigned long addr, size; | 541 | unsigned long addr, size; |
534 | struct fb_info *p; | 542 | struct fb_info *p; |
543 | int err; | ||
535 | 544 | ||
536 | if ((dp->resource[0].flags & IORESOURCE_MEM) == 0) | 545 | if ((dp->resource[0].flags & IORESOURCE_MEM) == 0) |
537 | return -ENODEV; | 546 | return -ENODEV; |
@@ -560,7 +569,13 @@ asiliantfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) | |||
560 | pci_write_config_dword(dp, 4, 0x02800083); | 569 | pci_write_config_dword(dp, 4, 0x02800083); |
561 | writeb(3, p->screen_base + 0x400784); | 570 | writeb(3, p->screen_base + 0x400784); |
562 | 571 | ||
563 | init_asiliant(p, addr); | 572 | err = init_asiliant(p, addr); |
573 | if (err) { | ||
574 | iounmap(p->screen_base); | ||
575 | release_mem_region(addr, size); | ||
576 | framebuffer_release(p); | ||
577 | return err; | ||
578 | } | ||
564 | 579 | ||
565 | pci_set_drvdata(dp, p); | 580 | pci_set_drvdata(dp, p); |
566 | return 0; | 581 | return 0; |
@@ -571,6 +586,7 @@ static void __devexit asiliantfb_remove(struct pci_dev *dp) | |||
571 | struct fb_info *p = pci_get_drvdata(dp); | 586 | struct fb_info *p = pci_get_drvdata(dp); |
572 | 587 | ||
573 | unregister_framebuffer(p); | 588 | unregister_framebuffer(p); |
589 | fb_dealloc_cmap(&p->cmap); | ||
574 | iounmap(p->screen_base); | 590 | iounmap(p->screen_base); |
575 | release_mem_region(pci_resource_start(dp, 0), pci_resource_len(dp, 0)); | 591 | release_mem_region(pci_resource_start(dp, 0), pci_resource_len(dp, 0)); |
576 | pci_set_drvdata(dp, NULL); | 592 | pci_set_drvdata(dp, NULL); |
diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c index a8f60c33863c..0cc9724e61a2 100644 --- a/drivers/video/aty/mach64_accel.c +++ b/drivers/video/aty/mach64_accel.c | |||
@@ -39,7 +39,8 @@ void aty_reset_engine(const struct atyfb_par *par) | |||
39 | { | 39 | { |
40 | /* reset engine */ | 40 | /* reset engine */ |
41 | aty_st_le32(GEN_TEST_CNTL, | 41 | aty_st_le32(GEN_TEST_CNTL, |
42 | aty_ld_le32(GEN_TEST_CNTL, par) & ~GUI_ENGINE_ENABLE, par); | 42 | aty_ld_le32(GEN_TEST_CNTL, par) & |
43 | ~(GUI_ENGINE_ENABLE | HWCURSOR_ENABLE), par); | ||
43 | /* enable engine */ | 44 | /* enable engine */ |
44 | aty_st_le32(GEN_TEST_CNTL, | 45 | aty_st_le32(GEN_TEST_CNTL, |
45 | aty_ld_le32(GEN_TEST_CNTL, par) | GUI_ENGINE_ENABLE, par); | 46 | aty_ld_le32(GEN_TEST_CNTL, par) | GUI_ENGINE_ENABLE, par); |
diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c index faf95da8fcbc..04c710804bb0 100644 --- a/drivers/video/aty/mach64_cursor.c +++ b/drivers/video/aty/mach64_cursor.c | |||
@@ -77,9 +77,13 @@ static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
77 | if (par->asleep) | 77 | if (par->asleep) |
78 | return -EPERM; | 78 | return -EPERM; |
79 | 79 | ||
80 | /* Hide cursor */ | ||
81 | wait_for_fifo(1, par); | 80 | wait_for_fifo(1, par); |
82 | aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par) & ~HWCURSOR_ENABLE, par); | 81 | if (cursor->enable) |
82 | aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par) | ||
83 | | HWCURSOR_ENABLE, par); | ||
84 | else | ||
85 | aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par) | ||
86 | & ~HWCURSOR_ENABLE, par); | ||
83 | 87 | ||
84 | /* set position */ | 88 | /* set position */ |
85 | if (cursor->set & FB_CUR_SETPOS) { | 89 | if (cursor->set & FB_CUR_SETPOS) { |
@@ -109,7 +113,7 @@ static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
109 | y<<=1; | 113 | y<<=1; |
110 | h<<=1; | 114 | h<<=1; |
111 | } | 115 | } |
112 | wait_for_fifo(4, par); | 116 | wait_for_fifo(3, par); |
113 | aty_st_le32(CUR_OFFSET, (info->fix.smem_len >> 3) + (yoff << 1), par); | 117 | aty_st_le32(CUR_OFFSET, (info->fix.smem_len >> 3) + (yoff << 1), par); |
114 | aty_st_le32(CUR_HORZ_VERT_OFF, | 118 | aty_st_le32(CUR_HORZ_VERT_OFF, |
115 | ((u32) (64 - h + yoff) << 16) | xoff, par); | 119 | ((u32) (64 - h + yoff) << 16) | xoff, par); |
@@ -177,11 +181,6 @@ static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
177 | } | 181 | } |
178 | } | 182 | } |
179 | 183 | ||
180 | if (cursor->enable) { | ||
181 | wait_for_fifo(1, par); | ||
182 | aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, par) | ||
183 | | HWCURSOR_ENABLE, par); | ||
184 | } | ||
185 | return 0; | 184 | return 0; |
186 | } | 185 | } |
187 | 186 | ||
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 1de0c0032468..97a1f095f327 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c | |||
@@ -89,6 +89,9 @@ static struct radeon_device_id radeon_workaround_list[] = { | |||
89 | BUGFIX("Acer Aspire 2010", | 89 | BUGFIX("Acer Aspire 2010", |
90 | PCI_VENDOR_ID_AI, 0x0061, | 90 | PCI_VENDOR_ID_AI, 0x0061, |
91 | radeon_pm_off, radeon_reinitialize_M10), | 91 | radeon_pm_off, radeon_reinitialize_M10), |
92 | BUGFIX("Acer Travelmate 290D/292LMi", | ||
93 | PCI_VENDOR_ID_AI, 0x005a, | ||
94 | radeon_pm_off, radeon_reinitialize_M10), | ||
92 | { .ident = NULL } | 95 | { .ident = NULL } |
93 | }; | 96 | }; |
94 | 97 | ||
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 157057c79ca3..dd37cbcaf8ce 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c | |||
@@ -35,6 +35,8 @@ static int fb_notifier_callback(struct notifier_block *self, | |||
35 | return 0; | 35 | return 0; |
36 | 36 | ||
37 | bd = container_of(self, struct backlight_device, fb_notif); | 37 | bd = container_of(self, struct backlight_device, fb_notif); |
38 | if (!lock_fb_info(evdata->info)) | ||
39 | return -ENODEV; | ||
38 | mutex_lock(&bd->ops_lock); | 40 | mutex_lock(&bd->ops_lock); |
39 | if (bd->ops) | 41 | if (bd->ops) |
40 | if (!bd->ops->check_fb || | 42 | if (!bd->ops->check_fb || |
@@ -47,6 +49,7 @@ static int fb_notifier_callback(struct notifier_block *self, | |||
47 | backlight_update_status(bd); | 49 | backlight_update_status(bd); |
48 | } | 50 | } |
49 | mutex_unlock(&bd->ops_lock); | 51 | mutex_unlock(&bd->ops_lock); |
52 | unlock_fb_info(evdata->info); | ||
50 | return 0; | 53 | return 0; |
51 | } | 54 | } |
52 | 55 | ||
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index b6449470106c..0bb13df0fa89 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c | |||
@@ -40,6 +40,8 @@ static int fb_notifier_callback(struct notifier_block *self, | |||
40 | if (!ld->ops) | 40 | if (!ld->ops) |
41 | return 0; | 41 | return 0; |
42 | 42 | ||
43 | if (!lock_fb_info(evdata->info)) | ||
44 | return -ENODEV; | ||
43 | mutex_lock(&ld->ops_lock); | 45 | mutex_lock(&ld->ops_lock); |
44 | if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) { | 46 | if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) { |
45 | if (event == FB_EVENT_BLANK) { | 47 | if (event == FB_EVENT_BLANK) { |
@@ -51,6 +53,7 @@ static int fb_notifier_callback(struct notifier_block *self, | |||
51 | } | 53 | } |
52 | } | 54 | } |
53 | mutex_unlock(&ld->ops_lock); | 55 | mutex_unlock(&ld->ops_lock); |
56 | unlock_fb_info(evdata->info); | ||
54 | return 0; | 57 | return 0; |
55 | } | 58 | } |
56 | 59 | ||
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index a2aa6ddffbe2..d42e385f091c 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c | |||
@@ -34,8 +34,6 @@ | |||
34 | * | 34 | * |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #define CIRRUSFB_VERSION "2.0-pre2" | ||
38 | |||
39 | #include <linux/module.h> | 37 | #include <linux/module.h> |
40 | #include <linux/kernel.h> | 38 | #include <linux/kernel.h> |
41 | #include <linux/errno.h> | 39 | #include <linux/errno.h> |
@@ -72,20 +70,9 @@ | |||
72 | * | 70 | * |
73 | */ | 71 | */ |
74 | 72 | ||
75 | /* enable debug output? */ | ||
76 | /* #define CIRRUSFB_DEBUG 1 */ | ||
77 | |||
78 | /* disable runtime assertions? */ | 73 | /* disable runtime assertions? */ |
79 | /* #define CIRRUSFB_NDEBUG */ | 74 | /* #define CIRRUSFB_NDEBUG */ |
80 | 75 | ||
81 | /* debug output */ | ||
82 | #ifdef CIRRUSFB_DEBUG | ||
83 | #define DPRINTK(fmt, args...) \ | ||
84 | printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) | ||
85 | #else | ||
86 | #define DPRINTK(fmt, args...) | ||
87 | #endif | ||
88 | |||
89 | /* debugging assertions */ | 76 | /* debugging assertions */ |
90 | #ifndef CIRRUSFB_NDEBUG | 77 | #ifndef CIRRUSFB_NDEBUG |
91 | #define assert(expr) \ | 78 | #define assert(expr) \ |
@@ -108,14 +95,15 @@ | |||
108 | /* board types */ | 95 | /* board types */ |
109 | enum cirrus_board { | 96 | enum cirrus_board { |
110 | BT_NONE = 0, | 97 | BT_NONE = 0, |
111 | BT_SD64, | 98 | BT_SD64, /* GD5434 */ |
112 | BT_PICCOLO, | 99 | BT_PICCOLO, /* GD5426 */ |
113 | BT_PICASSO, | 100 | BT_PICASSO, /* GD5426 or GD5428 */ |
114 | BT_SPECTRUM, | 101 | BT_SPECTRUM, /* GD5426 or GD5428 */ |
115 | BT_PICASSO4, /* GD5446 */ | 102 | BT_PICASSO4, /* GD5446 */ |
116 | BT_ALPINE, /* GD543x/4x */ | 103 | BT_ALPINE, /* GD543x/4x */ |
117 | BT_GD5480, | 104 | BT_GD5480, |
118 | BT_LAGUNA, /* GD546x */ | 105 | BT_LAGUNA, /* GD5462/64 */ |
106 | BT_LAGUNAB, /* GD5465 */ | ||
119 | }; | 107 | }; |
120 | 108 | ||
121 | /* | 109 | /* |
@@ -150,15 +138,17 @@ static const struct cirrusfb_board_info_rec { | |||
150 | .maxclock = { | 138 | .maxclock = { |
151 | /* guess */ | 139 | /* guess */ |
152 | /* the SD64/P4 have a higher max. videoclock */ | 140 | /* the SD64/P4 have a higher max. videoclock */ |
153 | 140000, 140000, 140000, 140000, 140000, | 141 | 135100, 135100, 85500, 85500, 0 |
154 | }, | 142 | }, |
155 | .init_sr07 = true, | 143 | .init_sr07 = true, |
156 | .init_sr1f = true, | 144 | .init_sr1f = true, |
157 | .scrn_start_bit19 = true, | 145 | .scrn_start_bit19 = true, |
158 | .sr07 = 0xF0, | 146 | .sr07 = 0xF0, |
159 | .sr07_1bpp = 0xF0, | 147 | .sr07_1bpp = 0xF0, |
148 | .sr07_1bpp_mux = 0xF6, | ||
160 | .sr07_8bpp = 0xF1, | 149 | .sr07_8bpp = 0xF1, |
161 | .sr1f = 0x20 | 150 | .sr07_8bpp_mux = 0xF7, |
151 | .sr1f = 0x1E | ||
162 | }, | 152 | }, |
163 | [BT_PICCOLO] = { | 153 | [BT_PICCOLO] = { |
164 | .name = "CL Piccolo", | 154 | .name = "CL Piccolo", |
@@ -210,9 +200,11 @@ static const struct cirrusfb_board_info_rec { | |||
210 | .init_sr07 = true, | 200 | .init_sr07 = true, |
211 | .init_sr1f = false, | 201 | .init_sr1f = false, |
212 | .scrn_start_bit19 = true, | 202 | .scrn_start_bit19 = true, |
213 | .sr07 = 0x20, | 203 | .sr07 = 0xA0, |
214 | .sr07_1bpp = 0x20, | 204 | .sr07_1bpp = 0xA0, |
215 | .sr07_8bpp = 0x21, | 205 | .sr07_1bpp_mux = 0xA6, |
206 | .sr07_8bpp = 0xA1, | ||
207 | .sr07_8bpp_mux = 0xA7, | ||
216 | .sr1f = 0 | 208 | .sr1f = 0 |
217 | }, | 209 | }, |
218 | [BT_ALPINE] = { | 210 | [BT_ALPINE] = { |
@@ -225,8 +217,8 @@ static const struct cirrusfb_board_info_rec { | |||
225 | .init_sr1f = true, | 217 | .init_sr1f = true, |
226 | .scrn_start_bit19 = true, | 218 | .scrn_start_bit19 = true, |
227 | .sr07 = 0xA0, | 219 | .sr07 = 0xA0, |
228 | .sr07_1bpp = 0xA1, | 220 | .sr07_1bpp = 0xA0, |
229 | .sr07_1bpp_mux = 0xA7, | 221 | .sr07_1bpp_mux = 0xA6, |
230 | .sr07_8bpp = 0xA1, | 222 | .sr07_8bpp = 0xA1, |
231 | .sr07_8bpp_mux = 0xA7, | 223 | .sr07_8bpp_mux = 0xA7, |
232 | .sr1f = 0x1C | 224 | .sr1f = 0x1C |
@@ -247,8 +239,18 @@ static const struct cirrusfb_board_info_rec { | |||
247 | [BT_LAGUNA] = { | 239 | [BT_LAGUNA] = { |
248 | .name = "CL Laguna", | 240 | .name = "CL Laguna", |
249 | .maxclock = { | 241 | .maxclock = { |
250 | /* guess */ | 242 | /* taken from X11 code */ |
251 | 135100, 135100, 135100, 135100, 135100, | 243 | 170000, 170000, 170000, 170000, 135100, |
244 | }, | ||
245 | .init_sr07 = false, | ||
246 | .init_sr1f = false, | ||
247 | .scrn_start_bit19 = true, | ||
248 | }, | ||
249 | [BT_LAGUNAB] = { | ||
250 | .name = "CL Laguna AGP", | ||
251 | .maxclock = { | ||
252 | /* taken from X11 code */ | ||
253 | 170000, 250000, 170000, 170000, 135100, | ||
252 | }, | 254 | }, |
253 | .init_sr07 = false, | 255 | .init_sr07 = false, |
254 | .init_sr1f = false, | 256 | .init_sr1f = false, |
@@ -262,8 +264,8 @@ static const struct cirrusfb_board_info_rec { | |||
262 | 264 | ||
263 | static struct pci_device_id cirrusfb_pci_table[] = { | 265 | static struct pci_device_id cirrusfb_pci_table[] = { |
264 | CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE), | 266 | CHIP(PCI_DEVICE_ID_CIRRUS_5436, BT_ALPINE), |
265 | CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_ALPINE), | 267 | CHIP(PCI_DEVICE_ID_CIRRUS_5434_8, BT_SD64), |
266 | CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_ALPINE), | 268 | CHIP(PCI_DEVICE_ID_CIRRUS_5434_4, BT_SD64), |
267 | CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */ | 269 | CHIP(PCI_DEVICE_ID_CIRRUS_5430, BT_ALPINE), /* GD-5440 is same id */ |
268 | CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE), | 270 | CHIP(PCI_DEVICE_ID_CIRRUS_7543, BT_ALPINE), |
269 | CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE), | 271 | CHIP(PCI_DEVICE_ID_CIRRUS_7548, BT_ALPINE), |
@@ -271,7 +273,7 @@ static struct pci_device_id cirrusfb_pci_table[] = { | |||
271 | CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */ | 273 | CHIP(PCI_DEVICE_ID_CIRRUS_5446, BT_PICASSO4), /* Picasso 4 is 5446 */ |
272 | CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */ | 274 | CHIP(PCI_DEVICE_ID_CIRRUS_5462, BT_LAGUNA), /* CL Laguna */ |
273 | CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */ | 275 | CHIP(PCI_DEVICE_ID_CIRRUS_5464, BT_LAGUNA), /* CL Laguna 3D */ |
274 | CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNA), /* CL Laguna 3DA*/ | 276 | CHIP(PCI_DEVICE_ID_CIRRUS_5465, BT_LAGUNAB), /* CL Laguna 3DA*/ |
275 | { 0, } | 277 | { 0, } |
276 | }; | 278 | }; |
277 | MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table); | 279 | MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table); |
@@ -326,10 +328,6 @@ static const struct { | |||
326 | }; | 328 | }; |
327 | #endif /* CONFIG_ZORRO */ | 329 | #endif /* CONFIG_ZORRO */ |
328 | 330 | ||
329 | struct cirrusfb_regs { | ||
330 | int multiplexing; | ||
331 | }; | ||
332 | |||
333 | #ifdef CIRRUSFB_DEBUG | 331 | #ifdef CIRRUSFB_DEBUG |
334 | enum cirrusfb_dbg_reg_class { | 332 | enum cirrusfb_dbg_reg_class { |
335 | CRT, | 333 | CRT, |
@@ -340,10 +338,12 @@ enum cirrusfb_dbg_reg_class { | |||
340 | /* info about board */ | 338 | /* info about board */ |
341 | struct cirrusfb_info { | 339 | struct cirrusfb_info { |
342 | u8 __iomem *regbase; | 340 | u8 __iomem *regbase; |
341 | u8 __iomem *laguna_mmio; | ||
343 | enum cirrus_board btype; | 342 | enum cirrus_board btype; |
344 | unsigned char SFR; /* Shadow of special function register */ | 343 | unsigned char SFR; /* Shadow of special function register */ |
345 | 344 | ||
346 | struct cirrusfb_regs currentmode; | 345 | int multiplexing; |
346 | int doubleVCLK; | ||
347 | int blank_mode; | 347 | int blank_mode; |
348 | u32 pseudo_palette[16]; | 348 | u32 pseudo_palette[16]; |
349 | 349 | ||
@@ -357,43 +357,8 @@ static char *mode_option __devinitdata = "640x480@60"; | |||
357 | /**** BEGIN PROTOTYPES ******************************************************/ | 357 | /**** BEGIN PROTOTYPES ******************************************************/ |
358 | 358 | ||
359 | /*--- Interface used by the world ------------------------------------------*/ | 359 | /*--- Interface used by the world ------------------------------------------*/ |
360 | static int cirrusfb_init(void); | ||
361 | #ifndef MODULE | ||
362 | static int cirrusfb_setup(char *options); | ||
363 | #endif | ||
364 | |||
365 | static int cirrusfb_open(struct fb_info *info, int user); | ||
366 | static int cirrusfb_release(struct fb_info *info, int user); | ||
367 | static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
368 | unsigned blue, unsigned transp, | ||
369 | struct fb_info *info); | ||
370 | static int cirrusfb_check_var(struct fb_var_screeninfo *var, | ||
371 | struct fb_info *info); | ||
372 | static int cirrusfb_set_par(struct fb_info *info); | ||
373 | static int cirrusfb_pan_display(struct fb_var_screeninfo *var, | 360 | static int cirrusfb_pan_display(struct fb_var_screeninfo *var, |
374 | struct fb_info *info); | 361 | struct fb_info *info); |
375 | static int cirrusfb_blank(int blank_mode, struct fb_info *info); | ||
376 | static void cirrusfb_fillrect(struct fb_info *info, | ||
377 | const struct fb_fillrect *region); | ||
378 | static void cirrusfb_copyarea(struct fb_info *info, | ||
379 | const struct fb_copyarea *area); | ||
380 | static void cirrusfb_imageblit(struct fb_info *info, | ||
381 | const struct fb_image *image); | ||
382 | |||
383 | /* function table of the above functions */ | ||
384 | static struct fb_ops cirrusfb_ops = { | ||
385 | .owner = THIS_MODULE, | ||
386 | .fb_open = cirrusfb_open, | ||
387 | .fb_release = cirrusfb_release, | ||
388 | .fb_setcolreg = cirrusfb_setcolreg, | ||
389 | .fb_check_var = cirrusfb_check_var, | ||
390 | .fb_set_par = cirrusfb_set_par, | ||
391 | .fb_pan_display = cirrusfb_pan_display, | ||
392 | .fb_blank = cirrusfb_blank, | ||
393 | .fb_fillrect = cirrusfb_fillrect, | ||
394 | .fb_copyarea = cirrusfb_copyarea, | ||
395 | .fb_imageblit = cirrusfb_imageblit, | ||
396 | }; | ||
397 | 362 | ||
398 | /*--- Internal routines ----------------------------------------------------*/ | 363 | /*--- Internal routines ----------------------------------------------------*/ |
399 | static void init_vgachip(struct fb_info *info); | 364 | static void init_vgachip(struct fb_info *info); |
@@ -421,22 +386,27 @@ static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, | |||
421 | static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, | 386 | static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, |
422 | u_short x, u_short y, | 387 | u_short x, u_short y, |
423 | u_short width, u_short height, | 388 | u_short width, u_short height, |
424 | u_char color, u_short line_length); | 389 | u32 fg_color, u32 bg_color, |
390 | u_short line_length, u_char blitmode); | ||
425 | 391 | ||
426 | static void bestclock(long freq, int *nom, int *den, int *div); | 392 | static void bestclock(long freq, int *nom, int *den, int *div); |
427 | 393 | ||
428 | #ifdef CIRRUSFB_DEBUG | 394 | #ifdef CIRRUSFB_DEBUG |
429 | static void cirrusfb_dump(void); | 395 | static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase); |
430 | static void cirrusfb_dbg_reg_dump(caddr_t regbase); | 396 | static void cirrusfb_dbg_print_regs(struct fb_info *info, |
431 | static void cirrusfb_dbg_print_regs(caddr_t regbase, | 397 | caddr_t regbase, |
432 | enum cirrusfb_dbg_reg_class reg_class, ...); | 398 | enum cirrusfb_dbg_reg_class reg_class, ...); |
433 | static void cirrusfb_dbg_print_byte(const char *name, unsigned char val); | ||
434 | #endif /* CIRRUSFB_DEBUG */ | 399 | #endif /* CIRRUSFB_DEBUG */ |
435 | 400 | ||
436 | /*** END PROTOTYPES ********************************************************/ | 401 | /*** END PROTOTYPES ********************************************************/ |
437 | /*****************************************************************************/ | 402 | /*****************************************************************************/ |
438 | /*** BEGIN Interface Used by the World ***************************************/ | 403 | /*** BEGIN Interface Used by the World ***************************************/ |
439 | 404 | ||
405 | static inline int is_laguna(const struct cirrusfb_info *cinfo) | ||
406 | { | ||
407 | return cinfo->btype == BT_LAGUNA || cinfo->btype == BT_LAGUNAB; | ||
408 | } | ||
409 | |||
440 | static int opencount; | 410 | static int opencount; |
441 | 411 | ||
442 | /*--- Open /dev/fbx ---------------------------------------------------------*/ | 412 | /*--- Open /dev/fbx ---------------------------------------------------------*/ |
@@ -460,85 +430,94 @@ static int cirrusfb_release(struct fb_info *info, int user) | |||
460 | /**** BEGIN Hardware specific Routines **************************************/ | 430 | /**** BEGIN Hardware specific Routines **************************************/ |
461 | 431 | ||
462 | /* Check if the MCLK is not a better clock source */ | 432 | /* Check if the MCLK is not a better clock source */ |
463 | static int cirrusfb_check_mclk(struct cirrusfb_info *cinfo, long freq) | 433 | static int cirrusfb_check_mclk(struct fb_info *info, long freq) |
464 | { | 434 | { |
435 | struct cirrusfb_info *cinfo = info->par; | ||
465 | long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f; | 436 | long mclk = vga_rseq(cinfo->regbase, CL_SEQR1F) & 0x3f; |
466 | 437 | ||
467 | /* Read MCLK value */ | 438 | /* Read MCLK value */ |
468 | mclk = (14318 * mclk) >> 3; | 439 | mclk = (14318 * mclk) >> 3; |
469 | DPRINTK("Read MCLK of %ld kHz\n", mclk); | 440 | dev_dbg(info->device, "Read MCLK of %ld kHz\n", mclk); |
470 | 441 | ||
471 | /* Determine if we should use MCLK instead of VCLK, and if so, what we | 442 | /* Determine if we should use MCLK instead of VCLK, and if so, what we |
472 | * should divide it by to get VCLK | 443 | * should divide it by to get VCLK |
473 | */ | 444 | */ |
474 | 445 | ||
475 | if (abs(freq - mclk) < 250) { | 446 | if (abs(freq - mclk) < 250) { |
476 | DPRINTK("Using VCLK = MCLK\n"); | 447 | dev_dbg(info->device, "Using VCLK = MCLK\n"); |
477 | return 1; | 448 | return 1; |
478 | } else if (abs(freq - (mclk / 2)) < 250) { | 449 | } else if (abs(freq - (mclk / 2)) < 250) { |
479 | DPRINTK("Using VCLK = MCLK/2\n"); | 450 | dev_dbg(info->device, "Using VCLK = MCLK/2\n"); |
480 | return 2; | 451 | return 2; |
481 | } | 452 | } |
482 | 453 | ||
483 | return 0; | 454 | return 0; |
484 | } | 455 | } |
485 | 456 | ||
486 | static int cirrusfb_check_var(struct fb_var_screeninfo *var, | 457 | static int cirrusfb_check_pixclock(const struct fb_var_screeninfo *var, |
487 | struct fb_info *info) | 458 | struct fb_info *info) |
488 | { | 459 | { |
489 | int yres; | 460 | long freq; |
490 | /* memory size in pixels */ | 461 | long maxclock; |
491 | unsigned pixels = info->screen_size * 8 / var->bits_per_pixel; | 462 | struct cirrusfb_info *cinfo = info->par; |
463 | unsigned maxclockidx = var->bits_per_pixel >> 3; | ||
492 | 464 | ||
493 | switch (var->bits_per_pixel) { | 465 | /* convert from ps to kHz */ |
494 | case 1: | 466 | freq = PICOS2KHZ(var->pixclock); |
495 | pixels /= 4; | ||
496 | break; /* 8 pixel per byte, only 1/4th of mem usable */ | ||
497 | case 8: | ||
498 | case 16: | ||
499 | case 32: | ||
500 | break; /* 1 pixel == 1 byte */ | ||
501 | default: | ||
502 | printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..." | ||
503 | "color depth not supported.\n", | ||
504 | var->xres, var->yres, var->bits_per_pixel); | ||
505 | DPRINTK("EXIT - EINVAL error\n"); | ||
506 | return -EINVAL; | ||
507 | } | ||
508 | 467 | ||
509 | if (var->xres_virtual < var->xres) | 468 | dev_dbg(info->device, "desired pixclock: %ld kHz\n", freq); |
510 | var->xres_virtual = var->xres; | ||
511 | /* use highest possible virtual resolution */ | ||
512 | if (var->yres_virtual == -1) { | ||
513 | var->yres_virtual = pixels / var->xres_virtual; | ||
514 | 469 | ||
515 | printk(KERN_INFO "cirrusfb: virtual resolution set to " | 470 | maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx]; |
516 | "maximum of %dx%d\n", var->xres_virtual, | 471 | cinfo->multiplexing = 0; |
517 | var->yres_virtual); | ||
518 | } | ||
519 | if (var->yres_virtual < var->yres) | ||
520 | var->yres_virtual = var->yres; | ||
521 | 472 | ||
522 | if (var->xres_virtual * var->yres_virtual > pixels) { | 473 | /* If the frequency is greater than we can support, we might be able |
523 | printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected... " | 474 | * to use multiplexing for the video mode */ |
524 | "virtual resolution too high to fit into video memory!\n", | 475 | if (freq > maxclock) { |
525 | var->xres_virtual, var->yres_virtual, | 476 | dev_err(info->device, |
526 | var->bits_per_pixel); | 477 | "Frequency greater than maxclock (%ld kHz)\n", |
527 | DPRINTK("EXIT - EINVAL error\n"); | 478 | maxclock); |
528 | return -EINVAL; | 479 | return -EINVAL; |
529 | } | 480 | } |
481 | /* | ||
482 | * Additional constraint: 8bpp uses DAC clock doubling to allow maximum | ||
483 | * pixel clock | ||
484 | */ | ||
485 | if (var->bits_per_pixel == 8) { | ||
486 | switch (cinfo->btype) { | ||
487 | case BT_ALPINE: | ||
488 | case BT_SD64: | ||
489 | case BT_PICASSO4: | ||
490 | if (freq > 85500) | ||
491 | cinfo->multiplexing = 1; | ||
492 | break; | ||
493 | case BT_GD5480: | ||
494 | if (freq > 135100) | ||
495 | cinfo->multiplexing = 1; | ||
496 | break; | ||
530 | 497 | ||
498 | default: | ||
499 | break; | ||
500 | } | ||
501 | } | ||
531 | 502 | ||
532 | if (var->xoffset < 0) | 503 | /* If we have a 1MB 5434, we need to put ourselves in a mode where |
533 | var->xoffset = 0; | 504 | * the VCLK is double the pixel clock. */ |
534 | if (var->yoffset < 0) | 505 | cinfo->doubleVCLK = 0; |
535 | var->yoffset = 0; | 506 | if (cinfo->btype == BT_SD64 && info->fix.smem_len <= MB_ && |
507 | var->bits_per_pixel == 16) { | ||
508 | cinfo->doubleVCLK = 1; | ||
509 | } | ||
536 | 510 | ||
537 | /* truncate xoffset and yoffset to maximum if too high */ | 511 | return 0; |
538 | if (var->xoffset > var->xres_virtual - var->xres) | 512 | } |
539 | var->xoffset = var->xres_virtual - var->xres - 1; | 513 | |
540 | if (var->yoffset > var->yres_virtual - var->yres) | 514 | static int cirrusfb_check_var(struct fb_var_screeninfo *var, |
541 | var->yoffset = var->yres_virtual - var->yres - 1; | 515 | struct fb_info *info) |
516 | { | ||
517 | int yres; | ||
518 | /* memory size in pixels */ | ||
519 | unsigned pixels = info->screen_size * 8 / var->bits_per_pixel; | ||
520 | struct cirrusfb_info *cinfo = info->par; | ||
542 | 521 | ||
543 | switch (var->bits_per_pixel) { | 522 | switch (var->bits_per_pixel) { |
544 | case 1: | 523 | case 1: |
@@ -550,7 +529,7 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, | |||
550 | 529 | ||
551 | case 8: | 530 | case 8: |
552 | var->red.offset = 0; | 531 | var->red.offset = 0; |
553 | var->red.length = 6; | 532 | var->red.length = 8; |
554 | var->green = var->red; | 533 | var->green = var->red; |
555 | var->blue = var->red; | 534 | var->blue = var->red; |
556 | break; | 535 | break; |
@@ -561,20 +540,20 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, | |||
561 | var->green.offset = -3; | 540 | var->green.offset = -3; |
562 | var->blue.offset = 8; | 541 | var->blue.offset = 8; |
563 | } else { | 542 | } else { |
564 | var->red.offset = 10; | 543 | var->red.offset = 11; |
565 | var->green.offset = 5; | 544 | var->green.offset = 5; |
566 | var->blue.offset = 0; | 545 | var->blue.offset = 0; |
567 | } | 546 | } |
568 | var->red.length = 5; | 547 | var->red.length = 5; |
569 | var->green.length = 5; | 548 | var->green.length = 6; |
570 | var->blue.length = 5; | 549 | var->blue.length = 5; |
571 | break; | 550 | break; |
572 | 551 | ||
573 | case 32: | 552 | case 24: |
574 | if (isPReP) { | 553 | if (isPReP) { |
575 | var->red.offset = 8; | 554 | var->red.offset = 0; |
576 | var->green.offset = 16; | 555 | var->green.offset = 8; |
577 | var->blue.offset = 24; | 556 | var->blue.offset = 16; |
578 | } else { | 557 | } else { |
579 | var->red.offset = 16; | 558 | var->red.offset = 16; |
580 | var->green.offset = 8; | 559 | var->green.offset = 8; |
@@ -586,12 +565,45 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, | |||
586 | break; | 565 | break; |
587 | 566 | ||
588 | default: | 567 | default: |
589 | DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel); | 568 | dev_dbg(info->device, |
569 | "Unsupported bpp size: %d\n", var->bits_per_pixel); | ||
590 | assert(false); | 570 | assert(false); |
591 | /* should never occur */ | 571 | /* should never occur */ |
592 | break; | 572 | break; |
593 | } | 573 | } |
594 | 574 | ||
575 | if (var->xres_virtual < var->xres) | ||
576 | var->xres_virtual = var->xres; | ||
577 | /* use highest possible virtual resolution */ | ||
578 | if (var->yres_virtual == -1) { | ||
579 | var->yres_virtual = pixels / var->xres_virtual; | ||
580 | |||
581 | dev_info(info->device, | ||
582 | "virtual resolution set to maximum of %dx%d\n", | ||
583 | var->xres_virtual, var->yres_virtual); | ||
584 | } | ||
585 | if (var->yres_virtual < var->yres) | ||
586 | var->yres_virtual = var->yres; | ||
587 | |||
588 | if (var->xres_virtual * var->yres_virtual > pixels) { | ||
589 | dev_err(info->device, "mode %dx%dx%d rejected... " | ||
590 | "virtual resolution too high to fit into video memory!\n", | ||
591 | var->xres_virtual, var->yres_virtual, | ||
592 | var->bits_per_pixel); | ||
593 | return -EINVAL; | ||
594 | } | ||
595 | |||
596 | if (var->xoffset < 0) | ||
597 | var->xoffset = 0; | ||
598 | if (var->yoffset < 0) | ||
599 | var->yoffset = 0; | ||
600 | |||
601 | /* truncate xoffset and yoffset to maximum if too high */ | ||
602 | if (var->xoffset > var->xres_virtual - var->xres) | ||
603 | var->xoffset = var->xres_virtual - var->xres - 1; | ||
604 | if (var->yoffset > var->yres_virtual - var->yres) | ||
605 | var->yoffset = var->yres_virtual - var->yres - 1; | ||
606 | |||
595 | var->red.msb_right = | 607 | var->red.msb_right = |
596 | var->green.msb_right = | 608 | var->green.msb_right = |
597 | var->blue.msb_right = | 609 | var->blue.msb_right = |
@@ -606,99 +618,31 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, | |||
606 | yres = (yres + 1) / 2; | 618 | yres = (yres + 1) / 2; |
607 | 619 | ||
608 | if (yres >= 1280) { | 620 | if (yres >= 1280) { |
609 | printk(KERN_ERR "cirrusfb: ERROR: VerticalTotal >= 1280; " | 621 | dev_err(info->device, "ERROR: VerticalTotal >= 1280; " |
610 | "special treatment required! (TODO)\n"); | 622 | "special treatment required! (TODO)\n"); |
611 | DPRINTK("EXIT - EINVAL error\n"); | ||
612 | return -EINVAL; | 623 | return -EINVAL; |
613 | } | 624 | } |
614 | 625 | ||
615 | return 0; | 626 | if (cirrusfb_check_pixclock(var, info)) |
616 | } | 627 | return -EINVAL; |
617 | |||
618 | static int cirrusfb_decode_var(const struct fb_var_screeninfo *var, | ||
619 | struct cirrusfb_regs *regs, | ||
620 | struct fb_info *info) | ||
621 | { | ||
622 | long freq; | ||
623 | long maxclock; | ||
624 | int maxclockidx = var->bits_per_pixel >> 3; | ||
625 | struct cirrusfb_info *cinfo = info->par; | ||
626 | |||
627 | switch (var->bits_per_pixel) { | ||
628 | case 1: | ||
629 | info->fix.line_length = var->xres_virtual / 8; | ||
630 | info->fix.visual = FB_VISUAL_MONO10; | ||
631 | break; | ||
632 | |||
633 | case 8: | ||
634 | info->fix.line_length = var->xres_virtual; | ||
635 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
636 | break; | ||
637 | |||
638 | case 16: | ||
639 | case 32: | ||
640 | info->fix.line_length = var->xres_virtual * maxclockidx; | ||
641 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
642 | break; | ||
643 | |||
644 | default: | ||
645 | DPRINTK("Unsupported bpp size: %d\n", var->bits_per_pixel); | ||
646 | assert(false); | ||
647 | /* should never occur */ | ||
648 | break; | ||
649 | } | ||
650 | |||
651 | info->fix.type = FB_TYPE_PACKED_PIXELS; | ||
652 | |||
653 | /* convert from ps to kHz */ | ||
654 | freq = PICOS2KHZ(var->pixclock); | ||
655 | |||
656 | DPRINTK("desired pixclock: %ld kHz\n", freq); | ||
657 | |||
658 | maxclock = cirrusfb_board_info[cinfo->btype].maxclock[maxclockidx]; | ||
659 | regs->multiplexing = 0; | ||
660 | 628 | ||
661 | /* If the frequency is greater than we can support, we might be able | 629 | if (!is_laguna(cinfo)) |
662 | * to use multiplexing for the video mode */ | 630 | var->accel_flags = FB_ACCELF_TEXT; |
663 | if (freq > maxclock) { | ||
664 | switch (cinfo->btype) { | ||
665 | case BT_ALPINE: | ||
666 | case BT_GD5480: | ||
667 | regs->multiplexing = 1; | ||
668 | break; | ||
669 | 631 | ||
670 | default: | ||
671 | printk(KERN_ERR "cirrusfb: Frequency greater " | ||
672 | "than maxclock (%ld kHz)\n", maxclock); | ||
673 | DPRINTK("EXIT - return -EINVAL\n"); | ||
674 | return -EINVAL; | ||
675 | } | ||
676 | } | ||
677 | #if 0 | ||
678 | /* TODO: If we have a 1MB 5434, we need to put ourselves in a mode where | ||
679 | * the VCLK is double the pixel clock. */ | ||
680 | switch (var->bits_per_pixel) { | ||
681 | case 16: | ||
682 | case 32: | ||
683 | if (var->xres <= 800) | ||
684 | /* Xbh has this type of clock for 32-bit */ | ||
685 | freq /= 2; | ||
686 | break; | ||
687 | } | ||
688 | #endif | ||
689 | return 0; | 632 | return 0; |
690 | } | 633 | } |
691 | 634 | ||
692 | static void cirrusfb_set_mclk_as_source(const struct cirrusfb_info *cinfo, | 635 | static void cirrusfb_set_mclk_as_source(const struct fb_info *info, int div) |
693 | int div) | ||
694 | { | 636 | { |
637 | struct cirrusfb_info *cinfo = info->par; | ||
695 | unsigned char old1f, old1e; | 638 | unsigned char old1f, old1e; |
639 | |||
696 | assert(cinfo != NULL); | 640 | assert(cinfo != NULL); |
697 | old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40; | 641 | old1f = vga_rseq(cinfo->regbase, CL_SEQR1F) & ~0x40; |
698 | 642 | ||
699 | if (div) { | 643 | if (div) { |
700 | DPRINTK("Set %s as pixclock source.\n", | 644 | dev_dbg(info->device, "Set %s as pixclock source.\n", |
701 | (div == 2) ? "MCLK/2" : "MCLK"); | 645 | (div == 2) ? "MCLK/2" : "MCLK"); |
702 | old1f |= 0x40; | 646 | old1f |= 0x40; |
703 | old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1; | 647 | old1e = vga_rseq(cinfo->regbase, CL_SEQR1E) & ~0x1; |
704 | if (div == 2) | 648 | if (div == 2) |
@@ -718,101 +662,119 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
718 | { | 662 | { |
719 | struct cirrusfb_info *cinfo = info->par; | 663 | struct cirrusfb_info *cinfo = info->par; |
720 | struct fb_var_screeninfo *var = &info->var; | 664 | struct fb_var_screeninfo *var = &info->var; |
721 | struct cirrusfb_regs regs; | ||
722 | u8 __iomem *regbase = cinfo->regbase; | 665 | u8 __iomem *regbase = cinfo->regbase; |
723 | unsigned char tmp; | 666 | unsigned char tmp; |
724 | int offset = 0, err; | 667 | int pitch; |
725 | const struct cirrusfb_board_info_rec *bi; | 668 | const struct cirrusfb_board_info_rec *bi; |
726 | int hdispend, hsyncstart, hsyncend, htotal; | 669 | int hdispend, hsyncstart, hsyncend, htotal; |
727 | int yres, vdispend, vsyncstart, vsyncend, vtotal; | 670 | int yres, vdispend, vsyncstart, vsyncend, vtotal; |
728 | long freq; | 671 | long freq; |
729 | int nom, den, div; | 672 | int nom, den, div; |
673 | unsigned int control = 0, format = 0, threshold = 0; | ||
730 | 674 | ||
731 | DPRINTK("ENTER\n"); | 675 | dev_dbg(info->device, "Requested mode: %dx%dx%d\n", |
732 | DPRINTK("Requested mode: %dx%dx%d\n", | ||
733 | var->xres, var->yres, var->bits_per_pixel); | 676 | var->xres, var->yres, var->bits_per_pixel); |
734 | DPRINTK("pixclock: %d\n", var->pixclock); | ||
735 | 677 | ||
736 | init_vgachip(info); | 678 | switch (var->bits_per_pixel) { |
679 | case 1: | ||
680 | info->fix.line_length = var->xres_virtual / 8; | ||
681 | info->fix.visual = FB_VISUAL_MONO10; | ||
682 | break; | ||
737 | 683 | ||
738 | err = cirrusfb_decode_var(var, ®s, info); | 684 | case 8: |
739 | if (err) { | 685 | info->fix.line_length = var->xres_virtual; |
740 | /* should never happen */ | 686 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; |
741 | DPRINTK("mode change aborted. invalid var.\n"); | 687 | break; |
742 | return -EINVAL; | 688 | |
689 | case 16: | ||
690 | case 24: | ||
691 | info->fix.line_length = var->xres_virtual * | ||
692 | var->bits_per_pixel >> 3; | ||
693 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
694 | break; | ||
743 | } | 695 | } |
696 | info->fix.type = FB_TYPE_PACKED_PIXELS; | ||
697 | |||
698 | init_vgachip(info); | ||
744 | 699 | ||
745 | bi = &cirrusfb_board_info[cinfo->btype]; | 700 | bi = &cirrusfb_board_info[cinfo->btype]; |
746 | 701 | ||
747 | hsyncstart = var->xres + var->right_margin; | 702 | hsyncstart = var->xres + var->right_margin; |
748 | hsyncend = hsyncstart + var->hsync_len; | 703 | hsyncend = hsyncstart + var->hsync_len; |
749 | htotal = (hsyncend + var->left_margin) / 8 - 5; | 704 | htotal = (hsyncend + var->left_margin) / 8; |
750 | hdispend = var->xres / 8 - 1; | 705 | hdispend = var->xres / 8; |
751 | hsyncstart = hsyncstart / 8 + 1; | 706 | hsyncstart = hsyncstart / 8; |
752 | hsyncend = hsyncend / 8 + 1; | 707 | hsyncend = hsyncend / 8; |
753 | 708 | ||
754 | yres = var->yres; | 709 | vdispend = var->yres; |
755 | vsyncstart = yres + var->lower_margin; | 710 | vsyncstart = vdispend + var->lower_margin; |
756 | vsyncend = vsyncstart + var->vsync_len; | 711 | vsyncend = vsyncstart + var->vsync_len; |
757 | vtotal = vsyncend + var->upper_margin; | 712 | vtotal = vsyncend + var->upper_margin; |
758 | vdispend = yres - 1; | ||
759 | 713 | ||
760 | if (var->vmode & FB_VMODE_DOUBLE) { | 714 | if (var->vmode & FB_VMODE_DOUBLE) { |
761 | yres *= 2; | 715 | vdispend *= 2; |
762 | vsyncstart *= 2; | 716 | vsyncstart *= 2; |
763 | vsyncend *= 2; | 717 | vsyncend *= 2; |
764 | vtotal *= 2; | 718 | vtotal *= 2; |
765 | } else if (var->vmode & FB_VMODE_INTERLACED) { | 719 | } else if (var->vmode & FB_VMODE_INTERLACED) { |
766 | yres = (yres + 1) / 2; | 720 | vdispend = (vdispend + 1) / 2; |
767 | vsyncstart = (vsyncstart + 1) / 2; | 721 | vsyncstart = (vsyncstart + 1) / 2; |
768 | vsyncend = (vsyncend + 1) / 2; | 722 | vsyncend = (vsyncend + 1) / 2; |
769 | vtotal = (vtotal + 1) / 2; | 723 | vtotal = (vtotal + 1) / 2; |
770 | } | 724 | } |
771 | 725 | yres = vdispend; | |
772 | vtotal -= 2; | ||
773 | vsyncstart -= 1; | ||
774 | vsyncend -= 1; | ||
775 | |||
776 | if (yres >= 1024) { | 726 | if (yres >= 1024) { |
777 | vtotal /= 2; | 727 | vtotal /= 2; |
778 | vsyncstart /= 2; | 728 | vsyncstart /= 2; |
779 | vsyncend /= 2; | 729 | vsyncend /= 2; |
780 | vdispend /= 2; | 730 | vdispend /= 2; |
781 | } | 731 | } |
782 | if (regs.multiplexing) { | 732 | |
733 | vdispend -= 1; | ||
734 | vsyncstart -= 1; | ||
735 | vsyncend -= 1; | ||
736 | vtotal -= 2; | ||
737 | |||
738 | if (cinfo->multiplexing) { | ||
783 | htotal /= 2; | 739 | htotal /= 2; |
784 | hsyncstart /= 2; | 740 | hsyncstart /= 2; |
785 | hsyncend /= 2; | 741 | hsyncend /= 2; |
786 | hdispend /= 2; | 742 | hdispend /= 2; |
787 | } | 743 | } |
744 | |||
745 | htotal -= 5; | ||
746 | hdispend -= 1; | ||
747 | hsyncstart += 1; | ||
748 | hsyncend += 1; | ||
749 | |||
788 | /* unlock register VGA_CRTC_H_TOTAL..CRT7 */ | 750 | /* unlock register VGA_CRTC_H_TOTAL..CRT7 */ |
789 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */ | 751 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); /* previously: 0x00) */ |
790 | 752 | ||
791 | /* if debugging is enabled, all parameters get output before writing */ | 753 | /* if debugging is enabled, all parameters get output before writing */ |
792 | DPRINTK("CRT0: %d\n", htotal); | 754 | dev_dbg(info->device, "CRT0: %d\n", htotal); |
793 | vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal); | 755 | vga_wcrt(regbase, VGA_CRTC_H_TOTAL, htotal); |
794 | 756 | ||
795 | DPRINTK("CRT1: %d\n", hdispend); | 757 | dev_dbg(info->device, "CRT1: %d\n", hdispend); |
796 | vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend); | 758 | vga_wcrt(regbase, VGA_CRTC_H_DISP, hdispend); |
797 | 759 | ||
798 | DPRINTK("CRT2: %d\n", var->xres / 8); | 760 | dev_dbg(info->device, "CRT2: %d\n", var->xres / 8); |
799 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8); | 761 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_START, var->xres / 8); |
800 | 762 | ||
801 | /* + 128: Compatible read */ | 763 | /* + 128: Compatible read */ |
802 | DPRINTK("CRT3: 128+%d\n", (htotal + 5) % 32); | 764 | dev_dbg(info->device, "CRT3: 128+%d\n", (htotal + 5) % 32); |
803 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_END, | 765 | vga_wcrt(regbase, VGA_CRTC_H_BLANK_END, |
804 | 128 + ((htotal + 5) % 32)); | 766 | 128 + ((htotal + 5) % 32)); |
805 | 767 | ||
806 | DPRINTK("CRT4: %d\n", hsyncstart); | 768 | dev_dbg(info->device, "CRT4: %d\n", hsyncstart); |
807 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart); | 769 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_START, hsyncstart); |
808 | 770 | ||
809 | tmp = hsyncend % 32; | 771 | tmp = hsyncend % 32; |
810 | if ((htotal + 5) & 32) | 772 | if ((htotal + 5) & 32) |
811 | tmp += 128; | 773 | tmp += 128; |
812 | DPRINTK("CRT5: %d\n", tmp); | 774 | dev_dbg(info->device, "CRT5: %d\n", tmp); |
813 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp); | 775 | vga_wcrt(regbase, VGA_CRTC_H_SYNC_END, tmp); |
814 | 776 | ||
815 | DPRINTK("CRT6: %d\n", vtotal & 0xff); | 777 | dev_dbg(info->device, "CRT6: %d\n", vtotal & 0xff); |
816 | vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff); | 778 | vga_wcrt(regbase, VGA_CRTC_V_TOTAL, vtotal & 0xff); |
817 | 779 | ||
818 | tmp = 16; /* LineCompare bit #9 */ | 780 | tmp = 16; /* LineCompare bit #9 */ |
@@ -830,7 +792,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
830 | tmp |= 64; | 792 | tmp |= 64; |
831 | if (vsyncstart & 512) | 793 | if (vsyncstart & 512) |
832 | tmp |= 128; | 794 | tmp |= 128; |
833 | DPRINTK("CRT7: %d\n", tmp); | 795 | dev_dbg(info->device, "CRT7: %d\n", tmp); |
834 | vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp); | 796 | vga_wcrt(regbase, VGA_CRTC_OVERFLOW, tmp); |
835 | 797 | ||
836 | tmp = 0x40; /* LineCompare bit #8 */ | 798 | tmp = 0x40; /* LineCompare bit #8 */ |
@@ -838,25 +800,25 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
838 | tmp |= 0x20; | 800 | tmp |= 0x20; |
839 | if (var->vmode & FB_VMODE_DOUBLE) | 801 | if (var->vmode & FB_VMODE_DOUBLE) |
840 | tmp |= 0x80; | 802 | tmp |= 0x80; |
841 | DPRINTK("CRT9: %d\n", tmp); | 803 | dev_dbg(info->device, "CRT9: %d\n", tmp); |
842 | vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp); | 804 | vga_wcrt(regbase, VGA_CRTC_MAX_SCAN, tmp); |
843 | 805 | ||
844 | DPRINTK("CRT10: %d\n", vsyncstart & 0xff); | 806 | dev_dbg(info->device, "CRT10: %d\n", vsyncstart & 0xff); |
845 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff); | 807 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_START, vsyncstart & 0xff); |
846 | 808 | ||
847 | DPRINTK("CRT11: 64+32+%d\n", vsyncend % 16); | 809 | dev_dbg(info->device, "CRT11: 64+32+%d\n", vsyncend % 16); |
848 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32); | 810 | vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, vsyncend % 16 + 64 + 32); |
849 | 811 | ||
850 | DPRINTK("CRT12: %d\n", vdispend & 0xff); | 812 | dev_dbg(info->device, "CRT12: %d\n", vdispend & 0xff); |
851 | vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff); | 813 | vga_wcrt(regbase, VGA_CRTC_V_DISP_END, vdispend & 0xff); |
852 | 814 | ||
853 | DPRINTK("CRT15: %d\n", (vdispend + 1) & 0xff); | 815 | dev_dbg(info->device, "CRT15: %d\n", (vdispend + 1) & 0xff); |
854 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff); | 816 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_START, (vdispend + 1) & 0xff); |
855 | 817 | ||
856 | DPRINTK("CRT16: %d\n", vtotal & 0xff); | 818 | dev_dbg(info->device, "CRT16: %d\n", vtotal & 0xff); |
857 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff); | 819 | vga_wcrt(regbase, VGA_CRTC_V_BLANK_END, vtotal & 0xff); |
858 | 820 | ||
859 | DPRINTK("CRT18: 0xff\n"); | 821 | dev_dbg(info->device, "CRT18: 0xff\n"); |
860 | vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff); | 822 | vga_wcrt(regbase, VGA_CRTC_LINE_COMPARE, 0xff); |
861 | 823 | ||
862 | tmp = 0; | 824 | tmp = 0; |
@@ -871,41 +833,75 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
871 | if (vtotal & 512) | 833 | if (vtotal & 512) |
872 | tmp |= 128; | 834 | tmp |= 128; |
873 | 835 | ||
874 | DPRINTK("CRT1a: %d\n", tmp); | 836 | dev_dbg(info->device, "CRT1a: %d\n", tmp); |
875 | vga_wcrt(regbase, CL_CRT1A, tmp); | 837 | vga_wcrt(regbase, CL_CRT1A, tmp); |
876 | 838 | ||
877 | freq = PICOS2KHZ(var->pixclock); | 839 | freq = PICOS2KHZ(var->pixclock); |
840 | if (var->bits_per_pixel == 24) | ||
841 | if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64) | ||
842 | freq *= 3; | ||
843 | if (cinfo->multiplexing) | ||
844 | freq /= 2; | ||
845 | if (cinfo->doubleVCLK) | ||
846 | freq *= 2; | ||
847 | |||
878 | bestclock(freq, &nom, &den, &div); | 848 | bestclock(freq, &nom, &den, &div); |
879 | 849 | ||
850 | dev_dbg(info->device, "VCLK freq: %ld kHz nom: %d den: %d div: %d\n", | ||
851 | freq, nom, den, div); | ||
852 | |||
880 | /* set VCLK0 */ | 853 | /* set VCLK0 */ |
881 | /* hardware RefClock: 14.31818 MHz */ | 854 | /* hardware RefClock: 14.31818 MHz */ |
882 | /* formula: VClk = (OSC * N) / (D * (1+P)) */ | 855 | /* formula: VClk = (OSC * N) / (D * (1+P)) */ |
883 | /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ | 856 | /* Example: VClk = (14.31818 * 91) / (23 * (1+1)) = 28.325 MHz */ |
884 | 857 | ||
885 | if (cinfo->btype == BT_ALPINE) { | 858 | if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_PICASSO4 || |
859 | cinfo->btype == BT_SD64) { | ||
886 | /* if freq is close to mclk or mclk/2 select mclk | 860 | /* if freq is close to mclk or mclk/2 select mclk |
887 | * as clock source | 861 | * as clock source |
888 | */ | 862 | */ |
889 | int divMCLK = cirrusfb_check_mclk(cinfo, freq); | 863 | int divMCLK = cirrusfb_check_mclk(info, freq); |
890 | if (divMCLK) { | 864 | if (divMCLK) |
891 | nom = 0; | 865 | nom = 0; |
892 | cirrusfb_set_mclk_as_source(cinfo, divMCLK); | 866 | cirrusfb_set_mclk_as_source(info, divMCLK); |
867 | } | ||
868 | if (is_laguna(cinfo)) { | ||
869 | long pcifc = fb_readl(cinfo->laguna_mmio + 0x3fc); | ||
870 | unsigned char tile = fb_readb(cinfo->laguna_mmio + 0x407); | ||
871 | unsigned short tile_control; | ||
872 | |||
873 | if (cinfo->btype == BT_LAGUNAB) { | ||
874 | tile_control = fb_readw(cinfo->laguna_mmio + 0x2c4); | ||
875 | tile_control &= ~0x80; | ||
876 | fb_writew(tile_control, cinfo->laguna_mmio + 0x2c4); | ||
893 | } | 877 | } |
878 | |||
879 | fb_writel(pcifc | 0x10000000l, cinfo->laguna_mmio + 0x3fc); | ||
880 | fb_writeb(tile & 0x3f, cinfo->laguna_mmio + 0x407); | ||
881 | control = fb_readw(cinfo->laguna_mmio + 0x402); | ||
882 | threshold = fb_readw(cinfo->laguna_mmio + 0xea); | ||
883 | control &= ~0x6800; | ||
884 | format = 0; | ||
885 | threshold &= 0xffc0 & 0x3fbf; | ||
894 | } | 886 | } |
895 | if (nom) { | 887 | if (nom) { |
896 | vga_wseq(regbase, CL_SEQRB, nom); | ||
897 | tmp = den << 1; | 888 | tmp = den << 1; |
898 | if (div != 0) | 889 | if (div != 0) |
899 | tmp |= 1; | 890 | tmp |= 1; |
900 | |||
901 | /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ | 891 | /* 6 bit denom; ONLY 5434!!! (bugged me 10 days) */ |
902 | if ((cinfo->btype == BT_SD64) || | 892 | if ((cinfo->btype == BT_SD64) || |
903 | (cinfo->btype == BT_ALPINE) || | 893 | (cinfo->btype == BT_ALPINE) || |
904 | (cinfo->btype == BT_GD5480)) | 894 | (cinfo->btype == BT_GD5480)) |
905 | tmp |= 0x80; | 895 | tmp |= 0x80; |
906 | 896 | ||
907 | DPRINTK("CL_SEQR1B: %ld\n", (long) tmp); | 897 | /* Laguna chipset has reversed clock registers */ |
908 | vga_wseq(regbase, CL_SEQR1B, tmp); | 898 | if (is_laguna(cinfo)) { |
899 | vga_wseq(regbase, CL_SEQRE, tmp); | ||
900 | vga_wseq(regbase, CL_SEQR1E, nom); | ||
901 | } else { | ||
902 | vga_wseq(regbase, CL_SEQRE, nom); | ||
903 | vga_wseq(regbase, CL_SEQR1E, tmp); | ||
904 | } | ||
909 | } | 905 | } |
910 | 906 | ||
911 | if (yres >= 1024) | 907 | if (yres >= 1024) |
@@ -916,9 +912,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
916 | * address wrap, no compat. */ | 912 | * address wrap, no compat. */ |
917 | vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3); | 913 | vga_wcrt(regbase, VGA_CRTC_MODE, 0xc3); |
918 | 914 | ||
919 | /* HAEH? vga_wcrt(regbase, VGA_CRTC_V_SYNC_END, 0x20); | ||
920 | * previously: 0x00 unlock VGA_CRTC_H_TOTAL..CRT7 */ | ||
921 | |||
922 | /* don't know if it would hurt to also program this if no interlaced */ | 915 | /* don't know if it would hurt to also program this if no interlaced */ |
923 | /* mode is used, but I feel better this way.. :-) */ | 916 | /* mode is used, but I feel better this way.. :-) */ |
924 | if (var->vmode & FB_VMODE_INTERLACED) | 917 | if (var->vmode & FB_VMODE_INTERLACED) |
@@ -926,19 +919,15 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
926 | else | 919 | else |
927 | vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */ | 920 | vga_wcrt(regbase, VGA_CRTC_REGS, 0x00); /* interlace control */ |
928 | 921 | ||
929 | vga_wseq(regbase, VGA_SEQ_CHARACTER_MAP, 0); | 922 | /* adjust horizontal/vertical sync type (low/high), use VCLK3 */ |
930 | |||
931 | /* adjust horizontal/vertical sync type (low/high) */ | ||
932 | /* enable display memory & CRTC I/O address for color mode */ | 923 | /* enable display memory & CRTC I/O address for color mode */ |
933 | tmp = 0x03; | 924 | tmp = 0x03 | 0xc; |
934 | if (var->sync & FB_SYNC_HOR_HIGH_ACT) | 925 | if (var->sync & FB_SYNC_HOR_HIGH_ACT) |
935 | tmp |= 0x40; | 926 | tmp |= 0x40; |
936 | if (var->sync & FB_SYNC_VERT_HIGH_ACT) | 927 | if (var->sync & FB_SYNC_VERT_HIGH_ACT) |
937 | tmp |= 0x80; | 928 | tmp |= 0x80; |
938 | WGen(cinfo, VGA_MIS_W, tmp); | 929 | WGen(cinfo, VGA_MIS_W, tmp); |
939 | 930 | ||
940 | /* Screen A Preset Row-Scan register */ | ||
941 | vga_wcrt(regbase, VGA_CRTC_PRESET_ROW, 0); | ||
942 | /* text cursor on and start line */ | 931 | /* text cursor on and start line */ |
943 | vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0); | 932 | vga_wcrt(regbase, VGA_CRTC_CURSOR_START, 0); |
944 | /* text cursor end line */ | 933 | /* text cursor end line */ |
@@ -952,7 +941,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
952 | 941 | ||
953 | /* programming for different color depths */ | 942 | /* programming for different color depths */ |
954 | if (var->bits_per_pixel == 1) { | 943 | if (var->bits_per_pixel == 1) { |
955 | DPRINTK("cirrusfb: preparing for 1 bit deep display\n"); | 944 | dev_dbg(info->device, "preparing for 1 bit deep display\n"); |
956 | vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */ | 945 | vga_wgfx(regbase, VGA_GFX_MODE, 0); /* mode register */ |
957 | 946 | ||
958 | /* SR07 */ | 947 | /* SR07 */ |
@@ -964,68 +953,53 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
964 | case BT_PICASSO4: | 953 | case BT_PICASSO4: |
965 | case BT_ALPINE: | 954 | case BT_ALPINE: |
966 | case BT_GD5480: | 955 | case BT_GD5480: |
967 | DPRINTK(" (for GD54xx)\n"); | ||
968 | vga_wseq(regbase, CL_SEQR7, | 956 | vga_wseq(regbase, CL_SEQR7, |
969 | regs.multiplexing ? | 957 | cinfo->multiplexing ? |
970 | bi->sr07_1bpp_mux : bi->sr07_1bpp); | 958 | bi->sr07_1bpp_mux : bi->sr07_1bpp); |
971 | break; | 959 | break; |
972 | 960 | ||
973 | case BT_LAGUNA: | 961 | case BT_LAGUNA: |
974 | DPRINTK(" (for GD546x)\n"); | 962 | case BT_LAGUNAB: |
975 | vga_wseq(regbase, CL_SEQR7, | 963 | vga_wseq(regbase, CL_SEQR7, |
976 | vga_rseq(regbase, CL_SEQR7) & ~0x01); | 964 | vga_rseq(regbase, CL_SEQR7) & ~0x01); |
977 | break; | 965 | break; |
978 | 966 | ||
979 | default: | 967 | default: |
980 | printk(KERN_WARNING "cirrusfb: unknown Board\n"); | 968 | dev_warn(info->device, "unknown Board\n"); |
981 | break; | 969 | break; |
982 | } | 970 | } |
983 | 971 | ||
984 | /* Extended Sequencer Mode */ | 972 | /* Extended Sequencer Mode */ |
985 | switch (cinfo->btype) { | 973 | switch (cinfo->btype) { |
986 | case BT_SD64: | ||
987 | /* setting the SEQRF on SD64 is not necessary | ||
988 | * (only during init) | ||
989 | */ | ||
990 | DPRINTK("(for SD64)\n"); | ||
991 | /* MCLK select */ | ||
992 | vga_wseq(regbase, CL_SEQR1F, 0x1a); | ||
993 | break; | ||
994 | 974 | ||
995 | case BT_PICCOLO: | 975 | case BT_PICCOLO: |
996 | case BT_SPECTRUM: | 976 | case BT_SPECTRUM: |
997 | DPRINTK("(for Piccolo/Spectrum)\n"); | ||
998 | /* ### ueberall 0x22? */ | ||
999 | /* ##vorher 1c MCLK select */ | ||
1000 | vga_wseq(regbase, CL_SEQR1F, 0x22); | ||
1001 | /* evtl d0 bei 1 bit? avoid FIFO underruns..? */ | 977 | /* evtl d0 bei 1 bit? avoid FIFO underruns..? */ |
1002 | vga_wseq(regbase, CL_SEQRF, 0xb0); | 978 | vga_wseq(regbase, CL_SEQRF, 0xb0); |
1003 | break; | 979 | break; |
1004 | 980 | ||
1005 | case BT_PICASSO: | 981 | case BT_PICASSO: |
1006 | DPRINTK("(for Picasso)\n"); | ||
1007 | /* ##vorher 22 MCLK select */ | ||
1008 | vga_wseq(regbase, CL_SEQR1F, 0x22); | ||
1009 | /* ## vorher d0 avoid FIFO underruns..? */ | 982 | /* ## vorher d0 avoid FIFO underruns..? */ |
1010 | vga_wseq(regbase, CL_SEQRF, 0xd0); | 983 | vga_wseq(regbase, CL_SEQRF, 0xd0); |
1011 | break; | 984 | break; |
1012 | 985 | ||
986 | case BT_SD64: | ||
1013 | case BT_PICASSO4: | 987 | case BT_PICASSO4: |
1014 | case BT_ALPINE: | 988 | case BT_ALPINE: |
1015 | case BT_GD5480: | 989 | case BT_GD5480: |
1016 | case BT_LAGUNA: | 990 | case BT_LAGUNA: |
1017 | DPRINTK(" (for GD54xx)\n"); | 991 | case BT_LAGUNAB: |
1018 | /* do nothing */ | 992 | /* do nothing */ |
1019 | break; | 993 | break; |
1020 | 994 | ||
1021 | default: | 995 | default: |
1022 | printk(KERN_WARNING "cirrusfb: unknown Board\n"); | 996 | dev_warn(info->device, "unknown Board\n"); |
1023 | break; | 997 | break; |
1024 | } | 998 | } |
1025 | 999 | ||
1026 | /* pixel mask: pass-through for first plane */ | 1000 | /* pixel mask: pass-through for first plane */ |
1027 | WGen(cinfo, VGA_PEL_MSK, 0x01); | 1001 | WGen(cinfo, VGA_PEL_MSK, 0x01); |
1028 | if (regs.multiplexing) | 1002 | if (cinfo->multiplexing) |
1029 | /* hidden dac reg: 1280x1024 */ | 1003 | /* hidden dac reg: 1280x1024 */ |
1030 | WHDR(cinfo, 0x4a); | 1004 | WHDR(cinfo, 0x4a); |
1031 | else | 1005 | else |
@@ -1035,7 +1009,6 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1035 | vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06); | 1009 | vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x06); |
1036 | /* plane mask: only write to first plane */ | 1010 | /* plane mask: only write to first plane */ |
1037 | vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01); | 1011 | vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0x01); |
1038 | offset = var->xres_virtual / 16; | ||
1039 | } | 1012 | } |
1040 | 1013 | ||
1041 | /****************************************************** | 1014 | /****************************************************** |
@@ -1045,7 +1018,7 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1045 | */ | 1018 | */ |
1046 | 1019 | ||
1047 | else if (var->bits_per_pixel == 8) { | 1020 | else if (var->bits_per_pixel == 8) { |
1048 | DPRINTK("cirrusfb: preparing for 8 bit deep display\n"); | 1021 | dev_dbg(info->device, "preparing for 8 bit deep display\n"); |
1049 | switch (cinfo->btype) { | 1022 | switch (cinfo->btype) { |
1050 | case BT_SD64: | 1023 | case BT_SD64: |
1051 | case BT_PICCOLO: | 1024 | case BT_PICCOLO: |
@@ -1054,34 +1027,27 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1054 | case BT_PICASSO4: | 1027 | case BT_PICASSO4: |
1055 | case BT_ALPINE: | 1028 | case BT_ALPINE: |
1056 | case BT_GD5480: | 1029 | case BT_GD5480: |
1057 | DPRINTK(" (for GD54xx)\n"); | ||
1058 | vga_wseq(regbase, CL_SEQR7, | 1030 | vga_wseq(regbase, CL_SEQR7, |
1059 | regs.multiplexing ? | 1031 | cinfo->multiplexing ? |
1060 | bi->sr07_8bpp_mux : bi->sr07_8bpp); | 1032 | bi->sr07_8bpp_mux : bi->sr07_8bpp); |
1061 | break; | 1033 | break; |
1062 | 1034 | ||
1063 | case BT_LAGUNA: | 1035 | case BT_LAGUNA: |
1064 | DPRINTK(" (for GD546x)\n"); | 1036 | case BT_LAGUNAB: |
1065 | vga_wseq(regbase, CL_SEQR7, | 1037 | vga_wseq(regbase, CL_SEQR7, |
1066 | vga_rseq(regbase, CL_SEQR7) | 0x01); | 1038 | vga_rseq(regbase, CL_SEQR7) | 0x01); |
1039 | threshold |= 0x10; | ||
1067 | break; | 1040 | break; |
1068 | 1041 | ||
1069 | default: | 1042 | default: |
1070 | printk(KERN_WARNING "cirrusfb: unknown Board\n"); | 1043 | dev_warn(info->device, "unknown Board\n"); |
1071 | break; | 1044 | break; |
1072 | } | 1045 | } |
1073 | 1046 | ||
1074 | switch (cinfo->btype) { | 1047 | switch (cinfo->btype) { |
1075 | case BT_SD64: | ||
1076 | /* MCLK select */ | ||
1077 | vga_wseq(regbase, CL_SEQR1F, 0x1d); | ||
1078 | break; | ||
1079 | |||
1080 | case BT_PICCOLO: | 1048 | case BT_PICCOLO: |
1081 | case BT_PICASSO: | 1049 | case BT_PICASSO: |
1082 | case BT_SPECTRUM: | 1050 | case BT_SPECTRUM: |
1083 | /* ### vorher 1c MCLK select */ | ||
1084 | vga_wseq(regbase, CL_SEQR1F, 0x22); | ||
1085 | /* Fast Page-Mode writes */ | 1051 | /* Fast Page-Mode writes */ |
1086 | vga_wseq(regbase, CL_SEQRF, 0xb0); | 1052 | vga_wseq(regbase, CL_SEQRF, 0xb0); |
1087 | break; | 1053 | break; |
@@ -1091,40 +1057,27 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1091 | /* ### INCOMPLETE!! */ | 1057 | /* ### INCOMPLETE!! */ |
1092 | vga_wseq(regbase, CL_SEQRF, 0xb8); | 1058 | vga_wseq(regbase, CL_SEQRF, 0xb8); |
1093 | #endif | 1059 | #endif |
1094 | /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */ | ||
1095 | break; | ||
1096 | |||
1097 | case BT_ALPINE: | 1060 | case BT_ALPINE: |
1098 | DPRINTK(" (for GD543x)\n"); | 1061 | case BT_SD64: |
1099 | /* We already set SRF and SR1F */ | ||
1100 | break; | ||
1101 | |||
1102 | case BT_GD5480: | 1062 | case BT_GD5480: |
1103 | case BT_LAGUNA: | 1063 | case BT_LAGUNA: |
1104 | DPRINTK(" (for GD54xx)\n"); | 1064 | case BT_LAGUNAB: |
1105 | /* do nothing */ | 1065 | /* do nothing */ |
1106 | break; | 1066 | break; |
1107 | 1067 | ||
1108 | default: | 1068 | default: |
1109 | printk(KERN_WARNING "cirrusfb: unknown Board\n"); | 1069 | dev_warn(info->device, "unknown board\n"); |
1110 | break; | 1070 | break; |
1111 | } | 1071 | } |
1112 | 1072 | ||
1113 | /* mode register: 256 color mode */ | 1073 | /* mode register: 256 color mode */ |
1114 | vga_wgfx(regbase, VGA_GFX_MODE, 64); | 1074 | vga_wgfx(regbase, VGA_GFX_MODE, 64); |
1115 | /* pixel mask: pass-through all planes */ | 1075 | if (cinfo->multiplexing) |
1116 | WGen(cinfo, VGA_PEL_MSK, 0xff); | ||
1117 | if (regs.multiplexing) | ||
1118 | /* hidden dac reg: 1280x1024 */ | 1076 | /* hidden dac reg: 1280x1024 */ |
1119 | WHDR(cinfo, 0x4a); | 1077 | WHDR(cinfo, 0x4a); |
1120 | else | 1078 | else |
1121 | /* hidden dac: nothing */ | 1079 | /* hidden dac: nothing */ |
1122 | WHDR(cinfo, 0); | 1080 | WHDR(cinfo, 0); |
1123 | /* memory mode: chain4, ext. memory */ | ||
1124 | vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a); | ||
1125 | /* plane mask: enable writing to all 4 planes */ | ||
1126 | vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff); | ||
1127 | offset = var->xres_virtual / 8; | ||
1128 | } | 1081 | } |
1129 | 1082 | ||
1130 | /****************************************************** | 1083 | /****************************************************** |
@@ -1134,147 +1087,110 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1134 | */ | 1087 | */ |
1135 | 1088 | ||
1136 | else if (var->bits_per_pixel == 16) { | 1089 | else if (var->bits_per_pixel == 16) { |
1137 | DPRINTK("cirrusfb: preparing for 16 bit deep display\n"); | 1090 | dev_dbg(info->device, "preparing for 16 bit deep display\n"); |
1138 | switch (cinfo->btype) { | 1091 | switch (cinfo->btype) { |
1139 | case BT_SD64: | ||
1140 | /* Extended Sequencer Mode: 256c col. mode */ | ||
1141 | vga_wseq(regbase, CL_SEQR7, 0xf7); | ||
1142 | /* MCLK select */ | ||
1143 | vga_wseq(regbase, CL_SEQR1F, 0x1e); | ||
1144 | break; | ||
1145 | |||
1146 | case BT_PICCOLO: | 1092 | case BT_PICCOLO: |
1147 | case BT_SPECTRUM: | 1093 | case BT_SPECTRUM: |
1148 | vga_wseq(regbase, CL_SEQR7, 0x87); | 1094 | vga_wseq(regbase, CL_SEQR7, 0x87); |
1149 | /* Fast Page-Mode writes */ | 1095 | /* Fast Page-Mode writes */ |
1150 | vga_wseq(regbase, CL_SEQRF, 0xb0); | 1096 | vga_wseq(regbase, CL_SEQRF, 0xb0); |
1151 | /* MCLK select */ | ||
1152 | vga_wseq(regbase, CL_SEQR1F, 0x22); | ||
1153 | break; | 1097 | break; |
1154 | 1098 | ||
1155 | case BT_PICASSO: | 1099 | case BT_PICASSO: |
1156 | vga_wseq(regbase, CL_SEQR7, 0x27); | 1100 | vga_wseq(regbase, CL_SEQR7, 0x27); |
1157 | /* Fast Page-Mode writes */ | 1101 | /* Fast Page-Mode writes */ |
1158 | vga_wseq(regbase, CL_SEQRF, 0xb0); | 1102 | vga_wseq(regbase, CL_SEQRF, 0xb0); |
1159 | /* MCLK select */ | ||
1160 | vga_wseq(regbase, CL_SEQR1F, 0x22); | ||
1161 | break; | 1103 | break; |
1162 | 1104 | ||
1105 | case BT_SD64: | ||
1163 | case BT_PICASSO4: | 1106 | case BT_PICASSO4: |
1164 | vga_wseq(regbase, CL_SEQR7, 0x27); | ||
1165 | /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */ | ||
1166 | break; | ||
1167 | |||
1168 | case BT_ALPINE: | 1107 | case BT_ALPINE: |
1169 | DPRINTK(" (for GD543x)\n"); | 1108 | /* Extended Sequencer Mode: 256c col. mode */ |
1170 | vga_wseq(regbase, CL_SEQR7, 0xa7); | 1109 | vga_wseq(regbase, CL_SEQR7, |
1110 | cinfo->doubleVCLK ? 0xa3 : 0xa7); | ||
1171 | break; | 1111 | break; |
1172 | 1112 | ||
1173 | case BT_GD5480: | 1113 | case BT_GD5480: |
1174 | DPRINTK(" (for GD5480)\n"); | ||
1175 | vga_wseq(regbase, CL_SEQR7, 0x17); | 1114 | vga_wseq(regbase, CL_SEQR7, 0x17); |
1176 | /* We already set SRF and SR1F */ | 1115 | /* We already set SRF and SR1F */ |
1177 | break; | 1116 | break; |
1178 | 1117 | ||
1179 | case BT_LAGUNA: | 1118 | case BT_LAGUNA: |
1180 | DPRINTK(" (for GD546x)\n"); | 1119 | case BT_LAGUNAB: |
1181 | vga_wseq(regbase, CL_SEQR7, | 1120 | vga_wseq(regbase, CL_SEQR7, |
1182 | vga_rseq(regbase, CL_SEQR7) & ~0x01); | 1121 | vga_rseq(regbase, CL_SEQR7) & ~0x01); |
1122 | control |= 0x2000; | ||
1123 | format |= 0x1400; | ||
1124 | threshold |= 0x10; | ||
1183 | break; | 1125 | break; |
1184 | 1126 | ||
1185 | default: | 1127 | default: |
1186 | printk(KERN_WARNING "CIRRUSFB: unknown Board\n"); | 1128 | dev_warn(info->device, "unknown Board\n"); |
1187 | break; | 1129 | break; |
1188 | } | 1130 | } |
1189 | 1131 | ||
1190 | /* mode register: 256 color mode */ | 1132 | /* mode register: 256 color mode */ |
1191 | vga_wgfx(regbase, VGA_GFX_MODE, 64); | 1133 | vga_wgfx(regbase, VGA_GFX_MODE, 64); |
1192 | /* pixel mask: pass-through all planes */ | ||
1193 | WGen(cinfo, VGA_PEL_MSK, 0xff); | ||
1194 | #ifdef CONFIG_PCI | 1134 | #ifdef CONFIG_PCI |
1195 | WHDR(cinfo, 0xc0); /* Copy Xbh */ | 1135 | WHDR(cinfo, cinfo->doubleVCLK ? 0xe1 : 0xc1); |
1196 | #elif defined(CONFIG_ZORRO) | 1136 | #elif defined(CONFIG_ZORRO) |
1197 | /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */ | 1137 | /* FIXME: CONFIG_PCI and CONFIG_ZORRO may be defined both */ |
1198 | WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */ | 1138 | WHDR(cinfo, 0xa0); /* hidden dac reg: nothing special */ |
1199 | #endif | 1139 | #endif |
1200 | /* memory mode: chain4, ext. memory */ | ||
1201 | vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a); | ||
1202 | /* plane mask: enable writing to all 4 planes */ | ||
1203 | vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff); | ||
1204 | offset = var->xres_virtual / 4; | ||
1205 | } | 1140 | } |
1206 | 1141 | ||
1207 | /****************************************************** | 1142 | /****************************************************** |
1208 | * | 1143 | * |
1209 | * 32 bpp | 1144 | * 24 bpp |
1210 | * | 1145 | * |
1211 | */ | 1146 | */ |
1212 | 1147 | ||
1213 | else if (var->bits_per_pixel == 32) { | 1148 | else if (var->bits_per_pixel == 24) { |
1214 | DPRINTK("cirrusfb: preparing for 32 bit deep display\n"); | 1149 | dev_dbg(info->device, "preparing for 24 bit deep display\n"); |
1215 | switch (cinfo->btype) { | 1150 | switch (cinfo->btype) { |
1216 | case BT_SD64: | ||
1217 | /* Extended Sequencer Mode: 256c col. mode */ | ||
1218 | vga_wseq(regbase, CL_SEQR7, 0xf9); | ||
1219 | /* MCLK select */ | ||
1220 | vga_wseq(regbase, CL_SEQR1F, 0x1e); | ||
1221 | break; | ||
1222 | |||
1223 | case BT_PICCOLO: | 1151 | case BT_PICCOLO: |
1224 | case BT_SPECTRUM: | 1152 | case BT_SPECTRUM: |
1225 | vga_wseq(regbase, CL_SEQR7, 0x85); | 1153 | vga_wseq(regbase, CL_SEQR7, 0x85); |
1226 | /* Fast Page-Mode writes */ | 1154 | /* Fast Page-Mode writes */ |
1227 | vga_wseq(regbase, CL_SEQRF, 0xb0); | 1155 | vga_wseq(regbase, CL_SEQRF, 0xb0); |
1228 | /* MCLK select */ | ||
1229 | vga_wseq(regbase, CL_SEQR1F, 0x22); | ||
1230 | break; | 1156 | break; |
1231 | 1157 | ||
1232 | case BT_PICASSO: | 1158 | case BT_PICASSO: |
1233 | vga_wseq(regbase, CL_SEQR7, 0x25); | 1159 | vga_wseq(regbase, CL_SEQR7, 0x25); |
1234 | /* Fast Page-Mode writes */ | 1160 | /* Fast Page-Mode writes */ |
1235 | vga_wseq(regbase, CL_SEQRF, 0xb0); | 1161 | vga_wseq(regbase, CL_SEQRF, 0xb0); |
1236 | /* MCLK select */ | ||
1237 | vga_wseq(regbase, CL_SEQR1F, 0x22); | ||
1238 | break; | 1162 | break; |
1239 | 1163 | ||
1164 | case BT_SD64: | ||
1240 | case BT_PICASSO4: | 1165 | case BT_PICASSO4: |
1241 | vga_wseq(regbase, CL_SEQR7, 0x25); | ||
1242 | /* vga_wseq(regbase, CL_SEQR1F, 0x1c); */ | ||
1243 | break; | ||
1244 | |||
1245 | case BT_ALPINE: | 1166 | case BT_ALPINE: |
1246 | DPRINTK(" (for GD543x)\n"); | 1167 | /* Extended Sequencer Mode: 256c col. mode */ |
1247 | vga_wseq(regbase, CL_SEQR7, 0xa9); | 1168 | vga_wseq(regbase, CL_SEQR7, 0xa5); |
1248 | break; | 1169 | break; |
1249 | 1170 | ||
1250 | case BT_GD5480: | 1171 | case BT_GD5480: |
1251 | DPRINTK(" (for GD5480)\n"); | 1172 | vga_wseq(regbase, CL_SEQR7, 0x15); |
1252 | vga_wseq(regbase, CL_SEQR7, 0x19); | ||
1253 | /* We already set SRF and SR1F */ | 1173 | /* We already set SRF and SR1F */ |
1254 | break; | 1174 | break; |
1255 | 1175 | ||
1256 | case BT_LAGUNA: | 1176 | case BT_LAGUNA: |
1257 | DPRINTK(" (for GD546x)\n"); | 1177 | case BT_LAGUNAB: |
1258 | vga_wseq(regbase, CL_SEQR7, | 1178 | vga_wseq(regbase, CL_SEQR7, |
1259 | vga_rseq(regbase, CL_SEQR7) & ~0x01); | 1179 | vga_rseq(regbase, CL_SEQR7) & ~0x01); |
1180 | control |= 0x4000; | ||
1181 | format |= 0x2400; | ||
1182 | threshold |= 0x20; | ||
1260 | break; | 1183 | break; |
1261 | 1184 | ||
1262 | default: | 1185 | default: |
1263 | printk(KERN_WARNING "cirrusfb: unknown Board\n"); | 1186 | dev_warn(info->device, "unknown Board\n"); |
1264 | break; | 1187 | break; |
1265 | } | 1188 | } |
1266 | 1189 | ||
1267 | /* mode register: 256 color mode */ | 1190 | /* mode register: 256 color mode */ |
1268 | vga_wgfx(regbase, VGA_GFX_MODE, 64); | 1191 | vga_wgfx(regbase, VGA_GFX_MODE, 64); |
1269 | /* pixel mask: pass-through all planes */ | ||
1270 | WGen(cinfo, VGA_PEL_MSK, 0xff); | ||
1271 | /* hidden dac reg: 8-8-8 mode (24 or 32) */ | 1192 | /* hidden dac reg: 8-8-8 mode (24 or 32) */ |
1272 | WHDR(cinfo, 0xc5); | 1193 | WHDR(cinfo, 0xc5); |
1273 | /* memory mode: chain4, ext. memory */ | ||
1274 | vga_wseq(regbase, VGA_SEQ_MEMORY_MODE, 0x0a); | ||
1275 | /* plane mask: enable writing to all 4 planes */ | ||
1276 | vga_wseq(regbase, VGA_SEQ_PLANE_WRITE, 0xff); | ||
1277 | offset = var->xres_virtual / 4; | ||
1278 | } | 1194 | } |
1279 | 1195 | ||
1280 | /****************************************************** | 1196 | /****************************************************** |
@@ -1284,67 +1200,55 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1284 | */ | 1200 | */ |
1285 | 1201 | ||
1286 | else | 1202 | else |
1287 | printk(KERN_ERR "cirrusfb: What's this?? " | 1203 | dev_err(info->device, |
1288 | " requested color depth == %d.\n", | 1204 | "What's this? requested color depth == %d.\n", |
1289 | var->bits_per_pixel); | 1205 | var->bits_per_pixel); |
1290 | 1206 | ||
1291 | vga_wcrt(regbase, VGA_CRTC_OFFSET, offset & 0xff); | 1207 | pitch = info->fix.line_length >> 3; |
1208 | vga_wcrt(regbase, VGA_CRTC_OFFSET, pitch & 0xff); | ||
1292 | tmp = 0x22; | 1209 | tmp = 0x22; |
1293 | if (offset & 0x100) | 1210 | if (pitch & 0x100) |
1294 | tmp |= 0x10; /* offset overflow bit */ | 1211 | tmp |= 0x10; /* offset overflow bit */ |
1295 | 1212 | ||
1296 | /* screen start addr #16-18, fastpagemode cycles */ | 1213 | /* screen start addr #16-18, fastpagemode cycles */ |
1297 | vga_wcrt(regbase, CL_CRT1B, tmp); | 1214 | vga_wcrt(regbase, CL_CRT1B, tmp); |
1298 | 1215 | ||
1299 | if (cinfo->btype == BT_SD64 || | 1216 | /* screen start address bit 19 */ |
1300 | cinfo->btype == BT_PICASSO4 || | 1217 | if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) |
1301 | cinfo->btype == BT_ALPINE || | 1218 | vga_wcrt(regbase, CL_CRT1D, (pitch >> 9) & 1); |
1302 | cinfo->btype == BT_GD5480) | 1219 | |
1303 | /* screen start address bit 19 */ | 1220 | if (is_laguna(cinfo)) { |
1304 | vga_wcrt(regbase, CL_CRT1D, 0x00); | 1221 | tmp = 0; |
1305 | 1222 | if ((htotal + 5) & 256) | |
1306 | /* text cursor location high */ | 1223 | tmp |= 128; |
1307 | vga_wcrt(regbase, VGA_CRTC_CURSOR_HI, 0); | 1224 | if (hdispend & 256) |
1308 | /* text cursor location low */ | 1225 | tmp |= 64; |
1309 | vga_wcrt(regbase, VGA_CRTC_CURSOR_LO, 0); | 1226 | if (hsyncstart & 256) |
1310 | /* underline row scanline = at very bottom */ | 1227 | tmp |= 48; |
1311 | vga_wcrt(regbase, VGA_CRTC_UNDERLINE, 0); | 1228 | if (vtotal & 1024) |
1312 | 1229 | tmp |= 8; | |
1313 | /* controller mode */ | 1230 | if (vdispend & 1024) |
1314 | vga_wattr(regbase, VGA_ATC_MODE, 1); | 1231 | tmp |= 4; |
1315 | /* overscan (border) color */ | 1232 | if (vsyncstart & 1024) |
1316 | vga_wattr(regbase, VGA_ATC_OVERSCAN, 0); | 1233 | tmp |= 3; |
1317 | /* color plane enable */ | 1234 | |
1318 | vga_wattr(regbase, VGA_ATC_PLANE_ENABLE, 15); | 1235 | vga_wcrt(regbase, CL_CRT1E, tmp); |
1236 | dev_dbg(info->device, "CRT1e: %d\n", tmp); | ||
1237 | } | ||
1238 | |||
1319 | /* pixel panning */ | 1239 | /* pixel panning */ |
1320 | vga_wattr(regbase, CL_AR33, 0); | 1240 | vga_wattr(regbase, CL_AR33, 0); |
1321 | /* color select */ | ||
1322 | vga_wattr(regbase, VGA_ATC_COLOR_PAGE, 0); | ||
1323 | 1241 | ||
1324 | /* [ EGS: SetOffset(); ] */ | 1242 | /* [ EGS: SetOffset(); ] */ |
1325 | /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */ | 1243 | /* From SetOffset(): Turn on VideoEnable bit in Attribute controller */ |
1326 | AttrOn(cinfo); | 1244 | AttrOn(cinfo); |
1327 | 1245 | ||
1328 | /* set/reset register */ | 1246 | if (is_laguna(cinfo)) { |
1329 | vga_wgfx(regbase, VGA_GFX_SR_VALUE, 0); | 1247 | /* no tiles */ |
1330 | /* set/reset enable */ | 1248 | fb_writew(control | 0x1000, cinfo->laguna_mmio + 0x402); |
1331 | vga_wgfx(regbase, VGA_GFX_SR_ENABLE, 0); | 1249 | fb_writew(format, cinfo->laguna_mmio + 0xc0); |
1332 | /* color compare */ | 1250 | fb_writew(threshold, cinfo->laguna_mmio + 0xea); |
1333 | vga_wgfx(regbase, VGA_GFX_COMPARE_VALUE, 0); | 1251 | } |
1334 | /* data rotate */ | ||
1335 | vga_wgfx(regbase, VGA_GFX_DATA_ROTATE, 0); | ||
1336 | /* read map select */ | ||
1337 | vga_wgfx(regbase, VGA_GFX_PLANE_READ, 0); | ||
1338 | /* miscellaneous register */ | ||
1339 | vga_wgfx(regbase, VGA_GFX_MISC, 1); | ||
1340 | /* color don't care */ | ||
1341 | vga_wgfx(regbase, VGA_GFX_COMPARE_MASK, 15); | ||
1342 | /* bit mask */ | ||
1343 | vga_wgfx(regbase, VGA_GFX_BIT_MASK, 255); | ||
1344 | |||
1345 | /* graphics cursor attributes: nothing special */ | ||
1346 | vga_wseq(regbase, CL_SEQR12, 0x0); | ||
1347 | |||
1348 | /* finally, turn on everything - turn off "FullBandwidth" bit */ | 1252 | /* finally, turn on everything - turn off "FullBandwidth" bit */ |
1349 | /* also, set "DotClock%2" bit where requested */ | 1253 | /* also, set "DotClock%2" bit where requested */ |
1350 | tmp = 0x01; | 1254 | tmp = 0x01; |
@@ -1355,18 +1259,12 @@ static int cirrusfb_set_par_foo(struct fb_info *info) | |||
1355 | */ | 1259 | */ |
1356 | 1260 | ||
1357 | vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp); | 1261 | vga_wseq(regbase, VGA_SEQ_CLOCK_MODE, tmp); |
1358 | DPRINTK("CL_SEQR1: %d\n", tmp); | 1262 | dev_dbg(info->device, "CL_SEQR1: %d\n", tmp); |
1359 | |||
1360 | cinfo->currentmode = regs; | ||
1361 | |||
1362 | /* pan to requested offset */ | ||
1363 | cirrusfb_pan_display(var, info); | ||
1364 | 1263 | ||
1365 | #ifdef CIRRUSFB_DEBUG | 1264 | #ifdef CIRRUSFB_DEBUG |
1366 | cirrusfb_dump(); | 1265 | cirrusfb_dbg_reg_dump(info, NULL); |
1367 | #endif | 1266 | #endif |
1368 | 1267 | ||
1369 | DPRINTK("EXIT\n"); | ||
1370 | return 0; | 1268 | return 0; |
1371 | } | 1269 | } |
1372 | 1270 | ||
@@ -1418,27 +1316,19 @@ static int cirrusfb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
1418 | static int cirrusfb_pan_display(struct fb_var_screeninfo *var, | 1316 | static int cirrusfb_pan_display(struct fb_var_screeninfo *var, |
1419 | struct fb_info *info) | 1317 | struct fb_info *info) |
1420 | { | 1318 | { |
1421 | int xoffset = 0; | 1319 | int xoffset; |
1422 | int yoffset = 0; | ||
1423 | unsigned long base; | 1320 | unsigned long base; |
1424 | unsigned char tmp = 0, tmp2 = 0, xpix; | 1321 | unsigned char tmp, xpix; |
1425 | struct cirrusfb_info *cinfo = info->par; | 1322 | struct cirrusfb_info *cinfo = info->par; |
1426 | 1323 | ||
1427 | DPRINTK("ENTER\n"); | ||
1428 | DPRINTK("virtual offset: (%d,%d)\n", var->xoffset, var->yoffset); | ||
1429 | |||
1430 | /* no range checks for xoffset and yoffset, */ | 1324 | /* no range checks for xoffset and yoffset, */ |
1431 | /* as fb_pan_display has already done this */ | 1325 | /* as fb_pan_display has already done this */ |
1432 | if (var->vmode & FB_VMODE_YWRAP) | 1326 | if (var->vmode & FB_VMODE_YWRAP) |
1433 | return -EINVAL; | 1327 | return -EINVAL; |
1434 | 1328 | ||
1435 | info->var.xoffset = var->xoffset; | ||
1436 | info->var.yoffset = var->yoffset; | ||
1437 | |||
1438 | xoffset = var->xoffset * info->var.bits_per_pixel / 8; | 1329 | xoffset = var->xoffset * info->var.bits_per_pixel / 8; |
1439 | yoffset = var->yoffset; | ||
1440 | 1330 | ||
1441 | base = yoffset * info->fix.line_length + xoffset; | 1331 | base = var->yoffset * info->fix.line_length + xoffset; |
1442 | 1332 | ||
1443 | if (info->var.bits_per_pixel == 1) { | 1333 | if (info->var.bits_per_pixel == 1) { |
1444 | /* base is already correct */ | 1334 | /* base is already correct */ |
@@ -1448,14 +1338,15 @@ static int cirrusfb_pan_display(struct fb_var_screeninfo *var, | |||
1448 | xpix = (unsigned char) ((xoffset % 4) * 2); | 1338 | xpix = (unsigned char) ((xoffset % 4) * 2); |
1449 | } | 1339 | } |
1450 | 1340 | ||
1451 | cirrusfb_WaitBLT(cinfo->regbase); /* make sure all the BLT's are done */ | 1341 | if (!is_laguna(cinfo)) |
1342 | cirrusfb_WaitBLT(cinfo->regbase); | ||
1452 | 1343 | ||
1453 | /* lower 8 + 8 bits of screen start address */ | 1344 | /* lower 8 + 8 bits of screen start address */ |
1454 | vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, | 1345 | vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, base & 0xff); |
1455 | (unsigned char) (base & 0xff)); | 1346 | vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, (base >> 8) & 0xff); |
1456 | vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, | ||
1457 | (unsigned char) (base >> 8)); | ||
1458 | 1347 | ||
1348 | /* 0xf2 is %11110010, exclude tmp bits */ | ||
1349 | tmp = vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2; | ||
1459 | /* construct bits 16, 17 and 18 of screen start address */ | 1350 | /* construct bits 16, 17 and 18 of screen start address */ |
1460 | if (base & 0x10000) | 1351 | if (base & 0x10000) |
1461 | tmp |= 0x01; | 1352 | tmp |= 0x01; |
@@ -1464,13 +1355,17 @@ static int cirrusfb_pan_display(struct fb_var_screeninfo *var, | |||
1464 | if (base & 0x40000) | 1355 | if (base & 0x40000) |
1465 | tmp |= 0x08; | 1356 | tmp |= 0x08; |
1466 | 1357 | ||
1467 | /* 0xf2 is %11110010, exclude tmp bits */ | 1358 | vga_wcrt(cinfo->regbase, CL_CRT1B, tmp); |
1468 | tmp2 = (vga_rcrt(cinfo->regbase, CL_CRT1B) & 0xf2) | tmp; | ||
1469 | vga_wcrt(cinfo->regbase, CL_CRT1B, tmp2); | ||
1470 | 1359 | ||
1471 | /* construct bit 19 of screen start address */ | 1360 | /* construct bit 19 of screen start address */ |
1472 | if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) | 1361 | if (cirrusfb_board_info[cinfo->btype].scrn_start_bit19) { |
1473 | vga_wcrt(cinfo->regbase, CL_CRT1D, (base >> 12) & 0x80); | 1362 | tmp = vga_rcrt(cinfo->regbase, CL_CRT1D); |
1363 | if (is_laguna(cinfo)) | ||
1364 | tmp = (tmp & ~0x18) | ((base >> 16) & 0x18); | ||
1365 | else | ||
1366 | tmp = (tmp & ~0x80) | ((base >> 12) & 0x80); | ||
1367 | vga_wcrt(cinfo->regbase, CL_CRT1D, tmp); | ||
1368 | } | ||
1474 | 1369 | ||
1475 | /* write pixel panning value to AR33; this does not quite work in 8bpp | 1370 | /* write pixel panning value to AR33; this does not quite work in 8bpp |
1476 | * | 1371 | * |
@@ -1479,9 +1374,6 @@ static int cirrusfb_pan_display(struct fb_var_screeninfo *var, | |||
1479 | if (info->var.bits_per_pixel == 1) | 1374 | if (info->var.bits_per_pixel == 1) |
1480 | vga_wattr(cinfo->regbase, CL_AR33, xpix); | 1375 | vga_wattr(cinfo->regbase, CL_AR33, xpix); |
1481 | 1376 | ||
1482 | cirrusfb_WaitBLT(cinfo->regbase); | ||
1483 | |||
1484 | DPRINTK("EXIT\n"); | ||
1485 | return 0; | 1377 | return 0; |
1486 | } | 1378 | } |
1487 | 1379 | ||
@@ -1502,57 +1394,54 @@ static int cirrusfb_blank(int blank_mode, struct fb_info *info) | |||
1502 | struct cirrusfb_info *cinfo = info->par; | 1394 | struct cirrusfb_info *cinfo = info->par; |
1503 | int current_mode = cinfo->blank_mode; | 1395 | int current_mode = cinfo->blank_mode; |
1504 | 1396 | ||
1505 | DPRINTK("ENTER, blank mode = %d\n", blank_mode); | 1397 | dev_dbg(info->device, "ENTER, blank mode = %d\n", blank_mode); |
1506 | 1398 | ||
1507 | if (info->state != FBINFO_STATE_RUNNING || | 1399 | if (info->state != FBINFO_STATE_RUNNING || |
1508 | current_mode == blank_mode) { | 1400 | current_mode == blank_mode) { |
1509 | DPRINTK("EXIT, returning 0\n"); | 1401 | dev_dbg(info->device, "EXIT, returning 0\n"); |
1510 | return 0; | 1402 | return 0; |
1511 | } | 1403 | } |
1512 | 1404 | ||
1513 | /* Undo current */ | 1405 | /* Undo current */ |
1514 | if (current_mode == FB_BLANK_NORMAL || | 1406 | if (current_mode == FB_BLANK_NORMAL || |
1515 | current_mode == FB_BLANK_UNBLANK) { | 1407 | current_mode == FB_BLANK_UNBLANK) |
1516 | /* unblank the screen */ | ||
1517 | val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE); | ||
1518 | /* clear "FullBandwidth" bit */ | 1408 | /* clear "FullBandwidth" bit */ |
1519 | vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val & 0xdf); | 1409 | val = 0; |
1520 | /* and undo VESA suspend trickery */ | 1410 | else |
1521 | vga_wgfx(cinfo->regbase, CL_GRE, 0x00); | ||
1522 | } | ||
1523 | |||
1524 | /* set new */ | ||
1525 | if (blank_mode > FB_BLANK_NORMAL) { | ||
1526 | /* blank the screen */ | ||
1527 | val = vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE); | ||
1528 | /* set "FullBandwidth" bit */ | 1411 | /* set "FullBandwidth" bit */ |
1529 | vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val | 0x20); | 1412 | val = 0x20; |
1530 | } | 1413 | |
1414 | val |= vga_rseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE) & 0xdf; | ||
1415 | vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, val); | ||
1531 | 1416 | ||
1532 | switch (blank_mode) { | 1417 | switch (blank_mode) { |
1533 | case FB_BLANK_UNBLANK: | 1418 | case FB_BLANK_UNBLANK: |
1534 | case FB_BLANK_NORMAL: | 1419 | case FB_BLANK_NORMAL: |
1420 | val = 0x00; | ||
1535 | break; | 1421 | break; |
1536 | case FB_BLANK_VSYNC_SUSPEND: | 1422 | case FB_BLANK_VSYNC_SUSPEND: |
1537 | vga_wgfx(cinfo->regbase, CL_GRE, 0x04); | 1423 | val = 0x04; |
1538 | break; | 1424 | break; |
1539 | case FB_BLANK_HSYNC_SUSPEND: | 1425 | case FB_BLANK_HSYNC_SUSPEND: |
1540 | vga_wgfx(cinfo->regbase, CL_GRE, 0x02); | 1426 | val = 0x02; |
1541 | break; | 1427 | break; |
1542 | case FB_BLANK_POWERDOWN: | 1428 | case FB_BLANK_POWERDOWN: |
1543 | vga_wgfx(cinfo->regbase, CL_GRE, 0x06); | 1429 | val = 0x06; |
1544 | break; | 1430 | break; |
1545 | default: | 1431 | default: |
1546 | DPRINTK("EXIT, returning 1\n"); | 1432 | dev_dbg(info->device, "EXIT, returning 1\n"); |
1547 | return 1; | 1433 | return 1; |
1548 | } | 1434 | } |
1549 | 1435 | ||
1436 | vga_wgfx(cinfo->regbase, CL_GRE, val); | ||
1437 | |||
1550 | cinfo->blank_mode = blank_mode; | 1438 | cinfo->blank_mode = blank_mode; |
1551 | DPRINTK("EXIT, returning 0\n"); | 1439 | dev_dbg(info->device, "EXIT, returning 0\n"); |
1552 | 1440 | ||
1553 | /* Let fbcon do a soft blank for us */ | 1441 | /* Let fbcon do a soft blank for us */ |
1554 | return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0; | 1442 | return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0; |
1555 | } | 1443 | } |
1444 | |||
1556 | /**** END Hardware specific Routines **************************************/ | 1445 | /**** END Hardware specific Routines **************************************/ |
1557 | /****************************************************************************/ | 1446 | /****************************************************************************/ |
1558 | /**** BEGIN Internal Routines ***********************************************/ | 1447 | /**** BEGIN Internal Routines ***********************************************/ |
@@ -1562,8 +1451,6 @@ static void init_vgachip(struct fb_info *info) | |||
1562 | struct cirrusfb_info *cinfo = info->par; | 1451 | struct cirrusfb_info *cinfo = info->par; |
1563 | const struct cirrusfb_board_info_rec *bi; | 1452 | const struct cirrusfb_board_info_rec *bi; |
1564 | 1453 | ||
1565 | DPRINTK("ENTER\n"); | ||
1566 | |||
1567 | assert(cinfo != NULL); | 1454 | assert(cinfo != NULL); |
1568 | 1455 | ||
1569 | bi = &cirrusfb_board_info[cinfo->btype]; | 1456 | bi = &cirrusfb_board_info[cinfo->btype]; |
@@ -1591,25 +1478,23 @@ static void init_vgachip(struct fb_info *info) | |||
1591 | /* disable flickerfixer */ | 1478 | /* disable flickerfixer */ |
1592 | vga_wcrt(cinfo->regbase, CL_CRT51, 0x00); | 1479 | vga_wcrt(cinfo->regbase, CL_CRT51, 0x00); |
1593 | mdelay(100); | 1480 | mdelay(100); |
1594 | /* from Klaus' NetBSD driver: */ | ||
1595 | vga_wgfx(cinfo->regbase, CL_GR2F, 0x00); | ||
1596 | /* put blitter into 542x compat */ | ||
1597 | vga_wgfx(cinfo->regbase, CL_GR33, 0x00); | ||
1598 | /* mode */ | 1481 | /* mode */ |
1599 | vga_wgfx(cinfo->regbase, CL_GR31, 0x00); | 1482 | vga_wgfx(cinfo->regbase, CL_GR31, 0x00); |
1600 | break; | 1483 | case BT_GD5480: /* fall through */ |
1601 | |||
1602 | case BT_GD5480: | ||
1603 | /* from Klaus' NetBSD driver: */ | 1484 | /* from Klaus' NetBSD driver: */ |
1604 | vga_wgfx(cinfo->regbase, CL_GR2F, 0x00); | 1485 | vga_wgfx(cinfo->regbase, CL_GR2F, 0x00); |
1486 | case BT_ALPINE: /* fall through */ | ||
1487 | /* put blitter into 542x compat */ | ||
1488 | vga_wgfx(cinfo->regbase, CL_GR33, 0x00); | ||
1605 | break; | 1489 | break; |
1606 | 1490 | ||
1607 | case BT_ALPINE: | 1491 | case BT_LAGUNA: |
1492 | case BT_LAGUNAB: | ||
1608 | /* Nothing to do to reset the board. */ | 1493 | /* Nothing to do to reset the board. */ |
1609 | break; | 1494 | break; |
1610 | 1495 | ||
1611 | default: | 1496 | default: |
1612 | printk(KERN_ERR "cirrusfb: Warning: Unknown board type\n"); | 1497 | dev_err(info->device, "Warning: Unknown board type\n"); |
1613 | break; | 1498 | break; |
1614 | } | 1499 | } |
1615 | 1500 | ||
@@ -1629,31 +1514,28 @@ static void init_vgachip(struct fb_info *info) | |||
1629 | WGen(cinfo, CL_VSSM2, 0x01); | 1514 | WGen(cinfo, CL_VSSM2, 0x01); |
1630 | 1515 | ||
1631 | /* reset sequencer logic */ | 1516 | /* reset sequencer logic */ |
1632 | vga_wseq(cinfo->regbase, CL_SEQR0, 0x03); | 1517 | vga_wseq(cinfo->regbase, VGA_SEQ_RESET, 0x03); |
1633 | 1518 | ||
1634 | /* FullBandwidth (video off) and 8/9 dot clock */ | 1519 | /* FullBandwidth (video off) and 8/9 dot clock */ |
1635 | vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21); | 1520 | vga_wseq(cinfo->regbase, VGA_SEQ_CLOCK_MODE, 0x21); |
1636 | /* polarity (-/-), disable access to display memory, | ||
1637 | * VGA_CRTC_START_HI base address: color | ||
1638 | */ | ||
1639 | WGen(cinfo, VGA_MIS_W, 0xc1); | ||
1640 | 1521 | ||
1641 | /* "magic cookie" - doesn't make any sense to me.. */ | 1522 | /* "magic cookie" - doesn't make any sense to me.. */ |
1642 | /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */ | 1523 | /* vga_wgfx(cinfo->regbase, CL_GRA, 0xce); */ |
1643 | /* unlock all extension registers */ | 1524 | /* unlock all extension registers */ |
1644 | vga_wseq(cinfo->regbase, CL_SEQR6, 0x12); | 1525 | vga_wseq(cinfo->regbase, CL_SEQR6, 0x12); |
1645 | 1526 | ||
1646 | /* reset blitter */ | ||
1647 | vga_wgfx(cinfo->regbase, CL_GR31, 0x04); | ||
1648 | |||
1649 | switch (cinfo->btype) { | 1527 | switch (cinfo->btype) { |
1650 | case BT_GD5480: | 1528 | case BT_GD5480: |
1651 | vga_wseq(cinfo->regbase, CL_SEQRF, 0x98); | 1529 | vga_wseq(cinfo->regbase, CL_SEQRF, 0x98); |
1652 | break; | 1530 | break; |
1653 | case BT_ALPINE: | 1531 | case BT_ALPINE: |
1532 | case BT_LAGUNA: | ||
1533 | case BT_LAGUNAB: | ||
1654 | break; | 1534 | break; |
1655 | case BT_SD64: | 1535 | case BT_SD64: |
1536 | #ifdef CONFIG_ZORRO | ||
1656 | vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8); | 1537 | vga_wseq(cinfo->regbase, CL_SEQRF, 0xb8); |
1538 | #endif | ||
1657 | break; | 1539 | break; |
1658 | default: | 1540 | default: |
1659 | vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f); | 1541 | vga_wseq(cinfo->regbase, CL_SEQR16, 0x0f); |
@@ -1665,8 +1547,8 @@ static void init_vgachip(struct fb_info *info) | |||
1665 | vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff); | 1547 | vga_wseq(cinfo->regbase, VGA_SEQ_PLANE_WRITE, 0xff); |
1666 | /* character map select: doesn't even matter in gx mode */ | 1548 | /* character map select: doesn't even matter in gx mode */ |
1667 | vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); | 1549 | vga_wseq(cinfo->regbase, VGA_SEQ_CHARACTER_MAP, 0x00); |
1668 | /* memory mode: chain-4, no odd/even, ext. memory */ | 1550 | /* memory mode: chain4, ext. memory */ |
1669 | vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0e); | 1551 | vga_wseq(cinfo->regbase, VGA_SEQ_MEMORY_MODE, 0x0a); |
1670 | 1552 | ||
1671 | /* controller-internal base address of video memory */ | 1553 | /* controller-internal base address of video memory */ |
1672 | if (bi->init_sr07) | 1554 | if (bi->init_sr07) |
@@ -1692,20 +1574,12 @@ static void init_vgachip(struct fb_info *info) | |||
1692 | vga_wseq(cinfo->regbase, CL_SEQR18, 0x02); | 1574 | vga_wseq(cinfo->regbase, CL_SEQR18, 0x02); |
1693 | } | 1575 | } |
1694 | 1576 | ||
1695 | /* MCLK select etc. */ | ||
1696 | if (bi->init_sr1f) | ||
1697 | vga_wseq(cinfo->regbase, CL_SEQR1F, bi->sr1f); | ||
1698 | |||
1699 | /* Screen A preset row scan: none */ | 1577 | /* Screen A preset row scan: none */ |
1700 | vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00); | 1578 | vga_wcrt(cinfo->regbase, VGA_CRTC_PRESET_ROW, 0x00); |
1701 | /* Text cursor start: disable text cursor */ | 1579 | /* Text cursor start: disable text cursor */ |
1702 | vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); | 1580 | vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_START, 0x20); |
1703 | /* Text cursor end: - */ | 1581 | /* Text cursor end: - */ |
1704 | vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00); | 1582 | vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_END, 0x00); |
1705 | /* Screen start address high: 0 */ | ||
1706 | vga_wcrt(cinfo->regbase, VGA_CRTC_START_HI, 0x00); | ||
1707 | /* Screen start address low: 0 */ | ||
1708 | vga_wcrt(cinfo->regbase, VGA_CRTC_START_LO, 0x00); | ||
1709 | /* text cursor location high: 0 */ | 1583 | /* text cursor location high: 0 */ |
1710 | vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00); | 1584 | vga_wcrt(cinfo->regbase, VGA_CRTC_CURSOR_HI, 0x00); |
1711 | /* text cursor location low: 0 */ | 1585 | /* text cursor location low: 0 */ |
@@ -1713,10 +1587,6 @@ static void init_vgachip(struct fb_info *info) | |||
1713 | 1587 | ||
1714 | /* Underline Row scanline: - */ | 1588 | /* Underline Row scanline: - */ |
1715 | vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00); | 1589 | vga_wcrt(cinfo->regbase, VGA_CRTC_UNDERLINE, 0x00); |
1716 | /* mode control: timing enable, byte mode, no compat modes */ | ||
1717 | vga_wcrt(cinfo->regbase, VGA_CRTC_MODE, 0xc3); | ||
1718 | /* Line Compare: not needed */ | ||
1719 | vga_wcrt(cinfo->regbase, VGA_CRTC_LINE_COMPARE, 0x00); | ||
1720 | /* ### add 0x40 for text modes with > 30 MHz pixclock */ | 1590 | /* ### add 0x40 for text modes with > 30 MHz pixclock */ |
1721 | /* ext. display controls: ext.adr. wrap */ | 1591 | /* ext. display controls: ext.adr. wrap */ |
1722 | vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02); | 1592 | vga_wcrt(cinfo->regbase, CL_CRT1B, 0x02); |
@@ -1739,7 +1609,9 @@ static void init_vgachip(struct fb_info *info) | |||
1739 | vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f); | 1609 | vga_wgfx(cinfo->regbase, VGA_GFX_COMPARE_MASK, 0x0f); |
1740 | /* Bit Mask: no mask at all */ | 1610 | /* Bit Mask: no mask at all */ |
1741 | vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff); | 1611 | vga_wgfx(cinfo->regbase, VGA_GFX_BIT_MASK, 0xff); |
1742 | if (cinfo->btype == BT_ALPINE) | 1612 | |
1613 | if (cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64 || | ||
1614 | is_laguna(cinfo)) | ||
1743 | /* (5434 can't have bit 3 set for bitblt) */ | 1615 | /* (5434 can't have bit 3 set for bitblt) */ |
1744 | vga_wgfx(cinfo->regbase, CL_GRB, 0x20); | 1616 | vga_wgfx(cinfo->regbase, CL_GRB, 0x20); |
1745 | else | 1617 | else |
@@ -1779,18 +1651,11 @@ static void init_vgachip(struct fb_info *info) | |||
1779 | vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00); | 1651 | vga_wattr(cinfo->regbase, VGA_ATC_OVERSCAN, 0x00); |
1780 | /* Color Plane enable: Enable all 4 planes */ | 1652 | /* Color Plane enable: Enable all 4 planes */ |
1781 | vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f); | 1653 | vga_wattr(cinfo->regbase, VGA_ATC_PLANE_ENABLE, 0x0f); |
1782 | /* ### vga_wattr(cinfo->regbase, CL_AR33, 0x00); * Pixel Panning: - */ | ||
1783 | /* Color Select: - */ | 1654 | /* Color Select: - */ |
1784 | vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00); | 1655 | vga_wattr(cinfo->regbase, VGA_ATC_COLOR_PAGE, 0x00); |
1785 | 1656 | ||
1786 | WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */ | 1657 | WGen(cinfo, VGA_PEL_MSK, 0xff); /* Pixel mask: no mask */ |
1787 | 1658 | ||
1788 | if (cinfo->btype != BT_ALPINE && cinfo->btype != BT_GD5480) | ||
1789 | /* polarity (-/-), enable display mem, | ||
1790 | * VGA_CRTC_START_HI i/o base = color | ||
1791 | */ | ||
1792 | WGen(cinfo, VGA_MIS_W, 0xc3); | ||
1793 | |||
1794 | /* BLT Start/status: Blitter reset */ | 1659 | /* BLT Start/status: Blitter reset */ |
1795 | vga_wgfx(cinfo->regbase, CL_GR31, 0x04); | 1660 | vga_wgfx(cinfo->regbase, CL_GR31, 0x04); |
1796 | /* - " - : "end-of-reset" */ | 1661 | /* - " - : "end-of-reset" */ |
@@ -1798,8 +1663,6 @@ static void init_vgachip(struct fb_info *info) | |||
1798 | 1663 | ||
1799 | /* misc... */ | 1664 | /* misc... */ |
1800 | WHDR(cinfo, 0); /* Hidden DAC register: - */ | 1665 | WHDR(cinfo, 0); /* Hidden DAC register: - */ |
1801 | |||
1802 | DPRINTK("EXIT\n"); | ||
1803 | return; | 1666 | return; |
1804 | } | 1667 | } |
1805 | 1668 | ||
@@ -1808,8 +1671,6 @@ static void switch_monitor(struct cirrusfb_info *cinfo, int on) | |||
1808 | #ifdef CONFIG_ZORRO /* only works on Zorro boards */ | 1671 | #ifdef CONFIG_ZORRO /* only works on Zorro boards */ |
1809 | static int IsOn = 0; /* XXX not ok for multiple boards */ | 1672 | static int IsOn = 0; /* XXX not ok for multiple boards */ |
1810 | 1673 | ||
1811 | DPRINTK("ENTER\n"); | ||
1812 | |||
1813 | if (cinfo->btype == BT_PICASSO4) | 1674 | if (cinfo->btype == BT_PICASSO4) |
1814 | return; /* nothing to switch */ | 1675 | return; /* nothing to switch */ |
1815 | if (cinfo->btype == BT_ALPINE) | 1676 | if (cinfo->btype == BT_ALPINE) |
@@ -1819,8 +1680,6 @@ static void switch_monitor(struct cirrusfb_info *cinfo, int on) | |||
1819 | if (cinfo->btype == BT_PICASSO) { | 1680 | if (cinfo->btype == BT_PICASSO) { |
1820 | if ((on && !IsOn) || (!on && IsOn)) | 1681 | if ((on && !IsOn) || (!on && IsOn)) |
1821 | WSFR(cinfo, 0xff); | 1682 | WSFR(cinfo, 0xff); |
1822 | |||
1823 | DPRINTK("EXIT\n"); | ||
1824 | return; | 1683 | return; |
1825 | } | 1684 | } |
1826 | if (on) { | 1685 | if (on) { |
@@ -1847,11 +1706,10 @@ static void switch_monitor(struct cirrusfb_info *cinfo, int on) | |||
1847 | case BT_SPECTRUM: | 1706 | case BT_SPECTRUM: |
1848 | WSFR(cinfo, 0x4f); | 1707 | WSFR(cinfo, 0x4f); |
1849 | break; | 1708 | break; |
1850 | default: /* do nothing */ break; | 1709 | default: /* do nothing */ |
1710 | break; | ||
1851 | } | 1711 | } |
1852 | } | 1712 | } |
1853 | |||
1854 | DPRINTK("EXIT\n"); | ||
1855 | #endif /* CONFIG_ZORRO */ | 1713 | #endif /* CONFIG_ZORRO */ |
1856 | } | 1714 | } |
1857 | 1715 | ||
@@ -1859,6 +1717,17 @@ static void switch_monitor(struct cirrusfb_info *cinfo, int on) | |||
1859 | /* Linux 2.6-style accelerated functions */ | 1717 | /* Linux 2.6-style accelerated functions */ |
1860 | /******************************************/ | 1718 | /******************************************/ |
1861 | 1719 | ||
1720 | static int cirrusfb_sync(struct fb_info *info) | ||
1721 | { | ||
1722 | struct cirrusfb_info *cinfo = info->par; | ||
1723 | |||
1724 | if (!is_laguna(cinfo)) { | ||
1725 | while (vga_rgfx(cinfo->regbase, CL_GR31) & 0x03) | ||
1726 | cpu_relax(); | ||
1727 | } | ||
1728 | return 0; | ||
1729 | } | ||
1730 | |||
1862 | static void cirrusfb_fillrect(struct fb_info *info, | 1731 | static void cirrusfb_fillrect(struct fb_info *info, |
1863 | const struct fb_fillrect *region) | 1732 | const struct fb_fillrect *region) |
1864 | { | 1733 | { |
@@ -1894,8 +1763,8 @@ static void cirrusfb_fillrect(struct fb_info *info, | |||
1894 | info->var.bits_per_pixel, | 1763 | info->var.bits_per_pixel, |
1895 | (region->dx * m) / 8, region->dy, | 1764 | (region->dx * m) / 8, region->dy, |
1896 | (region->width * m) / 8, region->height, | 1765 | (region->width * m) / 8, region->height, |
1897 | color, | 1766 | color, color, |
1898 | info->fix.line_length); | 1767 | info->fix.line_length, 0x40); |
1899 | } | 1768 | } |
1900 | 1769 | ||
1901 | static void cirrusfb_copyarea(struct fb_info *info, | 1770 | static void cirrusfb_copyarea(struct fb_info *info, |
@@ -1943,9 +1812,46 @@ static void cirrusfb_imageblit(struct fb_info *info, | |||
1943 | const struct fb_image *image) | 1812 | const struct fb_image *image) |
1944 | { | 1813 | { |
1945 | struct cirrusfb_info *cinfo = info->par; | 1814 | struct cirrusfb_info *cinfo = info->par; |
1815 | unsigned char op = (info->var.bits_per_pixel == 24) ? 0xc : 0x4; | ||
1946 | 1816 | ||
1947 | cirrusfb_WaitBLT(cinfo->regbase); | 1817 | if (info->state != FBINFO_STATE_RUNNING) |
1948 | cfb_imageblit(info, image); | 1818 | return; |
1819 | /* Alpine/SD64 does not work at 24bpp ??? */ | ||
1820 | if (info->flags & FBINFO_HWACCEL_DISABLED || image->depth != 1) | ||
1821 | cfb_imageblit(info, image); | ||
1822 | else if ((cinfo->btype == BT_ALPINE || cinfo->btype == BT_SD64) && | ||
1823 | op == 0xc) | ||
1824 | cfb_imageblit(info, image); | ||
1825 | else { | ||
1826 | unsigned size = ((image->width + 7) >> 3) * image->height; | ||
1827 | int m = info->var.bits_per_pixel; | ||
1828 | u32 fg, bg; | ||
1829 | |||
1830 | if (info->var.bits_per_pixel == 8) { | ||
1831 | fg = image->fg_color; | ||
1832 | bg = image->bg_color; | ||
1833 | } else { | ||
1834 | fg = ((u32 *)(info->pseudo_palette))[image->fg_color]; | ||
1835 | bg = ((u32 *)(info->pseudo_palette))[image->bg_color]; | ||
1836 | } | ||
1837 | if (info->var.bits_per_pixel == 24) { | ||
1838 | /* clear background first */ | ||
1839 | cirrusfb_RectFill(cinfo->regbase, | ||
1840 | info->var.bits_per_pixel, | ||
1841 | (image->dx * m) / 8, image->dy, | ||
1842 | (image->width * m) / 8, | ||
1843 | image->height, | ||
1844 | bg, bg, | ||
1845 | info->fix.line_length, 0x40); | ||
1846 | } | ||
1847 | cirrusfb_RectFill(cinfo->regbase, | ||
1848 | info->var.bits_per_pixel, | ||
1849 | (image->dx * m) / 8, image->dy, | ||
1850 | (image->width * m) / 8, image->height, | ||
1851 | fg, bg, | ||
1852 | info->fix.line_length, op); | ||
1853 | memcpy(info->screen_base, image->data, size); | ||
1854 | } | ||
1949 | } | 1855 | } |
1950 | 1856 | ||
1951 | #ifdef CONFIG_PPC_PREP | 1857 | #ifdef CONFIG_PPC_PREP |
@@ -1953,12 +1859,8 @@ static void cirrusfb_imageblit(struct fb_info *info, | |||
1953 | #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000) | 1859 | #define PREP_IO_BASE ((volatile unsigned char *) 0x80000000) |
1954 | static void get_prep_addrs(unsigned long *display, unsigned long *registers) | 1860 | static void get_prep_addrs(unsigned long *display, unsigned long *registers) |
1955 | { | 1861 | { |
1956 | DPRINTK("ENTER\n"); | ||
1957 | |||
1958 | *display = PREP_VIDEO_BASE; | 1862 | *display = PREP_VIDEO_BASE; |
1959 | *registers = (unsigned long) PREP_IO_BASE; | 1863 | *registers = (unsigned long) PREP_IO_BASE; |
1960 | |||
1961 | DPRINTK("EXIT\n"); | ||
1962 | } | 1864 | } |
1963 | 1865 | ||
1964 | #endif /* CONFIG_PPC_PREP */ | 1866 | #endif /* CONFIG_PPC_PREP */ |
@@ -1970,40 +1872,43 @@ static int release_io_ports; | |||
1970 | * based on the DRAM bandwidth bit and DRAM bank switching bit. This | 1872 | * based on the DRAM bandwidth bit and DRAM bank switching bit. This |
1971 | * works with 1MB, 2MB and 4MB configurations (which the Motorola boards | 1873 | * works with 1MB, 2MB and 4MB configurations (which the Motorola boards |
1972 | * seem to have. */ | 1874 | * seem to have. */ |
1973 | static unsigned int __devinit cirrusfb_get_memsize(u8 __iomem *regbase) | 1875 | static unsigned int __devinit cirrusfb_get_memsize(struct fb_info *info, |
1876 | u8 __iomem *regbase) | ||
1974 | { | 1877 | { |
1975 | unsigned long mem; | 1878 | unsigned long mem; |
1976 | unsigned char SRF; | 1879 | struct cirrusfb_info *cinfo = info->par; |
1977 | 1880 | ||
1978 | DPRINTK("ENTER\n"); | 1881 | if (is_laguna(cinfo)) { |
1882 | unsigned char SR14 = vga_rseq(regbase, CL_SEQR14); | ||
1979 | 1883 | ||
1980 | SRF = vga_rseq(regbase, CL_SEQRF); | 1884 | mem = ((SR14 & 7) + 1) << 20; |
1981 | switch ((SRF & 0x18)) { | 1885 | } else { |
1982 | case 0x08: | 1886 | unsigned char SRF = vga_rseq(regbase, CL_SEQRF); |
1983 | mem = 512 * 1024; | 1887 | switch ((SRF & 0x18)) { |
1984 | break; | 1888 | case 0x08: |
1985 | case 0x10: | 1889 | mem = 512 * 1024; |
1986 | mem = 1024 * 1024; | 1890 | break; |
1987 | break; | 1891 | case 0x10: |
1988 | /* 64-bit DRAM data bus width; assume 2MB. Also indicates 2MB memory | 1892 | mem = 1024 * 1024; |
1989 | * on the 5430. | 1893 | break; |
1990 | */ | 1894 | /* 64-bit DRAM data bus width; assume 2MB. |
1991 | case 0x18: | 1895 | * Also indicates 2MB memory on the 5430. |
1992 | mem = 2048 * 1024; | 1896 | */ |
1993 | break; | 1897 | case 0x18: |
1994 | default: | 1898 | mem = 2048 * 1024; |
1995 | printk(KERN_WARNING "CLgenfb: Unknown memory size!\n"); | 1899 | break; |
1996 | mem = 1024 * 1024; | 1900 | default: |
1901 | dev_warn(info->device, "Unknown memory size!\n"); | ||
1902 | mem = 1024 * 1024; | ||
1903 | } | ||
1904 | /* If DRAM bank switching is enabled, there must be | ||
1905 | * twice as much memory installed. (4MB on the 5434) | ||
1906 | */ | ||
1907 | if (cinfo->btype != BT_ALPINE && (SRF & 0x80) != 0) | ||
1908 | mem *= 2; | ||
1997 | } | 1909 | } |
1998 | if (SRF & 0x80) | ||
1999 | /* If DRAM bank switching is enabled, there must be twice as much | ||
2000 | * memory installed. (4MB on the 5434) | ||
2001 | */ | ||
2002 | mem *= 2; | ||
2003 | 1910 | ||
2004 | /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */ | 1911 | /* TODO: Handling of GD5446/5480 (see XF86 sources ...) */ |
2005 | |||
2006 | DPRINTK("EXIT\n"); | ||
2007 | return mem; | 1912 | return mem; |
2008 | } | 1913 | } |
2009 | 1914 | ||
@@ -2014,8 +1919,6 @@ static void get_pci_addrs(const struct pci_dev *pdev, | |||
2014 | assert(display != NULL); | 1919 | assert(display != NULL); |
2015 | assert(registers != NULL); | 1920 | assert(registers != NULL); |
2016 | 1921 | ||
2017 | DPRINTK("ENTER\n"); | ||
2018 | |||
2019 | *display = 0; | 1922 | *display = 0; |
2020 | *registers = 0; | 1923 | *registers = 0; |
2021 | 1924 | ||
@@ -2030,14 +1933,15 @@ static void get_pci_addrs(const struct pci_dev *pdev, | |||
2030 | } | 1933 | } |
2031 | 1934 | ||
2032 | assert(*display != 0); | 1935 | assert(*display != 0); |
2033 | |||
2034 | DPRINTK("EXIT\n"); | ||
2035 | } | 1936 | } |
2036 | 1937 | ||
2037 | static void cirrusfb_pci_unmap(struct fb_info *info) | 1938 | static void cirrusfb_pci_unmap(struct fb_info *info) |
2038 | { | 1939 | { |
2039 | struct pci_dev *pdev = to_pci_dev(info->device); | 1940 | struct pci_dev *pdev = to_pci_dev(info->device); |
1941 | struct cirrusfb_info *cinfo = info->par; | ||
2040 | 1942 | ||
1943 | if (cinfo->laguna_mmio == NULL) | ||
1944 | iounmap(cinfo->laguna_mmio); | ||
2041 | iounmap(info->screen_base); | 1945 | iounmap(info->screen_base); |
2042 | #if 0 /* if system didn't claim this region, we would... */ | 1946 | #if 0 /* if system didn't claim this region, we would... */ |
2043 | release_mem_region(0xA0000, 65535); | 1947 | release_mem_region(0xA0000, 65535); |
@@ -2067,6 +1971,22 @@ static void cirrusfb_zorro_unmap(struct fb_info *info) | |||
2067 | } | 1971 | } |
2068 | #endif /* CONFIG_ZORRO */ | 1972 | #endif /* CONFIG_ZORRO */ |
2069 | 1973 | ||
1974 | /* function table of the above functions */ | ||
1975 | static struct fb_ops cirrusfb_ops = { | ||
1976 | .owner = THIS_MODULE, | ||
1977 | .fb_open = cirrusfb_open, | ||
1978 | .fb_release = cirrusfb_release, | ||
1979 | .fb_setcolreg = cirrusfb_setcolreg, | ||
1980 | .fb_check_var = cirrusfb_check_var, | ||
1981 | .fb_set_par = cirrusfb_set_par, | ||
1982 | .fb_pan_display = cirrusfb_pan_display, | ||
1983 | .fb_blank = cirrusfb_blank, | ||
1984 | .fb_fillrect = cirrusfb_fillrect, | ||
1985 | .fb_copyarea = cirrusfb_copyarea, | ||
1986 | .fb_sync = cirrusfb_sync, | ||
1987 | .fb_imageblit = cirrusfb_imageblit, | ||
1988 | }; | ||
1989 | |||
2070 | static int __devinit cirrusfb_set_fbinfo(struct fb_info *info) | 1990 | static int __devinit cirrusfb_set_fbinfo(struct fb_info *info) |
2071 | { | 1991 | { |
2072 | struct cirrusfb_info *cinfo = info->par; | 1992 | struct cirrusfb_info *cinfo = info->par; |
@@ -2077,10 +1997,16 @@ static int __devinit cirrusfb_set_fbinfo(struct fb_info *info) | |||
2077 | | FBINFO_HWACCEL_XPAN | 1997 | | FBINFO_HWACCEL_XPAN |
2078 | | FBINFO_HWACCEL_YPAN | 1998 | | FBINFO_HWACCEL_YPAN |
2079 | | FBINFO_HWACCEL_FILLRECT | 1999 | | FBINFO_HWACCEL_FILLRECT |
2000 | | FBINFO_HWACCEL_IMAGEBLIT | ||
2080 | | FBINFO_HWACCEL_COPYAREA; | 2001 | | FBINFO_HWACCEL_COPYAREA; |
2081 | if (noaccel) | 2002 | if (noaccel || is_laguna(cinfo)) { |
2082 | info->flags |= FBINFO_HWACCEL_DISABLED; | 2003 | info->flags |= FBINFO_HWACCEL_DISABLED; |
2004 | info->fix.accel = FB_ACCEL_NONE; | ||
2005 | } else | ||
2006 | info->fix.accel = FB_ACCEL_CIRRUS_ALPINE; | ||
2007 | |||
2083 | info->fbops = &cirrusfb_ops; | 2008 | info->fbops = &cirrusfb_ops; |
2009 | |||
2084 | if (cinfo->btype == BT_GD5480) { | 2010 | if (cinfo->btype == BT_GD5480) { |
2085 | if (var->bits_per_pixel == 16) | 2011 | if (var->bits_per_pixel == 16) |
2086 | info->screen_base += 1 * MB_; | 2012 | info->screen_base += 1 * MB_; |
@@ -2104,7 +2030,6 @@ static int __devinit cirrusfb_set_fbinfo(struct fb_info *info) | |||
2104 | 2030 | ||
2105 | /* FIXME: map region at 0xB8000 if available, fill in here */ | 2031 | /* FIXME: map region at 0xB8000 if available, fill in here */ |
2106 | info->fix.mmio_len = 0; | 2032 | info->fix.mmio_len = 0; |
2107 | info->fix.accel = FB_ACCEL_NONE; | ||
2108 | 2033 | ||
2109 | fb_alloc_cmap(&info->cmap, 256, 0); | 2034 | fb_alloc_cmap(&info->cmap, 256, 0); |
2110 | 2035 | ||
@@ -2115,70 +2040,56 @@ static int __devinit cirrusfb_register(struct fb_info *info) | |||
2115 | { | 2040 | { |
2116 | struct cirrusfb_info *cinfo = info->par; | 2041 | struct cirrusfb_info *cinfo = info->par; |
2117 | int err; | 2042 | int err; |
2118 | enum cirrus_board btype; | ||
2119 | |||
2120 | DPRINTK("ENTER\n"); | ||
2121 | |||
2122 | printk(KERN_INFO "cirrusfb: Driver for Cirrus Logic based " | ||
2123 | "graphic boards, v" CIRRUSFB_VERSION "\n"); | ||
2124 | |||
2125 | btype = cinfo->btype; | ||
2126 | 2043 | ||
2127 | /* sanity checks */ | 2044 | /* sanity checks */ |
2128 | assert(btype != BT_NONE); | 2045 | assert(cinfo->btype != BT_NONE); |
2129 | 2046 | ||
2130 | /* set all the vital stuff */ | 2047 | /* set all the vital stuff */ |
2131 | cirrusfb_set_fbinfo(info); | 2048 | cirrusfb_set_fbinfo(info); |
2132 | 2049 | ||
2133 | DPRINTK("cirrusfb: (RAM start set to: 0x%p)\n", info->screen_base); | 2050 | dev_dbg(info->device, "(RAM start set to: 0x%p)\n", info->screen_base); |
2134 | 2051 | ||
2135 | err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); | 2052 | err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); |
2136 | if (!err) { | 2053 | if (!err) { |
2137 | DPRINTK("wrong initial video mode\n"); | 2054 | dev_dbg(info->device, "wrong initial video mode\n"); |
2138 | err = -EINVAL; | 2055 | err = -EINVAL; |
2139 | goto err_dealloc_cmap; | 2056 | goto err_dealloc_cmap; |
2140 | } | 2057 | } |
2141 | 2058 | ||
2142 | info->var.activate = FB_ACTIVATE_NOW; | 2059 | info->var.activate = FB_ACTIVATE_NOW; |
2143 | 2060 | ||
2144 | err = cirrusfb_decode_var(&info->var, &cinfo->currentmode, info); | 2061 | err = cirrusfb_check_var(&info->var, info); |
2145 | if (err < 0) { | 2062 | if (err < 0) { |
2146 | /* should never happen */ | 2063 | /* should never happen */ |
2147 | DPRINTK("choking on default var... umm, no good.\n"); | 2064 | dev_dbg(info->device, |
2065 | "choking on default var... umm, no good.\n"); | ||
2148 | goto err_dealloc_cmap; | 2066 | goto err_dealloc_cmap; |
2149 | } | 2067 | } |
2150 | 2068 | ||
2151 | err = register_framebuffer(info); | 2069 | err = register_framebuffer(info); |
2152 | if (err < 0) { | 2070 | if (err < 0) { |
2153 | printk(KERN_ERR "cirrusfb: could not register " | 2071 | dev_err(info->device, |
2154 | "fb device; err = %d!\n", err); | 2072 | "could not register fb device; err = %d!\n", err); |
2155 | goto err_dealloc_cmap; | 2073 | goto err_dealloc_cmap; |
2156 | } | 2074 | } |
2157 | 2075 | ||
2158 | DPRINTK("EXIT, returning 0\n"); | ||
2159 | return 0; | 2076 | return 0; |
2160 | 2077 | ||
2161 | err_dealloc_cmap: | 2078 | err_dealloc_cmap: |
2162 | fb_dealloc_cmap(&info->cmap); | 2079 | fb_dealloc_cmap(&info->cmap); |
2163 | cinfo->unmap(info); | ||
2164 | framebuffer_release(info); | ||
2165 | return err; | 2080 | return err; |
2166 | } | 2081 | } |
2167 | 2082 | ||
2168 | static void __devexit cirrusfb_cleanup(struct fb_info *info) | 2083 | static void __devexit cirrusfb_cleanup(struct fb_info *info) |
2169 | { | 2084 | { |
2170 | struct cirrusfb_info *cinfo = info->par; | 2085 | struct cirrusfb_info *cinfo = info->par; |
2171 | DPRINTK("ENTER\n"); | ||
2172 | 2086 | ||
2173 | switch_monitor(cinfo, 0); | 2087 | switch_monitor(cinfo, 0); |
2174 | |||
2175 | unregister_framebuffer(info); | 2088 | unregister_framebuffer(info); |
2176 | fb_dealloc_cmap(&info->cmap); | 2089 | fb_dealloc_cmap(&info->cmap); |
2177 | printk("Framebuffer unregistered\n"); | 2090 | dev_dbg(info->device, "Framebuffer unregistered\n"); |
2178 | cinfo->unmap(info); | 2091 | cinfo->unmap(info); |
2179 | framebuffer_release(info); | 2092 | framebuffer_release(info); |
2180 | |||
2181 | DPRINTK("EXIT\n"); | ||
2182 | } | 2093 | } |
2183 | 2094 | ||
2184 | #ifdef CONFIG_PCI | 2095 | #ifdef CONFIG_PCI |
@@ -2187,7 +2098,6 @@ static int __devinit cirrusfb_pci_register(struct pci_dev *pdev, | |||
2187 | { | 2098 | { |
2188 | struct cirrusfb_info *cinfo; | 2099 | struct cirrusfb_info *cinfo; |
2189 | struct fb_info *info; | 2100 | struct fb_info *info; |
2190 | enum cirrus_board btype; | ||
2191 | unsigned long board_addr, board_size; | 2101 | unsigned long board_addr, board_size; |
2192 | int ret; | 2102 | int ret; |
2193 | 2103 | ||
@@ -2201,15 +2111,17 @@ static int __devinit cirrusfb_pci_register(struct pci_dev *pdev, | |||
2201 | if (!info) { | 2111 | if (!info) { |
2202 | printk(KERN_ERR "cirrusfb: could not allocate memory\n"); | 2112 | printk(KERN_ERR "cirrusfb: could not allocate memory\n"); |
2203 | ret = -ENOMEM; | 2113 | ret = -ENOMEM; |
2204 | goto err_disable; | 2114 | goto err_out; |
2205 | } | 2115 | } |
2206 | 2116 | ||
2207 | cinfo = info->par; | 2117 | cinfo = info->par; |
2208 | cinfo->btype = btype = (enum cirrus_board) ent->driver_data; | 2118 | cinfo->btype = (enum cirrus_board) ent->driver_data; |
2209 | 2119 | ||
2210 | DPRINTK(" Found PCI device, base address 0 is 0x%x, btype set to %d\n", | 2120 | dev_dbg(info->device, |
2211 | pdev->resource[0].start, btype); | 2121 | " Found PCI device, base address 0 is 0x%Lx, btype set to %d\n", |
2212 | DPRINTK(" base address 1 is 0x%x\n", pdev->resource[1].start); | 2122 | (unsigned long long)pdev->resource[0].start, cinfo->btype); |
2123 | dev_dbg(info->device, " base address 1 is 0x%Lx\n", | ||
2124 | (unsigned long long)pdev->resource[1].start); | ||
2213 | 2125 | ||
2214 | if (isPReP) { | 2126 | if (isPReP) { |
2215 | pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000); | 2127 | pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, 0x00000000); |
@@ -2219,30 +2131,30 @@ static int __devinit cirrusfb_pci_register(struct pci_dev *pdev, | |||
2219 | /* PReP dies if we ioremap the IO registers, but it works w/out... */ | 2131 | /* PReP dies if we ioremap the IO registers, but it works w/out... */ |
2220 | cinfo->regbase = (char __iomem *) info->fix.mmio_start; | 2132 | cinfo->regbase = (char __iomem *) info->fix.mmio_start; |
2221 | } else { | 2133 | } else { |
2222 | DPRINTK("Attempt to get PCI info for Cirrus Graphics Card\n"); | 2134 | dev_dbg(info->device, |
2135 | "Attempt to get PCI info for Cirrus Graphics Card\n"); | ||
2223 | get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start); | 2136 | get_pci_addrs(pdev, &board_addr, &info->fix.mmio_start); |
2224 | /* FIXME: this forces VGA. alternatives? */ | 2137 | /* FIXME: this forces VGA. alternatives? */ |
2225 | cinfo->regbase = NULL; | 2138 | cinfo->regbase = NULL; |
2139 | cinfo->laguna_mmio = ioremap(info->fix.mmio_start, 0x1000); | ||
2226 | } | 2140 | } |
2227 | 2141 | ||
2228 | DPRINTK("Board address: 0x%lx, register address: 0x%lx\n", | 2142 | dev_dbg(info->device, "Board address: 0x%lx, register address: 0x%lx\n", |
2229 | board_addr, info->fix.mmio_start); | 2143 | board_addr, info->fix.mmio_start); |
2230 | 2144 | ||
2231 | board_size = (btype == BT_GD5480) ? | 2145 | board_size = (cinfo->btype == BT_GD5480) ? |
2232 | 32 * MB_ : cirrusfb_get_memsize(cinfo->regbase); | 2146 | 32 * MB_ : cirrusfb_get_memsize(info, cinfo->regbase); |
2233 | 2147 | ||
2234 | ret = pci_request_regions(pdev, "cirrusfb"); | 2148 | ret = pci_request_regions(pdev, "cirrusfb"); |
2235 | if (ret < 0) { | 2149 | if (ret < 0) { |
2236 | printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, " | 2150 | dev_err(info->device, "cannot reserve region 0x%lx, abort\n", |
2237 | "abort\n", | 2151 | board_addr); |
2238 | board_addr); | ||
2239 | goto err_release_fb; | 2152 | goto err_release_fb; |
2240 | } | 2153 | } |
2241 | #if 0 /* if the system didn't claim this region, we would... */ | 2154 | #if 0 /* if the system didn't claim this region, we would... */ |
2242 | if (!request_mem_region(0xA0000, 65535, "cirrusfb")) { | 2155 | if (!request_mem_region(0xA0000, 65535, "cirrusfb")) { |
2243 | printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, abort\n" | 2156 | dev_err(info->device, "cannot reserve region 0x%lx, abort\n", |
2244 | , | 2157 | 0xA0000L); |
2245 | 0xA0000L); | ||
2246 | ret = -EBUSY; | 2158 | ret = -EBUSY; |
2247 | goto err_release_regions; | 2159 | goto err_release_regions; |
2248 | } | 2160 | } |
@@ -2260,16 +2172,17 @@ static int __devinit cirrusfb_pci_register(struct pci_dev *pdev, | |||
2260 | info->screen_size = board_size; | 2172 | info->screen_size = board_size; |
2261 | cinfo->unmap = cirrusfb_pci_unmap; | 2173 | cinfo->unmap = cirrusfb_pci_unmap; |
2262 | 2174 | ||
2263 | printk(KERN_INFO "RAM (%lu kB) at 0x%lx, Cirrus " | 2175 | dev_info(info->device, |
2264 | "Logic chipset on PCI bus\n", | 2176 | "Cirrus Logic chipset on PCI bus, RAM (%lu kB) at 0x%lx\n", |
2265 | info->screen_size >> 10, board_addr); | 2177 | info->screen_size >> 10, board_addr); |
2266 | pci_set_drvdata(pdev, info); | 2178 | pci_set_drvdata(pdev, info); |
2267 | 2179 | ||
2268 | ret = cirrusfb_register(info); | 2180 | ret = cirrusfb_register(info); |
2269 | if (ret) | 2181 | if (!ret) |
2270 | iounmap(info->screen_base); | 2182 | return 0; |
2271 | return ret; | ||
2272 | 2183 | ||
2184 | pci_set_drvdata(pdev, NULL); | ||
2185 | iounmap(info->screen_base); | ||
2273 | err_release_legacy: | 2186 | err_release_legacy: |
2274 | if (release_io_ports) | 2187 | if (release_io_ports) |
2275 | release_region(0x3C0, 32); | 2188 | release_region(0x3C0, 32); |
@@ -2279,8 +2192,9 @@ err_release_regions: | |||
2279 | #endif | 2192 | #endif |
2280 | pci_release_regions(pdev); | 2193 | pci_release_regions(pdev); |
2281 | err_release_fb: | 2194 | err_release_fb: |
2195 | if (cinfo->laguna_mmio != NULL) | ||
2196 | iounmap(cinfo->laguna_mmio); | ||
2282 | framebuffer_release(info); | 2197 | framebuffer_release(info); |
2283 | err_disable: | ||
2284 | err_out: | 2198 | err_out: |
2285 | return ret; | 2199 | return ret; |
2286 | } | 2200 | } |
@@ -2288,11 +2202,8 @@ err_out: | |||
2288 | static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev) | 2202 | static void __devexit cirrusfb_pci_unregister(struct pci_dev *pdev) |
2289 | { | 2203 | { |
2290 | struct fb_info *info = pci_get_drvdata(pdev); | 2204 | struct fb_info *info = pci_get_drvdata(pdev); |
2291 | DPRINTK("ENTER\n"); | ||
2292 | 2205 | ||
2293 | cirrusfb_cleanup(info); | 2206 | cirrusfb_cleanup(info); |
2294 | |||
2295 | DPRINTK("EXIT\n"); | ||
2296 | } | 2207 | } |
2297 | 2208 | ||
2298 | static struct pci_driver cirrusfb_pci_driver = { | 2209 | static struct pci_driver cirrusfb_pci_driver = { |
@@ -2324,8 +2235,6 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, | |||
2324 | if (cirrusfb_zorro_table2[btype].id2) | 2235 | if (cirrusfb_zorro_table2[btype].id2) |
2325 | z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL); | 2236 | z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL); |
2326 | size = cirrusfb_zorro_table2[btype].size; | 2237 | size = cirrusfb_zorro_table2[btype].size; |
2327 | printk(KERN_INFO "cirrusfb: %s board detected; ", | ||
2328 | cirrusfb_board_info[btype].name); | ||
2329 | 2238 | ||
2330 | info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); | 2239 | info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); |
2331 | if (!info) { | 2240 | if (!info) { |
@@ -2334,6 +2243,9 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, | |||
2334 | goto err_out; | 2243 | goto err_out; |
2335 | } | 2244 | } |
2336 | 2245 | ||
2246 | dev_info(info->device, "%s board detected\n", | ||
2247 | cirrusfb_board_info[btype].name); | ||
2248 | |||
2337 | cinfo = info->par; | 2249 | cinfo = info->par; |
2338 | cinfo->btype = btype; | 2250 | cinfo->btype = btype; |
2339 | 2251 | ||
@@ -2345,19 +2257,16 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, | |||
2345 | info->screen_size = size; | 2257 | info->screen_size = size; |
2346 | 2258 | ||
2347 | if (!zorro_request_device(z, "cirrusfb")) { | 2259 | if (!zorro_request_device(z, "cirrusfb")) { |
2348 | printk(KERN_ERR "cirrusfb: cannot reserve region 0x%lx, " | 2260 | dev_err(info->device, "cannot reserve region 0x%lx, abort\n", |
2349 | "abort\n", | 2261 | board_addr); |
2350 | board_addr); | ||
2351 | ret = -EBUSY; | 2262 | ret = -EBUSY; |
2352 | goto err_release_fb; | 2263 | goto err_release_fb; |
2353 | } | 2264 | } |
2354 | 2265 | ||
2355 | printk(" RAM (%lu MB) at $%lx, ", board_size / MB_, board_addr); | ||
2356 | |||
2357 | ret = -EIO; | 2266 | ret = -EIO; |
2358 | 2267 | ||
2359 | if (btype == BT_PICASSO4) { | 2268 | if (btype == BT_PICASSO4) { |
2360 | printk(KERN_INFO " REG at $%lx\n", board_addr + 0x600000); | 2269 | dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000); |
2361 | 2270 | ||
2362 | /* To be precise, for the P4 this is not the */ | 2271 | /* To be precise, for the P4 this is not the */ |
2363 | /* begin of the board, but the begin of RAM. */ | 2272 | /* begin of the board, but the begin of RAM. */ |
@@ -2367,7 +2276,7 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, | |||
2367 | if (!cinfo->regbase) | 2276 | if (!cinfo->regbase) |
2368 | goto err_release_region; | 2277 | goto err_release_region; |
2369 | 2278 | ||
2370 | DPRINTK("cirrusfb: Virtual address for board set to: $%p\n", | 2279 | dev_dbg(info->device, "Virtual address for board set to: $%p\n", |
2371 | cinfo->regbase); | 2280 | cinfo->regbase); |
2372 | cinfo->regbase += 0x600000; | 2281 | cinfo->regbase += 0x600000; |
2373 | info->fix.mmio_start = board_addr + 0x600000; | 2282 | info->fix.mmio_start = board_addr + 0x600000; |
@@ -2377,8 +2286,8 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, | |||
2377 | if (!info->screen_base) | 2286 | if (!info->screen_base) |
2378 | goto err_unmap_regbase; | 2287 | goto err_unmap_regbase; |
2379 | } else { | 2288 | } else { |
2380 | printk(KERN_INFO " REG at $%lx\n", | 2289 | dev_info(info->device, " REG at $%lx\n", |
2381 | (unsigned long) z2->resource.start); | 2290 | (unsigned long) z2->resource.start); |
2382 | 2291 | ||
2383 | info->fix.smem_start = board_addr; | 2292 | info->fix.smem_start = board_addr; |
2384 | if (board_addr > 0x01000000) | 2293 | if (board_addr > 0x01000000) |
@@ -2392,27 +2301,32 @@ static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, | |||
2392 | cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start); | 2301 | cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start); |
2393 | info->fix.mmio_start = z2->resource.start; | 2302 | info->fix.mmio_start = z2->resource.start; |
2394 | 2303 | ||
2395 | DPRINTK("cirrusfb: Virtual address for board set to: $%p\n", | 2304 | dev_dbg(info->device, "Virtual address for board set to: $%p\n", |
2396 | cinfo->regbase); | 2305 | cinfo->regbase); |
2397 | } | 2306 | } |
2398 | cinfo->unmap = cirrusfb_zorro_unmap; | 2307 | cinfo->unmap = cirrusfb_zorro_unmap; |
2399 | 2308 | ||
2400 | printk(KERN_INFO "Cirrus Logic chipset on Zorro bus\n"); | 2309 | dev_info(info->device, |
2310 | "Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n", | ||
2311 | board_size / MB_, board_addr); | ||
2312 | |||
2401 | zorro_set_drvdata(z, info); | 2313 | zorro_set_drvdata(z, info); |
2402 | 2314 | ||
2315 | /* MCLK select etc. */ | ||
2316 | if (cirrusfb_board_info[btype].init_sr1f) | ||
2317 | vga_wseq(cinfo->regbase, CL_SEQR1F, | ||
2318 | cirrusfb_board_info[btype].sr1f); | ||
2319 | |||
2403 | ret = cirrusfb_register(info); | 2320 | ret = cirrusfb_register(info); |
2404 | if (ret) { | 2321 | if (!ret) |
2405 | if (btype == BT_PICASSO4) { | 2322 | return 0; |
2406 | iounmap(info->screen_base); | 2323 | |
2407 | iounmap(cinfo->regbase - 0x600000); | 2324 | if (btype == BT_PICASSO4 || board_addr > 0x01000000) |
2408 | } else if (board_addr > 0x01000000) | 2325 | iounmap(info->screen_base); |
2409 | iounmap(info->screen_base); | ||
2410 | } | ||
2411 | return ret; | ||
2412 | 2326 | ||
2413 | err_unmap_regbase: | 2327 | err_unmap_regbase: |
2414 | /* Parental advisory: explicit hack */ | 2328 | if (btype == BT_PICASSO4) |
2415 | iounmap(cinfo->regbase - 0x600000); | 2329 | iounmap(cinfo->regbase - 0x600000); |
2416 | err_release_region: | 2330 | err_release_region: |
2417 | release_region(board_addr, board_size); | 2331 | release_region(board_addr, board_size); |
2418 | err_release_fb: | 2332 | err_release_fb: |
@@ -2424,11 +2338,8 @@ err_out: | |||
2424 | void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z) | 2338 | void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z) |
2425 | { | 2339 | { |
2426 | struct fb_info *info = zorro_get_drvdata(z); | 2340 | struct fb_info *info = zorro_get_drvdata(z); |
2427 | DPRINTK("ENTER\n"); | ||
2428 | 2341 | ||
2429 | cirrusfb_cleanup(info); | 2342 | cirrusfb_cleanup(info); |
2430 | |||
2431 | DPRINTK("EXIT\n"); | ||
2432 | } | 2343 | } |
2433 | 2344 | ||
2434 | static struct zorro_driver cirrusfb_zorro_driver = { | 2345 | static struct zorro_driver cirrusfb_zorro_driver = { |
@@ -2439,33 +2350,11 @@ static struct zorro_driver cirrusfb_zorro_driver = { | |||
2439 | }; | 2350 | }; |
2440 | #endif /* CONFIG_ZORRO */ | 2351 | #endif /* CONFIG_ZORRO */ |
2441 | 2352 | ||
2442 | static int __init cirrusfb_init(void) | ||
2443 | { | ||
2444 | int error = 0; | ||
2445 | |||
2446 | #ifndef MODULE | 2353 | #ifndef MODULE |
2447 | char *option = NULL; | 2354 | static int __init cirrusfb_setup(char *options) |
2448 | 2355 | { | |
2449 | if (fb_get_options("cirrusfb", &option)) | ||
2450 | return -ENODEV; | ||
2451 | cirrusfb_setup(option); | ||
2452 | #endif | ||
2453 | |||
2454 | #ifdef CONFIG_ZORRO | ||
2455 | error |= zorro_register_driver(&cirrusfb_zorro_driver); | ||
2456 | #endif | ||
2457 | #ifdef CONFIG_PCI | ||
2458 | error |= pci_register_driver(&cirrusfb_pci_driver); | ||
2459 | #endif | ||
2460 | return error; | ||
2461 | } | ||
2462 | |||
2463 | #ifndef MODULE | ||
2464 | static int __init cirrusfb_setup(char *options) { | ||
2465 | char *this_opt; | 2356 | char *this_opt; |
2466 | 2357 | ||
2467 | DPRINTK("ENTER\n"); | ||
2468 | |||
2469 | if (!options || !*options) | 2358 | if (!options || !*options) |
2470 | return 0; | 2359 | return 0; |
2471 | 2360 | ||
@@ -2473,8 +2362,6 @@ static int __init cirrusfb_setup(char *options) { | |||
2473 | if (!*this_opt) | 2362 | if (!*this_opt) |
2474 | continue; | 2363 | continue; |
2475 | 2364 | ||
2476 | DPRINTK("cirrusfb_setup: option '%s'\n", this_opt); | ||
2477 | |||
2478 | if (!strcmp(this_opt, "noaccel")) | 2365 | if (!strcmp(this_opt, "noaccel")) |
2479 | noaccel = 1; | 2366 | noaccel = 1; |
2480 | else if (!strncmp(this_opt, "mode:", 5)) | 2367 | else if (!strncmp(this_opt, "mode:", 5)) |
@@ -2494,6 +2381,27 @@ MODULE_AUTHOR("Copyright 1999,2000 Jeff Garzik <jgarzik@pobox.com>"); | |||
2494 | MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips"); | 2381 | MODULE_DESCRIPTION("Accelerated FBDev driver for Cirrus Logic chips"); |
2495 | MODULE_LICENSE("GPL"); | 2382 | MODULE_LICENSE("GPL"); |
2496 | 2383 | ||
2384 | static int __init cirrusfb_init(void) | ||
2385 | { | ||
2386 | int error = 0; | ||
2387 | |||
2388 | #ifndef MODULE | ||
2389 | char *option = NULL; | ||
2390 | |||
2391 | if (fb_get_options("cirrusfb", &option)) | ||
2392 | return -ENODEV; | ||
2393 | cirrusfb_setup(option); | ||
2394 | #endif | ||
2395 | |||
2396 | #ifdef CONFIG_ZORRO | ||
2397 | error |= zorro_register_driver(&cirrusfb_zorro_driver); | ||
2398 | #endif | ||
2399 | #ifdef CONFIG_PCI | ||
2400 | error |= pci_register_driver(&cirrusfb_pci_driver); | ||
2401 | #endif | ||
2402 | return error; | ||
2403 | } | ||
2404 | |||
2497 | static void __exit cirrusfb_exit(void) | 2405 | static void __exit cirrusfb_exit(void) |
2498 | { | 2406 | { |
2499 | #ifdef CONFIG_PCI | 2407 | #ifdef CONFIG_PCI |
@@ -2560,8 +2468,6 @@ static void AttrOn(const struct cirrusfb_info *cinfo) | |||
2560 | { | 2468 | { |
2561 | assert(cinfo != NULL); | 2469 | assert(cinfo != NULL); |
2562 | 2470 | ||
2563 | DPRINTK("ENTER\n"); | ||
2564 | |||
2565 | if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) { | 2471 | if (vga_rcrt(cinfo->regbase, CL_CRT24) & 0x80) { |
2566 | /* if we're just in "write value" mode, write back the */ | 2472 | /* if we're just in "write value" mode, write back the */ |
2567 | /* same value as before to not modify anything */ | 2473 | /* same value as before to not modify anything */ |
@@ -2574,8 +2480,6 @@ static void AttrOn(const struct cirrusfb_info *cinfo) | |||
2574 | 2480 | ||
2575 | /* dummy write on Reg0 to be on "write index" mode next time */ | 2481 | /* dummy write on Reg0 to be on "write index" mode next time */ |
2576 | vga_w(cinfo->regbase, VGA_ATT_IW, 0x00); | 2482 | vga_w(cinfo->regbase, VGA_ATT_IW, 0x00); |
2577 | |||
2578 | DPRINTK("EXIT\n"); | ||
2579 | } | 2483 | } |
2580 | 2484 | ||
2581 | /*** WHDR() - write into the Hidden DAC register ***/ | 2485 | /*** WHDR() - write into the Hidden DAC register ***/ |
@@ -2588,6 +2492,8 @@ static void WHDR(const struct cirrusfb_info *cinfo, unsigned char val) | |||
2588 | { | 2492 | { |
2589 | unsigned char dummy; | 2493 | unsigned char dummy; |
2590 | 2494 | ||
2495 | if (is_laguna(cinfo)) | ||
2496 | return; | ||
2591 | if (cinfo->btype == BT_PICASSO) { | 2497 | if (cinfo->btype == BT_PICASSO) { |
2592 | /* Klaus' hint for correct access to HDR on some boards */ | 2498 | /* Klaus' hint for correct access to HDR on some boards */ |
2593 | /* first write 0 to pixel mask (3c6) */ | 2499 | /* first write 0 to pixel mask (3c6) */ |
@@ -2655,7 +2561,8 @@ static void WClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned ch | |||
2655 | vga_w(cinfo->regbase, VGA_PEL_IW, regnum); | 2561 | vga_w(cinfo->regbase, VGA_PEL_IW, regnum); |
2656 | 2562 | ||
2657 | if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 || | 2563 | if (cinfo->btype == BT_PICASSO || cinfo->btype == BT_PICASSO4 || |
2658 | cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480) { | 2564 | cinfo->btype == BT_ALPINE || cinfo->btype == BT_GD5480 || |
2565 | cinfo->btype == BT_SD64 || is_laguna(cinfo)) { | ||
2659 | /* but DAC data register IS, at least for Picasso II */ | 2566 | /* but DAC data register IS, at least for Picasso II */ |
2660 | if (cinfo->btype == BT_PICASSO) | 2567 | if (cinfo->btype == BT_PICASSO) |
2661 | data += 0xfff; | 2568 | data += 0xfff; |
@@ -2702,9 +2609,8 @@ static void RClut(struct cirrusfb_info *cinfo, unsigned char regnum, unsigned ch | |||
2702 | /* FIXME: use interrupts instead */ | 2609 | /* FIXME: use interrupts instead */ |
2703 | static void cirrusfb_WaitBLT(u8 __iomem *regbase) | 2610 | static void cirrusfb_WaitBLT(u8 __iomem *regbase) |
2704 | { | 2611 | { |
2705 | /* now busy-wait until we're done */ | ||
2706 | while (vga_rgfx(regbase, CL_GR31) & 0x08) | 2612 | while (vga_rgfx(regbase, CL_GR31) & 0x08) |
2707 | /* do nothing */ ; | 2613 | cpu_relax(); |
2708 | } | 2614 | } |
2709 | 2615 | ||
2710 | /******************************************************************* | 2616 | /******************************************************************* |
@@ -2713,60 +2619,12 @@ static void cirrusfb_WaitBLT(u8 __iomem *regbase) | |||
2713 | perform accelerated "scrolling" | 2619 | perform accelerated "scrolling" |
2714 | ********************************************************************/ | 2620 | ********************************************************************/ |
2715 | 2621 | ||
2716 | static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, | 2622 | static void cirrusfb_set_blitter(u8 __iomem *regbase, |
2717 | u_short curx, u_short cury, | 2623 | u_short nwidth, u_short nheight, |
2718 | u_short destx, u_short desty, | 2624 | u_long nsrc, u_long ndest, |
2719 | u_short width, u_short height, | 2625 | u_short bltmode, u_short line_length) |
2720 | u_short line_length) | ||
2721 | { | ||
2722 | u_short nwidth, nheight; | ||
2723 | u_long nsrc, ndest; | ||
2724 | u_char bltmode; | ||
2725 | |||
2726 | DPRINTK("ENTER\n"); | ||
2727 | |||
2728 | nwidth = width - 1; | ||
2729 | nheight = height - 1; | ||
2730 | |||
2731 | bltmode = 0x00; | ||
2732 | /* if source adr < dest addr, do the Blt backwards */ | ||
2733 | if (cury <= desty) { | ||
2734 | if (cury == desty) { | ||
2735 | /* if src and dest are on the same line, check x */ | ||
2736 | if (curx < destx) | ||
2737 | bltmode |= 0x01; | ||
2738 | } else | ||
2739 | bltmode |= 0x01; | ||
2740 | } | ||
2741 | if (!bltmode) { | ||
2742 | /* standard case: forward blitting */ | ||
2743 | nsrc = (cury * line_length) + curx; | ||
2744 | ndest = (desty * line_length) + destx; | ||
2745 | } else { | ||
2746 | /* this means start addresses are at the end, | ||
2747 | * counting backwards | ||
2748 | */ | ||
2749 | nsrc = cury * line_length + curx + | ||
2750 | nheight * line_length + nwidth; | ||
2751 | ndest = desty * line_length + destx + | ||
2752 | nheight * line_length + nwidth; | ||
2753 | } | ||
2754 | |||
2755 | /* | ||
2756 | run-down of registers to be programmed: | ||
2757 | destination pitch | ||
2758 | source pitch | ||
2759 | BLT width/height | ||
2760 | source start | ||
2761 | destination start | ||
2762 | BLT mode | ||
2763 | BLT ROP | ||
2764 | VGA_GFX_SR_VALUE / VGA_GFX_SR_ENABLE: "fill color" | ||
2765 | start/stop | ||
2766 | */ | ||
2767 | |||
2768 | cirrusfb_WaitBLT(regbase); | ||
2769 | 2626 | ||
2627 | { | ||
2770 | /* pitch: set to line_length */ | 2628 | /* pitch: set to line_length */ |
2771 | /* dest pitch low */ | 2629 | /* dest pitch low */ |
2772 | vga_wgfx(regbase, CL_GR24, line_length & 0xff); | 2630 | vga_wgfx(regbase, CL_GR24, line_length & 0xff); |
@@ -2813,91 +2671,91 @@ static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, | |||
2813 | 2671 | ||
2814 | /* and finally: GO! */ | 2672 | /* and finally: GO! */ |
2815 | vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */ | 2673 | vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */ |
2816 | |||
2817 | DPRINTK("EXIT\n"); | ||
2818 | } | 2674 | } |
2819 | 2675 | ||
2820 | /******************************************************************* | 2676 | /******************************************************************* |
2821 | cirrusfb_RectFill() | 2677 | cirrusfb_BitBLT() |
2822 | 2678 | ||
2823 | perform accelerated rectangle fill | 2679 | perform accelerated "scrolling" |
2824 | ********************************************************************/ | 2680 | ********************************************************************/ |
2825 | 2681 | ||
2826 | static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, | 2682 | static void cirrusfb_BitBLT(u8 __iomem *regbase, int bits_per_pixel, |
2827 | u_short x, u_short y, u_short width, u_short height, | 2683 | u_short curx, u_short cury, |
2828 | u_char color, u_short line_length) | 2684 | u_short destx, u_short desty, |
2685 | u_short width, u_short height, | ||
2686 | u_short line_length) | ||
2829 | { | 2687 | { |
2830 | u_short nwidth, nheight; | 2688 | u_short nwidth = width - 1; |
2831 | u_long ndest; | 2689 | u_short nheight = height - 1; |
2832 | u_char op; | 2690 | u_long nsrc, ndest; |
2833 | 2691 | u_char bltmode; | |
2834 | DPRINTK("ENTER\n"); | ||
2835 | |||
2836 | nwidth = width - 1; | ||
2837 | nheight = height - 1; | ||
2838 | 2692 | ||
2839 | ndest = (y * line_length) + x; | 2693 | bltmode = 0x00; |
2694 | /* if source adr < dest addr, do the Blt backwards */ | ||
2695 | if (cury <= desty) { | ||
2696 | if (cury == desty) { | ||
2697 | /* if src and dest are on the same line, check x */ | ||
2698 | if (curx < destx) | ||
2699 | bltmode |= 0x01; | ||
2700 | } else | ||
2701 | bltmode |= 0x01; | ||
2702 | } | ||
2703 | /* standard case: forward blitting */ | ||
2704 | nsrc = (cury * line_length) + curx; | ||
2705 | ndest = (desty * line_length) + destx; | ||
2706 | if (bltmode) { | ||
2707 | /* this means start addresses are at the end, | ||
2708 | * counting backwards | ||
2709 | */ | ||
2710 | nsrc += nheight * line_length + nwidth; | ||
2711 | ndest += nheight * line_length + nwidth; | ||
2712 | } | ||
2840 | 2713 | ||
2841 | cirrusfb_WaitBLT(regbase); | 2714 | cirrusfb_WaitBLT(regbase); |
2842 | 2715 | ||
2843 | /* pitch: set to line_length */ | 2716 | cirrusfb_set_blitter(regbase, nwidth, nheight, |
2844 | vga_wgfx(regbase, CL_GR24, line_length & 0xff); /* dest pitch low */ | 2717 | nsrc, ndest, bltmode, line_length); |
2845 | vga_wgfx(regbase, CL_GR25, line_length >> 8); /* dest pitch hi */ | 2718 | } |
2846 | vga_wgfx(regbase, CL_GR26, line_length & 0xff); /* source pitch low */ | ||
2847 | vga_wgfx(regbase, CL_GR27, line_length >> 8); /* source pitch hi */ | ||
2848 | 2719 | ||
2849 | /* BLT width: actual number of pixels - 1 */ | 2720 | /******************************************************************* |
2850 | vga_wgfx(regbase, CL_GR20, nwidth & 0xff); /* BLT width low */ | 2721 | cirrusfb_RectFill() |
2851 | vga_wgfx(regbase, CL_GR21, nwidth >> 8); /* BLT width hi */ | ||
2852 | 2722 | ||
2853 | /* BLT height: actual number of lines -1 */ | 2723 | perform accelerated rectangle fill |
2854 | vga_wgfx(regbase, CL_GR22, nheight & 0xff); /* BLT height low */ | 2724 | ********************************************************************/ |
2855 | vga_wgfx(regbase, CL_GR23, nheight >> 8); /* BLT width hi */ | ||
2856 | 2725 | ||
2857 | /* BLT destination */ | 2726 | static void cirrusfb_RectFill(u8 __iomem *regbase, int bits_per_pixel, |
2858 | /* BLT dest low */ | 2727 | u_short x, u_short y, u_short width, u_short height, |
2859 | vga_wgfx(regbase, CL_GR28, (u_char) (ndest & 0xff)); | 2728 | u32 fg_color, u32 bg_color, u_short line_length, |
2860 | /* BLT dest mid */ | 2729 | u_char blitmode) |
2861 | vga_wgfx(regbase, CL_GR29, (u_char) (ndest >> 8)); | 2730 | { |
2862 | /* BLT dest hi */ | 2731 | u_long ndest = (y * line_length) + x; |
2863 | vga_wgfx(regbase, CL_GR2A, (u_char) (ndest >> 16)); | 2732 | u_char op; |
2864 | 2733 | ||
2865 | /* BLT source: set to 0 (is a dummy here anyway) */ | 2734 | cirrusfb_WaitBLT(regbase); |
2866 | vga_wgfx(regbase, CL_GR2C, 0x00); /* BLT src low */ | ||
2867 | vga_wgfx(regbase, CL_GR2D, 0x00); /* BLT src mid */ | ||
2868 | vga_wgfx(regbase, CL_GR2E, 0x00); /* BLT src hi */ | ||
2869 | 2735 | ||
2870 | /* This is a ColorExpand Blt, using the */ | 2736 | /* This is a ColorExpand Blt, using the */ |
2871 | /* same color for foreground and background */ | 2737 | /* same color for foreground and background */ |
2872 | vga_wgfx(regbase, VGA_GFX_SR_VALUE, color); /* foreground color */ | 2738 | vga_wgfx(regbase, VGA_GFX_SR_VALUE, bg_color); |
2873 | vga_wgfx(regbase, VGA_GFX_SR_ENABLE, color); /* background color */ | 2739 | vga_wgfx(regbase, VGA_GFX_SR_ENABLE, fg_color); |
2874 | 2740 | ||
2875 | op = 0xc0; | 2741 | op = 0x80; |
2876 | if (bits_per_pixel == 16) { | 2742 | if (bits_per_pixel >= 16) { |
2877 | vga_wgfx(regbase, CL_GR10, color); /* foreground color */ | 2743 | vga_wgfx(regbase, CL_GR10, bg_color >> 8); |
2878 | vga_wgfx(regbase, CL_GR11, color); /* background color */ | 2744 | vga_wgfx(regbase, CL_GR11, fg_color >> 8); |
2879 | op = 0x50; | 2745 | op = 0x90; |
2880 | op = 0xd0; | 2746 | } |
2881 | } else if (bits_per_pixel == 32) { | 2747 | if (bits_per_pixel >= 24) { |
2882 | vga_wgfx(regbase, CL_GR10, color); /* foreground color */ | 2748 | vga_wgfx(regbase, CL_GR12, bg_color >> 16); |
2883 | vga_wgfx(regbase, CL_GR11, color); /* background color */ | 2749 | vga_wgfx(regbase, CL_GR13, fg_color >> 16); |
2884 | vga_wgfx(regbase, CL_GR12, color); /* foreground color */ | 2750 | op = 0xa0; |
2885 | vga_wgfx(regbase, CL_GR13, color); /* background color */ | 2751 | } |
2886 | vga_wgfx(regbase, CL_GR14, 0); /* foreground color */ | 2752 | if (bits_per_pixel == 32) { |
2887 | vga_wgfx(regbase, CL_GR15, 0); /* background color */ | 2753 | vga_wgfx(regbase, CL_GR14, bg_color >> 24); |
2888 | op = 0x50; | 2754 | vga_wgfx(regbase, CL_GR15, fg_color >> 24); |
2889 | op = 0xf0; | 2755 | op = 0xb0; |
2890 | } | 2756 | } |
2891 | /* BLT mode: color expand, Enable 8x8 copy (faster?) */ | 2757 | cirrusfb_set_blitter(regbase, width - 1, height - 1, |
2892 | vga_wgfx(regbase, CL_GR30, op); /* BLT mode */ | 2758 | 0, ndest, op | blitmode, line_length); |
2893 | |||
2894 | /* BLT ROP: SrcCopy */ | ||
2895 | vga_wgfx(regbase, CL_GR32, 0x0d); /* BLT ROP */ | ||
2896 | |||
2897 | /* and finally: GO! */ | ||
2898 | vga_wgfx(regbase, CL_GR31, 0x02); /* BLT Start/status */ | ||
2899 | |||
2900 | DPRINTK("EXIT\n"); | ||
2901 | } | 2759 | } |
2902 | 2760 | ||
2903 | /************************************************************************** | 2761 | /************************************************************************** |
@@ -2917,8 +2775,6 @@ static void bestclock(long freq, int *nom, int *den, int *div) | |||
2917 | *den = 0; | 2775 | *den = 0; |
2918 | *div = 0; | 2776 | *div = 0; |
2919 | 2777 | ||
2920 | DPRINTK("ENTER\n"); | ||
2921 | |||
2922 | if (freq < 8000) | 2778 | if (freq < 8000) |
2923 | freq = 8000; | 2779 | freq = 8000; |
2924 | 2780 | ||
@@ -2960,12 +2816,6 @@ static void bestclock(long freq, int *nom, int *den, int *div) | |||
2960 | } | 2816 | } |
2961 | } | 2817 | } |
2962 | } | 2818 | } |
2963 | |||
2964 | DPRINTK("Best possible values for given frequency:\n"); | ||
2965 | DPRINTK(" freq: %ld kHz nom: %d den: %d div: %d\n", | ||
2966 | freq, *nom, *den, *div); | ||
2967 | |||
2968 | DPRINTK("EXIT\n"); | ||
2969 | } | 2819 | } |
2970 | 2820 | ||
2971 | /* ------------------------------------------------------------------------- | 2821 | /* ------------------------------------------------------------------------- |
@@ -2978,32 +2828,6 @@ static void bestclock(long freq, int *nom, int *den, int *div) | |||
2978 | #ifdef CIRRUSFB_DEBUG | 2828 | #ifdef CIRRUSFB_DEBUG |
2979 | 2829 | ||
2980 | /** | 2830 | /** |
2981 | * cirrusfb_dbg_print_byte | ||
2982 | * @name: name associated with byte value to be displayed | ||
2983 | * @val: byte value to be displayed | ||
2984 | * | ||
2985 | * DESCRIPTION: | ||
2986 | * Display an indented string, along with a hexidecimal byte value, and | ||
2987 | * its decoded bits. Bits 7 through 0 are listed in left-to-right | ||
2988 | * order. | ||
2989 | */ | ||
2990 | |||
2991 | static | ||
2992 | void cirrusfb_dbg_print_byte(const char *name, unsigned char val) | ||
2993 | { | ||
2994 | DPRINTK("%8s = 0x%02X (bits 7-0: %c%c%c%c%c%c%c%c)\n", | ||
2995 | name, val, | ||
2996 | val & 0x80 ? '1' : '0', | ||
2997 | val & 0x40 ? '1' : '0', | ||
2998 | val & 0x20 ? '1' : '0', | ||
2999 | val & 0x10 ? '1' : '0', | ||
3000 | val & 0x08 ? '1' : '0', | ||
3001 | val & 0x04 ? '1' : '0', | ||
3002 | val & 0x02 ? '1' : '0', | ||
3003 | val & 0x01 ? '1' : '0'); | ||
3004 | } | ||
3005 | |||
3006 | /** | ||
3007 | * cirrusfb_dbg_print_regs | 2831 | * cirrusfb_dbg_print_regs |
3008 | * @base: If using newmmio, the newmmio base address, otherwise %NULL | 2832 | * @base: If using newmmio, the newmmio base address, otherwise %NULL |
3009 | * @reg_class: type of registers to read: %CRT, or %SEQ | 2833 | * @reg_class: type of registers to read: %CRT, or %SEQ |
@@ -3014,9 +2838,9 @@ void cirrusfb_dbg_print_byte(const char *name, unsigned char val) | |||
3014 | * used at the given @base address to query the information. | 2838 | * used at the given @base address to query the information. |
3015 | */ | 2839 | */ |
3016 | 2840 | ||
3017 | static | 2841 | static void cirrusfb_dbg_print_regs(struct fb_info *info, |
3018 | void cirrusfb_dbg_print_regs(caddr_t regbase, | 2842 | caddr_t regbase, |
3019 | enum cirrusfb_dbg_reg_class reg_class, ...) | 2843 | enum cirrusfb_dbg_reg_class reg_class, ...) |
3020 | { | 2844 | { |
3021 | va_list list; | 2845 | va_list list; |
3022 | unsigned char val = 0; | 2846 | unsigned char val = 0; |
@@ -3042,7 +2866,7 @@ void cirrusfb_dbg_print_regs(caddr_t regbase, | |||
3042 | break; | 2866 | break; |
3043 | } | 2867 | } |
3044 | 2868 | ||
3045 | cirrusfb_dbg_print_byte(name, val); | 2869 | dev_dbg(info->device, "%8s = 0x%02X\n", name, val); |
3046 | 2870 | ||
3047 | name = va_arg(list, char *); | 2871 | name = va_arg(list, char *); |
3048 | } | 2872 | } |
@@ -3051,18 +2875,6 @@ void cirrusfb_dbg_print_regs(caddr_t regbase, | |||
3051 | } | 2875 | } |
3052 | 2876 | ||
3053 | /** | 2877 | /** |
3054 | * cirrusfb_dump | ||
3055 | * @cirrusfbinfo: | ||
3056 | * | ||
3057 | * DESCRIPTION: | ||
3058 | */ | ||
3059 | |||
3060 | static void cirrusfb_dump(void) | ||
3061 | { | ||
3062 | cirrusfb_dbg_reg_dump(NULL); | ||
3063 | } | ||
3064 | |||
3065 | /** | ||
3066 | * cirrusfb_dbg_reg_dump | 2878 | * cirrusfb_dbg_reg_dump |
3067 | * @base: If using newmmio, the newmmio base address, otherwise %NULL | 2879 | * @base: If using newmmio, the newmmio base address, otherwise %NULL |
3068 | * | 2880 | * |
@@ -3072,12 +2884,11 @@ static void cirrusfb_dump(void) | |||
3072 | * used at the given @base address to query the information. | 2884 | * used at the given @base address to query the information. |
3073 | */ | 2885 | */ |
3074 | 2886 | ||
3075 | static | 2887 | static void cirrusfb_dbg_reg_dump(struct fb_info *info, caddr_t regbase) |
3076 | void cirrusfb_dbg_reg_dump(caddr_t regbase) | ||
3077 | { | 2888 | { |
3078 | DPRINTK("CIRRUSFB VGA CRTC register dump:\n"); | 2889 | dev_dbg(info->device, "VGA CRTC register dump:\n"); |
3079 | 2890 | ||
3080 | cirrusfb_dbg_print_regs(regbase, CRT, | 2891 | cirrusfb_dbg_print_regs(info, regbase, CRT, |
3081 | "CR00", 0x00, | 2892 | "CR00", 0x00, |
3082 | "CR01", 0x01, | 2893 | "CR01", 0x01, |
3083 | "CR02", 0x02, | 2894 | "CR02", 0x02, |
@@ -3127,11 +2938,11 @@ void cirrusfb_dbg_reg_dump(caddr_t regbase) | |||
3127 | "CR3F", 0x3F, | 2938 | "CR3F", 0x3F, |
3128 | NULL); | 2939 | NULL); |
3129 | 2940 | ||
3130 | DPRINTK("\n"); | 2941 | dev_dbg(info->device, "\n"); |
3131 | 2942 | ||
3132 | DPRINTK("CIRRUSFB VGA SEQ register dump:\n"); | 2943 | dev_dbg(info->device, "VGA SEQ register dump:\n"); |
3133 | 2944 | ||
3134 | cirrusfb_dbg_print_regs(regbase, SEQ, | 2945 | cirrusfb_dbg_print_regs(info, regbase, SEQ, |
3135 | "SR00", 0x00, | 2946 | "SR00", 0x00, |
3136 | "SR01", 0x01, | 2947 | "SR01", 0x01, |
3137 | "SR02", 0x02, | 2948 | "SR02", 0x02, |
@@ -3160,7 +2971,7 @@ void cirrusfb_dbg_reg_dump(caddr_t regbase) | |||
3160 | "SR1F", 0x1F, | 2971 | "SR1F", 0x1F, |
3161 | NULL); | 2972 | NULL); |
3162 | 2973 | ||
3163 | DPRINTK("\n"); | 2974 | dev_dbg(info->device, "\n"); |
3164 | } | 2975 | } |
3165 | 2976 | ||
3166 | #endif /* CIRRUSFB_DEBUG */ | 2977 | #endif /* CIRRUSFB_DEBUG */ |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 1657b9608b04..2cd500a304f2 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -2954,8 +2954,11 @@ static int fbcon_fb_unbind(int idx) | |||
2954 | 2954 | ||
2955 | static int fbcon_fb_unregistered(struct fb_info *info) | 2955 | static int fbcon_fb_unregistered(struct fb_info *info) |
2956 | { | 2956 | { |
2957 | int i, idx = info->node; | 2957 | int i, idx; |
2958 | 2958 | ||
2959 | if (!lock_fb_info(info)) | ||
2960 | return -ENODEV; | ||
2961 | idx = info->node; | ||
2959 | for (i = first_fb_vc; i <= last_fb_vc; i++) { | 2962 | for (i = first_fb_vc; i <= last_fb_vc; i++) { |
2960 | if (con2fb_map[i] == idx) | 2963 | if (con2fb_map[i] == idx) |
2961 | con2fb_map[i] = -1; | 2964 | con2fb_map[i] = -1; |
@@ -2979,13 +2982,14 @@ static int fbcon_fb_unregistered(struct fb_info *info) | |||
2979 | } | 2982 | } |
2980 | } | 2983 | } |
2981 | 2984 | ||
2982 | if (!num_registered_fb) | ||
2983 | unregister_con_driver(&fb_con); | ||
2984 | |||
2985 | |||
2986 | if (primary_device == idx) | 2985 | if (primary_device == idx) |
2987 | primary_device = -1; | 2986 | primary_device = -1; |
2988 | 2987 | ||
2988 | unlock_fb_info(info); | ||
2989 | |||
2990 | if (!num_registered_fb) | ||
2991 | unregister_con_driver(&fb_con); | ||
2992 | |||
2989 | return 0; | 2993 | return 0; |
2990 | } | 2994 | } |
2991 | 2995 | ||
@@ -3021,9 +3025,13 @@ static inline void fbcon_select_primary(struct fb_info *info) | |||
3021 | 3025 | ||
3022 | static int fbcon_fb_registered(struct fb_info *info) | 3026 | static int fbcon_fb_registered(struct fb_info *info) |
3023 | { | 3027 | { |
3024 | int ret = 0, i, idx = info->node; | 3028 | int ret = 0, i, idx; |
3025 | 3029 | ||
3030 | if (!lock_fb_info(info)) | ||
3031 | return -ENODEV; | ||
3032 | idx = info->node; | ||
3026 | fbcon_select_primary(info); | 3033 | fbcon_select_primary(info); |
3034 | unlock_fb_info(info); | ||
3027 | 3035 | ||
3028 | if (info_idx == -1) { | 3036 | if (info_idx == -1) { |
3029 | for (i = first_fb_vc; i <= last_fb_vc; i++) { | 3037 | for (i = first_fb_vc; i <= last_fb_vc; i++) { |
@@ -3124,7 +3132,7 @@ static void fbcon_get_requirement(struct fb_info *info, | |||
3124 | } | 3132 | } |
3125 | } | 3133 | } |
3126 | 3134 | ||
3127 | static int fbcon_event_notify(struct notifier_block *self, | 3135 | static int fbcon_event_notify(struct notifier_block *self, |
3128 | unsigned long action, void *data) | 3136 | unsigned long action, void *data) |
3129 | { | 3137 | { |
3130 | struct fb_event *event = data; | 3138 | struct fb_event *event = data; |
@@ -3132,7 +3140,7 @@ static int fbcon_event_notify(struct notifier_block *self, | |||
3132 | struct fb_videomode *mode; | 3140 | struct fb_videomode *mode; |
3133 | struct fb_con2fbmap *con2fb; | 3141 | struct fb_con2fbmap *con2fb; |
3134 | struct fb_blit_caps *caps; | 3142 | struct fb_blit_caps *caps; |
3135 | int ret = 0; | 3143 | int idx, ret = 0; |
3136 | 3144 | ||
3137 | /* | 3145 | /* |
3138 | * ignore all events except driver registration and deregistration | 3146 | * ignore all events except driver registration and deregistration |
@@ -3144,23 +3152,54 @@ static int fbcon_event_notify(struct notifier_block *self, | |||
3144 | 3152 | ||
3145 | switch(action) { | 3153 | switch(action) { |
3146 | case FB_EVENT_SUSPEND: | 3154 | case FB_EVENT_SUSPEND: |
3155 | if (!lock_fb_info(info)) { | ||
3156 | ret = -ENODEV; | ||
3157 | goto done; | ||
3158 | } | ||
3147 | fbcon_suspended(info); | 3159 | fbcon_suspended(info); |
3160 | unlock_fb_info(info); | ||
3148 | break; | 3161 | break; |
3149 | case FB_EVENT_RESUME: | 3162 | case FB_EVENT_RESUME: |
3163 | if (!lock_fb_info(info)) { | ||
3164 | ret = -ENODEV; | ||
3165 | goto done; | ||
3166 | } | ||
3150 | fbcon_resumed(info); | 3167 | fbcon_resumed(info); |
3168 | unlock_fb_info(info); | ||
3151 | break; | 3169 | break; |
3152 | case FB_EVENT_MODE_CHANGE: | 3170 | case FB_EVENT_MODE_CHANGE: |
3171 | if (!lock_fb_info(info)) { | ||
3172 | ret = -ENODEV; | ||
3173 | goto done; | ||
3174 | } | ||
3153 | fbcon_modechanged(info); | 3175 | fbcon_modechanged(info); |
3176 | unlock_fb_info(info); | ||
3154 | break; | 3177 | break; |
3155 | case FB_EVENT_MODE_CHANGE_ALL: | 3178 | case FB_EVENT_MODE_CHANGE_ALL: |
3179 | if (!lock_fb_info(info)) { | ||
3180 | ret = -ENODEV; | ||
3181 | goto done; | ||
3182 | } | ||
3156 | fbcon_set_all_vcs(info); | 3183 | fbcon_set_all_vcs(info); |
3184 | unlock_fb_info(info); | ||
3157 | break; | 3185 | break; |
3158 | case FB_EVENT_MODE_DELETE: | 3186 | case FB_EVENT_MODE_DELETE: |
3159 | mode = event->data; | 3187 | mode = event->data; |
3188 | if (!lock_fb_info(info)) { | ||
3189 | ret = -ENODEV; | ||
3190 | goto done; | ||
3191 | } | ||
3160 | ret = fbcon_mode_deleted(info, mode); | 3192 | ret = fbcon_mode_deleted(info, mode); |
3193 | unlock_fb_info(info); | ||
3161 | break; | 3194 | break; |
3162 | case FB_EVENT_FB_UNBIND: | 3195 | case FB_EVENT_FB_UNBIND: |
3163 | ret = fbcon_fb_unbind(info->node); | 3196 | if (!lock_fb_info(info)) { |
3197 | ret = -ENODEV; | ||
3198 | goto done; | ||
3199 | } | ||
3200 | idx = info->node; | ||
3201 | unlock_fb_info(info); | ||
3202 | ret = fbcon_fb_unbind(idx); | ||
3164 | break; | 3203 | break; |
3165 | case FB_EVENT_FB_REGISTERED: | 3204 | case FB_EVENT_FB_REGISTERED: |
3166 | ret = fbcon_fb_registered(info); | 3205 | ret = fbcon_fb_registered(info); |
@@ -3178,17 +3217,31 @@ static int fbcon_event_notify(struct notifier_block *self, | |||
3178 | con2fb->framebuffer = con2fb_map[con2fb->console - 1]; | 3217 | con2fb->framebuffer = con2fb_map[con2fb->console - 1]; |
3179 | break; | 3218 | break; |
3180 | case FB_EVENT_BLANK: | 3219 | case FB_EVENT_BLANK: |
3220 | if (!lock_fb_info(info)) { | ||
3221 | ret = -ENODEV; | ||
3222 | goto done; | ||
3223 | } | ||
3181 | fbcon_fb_blanked(info, *(int *)event->data); | 3224 | fbcon_fb_blanked(info, *(int *)event->data); |
3225 | unlock_fb_info(info); | ||
3182 | break; | 3226 | break; |
3183 | case FB_EVENT_NEW_MODELIST: | 3227 | case FB_EVENT_NEW_MODELIST: |
3228 | if (!lock_fb_info(info)) { | ||
3229 | ret = -ENODEV; | ||
3230 | goto done; | ||
3231 | } | ||
3184 | fbcon_new_modelist(info); | 3232 | fbcon_new_modelist(info); |
3233 | unlock_fb_info(info); | ||
3185 | break; | 3234 | break; |
3186 | case FB_EVENT_GET_REQ: | 3235 | case FB_EVENT_GET_REQ: |
3187 | caps = event->data; | 3236 | caps = event->data; |
3237 | if (!lock_fb_info(info)) { | ||
3238 | ret = -ENODEV; | ||
3239 | goto done; | ||
3240 | } | ||
3188 | fbcon_get_requirement(info, caps); | 3241 | fbcon_get_requirement(info, caps); |
3242 | unlock_fb_info(info); | ||
3189 | break; | 3243 | break; |
3190 | } | 3244 | } |
3191 | |||
3192 | done: | 3245 | done: |
3193 | return ret; | 3246 | return ret; |
3194 | } | 3247 | } |
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c deleted file mode 100644 index 9704b73135f5..000000000000 --- a/drivers/video/cyblafb.c +++ /dev/null | |||
@@ -1,1683 +0,0 @@ | |||
1 | /* | ||
2 | * Frame buffer driver for Trident Cyberblade/i1 graphics core | ||
3 | * | ||
4 | * Copyright 2005 Knut Petersen <Knut_Petersen@t-online.de> | ||
5 | * | ||
6 | * CREDITS: | ||
7 | * tridentfb.c by Jani Monoses | ||
8 | * see files above for further credits | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #define CYBLAFB_DEBUG 0 | ||
13 | #define CYBLAFB_KD_GRAPHICS_QUIRK 1 | ||
14 | |||
15 | #define CYBLAFB_PIXMAPSIZE 8192 | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/fb.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/pci.h> | ||
22 | #include <asm/types.h> | ||
23 | #include <video/cyblafb.h> | ||
24 | |||
25 | #define VERSION "0.62" | ||
26 | |||
27 | struct cyblafb_par { | ||
28 | u32 pseudo_pal[16]; | ||
29 | struct fb_ops ops; | ||
30 | }; | ||
31 | |||
32 | static struct fb_fix_screeninfo cyblafb_fix __devinitdata = { | ||
33 | .id = "CyBla", | ||
34 | .type = FB_TYPE_PACKED_PIXELS, | ||
35 | .xpanstep = 1, | ||
36 | .ypanstep = 1, | ||
37 | .ywrapstep = 1, | ||
38 | .visual = FB_VISUAL_PSEUDOCOLOR, | ||
39 | .accel = FB_ACCEL_NONE, | ||
40 | }; | ||
41 | |||
42 | static char *mode __devinitdata = NULL; | ||
43 | static int bpp __devinitdata = 8; | ||
44 | static int ref __devinitdata = 75; | ||
45 | static int fp __devinitdata; | ||
46 | static int crt __devinitdata; | ||
47 | static int memsize __devinitdata; | ||
48 | |||
49 | static int basestride; | ||
50 | static int vesafb; | ||
51 | static int nativex; | ||
52 | static int center; | ||
53 | static int stretch; | ||
54 | static int pciwb = 1; | ||
55 | static int pcirb = 1; | ||
56 | static int pciwr = 1; | ||
57 | static int pcirr = 1; | ||
58 | static int disabled; | ||
59 | static int verbosity; | ||
60 | static int displaytype; | ||
61 | |||
62 | static void __iomem *io_virt; // iospace virtual memory address | ||
63 | |||
64 | module_param(mode, charp, 0); | ||
65 | module_param(bpp, int, 0); | ||
66 | module_param(ref, int, 0); | ||
67 | module_param(fp, int, 0); | ||
68 | module_param(crt, int, 0); | ||
69 | module_param(nativex, int, 0); | ||
70 | module_param(center, int, 0); | ||
71 | module_param(stretch, int, 0); | ||
72 | module_param(pciwb, int, 0); | ||
73 | module_param(pcirb, int, 0); | ||
74 | module_param(pciwr, int, 0); | ||
75 | module_param(pcirr, int, 0); | ||
76 | module_param(memsize, int, 0); | ||
77 | module_param(verbosity, int, 0); | ||
78 | |||
79 | //========================================= | ||
80 | // | ||
81 | // Well, we have to fix the upper layers. | ||
82 | // Until this has been done, we work around | ||
83 | // the bugs. | ||
84 | // | ||
85 | //========================================= | ||
86 | |||
87 | #if (CYBLAFB_KD_GRAPHICS_QUIRK && CYBLAFB_DEBUG) | ||
88 | if (disabled) { \ | ||
89 | printk("********\n");\ | ||
90 | dump_stack();\ | ||
91 | return val;\ | ||
92 | } | ||
93 | |||
94 | #elif CYBLAFB_KD_GRAPHICS_QUIRK | ||
95 | #define KD_GRAPHICS_RETURN(val)\ | ||
96 | if (disabled) {\ | ||
97 | return val;\ | ||
98 | } | ||
99 | #else | ||
100 | #define KD_GRAPHICS_RETURN(val) | ||
101 | #endif | ||
102 | |||
103 | //========================================= | ||
104 | // | ||
105 | // Port access macros for memory mapped io | ||
106 | // | ||
107 | //========================================= | ||
108 | |||
109 | #define out8(r, v) writeb(v, io_virt + r) | ||
110 | #define out32(r, v) writel(v, io_virt + r) | ||
111 | #define in8(r) readb(io_virt + r) | ||
112 | #define in32(r) readl(io_virt + r) | ||
113 | |||
114 | //====================================== | ||
115 | // | ||
116 | // Hardware access inline functions | ||
117 | // | ||
118 | //====================================== | ||
119 | |||
120 | static inline u8 read3X4(u32 reg) | ||
121 | { | ||
122 | out8(0x3D4, reg); | ||
123 | return in8(0x3D5); | ||
124 | } | ||
125 | |||
126 | static inline u8 read3C4(u32 reg) | ||
127 | { | ||
128 | out8(0x3C4, reg); | ||
129 | return in8(0x3C5); | ||
130 | } | ||
131 | |||
132 | static inline u8 read3CE(u32 reg) | ||
133 | { | ||
134 | out8(0x3CE, reg); | ||
135 | return in8(0x3CF); | ||
136 | } | ||
137 | |||
138 | static inline void write3X4(u32 reg, u8 val) | ||
139 | { | ||
140 | out8(0x3D4, reg); | ||
141 | out8(0x3D5, val); | ||
142 | } | ||
143 | |||
144 | static inline void write3C4(u32 reg, u8 val) | ||
145 | { | ||
146 | out8(0x3C4, reg); | ||
147 | out8(0x3C5, val); | ||
148 | } | ||
149 | |||
150 | static inline void write3CE(u32 reg, u8 val) | ||
151 | { | ||
152 | out8(0x3CE, reg); | ||
153 | out8(0x3CF, val); | ||
154 | } | ||
155 | |||
156 | static inline void write3C0(u32 reg, u8 val) | ||
157 | { | ||
158 | in8(0x3DA); // read to reset index | ||
159 | out8(0x3C0, reg); | ||
160 | out8(0x3C0, val); | ||
161 | } | ||
162 | |||
163 | //================================================= | ||
164 | // | ||
165 | // Enable memory mapped io and unprotect registers | ||
166 | // | ||
167 | //================================================= | ||
168 | |||
169 | static void enable_mmio(void) | ||
170 | { | ||
171 | u8 tmp; | ||
172 | |||
173 | outb(0x0B, 0x3C4); | ||
174 | inb(0x3C5); // Set NEW mode | ||
175 | outb(SR0E, 0x3C4); // write enable a lot of extended ports | ||
176 | outb(0x80, 0x3C5); | ||
177 | |||
178 | outb(SR11, 0x3C4); // write enable those extended ports that | ||
179 | outb(0x87, 0x3C5); // are not affected by SR0E_New | ||
180 | |||
181 | outb(CR1E, 0x3d4); // clear write protect bit for port 0x3c2 | ||
182 | tmp = inb(0x3d5) & 0xBF; | ||
183 | outb(CR1E, 0x3d4); | ||
184 | outb(tmp, 0x3d5); | ||
185 | |||
186 | outb(CR39, 0x3D4); | ||
187 | outb(inb(0x3D5) | 0x01, 0x3D5); // Enable mmio | ||
188 | } | ||
189 | |||
190 | //================================================= | ||
191 | // | ||
192 | // Set pixel clock VCLK1 | ||
193 | // - multipliers set elswhere | ||
194 | // - freq in units of 0.01 MHz | ||
195 | // | ||
196 | // Hardware bug: SR18 >= 250 is broken for the | ||
197 | // cyberblade/i1 | ||
198 | // | ||
199 | //================================================= | ||
200 | |||
201 | static void set_vclk(struct cyblafb_par *par, int freq) | ||
202 | { | ||
203 | u32 m, n, k; | ||
204 | int f, fi, d, di; | ||
205 | u8 lo = 0, hi = 0; | ||
206 | |||
207 | d = 2000; | ||
208 | k = freq >= 10000 ? 0 : freq >= 5000 ? 1 : freq >= 2500 ? 2 : 3; | ||
209 | for (m = 0; m < 64; m++) | ||
210 | for (n = 0; n < 250; n++) { | ||
211 | fi = (int)(((5864727 * (n + 8)) / | ||
212 | ((m + 2) * (1 << k))) >> 12); | ||
213 | if ((di = abs(fi - freq)) < d) { | ||
214 | d = di; | ||
215 | f = fi; | ||
216 | lo = (u8) n; | ||
217 | hi = (u8) ((k << 6) | m); | ||
218 | } | ||
219 | } | ||
220 | write3C4(SR19, hi); | ||
221 | write3C4(SR18, lo); | ||
222 | if (verbosity > 0) | ||
223 | output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n", | ||
224 | freq / 100, freq % 100, (hi & 0xc0) >> 6, hi & 0x3f, lo); | ||
225 | } | ||
226 | |||
227 | //================================================ | ||
228 | // | ||
229 | // Cyberblade specific Graphics Engine (GE) setup | ||
230 | // | ||
231 | //================================================ | ||
232 | |||
233 | static void cyblafb_setup_GE(int pitch, int bpp) | ||
234 | { | ||
235 | KD_GRAPHICS_RETURN(); | ||
236 | |||
237 | switch (bpp) { | ||
238 | case 8: | ||
239 | basestride = ((pitch >> 3) << 20) | (0 << 29); | ||
240 | break; | ||
241 | case 15: | ||
242 | basestride = ((pitch >> 3) << 20) | (5 << 29); | ||
243 | break; | ||
244 | case 16: | ||
245 | basestride = ((pitch >> 3) << 20) | (1 << 29); | ||
246 | break; | ||
247 | case 24: | ||
248 | case 32: | ||
249 | basestride = ((pitch >> 3) << 20) | (2 << 29); | ||
250 | break; | ||
251 | } | ||
252 | |||
253 | write3X4(CR36, 0x90); // reset GE | ||
254 | write3X4(CR36, 0x80); // enable GE | ||
255 | out32(GE24, 1 << 7); // reset all GE pointers by toggling | ||
256 | out32(GE24, 0); // d7 of GE24 | ||
257 | write3X4(CR2D, 0x00); // GE Timinigs, no delays | ||
258 | out32(GE6C, 0); // Pattern and Style, p 129, ok | ||
259 | } | ||
260 | |||
261 | //===================================================================== | ||
262 | // | ||
263 | // Cyberblade specific syncing | ||
264 | // | ||
265 | // A timeout might be caused by disabled mmio. | ||
266 | // Cause: | ||
267 | // - bit CR39 & 1 == 0 upon return, X trident driver bug | ||
268 | // - kdm bug (KD_GRAPHICS not set on first switch) | ||
269 | // - kernel design flaw (it believes in the correctness | ||
270 | // of kdm/X | ||
271 | // First we try to sync ignoring that problem, as most of the | ||
272 | // time that will succeed immediately and the enable_mmio() | ||
273 | // would only degrade performance. | ||
274 | // | ||
275 | //===================================================================== | ||
276 | |||
277 | static int cyblafb_sync(struct fb_info *info) | ||
278 | { | ||
279 | u32 status, i = 100000; | ||
280 | |||
281 | KD_GRAPHICS_RETURN(0); | ||
282 | |||
283 | while (((status = in32(GE20)) & 0xFe800000) && i != 0) | ||
284 | i--; | ||
285 | |||
286 | if (i == 0) { | ||
287 | enable_mmio(); | ||
288 | i = 1000000; | ||
289 | while (((status = in32(GE20)) & 0xFA800000) && i != 0) | ||
290 | i--; | ||
291 | if (i == 0) { | ||
292 | output("GE Timeout, status: %x\n", status); | ||
293 | if (status & 0x80000000) | ||
294 | output("Bresenham Engine : Busy\n"); | ||
295 | if (status & 0x40000000) | ||
296 | output("Setup Engine : Busy\n"); | ||
297 | if (status & 0x20000000) | ||
298 | output("SP / DPE : Busy\n"); | ||
299 | if (status & 0x10000000) | ||
300 | output("Memory Interface : Busy\n"); | ||
301 | if (status & 0x08000000) | ||
302 | output("Com Lst Proc : Busy\n"); | ||
303 | if (status & 0x04000000) | ||
304 | output("Block Write : Busy\n"); | ||
305 | if (status & 0x02000000) | ||
306 | output("Command Buffer : Full\n"); | ||
307 | if (status & 0x01000000) | ||
308 | output("RESERVED : Busy\n"); | ||
309 | if (status & 0x00800000) | ||
310 | output("PCI Write Buffer : Busy\n"); | ||
311 | cyblafb_setup_GE(info->var.xres, | ||
312 | info->var.bits_per_pixel); | ||
313 | } | ||
314 | } | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | //============================== | ||
320 | // | ||
321 | // Cyberblade specific fillrect | ||
322 | // | ||
323 | //============================== | ||
324 | |||
325 | static void cyblafb_fillrect(struct fb_info *info, const struct fb_fillrect *fr) | ||
326 | { | ||
327 | u32 bpp = info->var.bits_per_pixel, col, desty, height; | ||
328 | |||
329 | KD_GRAPHICS_RETURN(); | ||
330 | |||
331 | switch (bpp) { | ||
332 | default: | ||
333 | case 8: | ||
334 | col = fr->color; | ||
335 | col |= col << 8; | ||
336 | col |= col << 16; | ||
337 | break; | ||
338 | case 16: | ||
339 | col = ((u32 *) (info->pseudo_palette))[fr->color]; | ||
340 | col |= col << 16; | ||
341 | break; | ||
342 | case 32: | ||
343 | col = ((u32 *) (info->pseudo_palette))[fr->color]; | ||
344 | break; | ||
345 | } | ||
346 | |||
347 | desty = fr->dy; | ||
348 | height = fr->height; | ||
349 | while (height) { | ||
350 | out32(GEB8, basestride | ((desty * info->var.xres_virtual * | ||
351 | bpp) >> 6)); | ||
352 | out32(GE60, col); | ||
353 | out32(GE48, fr->rop ? 0x66 : ROP_S); | ||
354 | out32(GE44, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2); | ||
355 | out32(GE08, point(fr->dx, 0)); | ||
356 | out32(GE0C, point(fr->dx + fr->width - 1, | ||
357 | height > 4096 ? 4095 : height - 1)); | ||
358 | if (likely(height <= 4096)) | ||
359 | return; | ||
360 | desty += 4096; | ||
361 | height -= 4096; | ||
362 | } | ||
363 | } | ||
364 | |||
365 | //================================================ | ||
366 | // | ||
367 | // Cyberblade specific copyarea | ||
368 | // | ||
369 | // This function silently assumes that it never | ||
370 | // will be called with width or height exceeding | ||
371 | // 4096. | ||
372 | // | ||
373 | //================================================ | ||
374 | |||
375 | static void cyblafb_copyarea(struct fb_info *info, const struct fb_copyarea *ca) | ||
376 | { | ||
377 | u32 s1, s2, d1, d2, direction; | ||
378 | |||
379 | KD_GRAPHICS_RETURN(); | ||
380 | |||
381 | s1 = point(ca->sx, 0); | ||
382 | s2 = point(ca->sx + ca->width - 1, ca->height - 1); | ||
383 | d1 = point(ca->dx, 0); | ||
384 | d2 = point(ca->dx + ca->width - 1, ca->height - 1); | ||
385 | |||
386 | if ((ca->sy > ca->dy) || ((ca->sy == ca->dy) && (ca->sx > ca->dx))) | ||
387 | direction = 0; | ||
388 | else | ||
389 | direction = 2; | ||
390 | |||
391 | out32(GEB8, basestride | ((ca->dy * info->var.xres_virtual * | ||
392 | info->var.bits_per_pixel) >> 6)); | ||
393 | out32(GEC8, basestride | ((ca->sy * info->var.xres_virtual * | ||
394 | info->var.bits_per_pixel) >> 6)); | ||
395 | out32(GE44, 0xa0000000 | 1 << 19 | 1 << 2 | direction); | ||
396 | out32(GE00, direction ? s2 : s1); | ||
397 | out32(GE04, direction ? s1 : s2); | ||
398 | out32(GE08, direction ? d2 : d1); | ||
399 | out32(GE0C, direction ? d1 : d2); | ||
400 | } | ||
401 | |||
402 | //======================================================================= | ||
403 | // | ||
404 | // Cyberblade specific imageblit | ||
405 | // | ||
406 | // Accelerated for the most usual case, blitting 1 - bit deep | ||
407 | // character images. Everything else is passed to the generic imageblit | ||
408 | // unless it is so insane that it is better to printk an alert. | ||
409 | // | ||
410 | // Hardware bug: _Never_ blit across pixel column 2048, that will lock | ||
411 | // the system. We split those blit requests into three blitting | ||
412 | // operations. | ||
413 | // | ||
414 | //======================================================================= | ||
415 | |||
416 | static void cyblafb_imageblit(struct fb_info *info, | ||
417 | const struct fb_image *image) | ||
418 | { | ||
419 | u32 fgcol, bgcol; | ||
420 | u32 *pd = (u32 *) image->data; | ||
421 | u32 bpp = info->var.bits_per_pixel; | ||
422 | |||
423 | KD_GRAPHICS_RETURN(); | ||
424 | |||
425 | // Used only for drawing the penguine (image->depth > 1) | ||
426 | if (image->depth != 1) { | ||
427 | cfb_imageblit(info, image); | ||
428 | return; | ||
429 | } | ||
430 | // That should never happen, but it would be fatal | ||
431 | if (image->width == 0 || image->height == 0) { | ||
432 | output("imageblit: width/height 0 detected\n"); | ||
433 | return; | ||
434 | } | ||
435 | |||
436 | if (info->fix.visual == FB_VISUAL_TRUECOLOR || | ||
437 | info->fix.visual == FB_VISUAL_DIRECTCOLOR) { | ||
438 | fgcol = ((u32 *) (info->pseudo_palette))[image->fg_color]; | ||
439 | bgcol = ((u32 *) (info->pseudo_palette))[image->bg_color]; | ||
440 | } else { | ||
441 | fgcol = image->fg_color; | ||
442 | bgcol = image->bg_color; | ||
443 | } | ||
444 | |||
445 | switch (bpp) { | ||
446 | case 8: | ||
447 | fgcol |= fgcol << 8; | ||
448 | bgcol |= bgcol << 8; | ||
449 | case 16: | ||
450 | fgcol |= fgcol << 16; | ||
451 | bgcol |= bgcol << 16; | ||
452 | default: | ||
453 | break; | ||
454 | } | ||
455 | |||
456 | out32(GEB8, basestride | ((image->dy * info->var.xres_virtual * | ||
457 | bpp) >> 6)); | ||
458 | out32(GE60, fgcol); | ||
459 | out32(GE64, bgcol); | ||
460 | |||
461 | if (!(image->dx < 2048 && (image->dx + image->width - 1) >= 2048)) { | ||
462 | u32 dds = ((image->width + 31) >> 5) * image->height; | ||
463 | out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); | ||
464 | out32(GE08, point(image->dx, 0)); | ||
465 | out32(GE0C, point(image->dx + image->width - 1, | ||
466 | image->height - 1)); | ||
467 | while (dds--) | ||
468 | out32(GE9C, *pd++); | ||
469 | } else { | ||
470 | int i, j; | ||
471 | u32 ddstotal = (image->width + 31) >> 5; | ||
472 | u32 ddsleft = (2048 - image->dx + 31) >> 5; | ||
473 | u32 skipleft = ddstotal - ddsleft; | ||
474 | |||
475 | out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); | ||
476 | out32(GE08, point(image->dx, 0)); | ||
477 | out32(GE0C, point(2048 - 1, image->height - 1)); | ||
478 | for (i = 0; i < image->height; i++) { | ||
479 | for (j = 0; j < ddsleft; j++) | ||
480 | out32(GE9C, *pd++); | ||
481 | pd += skipleft; | ||
482 | } | ||
483 | |||
484 | if (image->dx % 32) { | ||
485 | out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); | ||
486 | out32(GE08, point(2048, 0)); | ||
487 | if (image->width > ddsleft << 5) | ||
488 | out32(GE0C, point(image->dx + (ddsleft << 5) - | ||
489 | 1, image->height - 1)); | ||
490 | else | ||
491 | out32(GE0C, point(image->dx + image->width - 1, | ||
492 | image->height - 1)); | ||
493 | pd = ((u32 *) image->data) + ddstotal - skipleft - 1; | ||
494 | for (i = 0; i < image->height; i++) { | ||
495 | out32(GE9C, swab32(swab32(*pd) << ((32 - | ||
496 | (image->dx & 31)) & 31))); | ||
497 | pd += ddstotal; | ||
498 | } | ||
499 | } | ||
500 | |||
501 | if (skipleft) { | ||
502 | out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19); | ||
503 | out32(GE08, point(image->dx + (ddsleft << 5), 0)); | ||
504 | out32(GE0C, point(image->dx + image->width - 1, | ||
505 | image->height - 1)); | ||
506 | pd = (u32 *) image->data; | ||
507 | for (i = 0; i < image->height; i++) { | ||
508 | pd += ddsleft; | ||
509 | for (j = 0; j < skipleft; j++) | ||
510 | out32(GE9C, *pd++); | ||
511 | } | ||
512 | } | ||
513 | } | ||
514 | } | ||
515 | |||
516 | //========================================================== | ||
517 | // | ||
518 | // Check if video mode is acceptable. We change var->??? if | ||
519 | // video mode is slightly off or return error otherwise. | ||
520 | // info->??? must not be changed! | ||
521 | // | ||
522 | //========================================================== | ||
523 | |||
524 | static int cyblafb_check_var(struct fb_var_screeninfo *var, | ||
525 | struct fb_info *info) | ||
526 | { | ||
527 | int bpp = var->bits_per_pixel; | ||
528 | |||
529 | // | ||
530 | // we try to support 8, 16, 24 and 32 bpp modes, | ||
531 | // default to 8 | ||
532 | // | ||
533 | // there is a 24 bpp mode, but for now we change requests to 32 bpp | ||
534 | // (This is what tridentfb does ... will be changed in the future) | ||
535 | // | ||
536 | // | ||
537 | if (bpp % 8 != 0 || bpp < 8 || bpp > 32) | ||
538 | bpp = 8; | ||
539 | if (bpp == 24) | ||
540 | bpp = var->bits_per_pixel = 32; | ||
541 | |||
542 | // | ||
543 | // interlaced modes are broken, fail if one is requested | ||
544 | // | ||
545 | if (var->vmode & FB_VMODE_INTERLACED) | ||
546 | return -EINVAL; | ||
547 | |||
548 | // | ||
549 | // fail if requested resolution is higher than physical | ||
550 | // flatpanel resolution | ||
551 | // | ||
552 | if ((displaytype == DISPLAY_FP) && nativex && var->xres > nativex) | ||
553 | return -EINVAL; | ||
554 | |||
555 | // | ||
556 | // we do not allow vclk to exceed 230 MHz. If the requested | ||
557 | // vclk is too high, we default to 200 MHz | ||
558 | // | ||
559 | if ((bpp == 32 ? 200000000 : 100000000) / var->pixclock > 23000) | ||
560 | var->pixclock = (bpp == 32 ? 200000000 : 100000000) / 20000; | ||
561 | |||
562 | // | ||
563 | // enforce (h|v)sync_len limits | ||
564 | // | ||
565 | var->hsync_len &= ~7; | ||
566 | if(var->hsync_len > 248) | ||
567 | var->hsync_len = 248; | ||
568 | |||
569 | var->vsync_len &= 15; | ||
570 | |||
571 | // | ||
572 | // Enforce horizontal and vertical hardware limits. | ||
573 | // 1600x1200 is mentioned as a maximum, but higher resolutions could | ||
574 | // work with slow refresh, small margins and short sync. | ||
575 | // | ||
576 | var->xres &= ~7; | ||
577 | |||
578 | if (((var->xres + var->left_margin + var->right_margin + | ||
579 | var->hsync_len) > (bpp == 32 ? 2040 : 4088)) || | ||
580 | ((var->yres + var->upper_margin + var->lower_margin + | ||
581 | var->vsync_len) > 2047)) | ||
582 | return -EINVAL; | ||
583 | |||
584 | if ((var->xres > 1600) || (var->yres > 1200)) | ||
585 | output("Mode %dx%d exceeds documented limits.\n", | ||
586 | var->xres, var->yres); | ||
587 | // | ||
588 | // try to be smart about (x|y)res_virtual problems. | ||
589 | // | ||
590 | if (var->xres > var->xres_virtual) | ||
591 | var->xres_virtual = var->xres; | ||
592 | if (var->yres > var->yres_virtual) | ||
593 | var->yres_virtual = var->yres; | ||
594 | |||
595 | if (bpp == 8 || bpp == 16) { | ||
596 | if (var->xres_virtual > 4088) | ||
597 | var->xres_virtual = 4088; | ||
598 | } else { | ||
599 | if (var->xres_virtual > 2040) | ||
600 | var->xres_virtual = 2040; | ||
601 | } | ||
602 | var->xres_virtual &= ~7; | ||
603 | while (var->xres_virtual * var->yres_virtual * bpp / 8 > | ||
604 | info->fix.smem_len) { | ||
605 | if (var->yres_virtual > var->yres) | ||
606 | var->yres_virtual--; | ||
607 | else if (var->xres_virtual > var->xres) | ||
608 | var->xres_virtual -= 8; | ||
609 | else | ||
610 | return -EINVAL; | ||
611 | } | ||
612 | |||
613 | switch (bpp) { | ||
614 | case 8: | ||
615 | var->red.offset = 0; | ||
616 | var->green.offset = 0; | ||
617 | var->blue.offset = 0; | ||
618 | var->red.length = 6; | ||
619 | var->green.length = 6; | ||
620 | var->blue.length = 6; | ||
621 | break; | ||
622 | case 16: | ||
623 | var->red.offset = 11; | ||
624 | var->green.offset = 5; | ||
625 | var->blue.offset = 0; | ||
626 | var->red.length = 5; | ||
627 | var->green.length = 6; | ||
628 | var->blue.length = 5; | ||
629 | break; | ||
630 | case 32: | ||
631 | var->red.offset = 16; | ||
632 | var->green.offset = 8; | ||
633 | var->blue.offset = 0; | ||
634 | var->red.length = 8; | ||
635 | var->green.length = 8; | ||
636 | var->blue.length = 8; | ||
637 | break; | ||
638 | default: | ||
639 | return -EINVAL; | ||
640 | } | ||
641 | |||
642 | return 0; | ||
643 | } | ||
644 | |||
645 | //===================================================================== | ||
646 | // | ||
647 | // Pan the display | ||
648 | // | ||
649 | // The datasheets defines crt start address to be 20 bits wide and | ||
650 | // to be programmed to CR0C, CR0D, CR1E and CR27. Actually there is | ||
651 | // CR2B[5] as an undocumented extension bit. Epia BIOS 2.07 does use | ||
652 | // it, so it is also safe to be used here. BTW: datasheet CR0E on page | ||
653 | // 90 really is CR1E, the real CRE is documented on page 72. | ||
654 | // | ||
655 | // BUT: | ||
656 | // | ||
657 | // As of internal version 0.60 we do not use vga panning any longer. | ||
658 | // Vga panning did not allow us the use of all available video memory | ||
659 | // and thus prevented ywrap scrolling. We do use the "right view" | ||
660 | // register now. | ||
661 | // | ||
662 | // | ||
663 | //===================================================================== | ||
664 | |||
665 | static int cyblafb_pan_display(struct fb_var_screeninfo *var, | ||
666 | struct fb_info *info) | ||
667 | { | ||
668 | KD_GRAPHICS_RETURN(0); | ||
669 | |||
670 | info->var.xoffset = var->xoffset; | ||
671 | info->var.yoffset = var->yoffset; | ||
672 | out32(GE10, 0x80000000 | ((var->xoffset + (var->yoffset * | ||
673 | var->xres_virtual)) * var->bits_per_pixel / 32)); | ||
674 | return 0; | ||
675 | } | ||
676 | |||
677 | //============================================ | ||
678 | // | ||
679 | // This will really help in case of a bug ... | ||
680 | // dump most gaphics core registers. | ||
681 | // | ||
682 | //============================================ | ||
683 | |||
684 | static void regdump(struct cyblafb_par *par) | ||
685 | { | ||
686 | int i; | ||
687 | |||
688 | if (verbosity < 2) | ||
689 | return; | ||
690 | |||
691 | printk("\n"); | ||
692 | for (i = 0; i <= 0xff; i++) { | ||
693 | outb(i, 0x3d4); | ||
694 | printk("CR%02x=%02x ", i, inb(0x3d5)); | ||
695 | if (i % 16 == 15) | ||
696 | printk("\n"); | ||
697 | } | ||
698 | |||
699 | outb(0x30, 0x3ce); | ||
700 | outb(inb(0x3cf) | 0x40, 0x3cf); | ||
701 | for (i = 0; i <= 0x1f; i++) { | ||
702 | if (i == 0 || (i > 2 && i < 8) || i == 0x10 || i == 0x11 | ||
703 | || i == 0x16) { | ||
704 | outb(i, 0x3d4); | ||
705 | printk("CR%02x=%02x ", i, inb(0x3d5)); | ||
706 | } else | ||
707 | printk("------- "); | ||
708 | if (i % 16 == 15) | ||
709 | printk("\n"); | ||
710 | } | ||
711 | outb(0x30, 0x3ce); | ||
712 | outb(inb(0x3cf) & 0xbf, 0x3cf); | ||
713 | |||
714 | printk("\n"); | ||
715 | for (i = 0; i <= 0x7f; i++) { | ||
716 | outb(i, 0x3ce); | ||
717 | printk("GR%02x=%02x ", i, inb(0x3cf)); | ||
718 | if (i % 16 == 15) | ||
719 | printk("\n"); | ||
720 | } | ||
721 | |||
722 | printk("\n"); | ||
723 | for (i = 0; i <= 0xff; i++) { | ||
724 | outb(i, 0x3c4); | ||
725 | printk("SR%02x=%02x ", i, inb(0x3c5)); | ||
726 | if (i % 16 == 15) | ||
727 | printk("\n"); | ||
728 | } | ||
729 | |||
730 | printk("\n"); | ||
731 | for (i = 0; i <= 0x1F; i++) { | ||
732 | inb(0x3da); // next access is index! | ||
733 | outb(i, 0x3c0); | ||
734 | printk("AR%02x=%02x ", i, inb(0x3c1)); | ||
735 | if (i % 16 == 15) | ||
736 | printk("\n"); | ||
737 | } | ||
738 | printk("\n"); | ||
739 | |||
740 | inb(0x3DA); // reset internal flag to 3c0 index | ||
741 | outb(0x20, 0x3C0); // enable attr | ||
742 | |||
743 | return; | ||
744 | } | ||
745 | |||
746 | //======================================================================= | ||
747 | // | ||
748 | // Save State | ||
749 | // | ||
750 | // This function is called while a switch to KD_TEXT is in progress, | ||
751 | // before any of the other functions are called. | ||
752 | // | ||
753 | //======================================================================= | ||
754 | |||
755 | static void cyblafb_save_state(struct fb_info *info) | ||
756 | { | ||
757 | struct cyblafb_par *par = info->par; | ||
758 | if (verbosity > 0) | ||
759 | output("Switching to KD_TEXT\n"); | ||
760 | disabled = 0; | ||
761 | regdump(par); | ||
762 | enable_mmio(); | ||
763 | return; | ||
764 | } | ||
765 | |||
766 | //======================================================================= | ||
767 | // | ||
768 | // Restore State | ||
769 | // | ||
770 | // This function is called while a switch to KD_GRAPHICS is in progress, | ||
771 | // We have to turn on vga style panning registers again because the | ||
772 | // trident driver of X does not know about GE10. | ||
773 | // | ||
774 | //======================================================================= | ||
775 | |||
776 | static void cyblafb_restore_state(struct fb_info *info) | ||
777 | { | ||
778 | if (verbosity > 0) | ||
779 | output("Switching to KD_GRAPHICS\n"); | ||
780 | out32(GE10, 0); | ||
781 | disabled = 1; | ||
782 | return; | ||
783 | } | ||
784 | |||
785 | //====================================== | ||
786 | // | ||
787 | // Set hardware to requested video mode | ||
788 | // | ||
789 | //====================================== | ||
790 | |||
791 | static int cyblafb_set_par(struct fb_info *info) | ||
792 | { | ||
793 | struct cyblafb_par *par = info->par; | ||
794 | u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, | ||
795 | hblankend, preendfetch, vtotal, vdispend, vsyncstart, | ||
796 | vsyncend, vblankstart, vblankend; | ||
797 | struct fb_var_screeninfo *var = &info->var; | ||
798 | int bpp = var->bits_per_pixel; | ||
799 | int i; | ||
800 | |||
801 | KD_GRAPHICS_RETURN(0); | ||
802 | |||
803 | if (verbosity > 0) | ||
804 | output("Switching to new mode: " | ||
805 | "fbset -g %d %d %d %d %d -t %d %d %d %d %d %d %d\n", | ||
806 | var->xres, var->yres, var->xres_virtual, | ||
807 | var->yres_virtual, var->bits_per_pixel, var->pixclock, | ||
808 | var->left_margin, var->right_margin, var->upper_margin, | ||
809 | var->lower_margin, var->hsync_len, var->vsync_len); | ||
810 | |||
811 | htotal = (var->xres + var->left_margin + var->right_margin + | ||
812 | var->hsync_len) / 8 - 5; | ||
813 | hdispend = var->xres / 8 - 1; | ||
814 | hsyncstart = (var->xres + var->right_margin) / 8; | ||
815 | hsyncend = var->hsync_len / 8; | ||
816 | hblankstart = hdispend + 1; | ||
817 | hblankend = htotal + 3; // should be htotal + 5, bios does it this way | ||
818 | preendfetch = ((var->xres >> 3) + 1) * ((bpp + 1) >> 3); | ||
819 | |||
820 | vtotal = var->yres + var->upper_margin + var->lower_margin + | ||
821 | var->vsync_len - 2; | ||
822 | vdispend = var->yres - 1; | ||
823 | vsyncstart = var->yres + var->lower_margin; | ||
824 | vblankstart = var->yres; | ||
825 | vblankend = vtotal; // should be vtotal + 2, but bios does it this way | ||
826 | vsyncend = var->vsync_len; | ||
827 | |||
828 | enable_mmio(); // necessary! ... check X ... | ||
829 | |||
830 | write3X4(CR11, read3X4(CR11) & 0x7F); // unlock cr00 .. cr07 | ||
831 | |||
832 | write3CE(GR30, 8); | ||
833 | |||
834 | if ((displaytype == DISPLAY_FP) && var->xres < nativex) { | ||
835 | |||
836 | // stretch or center ? | ||
837 | |||
838 | out8(0x3C2, 0xEB); | ||
839 | |||
840 | write3CE(GR30, read3CE(GR30) | 0x81); // shadow mode on | ||
841 | |||
842 | if (center) { | ||
843 | write3CE(GR52, (read3CE(GR52) & 0x7C) | 0x80); | ||
844 | write3CE(GR53, (read3CE(GR53) & 0x7C) | 0x80); | ||
845 | } else if (stretch) { | ||
846 | write3CE(GR5D, 0); | ||
847 | write3CE(GR52, (read3CE(GR52) & 0x7C) | 1); | ||
848 | write3CE(GR53, (read3CE(GR53) & 0x7C) | 1); | ||
849 | } | ||
850 | |||
851 | } else { | ||
852 | out8(0x3C2, 0x2B); | ||
853 | write3CE(GR30, 8); | ||
854 | } | ||
855 | |||
856 | // | ||
857 | // Setup CRxx regs | ||
858 | // | ||
859 | |||
860 | write3X4(CR00, htotal & 0xFF); | ||
861 | write3X4(CR01, hdispend & 0xFF); | ||
862 | write3X4(CR02, hblankstart & 0xFF); | ||
863 | write3X4(CR03, hblankend & 0x1F); | ||
864 | write3X4(CR04, hsyncstart & 0xFF); | ||
865 | write3X4(CR05, (hsyncend & 0x1F) | ((hblankend & 0x20) << 2)); | ||
866 | write3X4(CR06, vtotal & 0xFF); | ||
867 | write3X4(CR07, (vtotal & 0x100) >> 8 | | ||
868 | (vdispend & 0x100) >> 7 | | ||
869 | (vsyncstart & 0x100) >> 6 | | ||
870 | (vblankstart & 0x100) >> 5 | | ||
871 | 0x10 | | ||
872 | (vtotal & 0x200) >> 4 | | ||
873 | (vdispend & 0x200) >> 3 | (vsyncstart & 0x200) >> 2); | ||
874 | write3X4(CR08, 0); | ||
875 | write3X4(CR09, (vblankstart & 0x200) >> 4 | 0x40 | // FIX !!! | ||
876 | ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0)); | ||
877 | write3X4(CR0A, 0); // Init to some reasonable default | ||
878 | write3X4(CR0B, 0); // Init to some reasonable default | ||
879 | write3X4(CR0C, 0); // Offset 0 | ||
880 | write3X4(CR0D, 0); // Offset 0 | ||
881 | write3X4(CR0E, 0); // Init to some reasonable default | ||
882 | write3X4(CR0F, 0); // Init to some reasonable default | ||
883 | write3X4(CR10, vsyncstart & 0xFF); | ||
884 | write3X4(CR11, (vsyncend & 0x0F)); | ||
885 | write3X4(CR12, vdispend & 0xFF); | ||
886 | write3X4(CR13, ((info->var.xres_virtual * bpp) / (4 * 16)) & 0xFF); | ||
887 | write3X4(CR14, 0x40); // double word mode | ||
888 | write3X4(CR15, vblankstart & 0xFF); | ||
889 | write3X4(CR16, vblankend & 0xFF); | ||
890 | write3X4(CR17, 0xE3); | ||
891 | write3X4(CR18, 0xFF); | ||
892 | // CR19: needed for interlaced modes ... ignore it for now | ||
893 | write3X4(CR1A, 0x07); // Arbitration Control Counter 1 | ||
894 | write3X4(CR1B, 0x07); // Arbitration Control Counter 2 | ||
895 | write3X4(CR1C, 0x07); // Arbitration Control Counter 3 | ||
896 | write3X4(CR1D, 0x00); // Don't know, doesn't hurt ; -) | ||
897 | write3X4(CR1E, (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80); | ||
898 | // CR1F: do not set, contains BIOS info about memsize | ||
899 | write3X4(CR20, 0x20); // enabe wr buf, disable 16bit planar mode | ||
900 | write3X4(CR21, 0x20); // enable linear memory access | ||
901 | // CR22: RO cpu latch readback | ||
902 | // CR23: ??? | ||
903 | // CR24: RO AR flag state | ||
904 | // CR25: RAMDAC rw timing, pclk buffer tristate control ???? | ||
905 | // CR26: ??? | ||
906 | write3X4(CR27, (vdispend & 0x400) >> 6 | | ||
907 | (vsyncstart & 0x400) >> 5 | | ||
908 | (vblankstart & 0x400) >> 4 | | ||
909 | (vtotal & 0x400) >> 3 | | ||
910 | 0x8); | ||
911 | // CR28: ??? | ||
912 | write3X4(CR29, (read3X4(CR29) & 0xCF) | ((((info->var.xres_virtual * | ||
913 | bpp) / (4 * 16)) & 0x300) >> 4)); | ||
914 | write3X4(CR2A, read3X4(CR2A) | 0x40); | ||
915 | write3X4(CR2B, (htotal & 0x100) >> 8 | | ||
916 | (hdispend & 0x100) >> 7 | | ||
917 | // (0x00 & 0x100) >> 6 | hinterlace para bit 8 ??? | ||
918 | (hsyncstart & 0x100) >> 5 | | ||
919 | (hblankstart & 0x100) >> 4); | ||
920 | // CR2C: ??? | ||
921 | // CR2D: initialized in cyblafb_setup_GE() | ||
922 | write3X4(CR2F, 0x92); // conservative, better signal quality | ||
923 | // CR30: reserved | ||
924 | // CR31: reserved | ||
925 | // CR32: reserved | ||
926 | // CR33: reserved | ||
927 | // CR34: disabled in CR36 | ||
928 | // CR35: disabled in CR36 | ||
929 | // CR36: initialized in cyblafb_setup_GE | ||
930 | // CR37: i2c, ignore for now | ||
931 | write3X4(CR38, (bpp == 8) ? 0x00 : // | ||
932 | (bpp == 16) ? 0x05 : // highcolor | ||
933 | (bpp == 24) ? 0x29 : // packed 24bit truecolor | ||
934 | (bpp == 32) ? 0x09 : 0); // truecolor, 16 bit pixelbus | ||
935 | write3X4(CR39, 0x01 | // MMIO enable | ||
936 | (pcirb ? 0x02 : 0) | // pci read burst enable | ||
937 | (pciwb ? 0x04 : 0)); // pci write burst enable | ||
938 | write3X4(CR55, 0x1F | // pci clocks * 2 for STOP# during 1st data phase | ||
939 | (pcirr ? 0x40 : 0) | // pci read retry enable | ||
940 | (pciwr ? 0x80 : 0)); // pci write retry enable | ||
941 | write3X4(CR56, preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01) | 2 | ||
942 | : 0); | ||
943 | write3X4(CR57, preendfetch >> 8 < 2 ? preendfetch & 0xff : 0); | ||
944 | write3X4(CR58, 0x82); // Bios does this .... don't know more | ||
945 | // | ||
946 | // Setup SRxx regs | ||
947 | // | ||
948 | write3C4(SR00, 3); | ||
949 | write3C4(SR01, 1); //set char clock 8 dots wide | ||
950 | write3C4(SR02, 0x0F); //enable 4 maps needed in chain4 mode | ||
951 | write3C4(SR03, 0); //no character map select | ||
952 | write3C4(SR04, 0x0E); //memory mode: ext mem, even, chain4 | ||
953 | |||
954 | out8(0x3C4, 0x0b); | ||
955 | in8(0x3C5); // Set NEW mode | ||
956 | write3C4(SR0D, 0x00); // test ... check | ||
957 | |||
958 | set_vclk(par, (bpp == 32 ? 200000000 : 100000000) | ||
959 | / info->var.pixclock); //SR18, SR19 | ||
960 | |||
961 | // | ||
962 | // Setup GRxx regs | ||
963 | // | ||
964 | write3CE(GR00, 0x00); // test ... check | ||
965 | write3CE(GR01, 0x00); // test ... check | ||
966 | write3CE(GR02, 0x00); // test ... check | ||
967 | write3CE(GR03, 0x00); // test ... check | ||
968 | write3CE(GR04, 0x00); // test ... check | ||
969 | write3CE(GR05, 0x40); // no CGA compat, allow 256 col | ||
970 | write3CE(GR06, 0x05); // graphics mode | ||
971 | write3CE(GR07, 0x0F); // planes? | ||
972 | write3CE(GR08, 0xFF); // test ... check | ||
973 | write3CE(GR0F, (bpp == 32) ? 0x1A : 0x12); // vclk / 2 if 32bpp, chain4 | ||
974 | write3CE(GR20, 0xC0); // test ... check | ||
975 | write3CE(GR2F, 0xA0); // PCLK = VCLK, no skew, | ||
976 | |||
977 | // | ||
978 | // Setup ARxx regs | ||
979 | // | ||
980 | for (i = 0; i < 0x10; i++) // set AR00 .. AR0f | ||
981 | write3C0(i, i); | ||
982 | write3C0(AR10, 0x41); // graphics mode and support 256 color modes | ||
983 | write3C0(AR12, 0x0F); // planes | ||
984 | write3C0(AR13, 0); // horizontal pel panning | ||
985 | in8(0x3DA); // reset internal flag to 3c0 index | ||
986 | out8(0x3C0, 0x20); // enable attr | ||
987 | |||
988 | // | ||
989 | // Setup hidden RAMDAC command register | ||
990 | // | ||
991 | in8(0x3C8); // these reads are | ||
992 | in8(0x3C6); // necessary to | ||
993 | in8(0x3C6); // unmask the RAMDAC | ||
994 | in8(0x3C6); // command reg, otherwise | ||
995 | in8(0x3C6); // we would write the pixelmask reg! | ||
996 | out8(0x3C6, (bpp == 8) ? 0x00 : // 256 colors | ||
997 | (bpp == 15) ? 0x10 : // | ||
998 | (bpp == 16) ? 0x30 : // hicolor | ||
999 | (bpp == 24) ? 0xD0 : // truecolor | ||
1000 | (bpp == 32) ? 0xD0 : 0); // truecolor | ||
1001 | in8(0x3C8); | ||
1002 | |||
1003 | // | ||
1004 | // GR31 is not mentioned in the datasheet | ||
1005 | // | ||
1006 | if (displaytype == DISPLAY_FP) | ||
1007 | write3CE(GR31, (read3CE(GR31) & 0x8F) | | ||
1008 | ((info->var.yres > 1024) ? 0x50 : | ||
1009 | (info->var.yres > 768) ? 0x30 : | ||
1010 | (info->var.yres > 600) ? 0x20 : | ||
1011 | (info->var.yres > 480) ? 0x10 : 0)); | ||
1012 | |||
1013 | info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR | ||
1014 | : FB_VISUAL_TRUECOLOR; | ||
1015 | info->fix.line_length = info->var.xres_virtual * (bpp >> 3); | ||
1016 | info->cmap.len = (bpp == 8) ? 256 : 16; | ||
1017 | |||
1018 | // | ||
1019 | // init acceleration engine | ||
1020 | // | ||
1021 | cyblafb_setup_GE(info->var.xres_virtual, info->var.bits_per_pixel); | ||
1022 | |||
1023 | // | ||
1024 | // Set/clear flags to allow proper scroll mode selection. | ||
1025 | // | ||
1026 | if (var->xres == var->xres_virtual) | ||
1027 | info->flags &= ~FBINFO_HWACCEL_XPAN; | ||
1028 | else | ||
1029 | info->flags |= FBINFO_HWACCEL_XPAN; | ||
1030 | |||
1031 | if (var->yres == var->yres_virtual) | ||
1032 | info->flags &= ~FBINFO_HWACCEL_YPAN; | ||
1033 | else | ||
1034 | info->flags |= FBINFO_HWACCEL_YPAN; | ||
1035 | |||
1036 | if (info->fix.smem_len != | ||
1037 | var->xres_virtual * var->yres_virtual * bpp / 8) | ||
1038 | info->flags &= ~FBINFO_HWACCEL_YWRAP; | ||
1039 | else | ||
1040 | info->flags |= FBINFO_HWACCEL_YWRAP; | ||
1041 | |||
1042 | regdump(par); | ||
1043 | |||
1044 | return 0; | ||
1045 | } | ||
1046 | |||
1047 | //======================== | ||
1048 | // | ||
1049 | // Set one color register | ||
1050 | // | ||
1051 | //======================== | ||
1052 | |||
1053 | static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
1054 | unsigned blue, unsigned transp, | ||
1055 | struct fb_info *info) | ||
1056 | { | ||
1057 | int bpp = info->var.bits_per_pixel; | ||
1058 | |||
1059 | KD_GRAPHICS_RETURN(0); | ||
1060 | |||
1061 | if (regno >= info->cmap.len) | ||
1062 | return 1; | ||
1063 | |||
1064 | if (bpp == 8) { | ||
1065 | out8(0x3C6, 0xFF); | ||
1066 | out8(0x3C8, regno); | ||
1067 | out8(0x3C9, red >> 10); | ||
1068 | out8(0x3C9, green >> 10); | ||
1069 | out8(0x3C9, blue >> 10); | ||
1070 | |||
1071 | } else if (regno < 16) { | ||
1072 | if (bpp == 16) // RGB 565 | ||
1073 | ((u32 *) info->pseudo_palette)[regno] = | ||
1074 | (red & 0xF800) | | ||
1075 | ((green & 0xFC00) >> 5) | | ||
1076 | ((blue & 0xF800) >> 11); | ||
1077 | else if (bpp == 32) // ARGB 8888 | ||
1078 | ((u32 *) info->pseudo_palette)[regno] = | ||
1079 | ((transp & 0xFF00) << 16) | | ||
1080 | ((red & 0xFF00) << 8) | | ||
1081 | ((green & 0xFF00)) | ((blue & 0xFF00) >> 8); | ||
1082 | } | ||
1083 | |||
1084 | return 0; | ||
1085 | } | ||
1086 | |||
1087 | //========================================================== | ||
1088 | // | ||
1089 | // Try blanking the screen. For flat panels it does nothing | ||
1090 | // | ||
1091 | //========================================================== | ||
1092 | |||
1093 | static int cyblafb_blank(int blank_mode, struct fb_info *info) | ||
1094 | { | ||
1095 | unsigned char PMCont, DPMSCont; | ||
1096 | |||
1097 | KD_GRAPHICS_RETURN(0); | ||
1098 | |||
1099 | if (displaytype == DISPLAY_FP) | ||
1100 | return 0; | ||
1101 | |||
1102 | out8(0x83C8, 0x04); // DPMS Control | ||
1103 | PMCont = in8(0x83C6) & 0xFC; | ||
1104 | |||
1105 | DPMSCont = read3CE(GR23) & 0xFC; | ||
1106 | |||
1107 | switch (blank_mode) { | ||
1108 | case FB_BLANK_UNBLANK: // Screen: On, HSync: On, VSync: On | ||
1109 | case FB_BLANK_NORMAL: // Screen: Off, HSync: On, VSync: On | ||
1110 | PMCont |= 0x03; | ||
1111 | DPMSCont |= 0x00; | ||
1112 | break; | ||
1113 | case FB_BLANK_HSYNC_SUSPEND: // Screen: Off, HSync: Off, VSync: On | ||
1114 | PMCont |= 0x02; | ||
1115 | DPMSCont |= 0x01; | ||
1116 | break; | ||
1117 | case FB_BLANK_VSYNC_SUSPEND: // Screen: Off, HSync: On, VSync: Off | ||
1118 | PMCont |= 0x02; | ||
1119 | DPMSCont |= 0x02; | ||
1120 | break; | ||
1121 | case FB_BLANK_POWERDOWN: // Screen: Off, HSync: Off, VSync: Off | ||
1122 | PMCont |= 0x00; | ||
1123 | DPMSCont |= 0x03; | ||
1124 | break; | ||
1125 | } | ||
1126 | |||
1127 | write3CE(GR23, DPMSCont); | ||
1128 | out8(0x83C8, 4); | ||
1129 | out8(0x83C6, PMCont); | ||
1130 | // | ||
1131 | // let fbcon do a softblank for us | ||
1132 | // | ||
1133 | return (blank_mode == FB_BLANK_NORMAL) ? 1 : 0; | ||
1134 | } | ||
1135 | |||
1136 | static struct fb_ops cyblafb_ops __devinitdata = { | ||
1137 | .owner = THIS_MODULE, | ||
1138 | .fb_setcolreg = cyblafb_setcolreg, | ||
1139 | .fb_pan_display = cyblafb_pan_display, | ||
1140 | .fb_blank = cyblafb_blank, | ||
1141 | .fb_check_var = cyblafb_check_var, | ||
1142 | .fb_set_par = cyblafb_set_par, | ||
1143 | .fb_fillrect = cyblafb_fillrect, | ||
1144 | .fb_copyarea = cyblafb_copyarea, | ||
1145 | .fb_imageblit = cyblafb_imageblit, | ||
1146 | .fb_sync = cyblafb_sync, | ||
1147 | .fb_restore_state = cyblafb_restore_state, | ||
1148 | .fb_save_state = cyblafb_save_state, | ||
1149 | }; | ||
1150 | |||
1151 | //========================================================================== | ||
1152 | // | ||
1153 | // getstartupmode() decides about the inital video mode | ||
1154 | // | ||
1155 | // There is no reason to use modedb, a lot of video modes there would | ||
1156 | // need altered timings to display correctly. So I decided that it is much | ||
1157 | // better to provide a limited optimized set of modes plus the option of | ||
1158 | // using the mode in effect at startup time (might be selected using the | ||
1159 | // vga=??? parameter). After that the user might use fbset to select any | ||
1160 | // mode he likes, check_var will not try to alter geometry parameters as | ||
1161 | // it would be necessary otherwise. | ||
1162 | // | ||
1163 | //========================================================================== | ||
1164 | |||
1165 | static int __devinit getstartupmode(struct fb_info *info) | ||
1166 | { | ||
1167 | u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend, | ||
1168 | vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend, | ||
1169 | cr00, cr01, cr02, cr03, cr04, cr05, cr2b, | ||
1170 | cr06, cr07, cr09, cr10, cr11, cr12, cr15, cr16, cr27, | ||
1171 | cr38, sr0d, sr18, sr19, gr0f, fi, pxclkdiv, vclkdiv, tmp, i; | ||
1172 | |||
1173 | struct modus { | ||
1174 | int xres; int vxres; int yres; int vyres; | ||
1175 | int bpp; int pxclk; | ||
1176 | int left_margin; int right_margin; | ||
1177 | int upper_margin; int lower_margin; | ||
1178 | int hsync_len; int vsync_len; | ||
1179 | } modedb[5] = { | ||
1180 | { | ||
1181 | 0, 2048, 0, 4096, 0, 0, 0, 0, 0, 0, 0, 0}, { | ||
1182 | 640, 2048, 480, 4096, 0, 0, -40, 24, 17, 0, 216, 3}, { | ||
1183 | 800, 2048, 600, 4096, 0, 0, 96, 24, 14, 0, 136, 11}, { | ||
1184 | 1024, 2048, 768, 4096, 0, 0, 144, 24, 29, 0, 120, 3}, { | ||
1185 | 1280, 2048, 1024, 4096, 0, 0, 232, 16, 39, 0, 160, 3} | ||
1186 | }; | ||
1187 | |||
1188 | outb(0x00, 0x3d4); cr00 = inb(0x3d5); | ||
1189 | outb(0x01, 0x3d4); cr01 = inb(0x3d5); | ||
1190 | outb(0x02, 0x3d4); cr02 = inb(0x3d5); | ||
1191 | outb(0x03, 0x3d4); cr03 = inb(0x3d5); | ||
1192 | outb(0x04, 0x3d4); cr04 = inb(0x3d5); | ||
1193 | outb(0x05, 0x3d4); cr05 = inb(0x3d5); | ||
1194 | outb(0x06, 0x3d4); cr06 = inb(0x3d5); | ||
1195 | outb(0x07, 0x3d4); cr07 = inb(0x3d5); | ||
1196 | outb(0x09, 0x3d4); cr09 = inb(0x3d5); | ||
1197 | outb(0x10, 0x3d4); cr10 = inb(0x3d5); | ||
1198 | outb(0x11, 0x3d4); cr11 = inb(0x3d5); | ||
1199 | outb(0x12, 0x3d4); cr12 = inb(0x3d5); | ||
1200 | outb(0x15, 0x3d4); cr15 = inb(0x3d5); | ||
1201 | outb(0x16, 0x3d4); cr16 = inb(0x3d5); | ||
1202 | outb(0x27, 0x3d4); cr27 = inb(0x3d5); | ||
1203 | outb(0x2b, 0x3d4); cr2b = inb(0x3d5); | ||
1204 | outb(0x38, 0x3d4); cr38 = inb(0x3d5); | ||
1205 | |||
1206 | outb(0x0b, 0x3c4); | ||
1207 | inb(0x3c5); | ||
1208 | |||
1209 | outb(0x0d, 0x3c4); sr0d = inb(0x3c5); | ||
1210 | outb(0x18, 0x3c4); sr18 = inb(0x3c5); | ||
1211 | outb(0x19, 0x3c4); sr19 = inb(0x3c5); | ||
1212 | outb(0x0f, 0x3ce); gr0f = inb(0x3cf); | ||
1213 | |||
1214 | htotal = cr00 | (cr2b & 0x01) << 8; | ||
1215 | hdispend = cr01 | (cr2b & 0x02) << 7; | ||
1216 | hblankstart = cr02 | (cr2b & 0x10) << 4; | ||
1217 | hblankend = (cr03 & 0x1f) | (cr05 & 0x80) >> 2; | ||
1218 | hsyncstart = cr04 | (cr2b & 0x08) << 5; | ||
1219 | hsyncend = cr05 & 0x1f; | ||
1220 | |||
1221 | modedb[0].xres = hblankstart * 8; | ||
1222 | modedb[0].hsync_len = hsyncend * 8; | ||
1223 | modedb[0].right_margin = hsyncstart * 8 - modedb[0].xres; | ||
1224 | modedb[0].left_margin = (htotal + 5) * 8 - modedb[0].xres - | ||
1225 | modedb[0].right_margin - modedb[0].hsync_len; | ||
1226 | |||
1227 | vtotal = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4 | ||
1228 | | (cr27 & 0x80) << 3; | ||
1229 | vdispend = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3 | ||
1230 | | (cr27 & 0x10) << 6; | ||
1231 | vsyncstart = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2 | ||
1232 | | (cr27 & 0x20) << 5; | ||
1233 | vsyncend = cr11 & 0x0f; | ||
1234 | vblankstart = cr15 | (cr07 & 0x08) << 5 | (cr09 & 0x20) << 4 | ||
1235 | | (cr27 & 0x40) << 4; | ||
1236 | vblankend = cr16; | ||
1237 | |||
1238 | modedb[0].yres = vdispend + 1; | ||
1239 | modedb[0].vsync_len = vsyncend; | ||
1240 | modedb[0].lower_margin = vsyncstart - modedb[0].yres; | ||
1241 | modedb[0].upper_margin = vtotal - modedb[0].yres - | ||
1242 | modedb[0].lower_margin - modedb[0].vsync_len + 2; | ||
1243 | |||
1244 | tmp = cr38 & 0x3c; | ||
1245 | modedb[0].bpp = tmp == 0 ? 8 : tmp == 4 ? 16 : tmp == 28 ? 24 : | ||
1246 | tmp == 8 ? 32 : 8; | ||
1247 | |||
1248 | fi = ((5864727 * (sr18 + 8)) / | ||
1249 | (((sr19 & 0x3f) + 2) * (1 << ((sr19 & 0xc0) >> 6)))) >> 12; | ||
1250 | pxclkdiv = ((gr0f & 0x08) >> 3 | (gr0f & 0x40) >> 5) + 1; | ||
1251 | tmp = sr0d & 0x06; | ||
1252 | vclkdiv = tmp == 0 ? 2 : tmp == 2 ? 4 : tmp == 4 ? 8 : 3; // * 2 ! | ||
1253 | modedb[0].pxclk = ((100000000 * pxclkdiv * vclkdiv) >> 1) / fi; | ||
1254 | |||
1255 | if (verbosity > 0) | ||
1256 | output("detected startup mode: " | ||
1257 | "fbset -g %d %d %d ??? %d -t %d %d %d %d %d %d %d\n", | ||
1258 | modedb[0].xres, modedb[0].yres, modedb[0].xres, | ||
1259 | modedb[0].bpp, modedb[0].pxclk, modedb[0].left_margin, | ||
1260 | modedb[0].right_margin, modedb[0].upper_margin, | ||
1261 | modedb[0].lower_margin, modedb[0].hsync_len, | ||
1262 | modedb[0].vsync_len); | ||
1263 | |||
1264 | // | ||
1265 | // We use this goto target in case of a failed check_var. No, I really | ||
1266 | // do not want to do it in another way! | ||
1267 | // | ||
1268 | |||
1269 | tryagain: | ||
1270 | |||
1271 | i = (mode == NULL) ? 0 : | ||
1272 | !strncmp(mode, "640x480", 7) ? 1 : | ||
1273 | !strncmp(mode, "800x600", 7) ? 2 : | ||
1274 | !strncmp(mode, "1024x768", 8) ? 3 : | ||
1275 | !strncmp(mode, "1280x1024", 9) ? 4 : 0; | ||
1276 | |||
1277 | ref = (ref < 50) ? 50 : (ref > 85) ? 85 : ref; | ||
1278 | |||
1279 | if (i == 0) { | ||
1280 | info->var.pixclock = modedb[i].pxclk; | ||
1281 | info->var.bits_per_pixel = modedb[i].bpp; | ||
1282 | } else { | ||
1283 | info->var.pixclock = (100000000 / | ||
1284 | ((modedb[i].left_margin + | ||
1285 | modedb[i].xres + | ||
1286 | modedb[i].right_margin + | ||
1287 | modedb[i].hsync_len) * | ||
1288 | (modedb[i].upper_margin + | ||
1289 | modedb[i].yres + | ||
1290 | modedb[i].lower_margin + | ||
1291 | modedb[i].vsync_len) * ref / 10000)); | ||
1292 | info->var.bits_per_pixel = bpp; | ||
1293 | } | ||
1294 | |||
1295 | info->var.left_margin = modedb[i].left_margin; | ||
1296 | info->var.right_margin = modedb[i].right_margin; | ||
1297 | info->var.xres = modedb[i].xres; | ||
1298 | if (!(modedb[i].yres == 1280 && modedb[i].bpp == 32)) | ||
1299 | info->var.xres_virtual = modedb[i].vxres; | ||
1300 | else | ||
1301 | info->var.xres_virtual = modedb[i].xres; | ||
1302 | info->var.xoffset = 0; | ||
1303 | info->var.hsync_len = modedb[i].hsync_len; | ||
1304 | info->var.upper_margin = modedb[i].upper_margin; | ||
1305 | info->var.yres = modedb[i].yres; | ||
1306 | info->var.yres_virtual = modedb[i].vyres; | ||
1307 | info->var.yoffset = 0; | ||
1308 | info->var.lower_margin = modedb[i].lower_margin; | ||
1309 | info->var.vsync_len = modedb[i].vsync_len; | ||
1310 | info->var.sync = 0; | ||
1311 | info->var.vmode = FB_VMODE_NONINTERLACED; | ||
1312 | |||
1313 | if (cyblafb_check_var(&info->var, info)) { | ||
1314 | // 640x480 - 8@75 should really never fail. One case would | ||
1315 | // be fp == 1 and nativex < 640 ... give up then | ||
1316 | if (i == 1 && bpp == 8 && ref == 75) { | ||
1317 | output("Can't find a valid mode :-(\n"); | ||
1318 | return -EINVAL; | ||
1319 | } | ||
1320 | // Our detected mode is unlikely to fail. If it does, | ||
1321 | // try 640x480 - 8@75 ... | ||
1322 | if (i == 0) { | ||
1323 | mode = "640x480"; | ||
1324 | bpp = 8; | ||
1325 | ref = 75; | ||
1326 | output("Detected mode failed check_var! " | ||
1327 | "Trying 640x480 - 8@75\n"); | ||
1328 | goto tryagain; | ||
1329 | } | ||
1330 | // A specified video mode failed for some reason. | ||
1331 | // Try the startup mode first | ||
1332 | output("Specified mode '%s' failed check! " | ||
1333 | "Falling back to startup mode.\n", mode); | ||
1334 | mode = NULL; | ||
1335 | goto tryagain; | ||
1336 | } | ||
1337 | |||
1338 | return 0; | ||
1339 | } | ||
1340 | |||
1341 | //======================================================== | ||
1342 | // | ||
1343 | // Detect activated memory size. Undefined values require | ||
1344 | // memsize parameter. | ||
1345 | // | ||
1346 | //======================================================== | ||
1347 | |||
1348 | static unsigned int __devinit get_memsize(void) | ||
1349 | { | ||
1350 | unsigned char tmp; | ||
1351 | unsigned int k; | ||
1352 | |||
1353 | if (memsize) | ||
1354 | k = memsize * Kb; | ||
1355 | else { | ||
1356 | tmp = read3X4(CR1F) & 0x0F; | ||
1357 | switch (tmp) { | ||
1358 | case 0x03: | ||
1359 | k = 1 * 1024 * 1024; | ||
1360 | break; | ||
1361 | case 0x07: | ||
1362 | k = 2 * 1024 * 1024; | ||
1363 | break; | ||
1364 | case 0x0F: | ||
1365 | k = 4 * 1024 * 1024; | ||
1366 | break; | ||
1367 | case 0x04: | ||
1368 | k = 8 * 1024 * 1024; | ||
1369 | break; | ||
1370 | default: | ||
1371 | k = 1 * 1024 * 1024; | ||
1372 | output("Unknown memory size code %x in CR1F." | ||
1373 | " We default to 1 Mb for now, please" | ||
1374 | " do provide a memsize parameter!\n", tmp); | ||
1375 | } | ||
1376 | } | ||
1377 | |||
1378 | if (verbosity > 0) | ||
1379 | output("framebuffer size = %d Kb\n", k / Kb); | ||
1380 | return k; | ||
1381 | } | ||
1382 | |||
1383 | //========================================================= | ||
1384 | // | ||
1385 | // Detect if a flat panel monitor connected to the special | ||
1386 | // interface is active. Override is possible by fp and crt | ||
1387 | // parameters. | ||
1388 | // | ||
1389 | //========================================================= | ||
1390 | |||
1391 | static unsigned int __devinit get_displaytype(void) | ||
1392 | { | ||
1393 | if (fp) | ||
1394 | return DISPLAY_FP; | ||
1395 | if (crt) | ||
1396 | return DISPLAY_CRT; | ||
1397 | return (read3CE(GR33) & 0x10) ? DISPLAY_FP : DISPLAY_CRT; | ||
1398 | } | ||
1399 | |||
1400 | //===================================== | ||
1401 | // | ||
1402 | // Get native resolution of flat panel | ||
1403 | // | ||
1404 | //===================================== | ||
1405 | |||
1406 | static int __devinit get_nativex(void) | ||
1407 | { | ||
1408 | int x, y, tmp; | ||
1409 | |||
1410 | if (nativex) | ||
1411 | return nativex; | ||
1412 | |||
1413 | tmp = (read3CE(GR52) >> 4) & 3; | ||
1414 | |||
1415 | switch (tmp) { | ||
1416 | case 0: x = 1280; y = 1024; | ||
1417 | break; | ||
1418 | case 2: x = 1024; y = 768; | ||
1419 | break; | ||
1420 | case 3: x = 800; y = 600; | ||
1421 | break; | ||
1422 | case 4: x = 1400; y = 1050; | ||
1423 | break; | ||
1424 | case 1: | ||
1425 | default: | ||
1426 | x = 640; y = 480; | ||
1427 | break; | ||
1428 | } | ||
1429 | |||
1430 | if (verbosity > 0) | ||
1431 | output("%dx%d flat panel found\n", x, y); | ||
1432 | return x; | ||
1433 | } | ||
1434 | |||
1435 | static int __devinit cybla_pci_probe(struct pci_dev *dev, | ||
1436 | const struct pci_device_id *id) | ||
1437 | { | ||
1438 | struct fb_info *info; | ||
1439 | struct cyblafb_par *par; | ||
1440 | |||
1441 | info = framebuffer_alloc(sizeof(struct cyblafb_par), &dev->dev); | ||
1442 | if (!info) | ||
1443 | goto errout_alloc_info; | ||
1444 | |||
1445 | info->pixmap.addr = kzalloc(CYBLAFB_PIXMAPSIZE, GFP_KERNEL); | ||
1446 | if (!info->pixmap.addr) { | ||
1447 | output("allocation of pixmap buffer failed!\n"); | ||
1448 | goto errout_alloc_pixmap; | ||
1449 | } | ||
1450 | info->pixmap.size = CYBLAFB_PIXMAPSIZE - 4; | ||
1451 | info->pixmap.buf_align = 4; | ||
1452 | info->pixmap.access_align = 32; | ||
1453 | info->pixmap.flags = FB_PIXMAP_SYSTEM; | ||
1454 | info->pixmap.scan_align = 4; | ||
1455 | |||
1456 | par = info->par; | ||
1457 | par->ops = cyblafb_ops; | ||
1458 | |||
1459 | info->fix = cyblafb_fix; | ||
1460 | info->fbops = &par->ops; | ||
1461 | info->fix = cyblafb_fix; | ||
1462 | |||
1463 | if (pci_enable_device(dev)) { | ||
1464 | output("could not enable device!\n"); | ||
1465 | goto errout_enable; | ||
1466 | } | ||
1467 | // might already be requested by vga console or vesafb, | ||
1468 | // so we do care about success | ||
1469 | if (!request_region(0x3c0, 0x20, "cyblafb")) { | ||
1470 | output("region 0x3c0/0x20 already reserved\n"); | ||
1471 | vesafb |= 1; | ||
1472 | |||
1473 | } | ||
1474 | // | ||
1475 | // Graphics Engine Registers | ||
1476 | // | ||
1477 | if (!request_region(GEBase, 0x100, "cyblafb")) { | ||
1478 | output("region %#x/0x100 already reserved\n", GEBase); | ||
1479 | vesafb |= 2; | ||
1480 | } | ||
1481 | |||
1482 | regdump(par); | ||
1483 | |||
1484 | enable_mmio(); | ||
1485 | |||
1486 | // setup MMIO region | ||
1487 | info->fix.mmio_start = pci_resource_start(dev, 1); | ||
1488 | info->fix.mmio_len = 0x20000; | ||
1489 | |||
1490 | if (!request_mem_region(info->fix.mmio_start, | ||
1491 | info->fix.mmio_len, "cyblafb")) { | ||
1492 | output("request_mem_region failed for mmio region!\n"); | ||
1493 | goto errout_mmio_reqmem; | ||
1494 | } | ||
1495 | |||
1496 | io_virt = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); | ||
1497 | |||
1498 | if (!io_virt) { | ||
1499 | output("ioremap failed for mmio region\n"); | ||
1500 | goto errout_mmio_remap; | ||
1501 | } | ||
1502 | // setup framebuffer memory ... might already be requested | ||
1503 | // by vesafb. Not to fail in case of an unsuccessful request | ||
1504 | // is useful if both are loaded. | ||
1505 | info->fix.smem_start = pci_resource_start(dev, 0); | ||
1506 | info->fix.smem_len = get_memsize(); | ||
1507 | |||
1508 | if (!request_mem_region(info->fix.smem_start, | ||
1509 | info->fix.smem_len, "cyblafb")) { | ||
1510 | output("region %#lx/%#x already reserved\n", | ||
1511 | info->fix.smem_start, info->fix.smem_len); | ||
1512 | vesafb |= 4; | ||
1513 | } | ||
1514 | |||
1515 | info->screen_base = ioremap_nocache(info->fix.smem_start, | ||
1516 | info->fix.smem_len); | ||
1517 | |||
1518 | if (!info->screen_base) { | ||
1519 | output("ioremap failed for smem region\n"); | ||
1520 | goto errout_smem_remap; | ||
1521 | } | ||
1522 | |||
1523 | displaytype = get_displaytype(); | ||
1524 | |||
1525 | if (displaytype == DISPLAY_FP) | ||
1526 | nativex = get_nativex(); | ||
1527 | |||
1528 | info->flags = FBINFO_DEFAULT | ||
1529 | | FBINFO_HWACCEL_COPYAREA | ||
1530 | | FBINFO_HWACCEL_FILLRECT | ||
1531 | | FBINFO_HWACCEL_IMAGEBLIT | ||
1532 | | FBINFO_READS_FAST | ||
1533 | // | FBINFO_PARTIAL_PAN_OK | ||
1534 | | FBINFO_MISC_ALWAYS_SETPAR; | ||
1535 | |||
1536 | info->pseudo_palette = par->pseudo_pal; | ||
1537 | |||
1538 | if (getstartupmode(info)) | ||
1539 | goto errout_findmode; | ||
1540 | |||
1541 | fb_alloc_cmap(&info->cmap, 256, 0); | ||
1542 | |||
1543 | if (register_framebuffer(info)) { | ||
1544 | output("Could not register CyBla framebuffer\n"); | ||
1545 | goto errout_register; | ||
1546 | } | ||
1547 | |||
1548 | pci_set_drvdata(dev, info); | ||
1549 | |||
1550 | // | ||
1551 | // normal exit and error paths | ||
1552 | // | ||
1553 | |||
1554 | return 0; | ||
1555 | |||
1556 | errout_register: | ||
1557 | errout_findmode: | ||
1558 | iounmap(info->screen_base); | ||
1559 | errout_smem_remap: | ||
1560 | if (!(vesafb & 4)) | ||
1561 | release_mem_region(info->fix.smem_start, info->fix.smem_len); | ||
1562 | iounmap(io_virt); | ||
1563 | errout_mmio_remap: | ||
1564 | release_mem_region(info->fix.mmio_start, info->fix.mmio_len); | ||
1565 | errout_mmio_reqmem: | ||
1566 | if (!(vesafb & 1)) | ||
1567 | release_region(0x3c0, 32); | ||
1568 | errout_enable: | ||
1569 | kfree(info->pixmap.addr); | ||
1570 | errout_alloc_pixmap: | ||
1571 | framebuffer_release(info); | ||
1572 | errout_alloc_info: | ||
1573 | output("CyblaFB version %s aborting init.\n", VERSION); | ||
1574 | return -ENODEV; | ||
1575 | } | ||
1576 | |||
1577 | static void __devexit cybla_pci_remove(struct pci_dev *dev) | ||
1578 | { | ||
1579 | struct fb_info *info = pci_get_drvdata(dev); | ||
1580 | |||
1581 | unregister_framebuffer(info); | ||
1582 | iounmap(io_virt); | ||
1583 | iounmap(info->screen_base); | ||
1584 | if (!(vesafb & 4)) | ||
1585 | release_mem_region(info->fix.smem_start, info->fix.smem_len); | ||
1586 | release_mem_region(info->fix.mmio_start, info->fix.mmio_len); | ||
1587 | fb_dealloc_cmap(&info->cmap); | ||
1588 | if (!(vesafb & 2)) | ||
1589 | release_region(GEBase, 0x100); | ||
1590 | if (!(vesafb & 1)) | ||
1591 | release_region(0x3c0, 32); | ||
1592 | kfree(info->pixmap.addr); | ||
1593 | framebuffer_release(info); | ||
1594 | output("CyblaFB version %s normal exit.\n", VERSION); | ||
1595 | } | ||
1596 | |||
1597 | // | ||
1598 | // List of boards that we are trying to support | ||
1599 | // | ||
1600 | static struct pci_device_id cybla_devices[] = { | ||
1601 | {PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, | ||
1602 | {0,} | ||
1603 | }; | ||
1604 | |||
1605 | MODULE_DEVICE_TABLE(pci, cybla_devices); | ||
1606 | |||
1607 | static struct pci_driver cyblafb_pci_driver = { | ||
1608 | .name = "cyblafb", | ||
1609 | .id_table = cybla_devices, | ||
1610 | .probe = cybla_pci_probe, | ||
1611 | .remove = __devexit_p(cybla_pci_remove) | ||
1612 | }; | ||
1613 | |||
1614 | //============================================================= | ||
1615 | // | ||
1616 | // kernel command line example: | ||
1617 | // | ||
1618 | // video=cyblafb:1280x1024, bpp=16, ref=50 ... | ||
1619 | // | ||
1620 | // modprobe command line example: | ||
1621 | // | ||
1622 | // modprobe cyblafb mode=1280x1024 bpp=16 ref=50 ... | ||
1623 | // | ||
1624 | //============================================================= | ||
1625 | |||
1626 | static int __devinit cyblafb_init(void) | ||
1627 | { | ||
1628 | #ifndef MODULE | ||
1629 | char *options = NULL; | ||
1630 | char *opt; | ||
1631 | |||
1632 | if (fb_get_options("cyblafb", &options)) | ||
1633 | return -ENODEV; | ||
1634 | |||
1635 | if (options && *options) | ||
1636 | while ((opt = strsep(&options, ",")) != NULL) { | ||
1637 | if (!*opt) | ||
1638 | continue; | ||
1639 | else if (!strncmp(opt, "bpp=", 4)) | ||
1640 | bpp = simple_strtoul(opt + 4, NULL, 0); | ||
1641 | else if (!strncmp(opt, "ref=", 4)) | ||
1642 | ref = simple_strtoul(opt + 4, NULL, 0); | ||
1643 | else if (!strncmp(opt, "fp", 2)) | ||
1644 | displaytype = DISPLAY_FP; | ||
1645 | else if (!strncmp(opt, "crt", 3)) | ||
1646 | displaytype = DISPLAY_CRT; | ||
1647 | else if (!strncmp(opt, "nativex=", 8)) | ||
1648 | nativex = simple_strtoul(opt + 8, NULL, 0); | ||
1649 | else if (!strncmp(opt, "center", 6)) | ||
1650 | center = 1; | ||
1651 | else if (!strncmp(opt, "stretch", 7)) | ||
1652 | stretch = 1; | ||
1653 | else if (!strncmp(opt, "pciwb=", 6)) | ||
1654 | pciwb = simple_strtoul(opt + 6, NULL, 0); | ||
1655 | else if (!strncmp(opt, "pcirb=", 6)) | ||
1656 | pcirb = simple_strtoul(opt + 6, NULL, 0); | ||
1657 | else if (!strncmp(opt, "pciwr=", 6)) | ||
1658 | pciwr = simple_strtoul(opt + 6, NULL, 0); | ||
1659 | else if (!strncmp(opt, "pcirr=", 6)) | ||
1660 | pcirr = simple_strtoul(opt + 6, NULL, 0); | ||
1661 | else if (!strncmp(opt, "memsize=", 8)) | ||
1662 | memsize = simple_strtoul(opt + 8, NULL, 0); | ||
1663 | else if (!strncmp(opt, "verbosity=", 10)) | ||
1664 | verbosity = simple_strtoul(opt + 10, NULL, 0); | ||
1665 | else | ||
1666 | mode = opt; | ||
1667 | } | ||
1668 | #endif | ||
1669 | output("CyblaFB version %s initializing\n", VERSION); | ||
1670 | return pci_register_driver(&cyblafb_pci_driver); | ||
1671 | } | ||
1672 | |||
1673 | static void __exit cyblafb_exit(void) | ||
1674 | { | ||
1675 | pci_unregister_driver(&cyblafb_pci_driver); | ||
1676 | } | ||
1677 | |||
1678 | module_init(cyblafb_init); | ||
1679 | module_exit(cyblafb_exit); | ||
1680 | |||
1681 | MODULE_AUTHOR("Knut Petersen <knut_petersen@t-online.de>"); | ||
1682 | MODULE_DESCRIPTION("Framebuffer driver for Cyberblade/i1 graphics core"); | ||
1683 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index daf9b81878a4..0c5b9a9fd56f 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c | |||
@@ -129,6 +129,8 @@ static int set_system(const struct dmi_system_id *id) | |||
129 | screen_info.lfb_width = info->width; | 129 | screen_info.lfb_width = info->width; |
130 | if (screen_info.lfb_height == 0) | 130 | if (screen_info.lfb_height == 0) |
131 | screen_info.lfb_height = info->height; | 131 | screen_info.lfb_height = info->height; |
132 | if (screen_info.orig_video_isVGA == 0) | ||
133 | screen_info.orig_video_isVGA = VIDEO_TYPE_EFI; | ||
132 | 134 | ||
133 | return 0; | 135 | return 0; |
134 | } | 136 | } |
@@ -374,9 +376,10 @@ static int __init efifb_init(void) | |||
374 | int ret; | 376 | int ret; |
375 | char *option = NULL; | 377 | char *option = NULL; |
376 | 378 | ||
379 | dmi_check_system(dmi_system_table); | ||
380 | |||
377 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) | 381 | if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) |
378 | return -ENODEV; | 382 | return -ENODEV; |
379 | dmi_check_system(dmi_system_table); | ||
380 | 383 | ||
381 | if (fb_get_options("efifb", &option)) | 384 | if (fb_get_options("efifb", &option)) |
382 | return -ENODEV; | 385 | return -ENODEV; |
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 082026546aee..0a7a6679ee6e 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
@@ -85,8 +85,9 @@ EXPORT_SYMBOL_GPL(fb_deferred_io_fsync); | |||
85 | 85 | ||
86 | /* vm_ops->page_mkwrite handler */ | 86 | /* vm_ops->page_mkwrite handler */ |
87 | static int fb_deferred_io_mkwrite(struct vm_area_struct *vma, | 87 | static int fb_deferred_io_mkwrite(struct vm_area_struct *vma, |
88 | struct page *page) | 88 | struct vm_fault *vmf) |
89 | { | 89 | { |
90 | struct page *page = vmf->page; | ||
90 | struct fb_info *info = vma->vm_private_data; | 91 | struct fb_info *info = vma->vm_private_data; |
91 | struct fb_deferred_io *fbdefio = info->fbdefio; | 92 | struct fb_deferred_io *fbdefio = info->fbdefio; |
92 | struct page *cur; | 93 | struct page *cur; |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index cfd9dce1ce0b..2ac32e6b5953 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -46,6 +46,17 @@ | |||
46 | struct fb_info *registered_fb[FB_MAX] __read_mostly; | 46 | struct fb_info *registered_fb[FB_MAX] __read_mostly; |
47 | int num_registered_fb __read_mostly; | 47 | int num_registered_fb __read_mostly; |
48 | 48 | ||
49 | int lock_fb_info(struct fb_info *info) | ||
50 | { | ||
51 | mutex_lock(&info->lock); | ||
52 | if (!info->fbops) { | ||
53 | mutex_unlock(&info->lock); | ||
54 | return 0; | ||
55 | } | ||
56 | return 1; | ||
57 | } | ||
58 | EXPORT_SYMBOL(lock_fb_info); | ||
59 | |||
49 | /* | 60 | /* |
50 | * Helpers | 61 | * Helpers |
51 | */ | 62 | */ |
@@ -1086,13 +1097,8 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
1086 | return -EINVAL; | 1097 | return -EINVAL; |
1087 | con2fb.framebuffer = -1; | 1098 | con2fb.framebuffer = -1; |
1088 | event.data = &con2fb; | 1099 | event.data = &con2fb; |
1089 | |||
1090 | if (!lock_fb_info(info)) | ||
1091 | return -ENODEV; | ||
1092 | event.info = info; | 1100 | event.info = info; |
1093 | fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); | 1101 | fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event); |
1094 | unlock_fb_info(info); | ||
1095 | |||
1096 | ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; | 1102 | ret = copy_to_user(argp, &con2fb, sizeof(con2fb)) ? -EFAULT : 0; |
1097 | break; | 1103 | break; |
1098 | case FBIOPUT_CON2FBMAP: | 1104 | case FBIOPUT_CON2FBMAP: |
@@ -1109,12 +1115,8 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
1109 | break; | 1115 | break; |
1110 | } | 1116 | } |
1111 | event.data = &con2fb; | 1117 | event.data = &con2fb; |
1112 | if (!lock_fb_info(info)) | ||
1113 | return -ENODEV; | ||
1114 | event.info = info; | 1118 | event.info = info; |
1115 | ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, | 1119 | ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); |
1116 | &event); | ||
1117 | unlock_fb_info(info); | ||
1118 | break; | 1120 | break; |
1119 | case FBIOBLANK: | 1121 | case FBIOBLANK: |
1120 | if (!lock_fb_info(info)) | 1122 | if (!lock_fb_info(info)) |
diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h index f132aab8c5de..c03f7f55c76d 100644 --- a/drivers/video/nvidia/nv_type.h +++ b/drivers/video/nvidia/nv_type.h | |||
@@ -5,7 +5,6 @@ | |||
5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
6 | #include <linux/i2c.h> | 6 | #include <linux/i2c.h> |
7 | #include <linux/i2c-algo-bit.h> | 7 | #include <linux/i2c-algo-bit.h> |
8 | #include <linux/mutex.h> | ||
9 | #include <video/vga.h> | 8 | #include <video/vga.h> |
10 | 9 | ||
11 | #define NV_ARCH_04 0x04 | 10 | #define NV_ARCH_04 0x04 |
@@ -99,7 +98,6 @@ struct nvidia_par { | |||
99 | RIVA_HW_STATE initial_state; | 98 | RIVA_HW_STATE initial_state; |
100 | RIVA_HW_STATE *CurrentState; | 99 | RIVA_HW_STATE *CurrentState; |
101 | struct vgastate vgastate; | 100 | struct vgastate vgastate; |
102 | struct mutex open_lock; | ||
103 | u32 pseudo_palette[16]; | 101 | u32 pseudo_palette[16]; |
104 | struct pci_dev *pci_dev; | 102 | struct pci_dev *pci_dev; |
105 | u32 Architecture; | 103 | u32 Architecture; |
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 9dbb5a5a267b..efe10ff86d63 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
@@ -1004,15 +1004,12 @@ static int nvidiafb_open(struct fb_info *info, int user) | |||
1004 | { | 1004 | { |
1005 | struct nvidia_par *par = info->par; | 1005 | struct nvidia_par *par = info->par; |
1006 | 1006 | ||
1007 | mutex_lock(&par->open_lock); | ||
1008 | |||
1009 | if (!par->open_count) { | 1007 | if (!par->open_count) { |
1010 | save_vga_x86(par); | 1008 | save_vga_x86(par); |
1011 | nvidia_save_vga(par, &par->initial_state); | 1009 | nvidia_save_vga(par, &par->initial_state); |
1012 | } | 1010 | } |
1013 | 1011 | ||
1014 | par->open_count++; | 1012 | par->open_count++; |
1015 | mutex_unlock(&par->open_lock); | ||
1016 | return 0; | 1013 | return 0; |
1017 | } | 1014 | } |
1018 | 1015 | ||
@@ -1021,8 +1018,6 @@ static int nvidiafb_release(struct fb_info *info, int user) | |||
1021 | struct nvidia_par *par = info->par; | 1018 | struct nvidia_par *par = info->par; |
1022 | int err = 0; | 1019 | int err = 0; |
1023 | 1020 | ||
1024 | mutex_lock(&par->open_lock); | ||
1025 | |||
1026 | if (!par->open_count) { | 1021 | if (!par->open_count) { |
1027 | err = -EINVAL; | 1022 | err = -EINVAL; |
1028 | goto done; | 1023 | goto done; |
@@ -1035,7 +1030,6 @@ static int nvidiafb_release(struct fb_info *info, int user) | |||
1035 | 1030 | ||
1036 | par->open_count--; | 1031 | par->open_count--; |
1037 | done: | 1032 | done: |
1038 | mutex_unlock(&par->open_lock); | ||
1039 | return err; | 1033 | return err; |
1040 | } | 1034 | } |
1041 | 1035 | ||
@@ -1300,7 +1294,6 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd, | |||
1300 | 1294 | ||
1301 | par = info->par; | 1295 | par = info->par; |
1302 | par->pci_dev = pd; | 1296 | par->pci_dev = pd; |
1303 | mutex_init(&par->open_lock); | ||
1304 | info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL); | 1297 | info->pixmap.addr = kzalloc(8 * 1024, GFP_KERNEL); |
1305 | 1298 | ||
1306 | if (info->pixmap.addr == NULL) | 1299 | if (info->pixmap.addr == NULL) |
diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c index f24df0b54e1c..8aa6e47202b9 100644 --- a/drivers/video/omap/hwa742.c +++ b/drivers/video/omap/hwa742.c | |||
@@ -742,7 +742,7 @@ static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div) | |||
742 | if (calc_reg_timing(sysclk, div) == 0) | 742 | if (calc_reg_timing(sysclk, div) == 0) |
743 | break; | 743 | break; |
744 | } | 744 | } |
745 | if (div > max_clk_div) | 745 | if (div >= max_clk_div) |
746 | goto err; | 746 | goto err; |
747 | 747 | ||
748 | *extif_mem_div = div; | 748 | *extif_mem_div = div; |
@@ -752,7 +752,7 @@ static int calc_extif_timings(unsigned long sysclk, int *extif_mem_div) | |||
752 | break; | 752 | break; |
753 | } | 753 | } |
754 | 754 | ||
755 | if (div > max_clk_div) | 755 | if (div >= max_clk_div) |
756 | goto err; | 756 | goto err; |
757 | 757 | ||
758 | return 0; | 758 | return 0; |
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index 1a49519dafa4..060d72fe57cb 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c | |||
@@ -338,7 +338,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi) | |||
338 | 338 | ||
339 | omapfb_rqueue_lock(fbdev); | 339 | omapfb_rqueue_lock(fbdev); |
340 | switch (blank) { | 340 | switch (blank) { |
341 | case VESA_NO_BLANKING: | 341 | case FB_BLANK_UNBLANK: |
342 | if (fbdev->state == OMAPFB_SUSPENDED) { | 342 | if (fbdev->state == OMAPFB_SUSPENDED) { |
343 | if (fbdev->ctrl->resume) | 343 | if (fbdev->ctrl->resume) |
344 | fbdev->ctrl->resume(); | 344 | fbdev->ctrl->resume(); |
@@ -349,7 +349,7 @@ static int omapfb_blank(int blank, struct fb_info *fbi) | |||
349 | do_update = 1; | 349 | do_update = 1; |
350 | } | 350 | } |
351 | break; | 351 | break; |
352 | case VESA_POWERDOWN: | 352 | case FB_BLANK_POWERDOWN: |
353 | if (fbdev->state == OMAPFB_ACTIVE) { | 353 | if (fbdev->state == OMAPFB_ACTIVE) { |
354 | fbdev->panel->disable(fbdev->panel); | 354 | fbdev->panel->disable(fbdev->panel); |
355 | if (fbdev->ctrl->suspend) | 355 | if (fbdev->ctrl->suspend) |
@@ -1818,7 +1818,7 @@ static int omapfb_suspend(struct platform_device *pdev, pm_message_t mesg) | |||
1818 | { | 1818 | { |
1819 | struct omapfb_device *fbdev = platform_get_drvdata(pdev); | 1819 | struct omapfb_device *fbdev = platform_get_drvdata(pdev); |
1820 | 1820 | ||
1821 | omapfb_blank(VESA_POWERDOWN, fbdev->fb_info[0]); | 1821 | omapfb_blank(FB_BLANK_POWERDOWN, fbdev->fb_info[0]); |
1822 | 1822 | ||
1823 | return 0; | 1823 | return 0; |
1824 | } | 1824 | } |
@@ -1828,7 +1828,7 @@ static int omapfb_resume(struct platform_device *pdev) | |||
1828 | { | 1828 | { |
1829 | struct omapfb_device *fbdev = platform_get_drvdata(pdev); | 1829 | struct omapfb_device *fbdev = platform_get_drvdata(pdev); |
1830 | 1830 | ||
1831 | omapfb_blank(VESA_NO_BLANKING, fbdev->fb_info[0]); | 1831 | omapfb_blank(FB_BLANK_UNBLANK, fbdev->fb_info[0]); |
1832 | return 0; | 1832 | return 0; |
1833 | } | 1833 | } |
1834 | 1834 | ||
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index a7b01d2724b5..0726aecf3b7e 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c | |||
@@ -50,9 +50,22 @@ | |||
50 | #define dbg(fmt, args...) do { } while (0) | 50 | #define dbg(fmt, args...) do { } while (0) |
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | static const int __devinitconst s1d13xxxfb_revisions[] = { | 53 | /* |
54 | S1D13506_CHIP_REV, /* Rev.4 on HP Jornada 7xx S1D13506 */ | 54 | * List of card production ids |
55 | S1D13806_CHIP_REV, /* Rev.7 on .. */ | 55 | */ |
56 | static const int s1d13xxxfb_prod_ids[] = { | ||
57 | S1D13505_PROD_ID, | ||
58 | S1D13506_PROD_ID, | ||
59 | S1D13806_PROD_ID, | ||
60 | }; | ||
61 | |||
62 | /* | ||
63 | * List of card strings | ||
64 | */ | ||
65 | static const char *s1d13xxxfb_prod_names[] = { | ||
66 | "S1D13505", | ||
67 | "S1D13506", | ||
68 | "S1D13806", | ||
56 | }; | 69 | }; |
57 | 70 | ||
58 | /* | 71 | /* |
@@ -377,7 +390,6 @@ s1d13xxxfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | |||
377 | return 0; | 390 | return 0; |
378 | } | 391 | } |
379 | 392 | ||
380 | |||
381 | /* framebuffer information structures */ | 393 | /* framebuffer information structures */ |
382 | 394 | ||
383 | static struct fb_ops s1d13xxxfb_fbops = { | 395 | static struct fb_ops s1d13xxxfb_fbops = { |
@@ -544,7 +556,7 @@ s1d13xxxfb_probe(struct platform_device *pdev) | |||
544 | struct s1d13xxxfb_pdata *pdata = NULL; | 556 | struct s1d13xxxfb_pdata *pdata = NULL; |
545 | int ret = 0; | 557 | int ret = 0; |
546 | int i; | 558 | int i; |
547 | u8 revision; | 559 | u8 revision, prod_id; |
548 | 560 | ||
549 | dbg("probe called: device is %p\n", pdev); | 561 | dbg("probe called: device is %p\n", pdev); |
550 | 562 | ||
@@ -613,19 +625,31 @@ s1d13xxxfb_probe(struct platform_device *pdev) | |||
613 | goto bail; | 625 | goto bail; |
614 | } | 626 | } |
615 | 627 | ||
616 | revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2; | 628 | /* production id is top 6 bits */ |
617 | 629 | prod_id = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2; | |
630 | /* revision id is lower 2 bits */ | ||
631 | revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) & 0x3; | ||
618 | ret = -ENODEV; | 632 | ret = -ENODEV; |
619 | 633 | ||
620 | for (i = 0; i < ARRAY_SIZE(s1d13xxxfb_revisions); i++) { | 634 | for (i = 0; i < ARRAY_SIZE(s1d13xxxfb_prod_ids); i++) { |
621 | if (revision == s1d13xxxfb_revisions[i]) | 635 | if (prod_id == s1d13xxxfb_prod_ids[i]) { |
636 | /* looks like we got it in our list */ | ||
637 | default_par->prod_id = prod_id; | ||
638 | default_par->revision = revision; | ||
622 | ret = 0; | 639 | ret = 0; |
640 | break; | ||
641 | } | ||
623 | } | 642 | } |
624 | 643 | ||
625 | if (!ret) | 644 | if (!ret) { |
645 | printk(KERN_INFO PFX "chip production id %i = %s\n", | ||
646 | prod_id, s1d13xxxfb_prod_names[i]); | ||
626 | printk(KERN_INFO PFX "chip revision %i\n", revision); | 647 | printk(KERN_INFO PFX "chip revision %i\n", revision); |
627 | else { | 648 | } else { |
628 | printk(KERN_INFO PFX "unknown chip revision %i\n", revision); | 649 | printk(KERN_INFO PFX |
650 | "unknown chip production id %i, revision %i\n", | ||
651 | prod_id, revision); | ||
652 | printk(KERN_INFO PFX "please contant maintainer\n"); | ||
629 | goto bail; | 653 | goto bail; |
630 | } | 654 | } |
631 | 655 | ||
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c new file mode 100644 index 000000000000..5e9c6302433b --- /dev/null +++ b/drivers/video/s3c-fb.c | |||
@@ -0,0 +1,1036 @@ | |||
1 | /* linux/drivers/video/s3c-fb.c | ||
2 | * | ||
3 | * Copyright 2008 Openmoko Inc. | ||
4 | * Copyright 2008 Simtec Electronics | ||
5 | * Ben Dooks <ben@simtec.co.uk> | ||
6 | * http://armlinux.simtec.co.uk/ | ||
7 | * | ||
8 | * Samsung SoC Framebuffer driver | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/gfp.h> | ||
21 | #include <linux/clk.h> | ||
22 | #include <linux/fb.h> | ||
23 | #include <linux/io.h> | ||
24 | |||
25 | #include <mach/map.h> | ||
26 | #include <mach/regs-fb.h> | ||
27 | #include <plat/fb.h> | ||
28 | |||
29 | /* This driver will export a number of framebuffer interfaces depending | ||
30 | * on the configuration passed in via the platform data. Each fb instance | ||
31 | * maps to a hardware window. Currently there is no support for runtime | ||
32 | * setting of the alpha-blending functions that each window has, so only | ||
33 | * window 0 is actually useful. | ||
34 | * | ||
35 | * Window 0 is treated specially, it is used for the basis of the LCD | ||
36 | * output timings and as the control for the output power-down state. | ||
37 | */ | ||
38 | |||
39 | /* note, some of the functions that get called are derived from including | ||
40 | * <mach/regs-fb.h> as they are specific to the architecture that the code | ||
41 | * is being built for. | ||
42 | */ | ||
43 | |||
44 | #ifdef CONFIG_FB_S3C_DEBUG_REGWRITE | ||
45 | #undef writel | ||
46 | #define writel(v, r) do { \ | ||
47 | printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \ | ||
48 | __raw_writel(v, r); } while(0) | ||
49 | #endif /* FB_S3C_DEBUG_REGWRITE */ | ||
50 | |||
51 | struct s3c_fb; | ||
52 | |||
53 | /** | ||
54 | * struct s3c_fb_win - per window private data for each framebuffer. | ||
55 | * @windata: The platform data supplied for the window configuration. | ||
56 | * @parent: The hardware that this window is part of. | ||
57 | * @fbinfo: Pointer pack to the framebuffer info for this window. | ||
58 | * @palette_buffer: Buffer/cache to hold palette entries. | ||
59 | * @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/ | ||
60 | * @index: The window number of this window. | ||
61 | * @palette: The bitfields for changing r/g/b into a hardware palette entry. | ||
62 | */ | ||
63 | struct s3c_fb_win { | ||
64 | struct s3c_fb_pd_win *windata; | ||
65 | struct s3c_fb *parent; | ||
66 | struct fb_info *fbinfo; | ||
67 | struct s3c_fb_palette palette; | ||
68 | |||
69 | u32 *palette_buffer; | ||
70 | u32 pseudo_palette[16]; | ||
71 | unsigned int index; | ||
72 | }; | ||
73 | |||
74 | /** | ||
75 | * struct s3c_fb - overall hardware state of the hardware | ||
76 | * @dev: The device that we bound to, for printing, etc. | ||
77 | * @regs_res: The resource we claimed for the IO registers. | ||
78 | * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk. | ||
79 | * @regs: The mapped hardware registers. | ||
80 | * @enabled: A bitmask of enabled hardware windows. | ||
81 | * @pdata: The platform configuration data passed with the device. | ||
82 | * @windows: The hardware windows that have been claimed. | ||
83 | */ | ||
84 | struct s3c_fb { | ||
85 | struct device *dev; | ||
86 | struct resource *regs_res; | ||
87 | struct clk *bus_clk; | ||
88 | void __iomem *regs; | ||
89 | |||
90 | unsigned char enabled; | ||
91 | |||
92 | struct s3c_fb_platdata *pdata; | ||
93 | struct s3c_fb_win *windows[S3C_FB_MAX_WIN]; | ||
94 | }; | ||
95 | |||
96 | /** | ||
97 | * s3c_fb_win_has_palette() - determine if a mode has a palette | ||
98 | * @win: The window number being queried. | ||
99 | * @bpp: The number of bits per pixel to test. | ||
100 | * | ||
101 | * Work out if the given window supports palletised data at the specified bpp. | ||
102 | */ | ||
103 | static int s3c_fb_win_has_palette(unsigned int win, unsigned int bpp) | ||
104 | { | ||
105 | return s3c_fb_win_pal_size(win) <= (1 << bpp); | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * s3c_fb_check_var() - framebuffer layer request to verify a given mode. | ||
110 | * @var: The screen information to verify. | ||
111 | * @info: The framebuffer device. | ||
112 | * | ||
113 | * Framebuffer layer call to verify the given information and allow us to | ||
114 | * update various information depending on the hardware capabilities. | ||
115 | */ | ||
116 | static int s3c_fb_check_var(struct fb_var_screeninfo *var, | ||
117 | struct fb_info *info) | ||
118 | { | ||
119 | struct s3c_fb_win *win = info->par; | ||
120 | struct s3c_fb_pd_win *windata = win->windata; | ||
121 | struct s3c_fb *sfb = win->parent; | ||
122 | |||
123 | dev_dbg(sfb->dev, "checking parameters\n"); | ||
124 | |||
125 | var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres); | ||
126 | var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres); | ||
127 | |||
128 | if (!s3c_fb_validate_win_bpp(win->index, var->bits_per_pixel)) { | ||
129 | dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n", | ||
130 | win->index, var->bits_per_pixel); | ||
131 | return -EINVAL; | ||
132 | } | ||
133 | |||
134 | /* always ensure these are zero, for drop through cases below */ | ||
135 | var->transp.offset = 0; | ||
136 | var->transp.length = 0; | ||
137 | |||
138 | switch (var->bits_per_pixel) { | ||
139 | case 1: | ||
140 | case 2: | ||
141 | case 4: | ||
142 | case 8: | ||
143 | if (!s3c_fb_win_has_palette(win->index, var->bits_per_pixel)) { | ||
144 | /* non palletised, A:1,R:2,G:3,B:2 mode */ | ||
145 | var->red.offset = 4; | ||
146 | var->green.offset = 2; | ||
147 | var->blue.offset = 0; | ||
148 | var->red.length = 5; | ||
149 | var->green.length = 3; | ||
150 | var->blue.length = 2; | ||
151 | var->transp.offset = 7; | ||
152 | var->transp.length = 1; | ||
153 | } else { | ||
154 | var->red.offset = 0; | ||
155 | var->red.length = var->bits_per_pixel; | ||
156 | var->green = var->red; | ||
157 | var->blue = var->red; | ||
158 | } | ||
159 | break; | ||
160 | |||
161 | case 19: | ||
162 | /* 666 with one bit alpha/transparency */ | ||
163 | var->transp.offset = 18; | ||
164 | var->transp.length = 1; | ||
165 | case 18: | ||
166 | var->bits_per_pixel = 32; | ||
167 | |||
168 | /* 666 format */ | ||
169 | var->red.offset = 12; | ||
170 | var->green.offset = 6; | ||
171 | var->blue.offset = 0; | ||
172 | var->red.length = 6; | ||
173 | var->green.length = 6; | ||
174 | var->blue.length = 6; | ||
175 | break; | ||
176 | |||
177 | case 16: | ||
178 | /* 16 bpp, 565 format */ | ||
179 | var->red.offset = 11; | ||
180 | var->green.offset = 5; | ||
181 | var->blue.offset = 0; | ||
182 | var->red.length = 5; | ||
183 | var->green.length = 6; | ||
184 | var->blue.length = 5; | ||
185 | break; | ||
186 | |||
187 | case 28: | ||
188 | case 25: | ||
189 | var->transp.length = var->bits_per_pixel - 24; | ||
190 | var->transp.offset = 24; | ||
191 | /* drop through */ | ||
192 | case 24: | ||
193 | /* our 24bpp is unpacked, so 32bpp */ | ||
194 | var->bits_per_pixel = 32; | ||
195 | case 32: | ||
196 | var->red.offset = 16; | ||
197 | var->red.length = 8; | ||
198 | var->green.offset = 8; | ||
199 | var->green.length = 8; | ||
200 | var->blue.offset = 0; | ||
201 | var->blue.length = 8; | ||
202 | break; | ||
203 | |||
204 | default: | ||
205 | dev_err(sfb->dev, "invalid bpp\n"); | ||
206 | } | ||
207 | |||
208 | dev_dbg(sfb->dev, "%s: verified parameters\n", __func__); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | /** | ||
213 | * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock. | ||
214 | * @sfb: The hardware state. | ||
215 | * @pixclock: The pixel clock wanted, in picoseconds. | ||
216 | * | ||
217 | * Given the specified pixel clock, work out the necessary divider to get | ||
218 | * close to the output frequency. | ||
219 | */ | ||
220 | static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk) | ||
221 | { | ||
222 | unsigned long clk = clk_get_rate(sfb->bus_clk); | ||
223 | unsigned long long tmp; | ||
224 | unsigned int result; | ||
225 | |||
226 | tmp = (unsigned long long)clk; | ||
227 | tmp *= pixclk; | ||
228 | |||
229 | do_div(tmp, 1000000000UL); | ||
230 | result = (unsigned int)tmp / 1000; | ||
231 | |||
232 | dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n", | ||
233 | pixclk, clk, result, clk / result); | ||
234 | |||
235 | return result; | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * s3c_fb_align_word() - align pixel count to word boundary | ||
240 | * @bpp: The number of bits per pixel | ||
241 | * @pix: The value to be aligned. | ||
242 | * | ||
243 | * Align the given pixel count so that it will start on an 32bit word | ||
244 | * boundary. | ||
245 | */ | ||
246 | static int s3c_fb_align_word(unsigned int bpp, unsigned int pix) | ||
247 | { | ||
248 | int pix_per_word; | ||
249 | |||
250 | if (bpp > 16) | ||
251 | return pix; | ||
252 | |||
253 | pix_per_word = (8 * 32) / bpp; | ||
254 | return ALIGN(pix, pix_per_word); | ||
255 | } | ||
256 | |||
257 | /** | ||
258 | * s3c_fb_set_par() - framebuffer request to set new framebuffer state. | ||
259 | * @info: The framebuffer to change. | ||
260 | * | ||
261 | * Framebuffer layer request to set a new mode for the specified framebuffer | ||
262 | */ | ||
263 | static int s3c_fb_set_par(struct fb_info *info) | ||
264 | { | ||
265 | struct fb_var_screeninfo *var = &info->var; | ||
266 | struct s3c_fb_win *win = info->par; | ||
267 | struct s3c_fb *sfb = win->parent; | ||
268 | void __iomem *regs = sfb->regs; | ||
269 | int win_no = win->index; | ||
270 | u32 data; | ||
271 | u32 pagewidth; | ||
272 | int clkdiv; | ||
273 | |||
274 | dev_dbg(sfb->dev, "setting framebuffer parameters\n"); | ||
275 | |||
276 | switch (var->bits_per_pixel) { | ||
277 | case 32: | ||
278 | case 24: | ||
279 | case 16: | ||
280 | case 12: | ||
281 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
282 | break; | ||
283 | case 8: | ||
284 | if (s3c_fb_win_has_palette(win_no, 8)) | ||
285 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
286 | else | ||
287 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
288 | break; | ||
289 | case 1: | ||
290 | info->fix.visual = FB_VISUAL_MONO01; | ||
291 | break; | ||
292 | default: | ||
293 | info->fix.visual = FB_VISUAL_PSEUDOCOLOR; | ||
294 | break; | ||
295 | } | ||
296 | |||
297 | info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8; | ||
298 | |||
299 | /* disable the window whilst we update it */ | ||
300 | writel(0, regs + WINCON(win_no)); | ||
301 | |||
302 | /* use window 0 as the basis for the lcd output timings */ | ||
303 | |||
304 | if (win_no == 0) { | ||
305 | clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock); | ||
306 | |||
307 | data = sfb->pdata->vidcon0; | ||
308 | data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR); | ||
309 | |||
310 | if (clkdiv > 1) | ||
311 | data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR; | ||
312 | else | ||
313 | data &= ~VIDCON0_CLKDIR; /* 1:1 clock */ | ||
314 | |||
315 | /* write the timing data to the panel */ | ||
316 | |||
317 | data |= VIDCON0_ENVID | VIDCON0_ENVID_F; | ||
318 | writel(data, regs + VIDCON0); | ||
319 | |||
320 | data = VIDTCON0_VBPD(var->upper_margin - 1) | | ||
321 | VIDTCON0_VFPD(var->lower_margin - 1) | | ||
322 | VIDTCON0_VSPW(var->vsync_len - 1); | ||
323 | |||
324 | writel(data, regs + VIDTCON0); | ||
325 | |||
326 | data = VIDTCON1_HBPD(var->left_margin - 1) | | ||
327 | VIDTCON1_HFPD(var->right_margin - 1) | | ||
328 | VIDTCON1_HSPW(var->hsync_len - 1); | ||
329 | |||
330 | writel(data, regs + VIDTCON1); | ||
331 | |||
332 | data = VIDTCON2_LINEVAL(var->yres - 1) | | ||
333 | VIDTCON2_HOZVAL(var->xres - 1); | ||
334 | writel(data, regs + VIDTCON2); | ||
335 | } | ||
336 | |||
337 | /* write the buffer address */ | ||
338 | |||
339 | writel(info->fix.smem_start, regs + VIDW_BUF_START(win_no)); | ||
340 | |||
341 | data = info->fix.smem_start + info->fix.line_length * var->yres; | ||
342 | writel(data, regs + VIDW_BUF_END(win_no)); | ||
343 | |||
344 | pagewidth = (var->xres * var->bits_per_pixel) >> 3; | ||
345 | data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) | | ||
346 | VIDW_BUF_SIZE_PAGEWIDTH(pagewidth); | ||
347 | writel(data, regs + VIDW_BUF_SIZE(win_no)); | ||
348 | |||
349 | /* write 'OSD' registers to control position of framebuffer */ | ||
350 | |||
351 | data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0); | ||
352 | writel(data, regs + VIDOSD_A(win_no)); | ||
353 | |||
354 | data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel, | ||
355 | var->xres - 1)) | | ||
356 | VIDOSDxB_BOTRIGHT_Y(var->yres - 1); | ||
357 | |||
358 | writel(data, regs + VIDOSD_B(win_no)); | ||
359 | |||
360 | data = var->xres * var->yres; | ||
361 | if (s3c_fb_has_osd_d(win_no)) { | ||
362 | writel(data, regs + VIDOSD_D(win_no)); | ||
363 | writel(0, regs + VIDOSD_C(win_no)); | ||
364 | } else | ||
365 | writel(data, regs + VIDOSD_C(win_no)); | ||
366 | |||
367 | data = WINCONx_ENWIN; | ||
368 | |||
369 | /* note, since we have to round up the bits-per-pixel, we end up | ||
370 | * relying on the bitfield information for r/g/b/a to work out | ||
371 | * exactly which mode of operation is intended. */ | ||
372 | |||
373 | switch (var->bits_per_pixel) { | ||
374 | case 1: | ||
375 | data |= WINCON0_BPPMODE_1BPP; | ||
376 | data |= WINCONx_BITSWP; | ||
377 | data |= WINCONx_BURSTLEN_4WORD; | ||
378 | break; | ||
379 | case 2: | ||
380 | data |= WINCON0_BPPMODE_2BPP; | ||
381 | data |= WINCONx_BITSWP; | ||
382 | data |= WINCONx_BURSTLEN_8WORD; | ||
383 | break; | ||
384 | case 4: | ||
385 | data |= WINCON0_BPPMODE_4BPP; | ||
386 | data |= WINCONx_BITSWP; | ||
387 | data |= WINCONx_BURSTLEN_8WORD; | ||
388 | break; | ||
389 | case 8: | ||
390 | if (var->transp.length != 0) | ||
391 | data |= WINCON1_BPPMODE_8BPP_1232; | ||
392 | else | ||
393 | data |= WINCON0_BPPMODE_8BPP_PALETTE; | ||
394 | data |= WINCONx_BURSTLEN_8WORD; | ||
395 | data |= WINCONx_BYTSWP; | ||
396 | break; | ||
397 | case 16: | ||
398 | if (var->transp.length != 0) | ||
399 | data |= WINCON1_BPPMODE_16BPP_A1555; | ||
400 | else | ||
401 | data |= WINCON0_BPPMODE_16BPP_565; | ||
402 | data |= WINCONx_HAWSWP; | ||
403 | data |= WINCONx_BURSTLEN_16WORD; | ||
404 | break; | ||
405 | case 24: | ||
406 | case 32: | ||
407 | if (var->red.length == 6) { | ||
408 | if (var->transp.length != 0) | ||
409 | data |= WINCON1_BPPMODE_19BPP_A1666; | ||
410 | else | ||
411 | data |= WINCON1_BPPMODE_18BPP_666; | ||
412 | } else if (var->transp.length != 0) | ||
413 | data |= WINCON1_BPPMODE_25BPP_A1888; | ||
414 | else | ||
415 | data |= WINCON0_BPPMODE_24BPP_888; | ||
416 | |||
417 | data |= WINCONx_BURSTLEN_16WORD; | ||
418 | break; | ||
419 | } | ||
420 | |||
421 | writel(data, regs + WINCON(win_no)); | ||
422 | writel(0x0, regs + WINxMAP(win_no)); | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | /** | ||
428 | * s3c_fb_update_palette() - set or schedule a palette update. | ||
429 | * @sfb: The hardware information. | ||
430 | * @win: The window being updated. | ||
431 | * @reg: The palette index being changed. | ||
432 | * @value: The computed palette value. | ||
433 | * | ||
434 | * Change the value of a palette register, either by directly writing to | ||
435 | * the palette (this requires the palette RAM to be disconnected from the | ||
436 | * hardware whilst this is in progress) or schedule the update for later. | ||
437 | * | ||
438 | * At the moment, since we have no VSYNC interrupt support, we simply set | ||
439 | * the palette entry directly. | ||
440 | */ | ||
441 | static void s3c_fb_update_palette(struct s3c_fb *sfb, | ||
442 | struct s3c_fb_win *win, | ||
443 | unsigned int reg, | ||
444 | u32 value) | ||
445 | { | ||
446 | void __iomem *palreg; | ||
447 | u32 palcon; | ||
448 | |||
449 | palreg = sfb->regs + s3c_fb_pal_reg(win->index, reg); | ||
450 | |||
451 | dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n", | ||
452 | __func__, win->index, reg, palreg, value); | ||
453 | |||
454 | win->palette_buffer[reg] = value; | ||
455 | |||
456 | palcon = readl(sfb->regs + WPALCON); | ||
457 | writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON); | ||
458 | |||
459 | if (s3c_fb_pal_is16(win->index)) | ||
460 | writew(value, palreg); | ||
461 | else | ||
462 | writel(value, palreg); | ||
463 | |||
464 | writel(palcon, sfb->regs + WPALCON); | ||
465 | } | ||
466 | |||
467 | static inline unsigned int chan_to_field(unsigned int chan, | ||
468 | struct fb_bitfield *bf) | ||
469 | { | ||
470 | chan &= 0xffff; | ||
471 | chan >>= 16 - bf->length; | ||
472 | return chan << bf->offset; | ||
473 | } | ||
474 | |||
475 | /** | ||
476 | * s3c_fb_setcolreg() - framebuffer layer request to change palette. | ||
477 | * @regno: The palette index to change. | ||
478 | * @red: The red field for the palette data. | ||
479 | * @green: The green field for the palette data. | ||
480 | * @blue: The blue field for the palette data. | ||
481 | * @trans: The transparency (alpha) field for the palette data. | ||
482 | * @info: The framebuffer being changed. | ||
483 | */ | ||
484 | static int s3c_fb_setcolreg(unsigned regno, | ||
485 | unsigned red, unsigned green, unsigned blue, | ||
486 | unsigned transp, struct fb_info *info) | ||
487 | { | ||
488 | struct s3c_fb_win *win = info->par; | ||
489 | struct s3c_fb *sfb = win->parent; | ||
490 | unsigned int val; | ||
491 | |||
492 | dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n", | ||
493 | __func__, win->index, regno, red, green, blue); | ||
494 | |||
495 | switch (info->fix.visual) { | ||
496 | case FB_VISUAL_TRUECOLOR: | ||
497 | /* true-colour, use pseudo-palette */ | ||
498 | |||
499 | if (regno < 16) { | ||
500 | u32 *pal = info->pseudo_palette; | ||
501 | |||
502 | val = chan_to_field(red, &info->var.red); | ||
503 | val |= chan_to_field(green, &info->var.green); | ||
504 | val |= chan_to_field(blue, &info->var.blue); | ||
505 | |||
506 | pal[regno] = val; | ||
507 | } | ||
508 | break; | ||
509 | |||
510 | case FB_VISUAL_PSEUDOCOLOR: | ||
511 | if (regno < s3c_fb_win_pal_size(win->index)) { | ||
512 | val = chan_to_field(red, &win->palette.r); | ||
513 | val |= chan_to_field(green, &win->palette.g); | ||
514 | val |= chan_to_field(blue, &win->palette.b); | ||
515 | |||
516 | s3c_fb_update_palette(sfb, win, regno, val); | ||
517 | } | ||
518 | |||
519 | break; | ||
520 | |||
521 | default: | ||
522 | return 1; /* unknown type */ | ||
523 | } | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | /** | ||
529 | * s3c_fb_enable() - Set the state of the main LCD output | ||
530 | * @sfb: The main framebuffer state. | ||
531 | * @enable: The state to set. | ||
532 | */ | ||
533 | static void s3c_fb_enable(struct s3c_fb *sfb, int enable) | ||
534 | { | ||
535 | u32 vidcon0 = readl(sfb->regs + VIDCON0); | ||
536 | |||
537 | if (enable) | ||
538 | vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F; | ||
539 | else { | ||
540 | /* see the note in the framebuffer datasheet about | ||
541 | * why you cannot take both of these bits down at the | ||
542 | * same time. */ | ||
543 | |||
544 | if (!(vidcon0 & VIDCON0_ENVID)) | ||
545 | return; | ||
546 | |||
547 | vidcon0 |= VIDCON0_ENVID; | ||
548 | vidcon0 &= ~VIDCON0_ENVID_F; | ||
549 | } | ||
550 | |||
551 | writel(vidcon0, sfb->regs + VIDCON0); | ||
552 | } | ||
553 | |||
554 | /** | ||
555 | * s3c_fb_blank() - blank or unblank the given window | ||
556 | * @blank_mode: The blank state from FB_BLANK_* | ||
557 | * @info: The framebuffer to blank. | ||
558 | * | ||
559 | * Framebuffer layer request to change the power state. | ||
560 | */ | ||
561 | static int s3c_fb_blank(int blank_mode, struct fb_info *info) | ||
562 | { | ||
563 | struct s3c_fb_win *win = info->par; | ||
564 | struct s3c_fb *sfb = win->parent; | ||
565 | unsigned int index = win->index; | ||
566 | u32 wincon; | ||
567 | |||
568 | dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); | ||
569 | |||
570 | wincon = readl(sfb->regs + WINCON(index)); | ||
571 | |||
572 | switch (blank_mode) { | ||
573 | case FB_BLANK_POWERDOWN: | ||
574 | wincon &= ~WINCONx_ENWIN; | ||
575 | sfb->enabled &= ~(1 << index); | ||
576 | /* fall through to FB_BLANK_NORMAL */ | ||
577 | |||
578 | case FB_BLANK_NORMAL: | ||
579 | /* disable the DMA and display 0x0 (black) */ | ||
580 | writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0), | ||
581 | sfb->regs + WINxMAP(index)); | ||
582 | break; | ||
583 | |||
584 | case FB_BLANK_UNBLANK: | ||
585 | writel(0x0, sfb->regs + WINxMAP(index)); | ||
586 | wincon |= WINCONx_ENWIN; | ||
587 | sfb->enabled |= (1 << index); | ||
588 | break; | ||
589 | |||
590 | case FB_BLANK_VSYNC_SUSPEND: | ||
591 | case FB_BLANK_HSYNC_SUSPEND: | ||
592 | default: | ||
593 | return 1; | ||
594 | } | ||
595 | |||
596 | writel(wincon, sfb->regs + WINCON(index)); | ||
597 | |||
598 | /* Check the enabled state to see if we need to be running the | ||
599 | * main LCD interface, as if there are no active windows then | ||
600 | * it is highly likely that we also do not need to output | ||
601 | * anything. | ||
602 | */ | ||
603 | |||
604 | /* We could do something like the following code, but the current | ||
605 | * system of using framebuffer events means that we cannot make | ||
606 | * the distinction between just window 0 being inactive and all | ||
607 | * the windows being down. | ||
608 | * | ||
609 | * s3c_fb_enable(sfb, sfb->enabled ? 1 : 0); | ||
610 | */ | ||
611 | |||
612 | /* we're stuck with this until we can do something about overriding | ||
613 | * the power control using the blanking event for a single fb. | ||
614 | */ | ||
615 | if (index == 0) | ||
616 | s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0); | ||
617 | |||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | static struct fb_ops s3c_fb_ops = { | ||
622 | .owner = THIS_MODULE, | ||
623 | .fb_check_var = s3c_fb_check_var, | ||
624 | .fb_set_par = s3c_fb_set_par, | ||
625 | .fb_blank = s3c_fb_blank, | ||
626 | .fb_setcolreg = s3c_fb_setcolreg, | ||
627 | .fb_fillrect = cfb_fillrect, | ||
628 | .fb_copyarea = cfb_copyarea, | ||
629 | .fb_imageblit = cfb_imageblit, | ||
630 | }; | ||
631 | |||
632 | /** | ||
633 | * s3c_fb_alloc_memory() - allocate display memory for framebuffer window | ||
634 | * @sfb: The base resources for the hardware. | ||
635 | * @win: The window to initialise memory for. | ||
636 | * | ||
637 | * Allocate memory for the given framebuffer. | ||
638 | */ | ||
639 | static int __devinit s3c_fb_alloc_memory(struct s3c_fb *sfb, | ||
640 | struct s3c_fb_win *win) | ||
641 | { | ||
642 | struct s3c_fb_pd_win *windata = win->windata; | ||
643 | unsigned int real_size, virt_size, size; | ||
644 | struct fb_info *fbi = win->fbinfo; | ||
645 | dma_addr_t map_dma; | ||
646 | |||
647 | dev_dbg(sfb->dev, "allocating memory for display\n"); | ||
648 | |||
649 | real_size = windata->win_mode.xres * windata->win_mode.yres; | ||
650 | virt_size = windata->virtual_x * windata->virtual_y; | ||
651 | |||
652 | dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n", | ||
653 | real_size, windata->win_mode.xres, windata->win_mode.yres, | ||
654 | virt_size, windata->virtual_x, windata->virtual_y); | ||
655 | |||
656 | size = (real_size > virt_size) ? real_size : virt_size; | ||
657 | size *= (windata->max_bpp > 16) ? 32 : windata->max_bpp; | ||
658 | size /= 8; | ||
659 | |||
660 | fbi->fix.smem_len = size; | ||
661 | size = PAGE_ALIGN(size); | ||
662 | |||
663 | dev_dbg(sfb->dev, "want %u bytes for window\n", size); | ||
664 | |||
665 | fbi->screen_base = dma_alloc_writecombine(sfb->dev, size, | ||
666 | &map_dma, GFP_KERNEL); | ||
667 | if (!fbi->screen_base) | ||
668 | return -ENOMEM; | ||
669 | |||
670 | dev_dbg(sfb->dev, "mapped %x to %p\n", | ||
671 | (unsigned int)map_dma, fbi->screen_base); | ||
672 | |||
673 | memset(fbi->screen_base, 0x0, size); | ||
674 | fbi->fix.smem_start = map_dma; | ||
675 | |||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | /** | ||
680 | * s3c_fb_free_memory() - free the display memory for the given window | ||
681 | * @sfb: The base resources for the hardware. | ||
682 | * @win: The window to free the display memory for. | ||
683 | * | ||
684 | * Free the display memory allocated by s3c_fb_alloc_memory(). | ||
685 | */ | ||
686 | static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win) | ||
687 | { | ||
688 | struct fb_info *fbi = win->fbinfo; | ||
689 | |||
690 | dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len), | ||
691 | fbi->screen_base, fbi->fix.smem_start); | ||
692 | } | ||
693 | |||
694 | /** | ||
695 | * s3c_fb_release_win() - release resources for a framebuffer window. | ||
696 | * @win: The window to cleanup the resources for. | ||
697 | * | ||
698 | * Release the resources that where claimed for the hardware window, | ||
699 | * such as the framebuffer instance and any memory claimed for it. | ||
700 | */ | ||
701 | static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win) | ||
702 | { | ||
703 | fb_dealloc_cmap(&win->fbinfo->cmap); | ||
704 | unregister_framebuffer(win->fbinfo); | ||
705 | s3c_fb_free_memory(sfb, win); | ||
706 | } | ||
707 | |||
708 | /** | ||
709 | * s3c_fb_probe_win() - register an hardware window | ||
710 | * @sfb: The base resources for the hardware | ||
711 | * @res: Pointer to where to place the resultant window. | ||
712 | * | ||
713 | * Allocate and do the basic initialisation for one of the hardware's graphics | ||
714 | * windows. | ||
715 | */ | ||
716 | static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no, | ||
717 | struct s3c_fb_win **res) | ||
718 | { | ||
719 | struct fb_var_screeninfo *var; | ||
720 | struct fb_videomode *initmode; | ||
721 | struct s3c_fb_pd_win *windata; | ||
722 | struct s3c_fb_win *win; | ||
723 | struct fb_info *fbinfo; | ||
724 | int palette_size; | ||
725 | int ret; | ||
726 | |||
727 | dev_dbg(sfb->dev, "probing window %d\n", win_no); | ||
728 | |||
729 | palette_size = s3c_fb_win_pal_size(win_no); | ||
730 | |||
731 | fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) + | ||
732 | palette_size * sizeof(u32), sfb->dev); | ||
733 | if (!fbinfo) { | ||
734 | dev_err(sfb->dev, "failed to allocate framebuffer\n"); | ||
735 | return -ENOENT; | ||
736 | } | ||
737 | |||
738 | windata = sfb->pdata->win[win_no]; | ||
739 | initmode = &windata->win_mode; | ||
740 | |||
741 | WARN_ON(windata->max_bpp == 0); | ||
742 | WARN_ON(windata->win_mode.xres == 0); | ||
743 | WARN_ON(windata->win_mode.yres == 0); | ||
744 | |||
745 | win = fbinfo->par; | ||
746 | var = &fbinfo->var; | ||
747 | win->fbinfo = fbinfo; | ||
748 | win->parent = sfb; | ||
749 | win->windata = windata; | ||
750 | win->index = win_no; | ||
751 | win->palette_buffer = (u32 *)(win + 1); | ||
752 | |||
753 | ret = s3c_fb_alloc_memory(sfb, win); | ||
754 | if (ret) { | ||
755 | dev_err(sfb->dev, "failed to allocate display memory\n"); | ||
756 | goto err_framebuffer; | ||
757 | } | ||
758 | |||
759 | /* setup the r/b/g positions for the window's palette */ | ||
760 | s3c_fb_init_palette(win_no, &win->palette); | ||
761 | |||
762 | /* setup the initial video mode from the window */ | ||
763 | fb_videomode_to_var(&fbinfo->var, initmode); | ||
764 | |||
765 | fbinfo->fix.type = FB_TYPE_PACKED_PIXELS; | ||
766 | fbinfo->fix.accel = FB_ACCEL_NONE; | ||
767 | fbinfo->var.activate = FB_ACTIVATE_NOW; | ||
768 | fbinfo->var.vmode = FB_VMODE_NONINTERLACED; | ||
769 | fbinfo->var.bits_per_pixel = windata->default_bpp; | ||
770 | fbinfo->fbops = &s3c_fb_ops; | ||
771 | fbinfo->flags = FBINFO_FLAG_DEFAULT; | ||
772 | fbinfo->pseudo_palette = &win->pseudo_palette; | ||
773 | |||
774 | /* prepare to actually start the framebuffer */ | ||
775 | |||
776 | ret = s3c_fb_check_var(&fbinfo->var, fbinfo); | ||
777 | if (ret < 0) { | ||
778 | dev_err(sfb->dev, "check_var failed on initial video params\n"); | ||
779 | goto err_alloc_mem; | ||
780 | } | ||
781 | |||
782 | /* create initial colour map */ | ||
783 | |||
784 | ret = fb_alloc_cmap(&fbinfo->cmap, s3c_fb_win_pal_size(win_no), 1); | ||
785 | if (ret == 0) | ||
786 | fb_set_cmap(&fbinfo->cmap, fbinfo); | ||
787 | else | ||
788 | dev_err(sfb->dev, "failed to allocate fb cmap\n"); | ||
789 | |||
790 | s3c_fb_set_par(fbinfo); | ||
791 | |||
792 | dev_dbg(sfb->dev, "about to register framebuffer\n"); | ||
793 | |||
794 | /* run the check_var and set_par on our configuration. */ | ||
795 | |||
796 | ret = register_framebuffer(fbinfo); | ||
797 | if (ret < 0) { | ||
798 | dev_err(sfb->dev, "failed to register framebuffer\n"); | ||
799 | goto err_alloc_mem; | ||
800 | } | ||
801 | |||
802 | *res = win; | ||
803 | dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id); | ||
804 | |||
805 | return 0; | ||
806 | |||
807 | err_alloc_mem: | ||
808 | s3c_fb_free_memory(sfb, win); | ||
809 | |||
810 | err_framebuffer: | ||
811 | unregister_framebuffer(fbinfo); | ||
812 | return ret; | ||
813 | } | ||
814 | |||
815 | /** | ||
816 | * s3c_fb_clear_win() - clear hardware window registers. | ||
817 | * @sfb: The base resources for the hardware. | ||
818 | * @win: The window to process. | ||
819 | * | ||
820 | * Reset the specific window registers to a known state. | ||
821 | */ | ||
822 | static void s3c_fb_clear_win(struct s3c_fb *sfb, int win) | ||
823 | { | ||
824 | void __iomem *regs = sfb->regs; | ||
825 | |||
826 | writel(0, regs + WINCON(win)); | ||
827 | writel(0xffffff, regs + WxKEYCONy(win, 0)); | ||
828 | writel(0xffffff, regs + WxKEYCONy(win, 1)); | ||
829 | |||
830 | writel(0, regs + VIDOSD_A(win)); | ||
831 | writel(0, regs + VIDOSD_B(win)); | ||
832 | writel(0, regs + VIDOSD_C(win)); | ||
833 | } | ||
834 | |||
835 | static int __devinit s3c_fb_probe(struct platform_device *pdev) | ||
836 | { | ||
837 | struct device *dev = &pdev->dev; | ||
838 | struct s3c_fb_platdata *pd; | ||
839 | struct s3c_fb *sfb; | ||
840 | struct resource *res; | ||
841 | int win; | ||
842 | int ret = 0; | ||
843 | |||
844 | pd = pdev->dev.platform_data; | ||
845 | if (!pd) { | ||
846 | dev_err(dev, "no platform data specified\n"); | ||
847 | return -EINVAL; | ||
848 | } | ||
849 | |||
850 | sfb = kzalloc(sizeof(struct s3c_fb), GFP_KERNEL); | ||
851 | if (!sfb) { | ||
852 | dev_err(dev, "no memory for framebuffers\n"); | ||
853 | return -ENOMEM; | ||
854 | } | ||
855 | |||
856 | sfb->dev = dev; | ||
857 | sfb->pdata = pd; | ||
858 | |||
859 | sfb->bus_clk = clk_get(dev, "lcd"); | ||
860 | if (IS_ERR(sfb->bus_clk)) { | ||
861 | dev_err(dev, "failed to get bus clock\n"); | ||
862 | goto err_sfb; | ||
863 | } | ||
864 | |||
865 | clk_enable(sfb->bus_clk); | ||
866 | |||
867 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
868 | if (!res) { | ||
869 | dev_err(dev, "failed to find registers\n"); | ||
870 | ret = -ENOENT; | ||
871 | goto err_clk; | ||
872 | } | ||
873 | |||
874 | sfb->regs_res = request_mem_region(res->start, resource_size(res), | ||
875 | dev_name(dev)); | ||
876 | if (!sfb->regs_res) { | ||
877 | dev_err(dev, "failed to claim register region\n"); | ||
878 | ret = -ENOENT; | ||
879 | goto err_clk; | ||
880 | } | ||
881 | |||
882 | sfb->regs = ioremap(res->start, resource_size(res)); | ||
883 | if (!sfb->regs) { | ||
884 | dev_err(dev, "failed to map registers\n"); | ||
885 | ret = -ENXIO; | ||
886 | goto err_req_region; | ||
887 | } | ||
888 | |||
889 | dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs); | ||
890 | |||
891 | /* setup gpio and output polarity controls */ | ||
892 | |||
893 | pd->setup_gpio(); | ||
894 | |||
895 | writel(pd->vidcon1, sfb->regs + VIDCON1); | ||
896 | |||
897 | /* zero all windows before we do anything */ | ||
898 | |||
899 | for (win = 0; win < S3C_FB_MAX_WIN; win++) | ||
900 | s3c_fb_clear_win(sfb, win); | ||
901 | |||
902 | /* we have the register setup, start allocating framebuffers */ | ||
903 | |||
904 | for (win = 0; win < S3C_FB_MAX_WIN; win++) { | ||
905 | if (!pd->win[win]) | ||
906 | continue; | ||
907 | |||
908 | ret = s3c_fb_probe_win(sfb, win, &sfb->windows[win]); | ||
909 | if (ret < 0) { | ||
910 | dev_err(dev, "failed to create window %d\n", win); | ||
911 | for (; win >= 0; win--) | ||
912 | s3c_fb_release_win(sfb, sfb->windows[win]); | ||
913 | goto err_ioremap; | ||
914 | } | ||
915 | } | ||
916 | |||
917 | platform_set_drvdata(pdev, sfb); | ||
918 | |||
919 | return 0; | ||
920 | |||
921 | err_ioremap: | ||
922 | iounmap(sfb->regs); | ||
923 | |||
924 | err_req_region: | ||
925 | release_resource(sfb->regs_res); | ||
926 | kfree(sfb->regs_res); | ||
927 | |||
928 | err_clk: | ||
929 | clk_disable(sfb->bus_clk); | ||
930 | clk_put(sfb->bus_clk); | ||
931 | |||
932 | err_sfb: | ||
933 | kfree(sfb); | ||
934 | return ret; | ||
935 | } | ||
936 | |||
937 | /** | ||
938 | * s3c_fb_remove() - Cleanup on module finalisation | ||
939 | * @pdev: The platform device we are bound to. | ||
940 | * | ||
941 | * Shutdown and then release all the resources that the driver allocated | ||
942 | * on initialisation. | ||
943 | */ | ||
944 | static int __devexit s3c_fb_remove(struct platform_device *pdev) | ||
945 | { | ||
946 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | ||
947 | int win; | ||
948 | |||
949 | for (win = 0; win <= S3C_FB_MAX_WIN; win++) | ||
950 | s3c_fb_release_win(sfb, sfb->windows[win]); | ||
951 | |||
952 | iounmap(sfb->regs); | ||
953 | |||
954 | clk_disable(sfb->bus_clk); | ||
955 | clk_put(sfb->bus_clk); | ||
956 | |||
957 | release_resource(sfb->regs_res); | ||
958 | kfree(sfb->regs_res); | ||
959 | |||
960 | kfree(sfb); | ||
961 | |||
962 | return 0; | ||
963 | } | ||
964 | |||
965 | #ifdef CONFIG_PM | ||
966 | static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state) | ||
967 | { | ||
968 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | ||
969 | struct s3c_fb_win *win; | ||
970 | int win_no; | ||
971 | |||
972 | for (win_no = S3C_FB_MAX_WIN; win_no >= 0; win_no--) { | ||
973 | win = sfb->windows[win_no]; | ||
974 | if (!win) | ||
975 | continue; | ||
976 | |||
977 | /* use the blank function to push into power-down */ | ||
978 | s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); | ||
979 | } | ||
980 | |||
981 | clk_disable(sfb->bus_clk); | ||
982 | return 0; | ||
983 | } | ||
984 | |||
985 | static int s3c_fb_resume(struct platform_device *pdev) | ||
986 | { | ||
987 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | ||
988 | struct s3c_fb_win *win; | ||
989 | int win_no; | ||
990 | |||
991 | clk_enable(sfb->bus_clk); | ||
992 | |||
993 | for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { | ||
994 | win = sfb->windows[win_no]; | ||
995 | if (!win) | ||
996 | continue; | ||
997 | |||
998 | dev_dbg(&pdev->dev, "resuming window %d\n", win_no); | ||
999 | s3c_fb_set_par(win->fbinfo); | ||
1000 | } | ||
1001 | |||
1002 | return 0; | ||
1003 | } | ||
1004 | #else | ||
1005 | #define s3c_fb_suspend NULL | ||
1006 | #define s3c_fb_resume NULL | ||
1007 | #endif | ||
1008 | |||
1009 | static struct platform_driver s3c_fb_driver = { | ||
1010 | .probe = s3c_fb_probe, | ||
1011 | .remove = s3c_fb_remove, | ||
1012 | .suspend = s3c_fb_suspend, | ||
1013 | .resume = s3c_fb_resume, | ||
1014 | .driver = { | ||
1015 | .name = "s3c-fb", | ||
1016 | .owner = THIS_MODULE, | ||
1017 | }, | ||
1018 | }; | ||
1019 | |||
1020 | static int __init s3c_fb_init(void) | ||
1021 | { | ||
1022 | return platform_driver_register(&s3c_fb_driver); | ||
1023 | } | ||
1024 | |||
1025 | static void __exit s3c_fb_cleanup(void) | ||
1026 | { | ||
1027 | platform_driver_unregister(&s3c_fb_driver); | ||
1028 | } | ||
1029 | |||
1030 | module_init(s3c_fb_init); | ||
1031 | module_exit(s3c_fb_cleanup); | ||
1032 | |||
1033 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | ||
1034 | MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver"); | ||
1035 | MODULE_LICENSE("GPL"); | ||
1036 | MODULE_ALIAS("platform:s3c-fb"); | ||
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index f5252c2552fd..bba53714a7b1 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c | |||
@@ -837,6 +837,8 @@ static int sgivwfb_remove(struct platform_device *dev) | |||
837 | iounmap(par->regs); | 837 | iounmap(par->regs); |
838 | iounmap(info->screen_base); | 838 | iounmap(info->screen_base); |
839 | release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE); | 839 | release_mem_region(DBE_REG_PHYS, DBE_REG_SIZE); |
840 | fb_dealloc_cmap(&info->cmap); | ||
841 | framebuffer_release(info); | ||
840 | } | 842 | } |
841 | return 0; | 843 | return 0; |
842 | } | 844 | } |
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index df5336561d13..a439159204a8 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c | |||
@@ -795,8 +795,9 @@ static int __devinit xxxfb_probe(struct pci_dev *dev, | |||
795 | if (!retval || retval == 4) | 795 | if (!retval || retval == 4) |
796 | return -EINVAL; | 796 | return -EINVAL; |
797 | 797 | ||
798 | /* This has to been done !!! */ | 798 | /* This has to be done! */ |
799 | fb_alloc_cmap(&info->cmap, cmap_len, 0); | 799 | if (fb_alloc_cmap(&info->cmap, cmap_len, 0)) |
800 | return -ENOMEM; | ||
800 | 801 | ||
801 | /* | 802 | /* |
802 | * The following is done in the case of having hardware with a static | 803 | * The following is done in the case of having hardware with a static |
@@ -820,8 +821,10 @@ static int __devinit xxxfb_probe(struct pci_dev *dev, | |||
820 | */ | 821 | */ |
821 | /* xxxfb_set_par(info); */ | 822 | /* xxxfb_set_par(info); */ |
822 | 823 | ||
823 | if (register_framebuffer(info) < 0) | 824 | if (register_framebuffer(info) < 0) { |
825 | fb_dealloc_cmap(&info->cmap); | ||
824 | return -EINVAL; | 826 | return -EINVAL; |
827 | } | ||
825 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, | 828 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, |
826 | info->fix.id); | 829 | info->fix.id); |
827 | pci_set_drvdata(dev, info); /* or platform_set_drvdata(pdev, info) */ | 830 | pci_set_drvdata(dev, info); /* or platform_set_drvdata(pdev, info) */ |
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index dcd98793d568..eb5d73a06702 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
@@ -1525,7 +1525,10 @@ static int sm501fb_init_fb(struct fb_info *fb, | |||
1525 | } | 1525 | } |
1526 | 1526 | ||
1527 | /* initialise and set the palette */ | 1527 | /* initialise and set the palette */ |
1528 | fb_alloc_cmap(&fb->cmap, NR_PALETTE, 0); | 1528 | if (fb_alloc_cmap(&fb->cmap, NR_PALETTE, 0)) { |
1529 | dev_err(info->dev, "failed to allocate cmap memory\n"); | ||
1530 | return -ENOMEM; | ||
1531 | } | ||
1529 | fb_set_cmap(&fb->cmap, fb); | 1532 | fb_set_cmap(&fb->cmap, fb); |
1530 | 1533 | ||
1531 | ret = (fb->fbops->fb_check_var)(&fb->var, fb); | 1534 | ret = (fb->fbops->fb_check_var)(&fb->var, fb); |
diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 5b11a00f49bc..609d0a521ca2 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c | |||
@@ -1421,13 +1421,16 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, | |||
1421 | goto fail; | 1421 | goto fail; |
1422 | } | 1422 | } |
1423 | 1423 | ||
1424 | fb_alloc_cmap(&info->cmap, 256, 0); | 1424 | if (fb_alloc_cmap(&info->cmap, 256, 0)) { |
1425 | printk(KERN_ERR "sstfb: can't alloc cmap memory.\n"); | ||
1426 | goto fail; | ||
1427 | } | ||
1425 | 1428 | ||
1426 | /* register fb */ | 1429 | /* register fb */ |
1427 | info->device = &pdev->dev; | 1430 | info->device = &pdev->dev; |
1428 | if (register_framebuffer(info) < 0) { | 1431 | if (register_framebuffer(info) < 0) { |
1429 | printk(KERN_ERR "sstfb: can't register framebuffer.\n"); | 1432 | printk(KERN_ERR "sstfb: can't register framebuffer.\n"); |
1430 | goto fail; | 1433 | goto fail_register; |
1431 | } | 1434 | } |
1432 | 1435 | ||
1433 | sstfb_clear_screen(info); | 1436 | sstfb_clear_screen(info); |
@@ -1441,8 +1444,9 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, | |||
1441 | 1444 | ||
1442 | return 0; | 1445 | return 0; |
1443 | 1446 | ||
1444 | fail: | 1447 | fail_register: |
1445 | fb_dealloc_cmap(&info->cmap); | 1448 | fb_dealloc_cmap(&info->cmap); |
1449 | fail: | ||
1446 | iounmap(info->screen_base); | 1450 | iounmap(info->screen_base); |
1447 | fail_fb_remap: | 1451 | fail_fb_remap: |
1448 | iounmap(par->mmio_vbase); | 1452 | iounmap(par->mmio_vbase); |
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 166481402412..eabaad765aeb 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c | |||
@@ -1262,24 +1262,25 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) | |||
1262 | info->flags = FBINFO_DEFAULT; | 1262 | info->flags = FBINFO_DEFAULT; |
1263 | info->pseudo_palette = &fb->pseudo_palette; | 1263 | info->pseudo_palette = &fb->pseudo_palette; |
1264 | 1264 | ||
1265 | /* This has to been done !!! */ | 1265 | /* This has to be done !!! */ |
1266 | fb_alloc_cmap(&info->cmap, NR_PALETTE, 0); | 1266 | if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0)) |
1267 | goto out_err1; | ||
1267 | stifb_init_display(fb); | 1268 | stifb_init_display(fb); |
1268 | 1269 | ||
1269 | if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb fb")) { | 1270 | if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb fb")) { |
1270 | printk(KERN_ERR "stifb: cannot reserve fb region 0x%04lx-0x%04lx\n", | 1271 | printk(KERN_ERR "stifb: cannot reserve fb region 0x%04lx-0x%04lx\n", |
1271 | fix->smem_start, fix->smem_start+fix->smem_len); | 1272 | fix->smem_start, fix->smem_start+fix->smem_len); |
1272 | goto out_err1; | 1273 | goto out_err2; |
1273 | } | 1274 | } |
1274 | 1275 | ||
1275 | if (!request_mem_region(fix->mmio_start, fix->mmio_len, "stifb mmio")) { | 1276 | if (!request_mem_region(fix->mmio_start, fix->mmio_len, "stifb mmio")) { |
1276 | printk(KERN_ERR "stifb: cannot reserve sti mmio region 0x%04lx-0x%04lx\n", | 1277 | printk(KERN_ERR "stifb: cannot reserve sti mmio region 0x%04lx-0x%04lx\n", |
1277 | fix->mmio_start, fix->mmio_start+fix->mmio_len); | 1278 | fix->mmio_start, fix->mmio_start+fix->mmio_len); |
1278 | goto out_err2; | 1279 | goto out_err3; |
1279 | } | 1280 | } |
1280 | 1281 | ||
1281 | if (register_framebuffer(&fb->info) < 0) | 1282 | if (register_framebuffer(&fb->info) < 0) |
1282 | goto out_err3; | 1283 | goto out_err4; |
1283 | 1284 | ||
1284 | sti->info = info; /* save for unregister_framebuffer() */ | 1285 | sti->info = info; /* save for unregister_framebuffer() */ |
1285 | 1286 | ||
@@ -1297,13 +1298,14 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) | |||
1297 | return 0; | 1298 | return 0; |
1298 | 1299 | ||
1299 | 1300 | ||
1300 | out_err3: | 1301 | out_err4: |
1301 | release_mem_region(fix->mmio_start, fix->mmio_len); | 1302 | release_mem_region(fix->mmio_start, fix->mmio_len); |
1302 | out_err2: | 1303 | out_err3: |
1303 | release_mem_region(fix->smem_start, fix->smem_len); | 1304 | release_mem_region(fix->smem_start, fix->smem_len); |
1305 | out_err2: | ||
1306 | fb_dealloc_cmap(&info->cmap); | ||
1304 | out_err1: | 1307 | out_err1: |
1305 | iounmap(info->screen_base); | 1308 | iounmap(info->screen_base); |
1306 | fb_dealloc_cmap(&info->cmap); | ||
1307 | out_err0: | 1309 | out_err0: |
1308 | kfree(fb); | 1310 | kfree(fb); |
1309 | return -ENXIO; | 1311 | return -ENXIO; |
diff --git a/drivers/video/sunxvr500.c b/drivers/video/sunxvr500.c index c2ba51b7ea18..18b950706cad 100644 --- a/drivers/video/sunxvr500.c +++ b/drivers/video/sunxvr500.c | |||
@@ -349,11 +349,14 @@ static int __devinit e3d_pci_register(struct pci_dev *pdev, | |||
349 | if (err < 0) { | 349 | if (err < 0) { |
350 | printk(KERN_ERR "e3d: Could not register framebuffer %s\n", | 350 | printk(KERN_ERR "e3d: Could not register framebuffer %s\n", |
351 | pci_name(pdev)); | 351 | pci_name(pdev)); |
352 | goto err_unmap_fb; | 352 | goto err_free_cmap; |
353 | } | 353 | } |
354 | 354 | ||
355 | return 0; | 355 | return 0; |
356 | 356 | ||
357 | err_free_cmap: | ||
358 | fb_dealloc_cmap(&info->cmap); | ||
359 | |||
357 | err_unmap_fb: | 360 | err_unmap_fb: |
358 | iounmap(ep->fb_base); | 361 | iounmap(ep->fb_base); |
359 | 362 | ||
@@ -389,6 +392,7 @@ static void __devexit e3d_pci_unregister(struct pci_dev *pdev) | |||
389 | pci_release_region(pdev, 0); | 392 | pci_release_region(pdev, 0); |
390 | pci_release_region(pdev, 1); | 393 | pci_release_region(pdev, 1); |
391 | 394 | ||
395 | fb_dealloc_cmap(&info->cmap); | ||
392 | framebuffer_release(info); | 396 | framebuffer_release(info); |
393 | 397 | ||
394 | pci_disable_device(pdev); | 398 | pci_disable_device(pdev); |
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 14bd3f3680b8..ee64771fbe3d 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c | |||
@@ -1393,6 +1393,7 @@ static void __devexit tdfxfb_remove(struct pci_dev *pdev) | |||
1393 | release_mem_region(pci_resource_start(pdev, 0), | 1393 | release_mem_region(pci_resource_start(pdev, 0), |
1394 | pci_resource_len(pdev, 0)); | 1394 | pci_resource_len(pdev, 0)); |
1395 | pci_set_drvdata(pdev, NULL); | 1395 | pci_set_drvdata(pdev, NULL); |
1396 | fb_dealloc_cmap(&info->cmap); | ||
1396 | framebuffer_release(info); | 1397 | framebuffer_release(info); |
1397 | } | 1398 | } |
1398 | 1399 | ||
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 680642c089c9..a86046ff60ad 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c | |||
@@ -1663,7 +1663,7 @@ tgafb_register(struct device *dev) | |||
1663 | if (register_framebuffer(info) < 0) { | 1663 | if (register_framebuffer(info) < 0) { |
1664 | printk(KERN_ERR "tgafb: Could not register framebuffer\n"); | 1664 | printk(KERN_ERR "tgafb: Could not register framebuffer\n"); |
1665 | ret = -EINVAL; | 1665 | ret = -EINVAL; |
1666 | goto err1; | 1666 | goto err2; |
1667 | } | 1667 | } |
1668 | 1668 | ||
1669 | if (tga_bus_pci) { | 1669 | if (tga_bus_pci) { |
@@ -1682,6 +1682,8 @@ tgafb_register(struct device *dev) | |||
1682 | 1682 | ||
1683 | return 0; | 1683 | return 0; |
1684 | 1684 | ||
1685 | err2: | ||
1686 | fb_dealloc_cmap(&info->cmap); | ||
1685 | err1: | 1687 | err1: |
1686 | if (mem_base) | 1688 | if (mem_base) |
1687 | iounmap(mem_base); | 1689 | iounmap(mem_base); |
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index 479b2e79ad68..03a9c35e9f55 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Frame buffer driver for Trident TGUI, Blade and Image series | 2 | * Frame buffer driver for Trident TGUI, Blade and Image series |
3 | * | 3 | * |
4 | * Copyright 2001, 2002 - Jani Monoses <jani@iv.ro> | 4 | * Copyright 2001, 2002 - Jani Monoses <jani@iv.ro> |
5 | * | 5 | * Copyright 2009 Krzysztof Helt <krzysztof.h1@wp.pl> |
6 | * | 6 | * |
7 | * CREDITS:(in order of appearance) | 7 | * CREDITS:(in order of appearance) |
8 | * skeletonfb.c by Geert Uytterhoeven and other fb code in drivers/video | 8 | * skeletonfb.c by Geert Uytterhoeven and other fb code in drivers/video |
@@ -490,7 +490,6 @@ static void tgui_copy_rect(struct tridentfb_par *par, | |||
490 | /* | 490 | /* |
491 | * Accel functions called by the upper layers | 491 | * Accel functions called by the upper layers |
492 | */ | 492 | */ |
493 | #ifdef CONFIG_FB_TRIDENT_ACCEL | ||
494 | static void tridentfb_fillrect(struct fb_info *info, | 493 | static void tridentfb_fillrect(struct fb_info *info, |
495 | const struct fb_fillrect *fr) | 494 | const struct fb_fillrect *fr) |
496 | { | 495 | { |
@@ -565,11 +564,6 @@ static int tridentfb_sync(struct fb_info *info) | |||
565 | par->wait_engine(par); | 564 | par->wait_engine(par); |
566 | return 0; | 565 | return 0; |
567 | } | 566 | } |
568 | #else | ||
569 | #define tridentfb_fillrect cfb_fillrect | ||
570 | #define tridentfb_copyarea cfb_copyarea | ||
571 | #define tridentfb_imageblit cfb_imageblit | ||
572 | #endif /* CONFIG_FB_TRIDENT_ACCEL */ | ||
573 | 567 | ||
574 | /* | 568 | /* |
575 | * Hardware access functions | 569 | * Hardware access functions |
@@ -1333,9 +1327,7 @@ static struct fb_ops tridentfb_ops = { | |||
1333 | .fb_fillrect = tridentfb_fillrect, | 1327 | .fb_fillrect = tridentfb_fillrect, |
1334 | .fb_copyarea = tridentfb_copyarea, | 1328 | .fb_copyarea = tridentfb_copyarea, |
1335 | .fb_imageblit = tridentfb_imageblit, | 1329 | .fb_imageblit = tridentfb_imageblit, |
1336 | #ifdef CONFIG_FB_TRIDENT_ACCEL | ||
1337 | .fb_sync = tridentfb_sync, | 1330 | .fb_sync = tridentfb_sync, |
1338 | #endif | ||
1339 | }; | 1331 | }; |
1340 | 1332 | ||
1341 | static int __devinit trident_pci_probe(struct pci_dev *dev, | 1333 | static int __devinit trident_pci_probe(struct pci_dev *dev, |
@@ -1359,10 +1351,6 @@ static int __devinit trident_pci_probe(struct pci_dev *dev, | |||
1359 | 1351 | ||
1360 | chip_id = id->device; | 1352 | chip_id = id->device; |
1361 | 1353 | ||
1362 | #ifndef CONFIG_FB_TRIDENT_ACCEL | ||
1363 | noaccel = 1; | ||
1364 | #endif | ||
1365 | |||
1366 | /* If PCI id is 0x9660 then further detect chip type */ | 1354 | /* If PCI id is 0x9660 then further detect chip type */ |
1367 | 1355 | ||
1368 | if (chip_id == TGUI9660) { | 1356 | if (chip_id == TGUI9660) { |
@@ -1490,6 +1478,9 @@ static int __devinit trident_pci_probe(struct pci_dev *dev, | |||
1490 | } else | 1478 | } else |
1491 | info->flags |= FBINFO_HWACCEL_DISABLED; | 1479 | info->flags |= FBINFO_HWACCEL_DISABLED; |
1492 | 1480 | ||
1481 | if (is_blade(chip_id) && chip_id != BLADE3D) | ||
1482 | info->flags |= FBINFO_READS_FAST; | ||
1483 | |||
1493 | info->pixmap.addr = kmalloc(4096, GFP_KERNEL); | 1484 | info->pixmap.addr = kmalloc(4096, GFP_KERNEL); |
1494 | if (!info->pixmap.addr) { | 1485 | if (!info->pixmap.addr) { |
1495 | err = -ENOMEM; | 1486 | err = -ENOMEM; |
@@ -1563,6 +1554,7 @@ static void __devexit trident_pci_remove(struct pci_dev *dev) | |||
1563 | release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); | 1554 | release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); |
1564 | pci_set_drvdata(dev, NULL); | 1555 | pci_set_drvdata(dev, NULL); |
1565 | kfree(info->pixmap.addr); | 1556 | kfree(info->pixmap.addr); |
1557 | fb_dealloc_cmap(&info->cmap); | ||
1566 | framebuffer_release(info); | 1558 | framebuffer_release(info); |
1567 | } | 1559 | } |
1568 | 1560 | ||
@@ -1663,4 +1655,5 @@ module_exit(tridentfb_exit); | |||
1663 | MODULE_AUTHOR("Jani Monoses <jani@iv.ro>"); | 1655 | MODULE_AUTHOR("Jani Monoses <jani@iv.ro>"); |
1664 | MODULE_DESCRIPTION("Framebuffer driver for Trident cards"); | 1656 | MODULE_DESCRIPTION("Framebuffer driver for Trident cards"); |
1665 | MODULE_LICENSE("GPL"); | 1657 | MODULE_LICENSE("GPL"); |
1658 | MODULE_ALIAS("cyblafb"); | ||
1666 | 1659 | ||
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index 74ae75899009..0b370aebdbfd 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c | |||
@@ -189,7 +189,7 @@ static int uvesafb_exec(struct uvesafb_ktask *task) | |||
189 | uvfb_tasks[seq] = task; | 189 | uvfb_tasks[seq] = task; |
190 | mutex_unlock(&uvfb_lock); | 190 | mutex_unlock(&uvfb_lock); |
191 | 191 | ||
192 | err = cn_netlink_send(m, 0, gfp_any()); | 192 | err = cn_netlink_send(m, 0, GFP_KERNEL); |
193 | if (err == -ESRCH) { | 193 | if (err == -ESRCH) { |
194 | /* | 194 | /* |
195 | * Try to start the userspace helper if sending | 195 | * Try to start the userspace helper if sending |
@@ -850,14 +850,16 @@ static int __devinit uvesafb_vbe_init_mode(struct fb_info *info) | |||
850 | if (vbemode) { | 850 | if (vbemode) { |
851 | for (i = 0; i < par->vbe_modes_cnt; i++) { | 851 | for (i = 0; i < par->vbe_modes_cnt; i++) { |
852 | if (par->vbe_modes[i].mode_id == vbemode) { | 852 | if (par->vbe_modes[i].mode_id == vbemode) { |
853 | modeid = i; | ||
854 | uvesafb_setup_var(&info->var, info, | ||
855 | &par->vbe_modes[modeid]); | ||
853 | fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, | 856 | fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, |
854 | &info->var, info); | 857 | &info->var, info); |
855 | /* | 858 | /* |
856 | * With pixclock set to 0, the default BIOS | 859 | * With pixclock set to 0, the default BIOS |
857 | * timings will be used in set_par(). | 860 | * timings will be used in set_par(). |
858 | */ | 861 | */ |
859 | info->var.pixclock = 0; | 862 | info->var.pixclock = 0; |
860 | modeid = i; | ||
861 | goto gotmode; | 863 | goto gotmode; |
862 | } | 864 | } |
863 | } | 865 | } |
@@ -904,8 +906,11 @@ static int __devinit uvesafb_vbe_init_mode(struct fb_info *info) | |||
904 | fb_videomode_to_var(&info->var, mode); | 906 | fb_videomode_to_var(&info->var, mode); |
905 | } else { | 907 | } else { |
906 | modeid = par->vbe_modes[0].mode_id; | 908 | modeid = par->vbe_modes[0].mode_id; |
909 | uvesafb_setup_var(&info->var, info, | ||
910 | &par->vbe_modes[modeid]); | ||
907 | fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, | 911 | fb_get_mode(FB_VSYNCTIMINGS | FB_IGNOREMON, 60, |
908 | &info->var, info); | 912 | &info->var, info); |
913 | |||
909 | goto gotmode; | 914 | goto gotmode; |
910 | } | 915 | } |
911 | } | 916 | } |
@@ -917,9 +922,9 @@ static int __devinit uvesafb_vbe_init_mode(struct fb_info *info) | |||
917 | if (modeid == -1) | 922 | if (modeid == -1) |
918 | return -EINVAL; | 923 | return -EINVAL; |
919 | 924 | ||
920 | gotmode: | ||
921 | uvesafb_setup_var(&info->var, info, &par->vbe_modes[modeid]); | 925 | uvesafb_setup_var(&info->var, info, &par->vbe_modes[modeid]); |
922 | 926 | ||
927 | gotmode: | ||
923 | /* | 928 | /* |
924 | * If we are not VBE3.0+ compliant, we're done -- the BIOS will | 929 | * If we are not VBE3.0+ compliant, we're done -- the BIOS will |
925 | * ignore our timings anyway. | 930 | * ignore our timings anyway. |
@@ -1552,7 +1557,7 @@ static void __devinit uvesafb_init_info(struct fb_info *info, | |||
1552 | } | 1557 | } |
1553 | 1558 | ||
1554 | info->flags = FBINFO_FLAG_DEFAULT | | 1559 | info->flags = FBINFO_FLAG_DEFAULT | |
1555 | (par->ypan) ? FBINFO_HWACCEL_YPAN : 0; | 1560 | (par->ypan ? FBINFO_HWACCEL_YPAN : 0); |
1556 | 1561 | ||
1557 | if (!par->ypan) | 1562 | if (!par->ypan) |
1558 | info->fbops->fb_pan_display = NULL; | 1563 | info->fbops->fb_pan_display = NULL; |
diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 7b0cef9ca8f9..4bb9a0b18950 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c | |||
@@ -119,7 +119,7 @@ static void set_valkyrie_clock(unsigned char *params); | |||
119 | static int valkyrie_var_to_par(struct fb_var_screeninfo *var, | 119 | static int valkyrie_var_to_par(struct fb_var_screeninfo *var, |
120 | struct fb_par_valkyrie *par, const struct fb_info *fb_info); | 120 | struct fb_par_valkyrie *par, const struct fb_info *fb_info); |
121 | 121 | ||
122 | static void valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p); | 122 | static int valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p); |
123 | static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, struct fb_fix_screeninfo *fix); | 123 | static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, struct fb_fix_screeninfo *fix); |
124 | static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p); | 124 | static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p); |
125 | 125 | ||
@@ -381,18 +381,22 @@ int __init valkyriefb_init(void) | |||
381 | 381 | ||
382 | valkyrie_choose_mode(p); | 382 | valkyrie_choose_mode(p); |
383 | mac_vmode_to_var(default_vmode, default_cmode, &p->info.var); | 383 | mac_vmode_to_var(default_vmode, default_cmode, &p->info.var); |
384 | valkyrie_init_info(&p->info, p); | 384 | err = valkyrie_init_info(&p->info, p); |
385 | if (err < 0) | ||
386 | goto out_free; | ||
385 | valkyrie_init_fix(&p->info.fix, p); | 387 | valkyrie_init_fix(&p->info.fix, p); |
386 | if (valkyriefb_set_par(&p->info)) | 388 | if (valkyriefb_set_par(&p->info)) |
387 | /* "can't happen" */ | 389 | /* "can't happen" */ |
388 | printk(KERN_ERR "valkyriefb: can't set default video mode\n"); | 390 | printk(KERN_ERR "valkyriefb: can't set default video mode\n"); |
389 | 391 | ||
390 | if ((err = register_framebuffer(&p->info)) != 0) | 392 | if ((err = register_framebuffer(&p->info)) != 0) |
391 | goto out_free; | 393 | goto out_cmap_free; |
392 | 394 | ||
393 | printk(KERN_INFO "fb%d: valkyrie frame buffer device\n", p->info.node); | 395 | printk(KERN_INFO "fb%d: valkyrie frame buffer device\n", p->info.node); |
394 | return 0; | 396 | return 0; |
395 | 397 | ||
398 | out_cmap_free: | ||
399 | fb_dealloc_cmap(&p->info.cmap); | ||
396 | out_free: | 400 | out_free: |
397 | if (p->frame_buffer) | 401 | if (p->frame_buffer) |
398 | iounmap(p->frame_buffer); | 402 | iounmap(p->frame_buffer); |
@@ -538,14 +542,15 @@ static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, | |||
538 | /* ywrapstep, xpanstep, ypanstep */ | 542 | /* ywrapstep, xpanstep, ypanstep */ |
539 | } | 543 | } |
540 | 544 | ||
541 | static void __init valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p) | 545 | static int __init valkyrie_init_info(struct fb_info *info, |
546 | struct fb_info_valkyrie *p) | ||
542 | { | 547 | { |
543 | info->fbops = &valkyriefb_ops; | 548 | info->fbops = &valkyriefb_ops; |
544 | info->screen_base = p->frame_buffer + 0x1000; | 549 | info->screen_base = p->frame_buffer + 0x1000; |
545 | info->flags = FBINFO_DEFAULT; | 550 | info->flags = FBINFO_DEFAULT; |
546 | info->pseudo_palette = p->pseudo_palette; | 551 | info->pseudo_palette = p->pseudo_palette; |
547 | fb_alloc_cmap(&info->cmap, 256, 0); | ||
548 | info->par = &p->par; | 552 | info->par = &p->par; |
553 | return fb_alloc_cmap(&info->cmap, 256, 0); | ||
549 | } | 554 | } |
550 | 555 | ||
551 | 556 | ||
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index e16322d157d0..d6856f43d241 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c | |||
@@ -438,7 +438,7 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
438 | info->var = vesafb_defined; | 438 | info->var = vesafb_defined; |
439 | info->fix = vesafb_fix; | 439 | info->fix = vesafb_fix; |
440 | info->flags = FBINFO_FLAG_DEFAULT | | 440 | info->flags = FBINFO_FLAG_DEFAULT | |
441 | (ypan) ? FBINFO_HWACCEL_YPAN : 0; | 441 | (ypan ? FBINFO_HWACCEL_YPAN : 0); |
442 | 442 | ||
443 | if (!ypan) | 443 | if (!ypan) |
444 | info->fbops->fb_pan_display = NULL; | 444 | info->fbops->fb_pan_display = NULL; |
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 93fe08d6c78f..cc919ae46571 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c | |||
@@ -543,6 +543,7 @@ static int vfb_remove(struct platform_device *dev) | |||
543 | if (info) { | 543 | if (info) { |
544 | unregister_framebuffer(info); | 544 | unregister_framebuffer(info); |
545 | rvfree(videomemory, videomemorysize); | 545 | rvfree(videomemory, videomemorysize); |
546 | fb_dealloc_cmap(&info->cmap); | ||
546 | framebuffer_release(info); | 547 | framebuffer_release(info); |
547 | } | 548 | } |
548 | return 0; | 549 | return 0; |
diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index 632523ff1fb7..45c54bfe99bb 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c | |||
@@ -267,13 +267,17 @@ int viafb_wait_engine_idle(void) | |||
267 | int loop = 0; | 267 | int loop = 0; |
268 | 268 | ||
269 | while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) & | 269 | while (!(readl(viaparinfo->io_virt + VIA_REG_STATUS) & |
270 | VIA_VR_QUEUE_BUSY) && (loop++ < MAXLOOP)) | 270 | VIA_VR_QUEUE_BUSY) && (loop < MAXLOOP)) { |
271 | loop++; | ||
271 | cpu_relax(); | 272 | cpu_relax(); |
273 | } | ||
272 | 274 | ||
273 | while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) & | 275 | while ((readl(viaparinfo->io_virt + VIA_REG_STATUS) & |
274 | (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && | 276 | (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) && |
275 | (loop++ < MAXLOOP)) | 277 | (loop < MAXLOOP)) { |
278 | loop++; | ||
276 | cpu_relax(); | 279 | cpu_relax(); |
280 | } | ||
277 | 281 | ||
278 | return loop >= MAXLOOP; | 282 | return loop >= MAXLOOP; |
279 | } | 283 | } |
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 37b433a08ce8..e327b84820d2 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c | |||
@@ -2059,25 +2059,21 @@ static void viafb_init_proc(struct proc_dir_entry **viafb_entry) | |||
2059 | if (viafb_entry) { | 2059 | if (viafb_entry) { |
2060 | entry = create_proc_entry("dvp0", 0, *viafb_entry); | 2060 | entry = create_proc_entry("dvp0", 0, *viafb_entry); |
2061 | if (entry) { | 2061 | if (entry) { |
2062 | entry->owner = THIS_MODULE; | ||
2063 | entry->read_proc = viafb_dvp0_proc_read; | 2062 | entry->read_proc = viafb_dvp0_proc_read; |
2064 | entry->write_proc = viafb_dvp0_proc_write; | 2063 | entry->write_proc = viafb_dvp0_proc_write; |
2065 | } | 2064 | } |
2066 | entry = create_proc_entry("dvp1", 0, *viafb_entry); | 2065 | entry = create_proc_entry("dvp1", 0, *viafb_entry); |
2067 | if (entry) { | 2066 | if (entry) { |
2068 | entry->owner = THIS_MODULE; | ||
2069 | entry->read_proc = viafb_dvp1_proc_read; | 2067 | entry->read_proc = viafb_dvp1_proc_read; |
2070 | entry->write_proc = viafb_dvp1_proc_write; | 2068 | entry->write_proc = viafb_dvp1_proc_write; |
2071 | } | 2069 | } |
2072 | entry = create_proc_entry("dfph", 0, *viafb_entry); | 2070 | entry = create_proc_entry("dfph", 0, *viafb_entry); |
2073 | if (entry) { | 2071 | if (entry) { |
2074 | entry->owner = THIS_MODULE; | ||
2075 | entry->read_proc = viafb_dfph_proc_read; | 2072 | entry->read_proc = viafb_dfph_proc_read; |
2076 | entry->write_proc = viafb_dfph_proc_write; | 2073 | entry->write_proc = viafb_dfph_proc_write; |
2077 | } | 2074 | } |
2078 | entry = create_proc_entry("dfpl", 0, *viafb_entry); | 2075 | entry = create_proc_entry("dfpl", 0, *viafb_entry); |
2079 | if (entry) { | 2076 | if (entry) { |
2080 | entry->owner = THIS_MODULE; | ||
2081 | entry->read_proc = viafb_dfpl_proc_read; | 2077 | entry->read_proc = viafb_dfpl_proc_read; |
2082 | entry->write_proc = viafb_dfpl_proc_write; | 2078 | entry->write_proc = viafb_dfpl_proc_write; |
2083 | } | 2079 | } |
@@ -2086,7 +2082,6 @@ static void viafb_init_proc(struct proc_dir_entry **viafb_entry) | |||
2086 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { | 2082 | viaparinfo->chip_info->lvds_chip_info2.lvds_chip_name) { |
2087 | entry = create_proc_entry("vt1636", 0, *viafb_entry); | 2083 | entry = create_proc_entry("vt1636", 0, *viafb_entry); |
2088 | if (entry) { | 2084 | if (entry) { |
2089 | entry->owner = THIS_MODULE; | ||
2090 | entry->read_proc = viafb_vt1636_proc_read; | 2085 | entry->read_proc = viafb_vt1636_proc_read; |
2091 | entry->write_proc = viafb_vt1636_proc_write; | 2086 | entry->write_proc = viafb_vt1636_proc_write; |
2092 | } | 2087 | } |
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 5777196bf6c9..5c52369ab9bb 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
@@ -23,15 +23,21 @@ | |||
23 | 23 | ||
24 | #ifdef DEBUG | 24 | #ifdef DEBUG |
25 | /* For development, we want to crash whenever the ring is screwed. */ | 25 | /* For development, we want to crash whenever the ring is screwed. */ |
26 | #define BAD_RING(vq, fmt...) \ | 26 | #define BAD_RING(_vq, fmt...) \ |
27 | do { dev_err(&vq->vq.vdev->dev, fmt); BUG(); } while(0) | 27 | do { dev_err(&(_vq)->vq.vdev->dev, fmt); BUG(); } while(0) |
28 | #define START_USE(vq) \ | 28 | /* Caller is supposed to guarantee no reentry. */ |
29 | do { if ((vq)->in_use) panic("in_use = %i\n", (vq)->in_use); (vq)->in_use = __LINE__; mb(); } while(0) | 29 | #define START_USE(_vq) \ |
30 | #define END_USE(vq) \ | 30 | do { \ |
31 | do { BUG_ON(!(vq)->in_use); (vq)->in_use = 0; mb(); } while(0) | 31 | if ((_vq)->in_use) \ |
32 | panic("in_use = %i\n", (_vq)->in_use); \ | ||
33 | (_vq)->in_use = __LINE__; \ | ||
34 | mb(); \ | ||
35 | } while(0) | ||
36 | #define END_USE(_vq) \ | ||
37 | do { BUG_ON(!(_vq)->in_use); (_vq)->in_use = 0; mb(); } while(0) | ||
32 | #else | 38 | #else |
33 | #define BAD_RING(vq, fmt...) \ | 39 | #define BAD_RING(_vq, fmt...) \ |
34 | do { dev_err(&vq->vq.vdev->dev, fmt); (vq)->broken = true; } while(0) | 40 | do { dev_err(&_vq->vq.vdev->dev, fmt); (_vq)->broken = true; } while(0) |
35 | #define START_USE(vq) | 41 | #define START_USE(vq) |
36 | #define END_USE(vq) | 42 | #define END_USE(vq) |
37 | #endif | 43 | #endif |
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 6cf155d6b350..3137361ccbfe 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c | |||
@@ -380,7 +380,7 @@ asm(".text \n\t" | |||
380 | * This function checks whether or not a SMBIOS/DMI record is | 380 | * This function checks whether or not a SMBIOS/DMI record is |
381 | * the 64bit CRU info or not | 381 | * the 64bit CRU info or not |
382 | */ | 382 | */ |
383 | static void __devinit dmi_find_cru(const struct dmi_header *dm) | 383 | static void __devinit dmi_find_cru(const struct dmi_header *dm, void *dummy) |
384 | { | 384 | { |
385 | struct smbios_cru64_info *smbios_cru64_ptr; | 385 | struct smbios_cru64_info *smbios_cru64_ptr; |
386 | unsigned long cru_physical_address; | 386 | unsigned long cru_physical_address; |
@@ -403,7 +403,7 @@ static int __devinit detect_cru_service(void) | |||
403 | { | 403 | { |
404 | cru_rom_addr = NULL; | 404 | cru_rom_addr = NULL; |
405 | 405 | ||
406 | dmi_walk(dmi_find_cru); | 406 | dmi_walk(dmi_find_cru, NULL); |
407 | 407 | ||
408 | /* if cru_rom_addr has been set then we found a CRU service */ | 408 | /* if cru_rom_addr has been set then we found a CRU service */ |
409 | return ((cru_rom_addr != NULL) ? 0 : -ENODEV); | 409 | return ((cru_rom_addr != NULL) ? 0 : -ENODEV); |